简介
定义:将一个类定义在另一个类的里面,里面那个类就是内部类,又称为嵌套类或者内置类。
内部类生成的字节码文件名格式为:OuterClass$InnerClass.class
内部类可以分成成员内部类、局部内部类以及匿名内部类。
在一个类中使用内部类,可以在内部类中直接存取其所在类的私有成员变量,尽管这些类成员被修饰为private。外部类不可以直接访问内部类成员变量,但是可以通过get方法来获得。
内部类的实例一定要绑定在外部类的实例上。如果从外部类中初始化一个内部类对象,那么内部类就会绑定在外部类对象上。内部类的对象实例化必须在外部类或外部类的非静态方法中实现。如果在外部类和非静态方法之外实例化内部类,需要使用外部类。
成员内部类
即内部类作为外部类的一个成员:
public class OuterClass{//外部类
private class InnnerClass{//内部类
}
}
示例:
class Outer{
Inner in =new Inner();//在外部类实例化内部类对象的引用
void ouf(){
in.inf();//在外部类方法中调用内部类方法
}
class Inner{
Inner(){//内部类构造方法
}
void inf(){//内部类成员方法
}
int y=0;//定义内部类成员变量
}
Inner fuc(){//外部类成员方法
in.y=4;//外部类不可以直接访问内部类成员变量:y=4是错的
return new Inner();//返回内部类引用
}
public static void main(String[] args){
Outer out=new Outer();
//内部类的对象实例化操作必须在外部类或外部类的非静态方法中
Outer.Inner in =out.fuc();
Outer.Inner in2=out.new Inner()//实例化内部类时,new之前提供外部类的引用
}
}
局部内部类
内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如类的方法里:
class Outer
{
int num=3;
//void method()
Object method()
{
final int x=9;
class Inner
{
void show()
{
System.out.println("show..."+num);
System.out.println("show..."+x);//从内部类中访问局部变量x,需要被声明为最终类型(final)
}
}
//Inner in =new Innner();
//in.show();
Object in =new Inner();
return in;
}
}
class InnerClassDemo1
{
public static void main(String[] args)
{
//new Outer().method();
Outer out =new Outer();
Object obj=out.method();//method方法调用后把结果传递给obj这个引用后,就出栈了,x消失了,但是对象还在堆里,因此x不能访问
}
注意:在方法中定义的内部类只能访问方法中final类型的局部变量。
匿名内部类
匿名内部类即内部类的简写格式。
存在的前提:内部类必须继承或者实现一个外部类或者接口
就是一个匿名子类对象
格式:new 父类or接口名(){子类内容}
示例1:
abstract class Demo
{
abstract void show();
}
class Outer
{
int num=4;
/*class Inner extends Demo
{
void show()
{
System.out.println("show..."+num);
}
}
*/
public void method()
{
//new Inner().show();
new Demo()//匿名内部类 Demo的子类
{
void show()
{
System.out.println("show..."+num);
}
}.show();//匿名内部类对象调用方法
}
}
class InnerClassDemo2
{
public static void main(String[] args)
{
new Outer().method();
}
}
示例2:
class Outer
{
void method()
{
Object obj=new Object()//匿名内部类+多态
{
public void show()
{
System.out.println("show run");
}
}
obj.show();//编译错误 因为匿名内部类这个子类对象被向上转型为了Object类型
//这样就不能再使用子类特有的方法(show)了
}
}
class InnerClassDemo3
{
public static void main(String[] args)
{
new Outer().method();
}
}
对象初始化过程
1、堆内创建对象空间,分配地址。成员变量默认初始化。
2、构造函数压栈,初始化父类的构造函数。(super();)
3、成员变量显式初始化
4、执行构造代码块
5、执行构造函数内本类具体的初始化。
示例:
class Parent
{
int num=9;
{//构造代码块
System.out.println("Parent block");//1:Parent block
}
Parent(){
super();//Object
//显式初始化
//构造代码块初始化
show();
}
void show(){
System.out.println("parent show..."+num);//被覆盖,运行子类的
}
}
class Son extends Parent{
int num =8;
{//构造代码块
System.out.println("son block");//3:son block
}
Son(){
super();
//显式初始化
//构造代码块初始化
show();
}
void show(){
System.out.println("son show..."+num);//2:son show...0 4:son show...8
}
}
public class Demo{
public static void main(String[] args){
new Son();
}
}
/*输出结果:
Parent block
son show...0
son block
son show...8
*/