1.匿名内部类(Android中最常用)
把内部类的定义和声明写到一起时,不用给这个类起个类名而是直接使用。这种形式的内部类没有类名,因此叫匿名内部类。
形式如下:new <类或接口> <类的主体>
常用的情景:
- 一个类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的事先或是覆盖。
- 只是为了获得一个对象实例,不需要知道其实际类型。
- 类名没有意义,也就是不需要使用到。
//例如线程的启动
new Thread(new Runnable() {
@Override
public void run() {
}
}).start;
//例如设置监听
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
2.局部内部类(方法内部类)
定义在方法内的内部类叫方法内部类,也就是局部内部类。
- 方法中的内部类没有访问修饰符, 即方法内部类对包围它的方法之外的任何东西都不可见。
- 局部内部类只能在方法内部中使用,一旦方法执行完毕,局部内部类就会从内存中删除。
- 局部内部类只能访问方法中的局部变量,并且这个局部变量必须定义为final。
public class Outter{
public void outterDo() {
final int a = 5;
System.out.println("在外部类的方法中");
class Inner {
private void innerDo() {
System.out.println("局部内部类的方法中");
System.out.println(a);//注意:如果局部内部类中要使用他所在方法中的局部变量,那么就需要将这个局部变量定义为final的。
}
}
Inner inner = new Inner();
inner.innerDo();
}
}
为什么需要将该局部变量定义为final?(匿名内部类同理)
局部内部类是非静态的,所在方法
outterDo()
执行完毕之后,方法的局部变量a
也将失效,而假设在其他地方还存在inner的引用,这个对象再次访问a时就找不到a了。为了避免局部变量和内部类的生命周期不同而起的冲突,Java会将成员变量拷贝一份到内部类中,拷贝意味着要维护数据一致性,所以要加上final修饰。
PS:在JDK8之前,内部类使用的外部类成员变量时必须加上final,但从JDK8开始编译器帮我们做了这项工作。但是如果修改了这个变量,编译器仍然会报错。
3.成员内部类
成员内部类义在一个类中,作为外部类的一个成员存在,与外部类的属性、方法并列。
成员内部类和静态内部类可以类比为非静态的成员变量和静态的成员变量。
它可以访问外部类的所有成员变量和方法。
public class Test1 {
private String member="这是外部类变量";
//成员内部类
class B{
public B() {//当内部类的构造器为Protected、private修饰时外部类外不可以访问
}
public void go(){
System.out.println("这是内部类B的go方法"+Test1.this.member);//内部类访问外部类变量
}
}
//可供成员的外部类中其他方法调用
public B show(){
return this.new B();//外部类调用
}
public static void main(String[] args) {
B b = new Test1().show();
}
}
public class A {
public static void main(String[] args) {
new Test1().show();
(new Test1()).new B().go();//外部类外访问内部类
}
}