内部类:定义在一个类的成员位置,和成员变量以及成员方法所在的位置是一样的,在位置上它们时平行的。
Class Outer{
//成员变量
private int num=10;
//成员方法
public void method(){
Inner i=new Inner();
i.function();
}
//内部类
class Inner{
public void function(){
System.out.println(num);
}
}
}
非静态内部类:没有用static修饰的内部类
由于内部类定义在外部类的成员位置,当我们想使用内部类时,必须要有一个外部类的对象(调用成员方法和成员变量时也是如此)。而我们对类的使用最常见的就是实例化类的对象,所以实例化内部类对象的语法为:
//new Outer()是先实例化一个外部类的对象,当这个对象想使用内部类时,要加上".",
//然后再用new Inner()实例化内部类的对象
new Outer().new Inner();
如同类中的方法能够访问类中所有的成员变量,内部类中可以直接访问外部类的成员,包括私有成员。
关键:内部类与外部类的方法处于平等的位置
静态内部类:用static修饰的内部类
静态内部类用了static修饰,所以静态内部类是属于外部类的,而不是属于外部类的对象,所以我们在创建静态内部类的对象时,不用先创建外部类的对象,而可以直接创建静态内部类的对象,语法为:
//这样写还是错误的,因为内部类是属于外部类的,所以内部类的全名应该是:外部类.内部类
//new Inner();
new Outer.Inner();
由于静态内部类是属于外部类的而不是属于外部类的对象,所以在静态内部类中不能访问外部类的非静态成员,只能访问外部类的静态成员。
局部内部类:加了局部两个字,说明它是定义在方法体中的内部类。出了方法便不可见了
class Outer{
public void function(){
//Inner i=new Inner(); //在声明局部内部类之前是无法实例化局部内部类对象的
//将类定义在方法体中,这个类就是局部内部类
class Inner{
public void method(){
System.out.println("method");
}
}
//只能在声明了局部内部类之后才能实例化其对象,并调用类中的方法
Inner i=new Inner();
i.method();
}
}
匿名内部类:可以把匿名内部类看成是一个没有名字的局部内部类,所以匿名内部类也必须定义在方法体中。由于匿名内部类 没有名字,我们无法在其定义之后实例化它的对象,所以必须在定义匿名内部类的时候就创建它的对象。
格式:
new 类/接口(){
如果是创建了继承这个类的子类对象,我们可以重写父类的方法
如果是创建了实现这个接口的子类对象,我们必须实现这个接口的所有方法
};
原理:创建了继承这个类的子类对象或者是创建了实现这个接口的子类对象
//先创建一个接口
interface Inner{
public void function();
}
class Outer{
public void method(){
/*
由于匿名内部类没有名字,所以我们无法在创建完匿名内部类以后实例化其对象,
只能在定义匿名内部类时就创建他的对象。
但是这样的话我们只在定义这个类的时候调用他的方法,在后面再想调用其方法时就没办法了。
好在java给我们提供了转型机制,我们可以用匿名内部类实现一个接口或者继承一个类,然后用
这个类的引用去接收匿名内部类的对象。这样一来我们就可以在匿名内部类中重写父类的方法,
或者是实现接口的所有方法。
new inner() {
@Override
public void function() {
System.out.println("function");
}
}.function();
*/
Inner i=new Inner(){
public void function(){
System.out.println("function");
}
};
i.function();
i.function();
}
}