Java内部类
Java内部类,我们不常用,今天有看了下,就做个笔记标记下。
内部类是指在一个类的内部或类的成员方法中再定义一个类。内部类名没有和文件同名的限制,只要符合类名称规范就行。内部类可以是静态static的,也可用public,default,protected和private修饰。而外部类只能使用public和default,对于外部顶级类还要加类名必须和文件名相同。内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两个类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后出现Outer.class和Outer$Inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。
内部类分为:1.成员内部类;2.局部内部类;3.静态内部类(嵌套内部类);4.匿名内部类
1.成员内部类
成员内部类,是指将内部类可以看作外部类的一个成员,内部类可以直接使用外部类的所有成员和方法,即使是private描述的。但外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来访问。由于成员内部类需要先创建了外部类,才能创建它自己的,因此成员内部类不能有static属性/方法,也不能包含静态内部类。
在成员内部类要引用外部类对象时,使用外部类.this来表示外部类对象,如:Outer.this。
1 public class Outer { 2 3 private String type; 4 5 public static void main(String[] args) { 6 Outer outer = new Outer(); 7 Outer.Inner inner = outer.new Inner(); 8 //Outer.Inner inner = new Outer().new Inner(); 9 inner.print("Hello World!"); 10 } 11 12 public class Inner { 13 private String type; 14 15 public void print(String str) { 16 System.out.println(Outer.this.type); 17 System.out.println(str); 18 } 19 } 20 }
成员内部类创建 Outer.Inner inner = new Outer().new Inner(); 。成员内部类的对象属于外部类对象,因此要创建内部类,必须创建外部类对象。
2.局部内部类
局部内部类,是指内部类定义在方法和作用域内。局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或作用域内才能使用,退出这些作用域后无法引用的。
3.静态内部类(嵌套内部类)
静态内部类,就是修饰为static的内部类。声明为static的内部类,可以看作内部类是外部类类的静态成员,就是说我们可以直接引用Outer.Inner。静态内部类不能声明为private,一般声明为public。静态内部类可以包含内部类。
1 public class Outer { 2 3 static String type; 4 5 public static void main(String[] args) { 6 Outer.Inner inner = new Outer.new Inner(); 7 inner.print("Hello World!"); 8 } 9 10 static public class Inner { 11 private String type; 12 13 public void print(String str) { 14 System.out.println(Outer.type); 15 System.out.println(str); 16 } 17 } 18 }
静态内部类创建 Outer.Inner inner = new Outer.new Inner(); 。静态内部类属于外部类,通过类名调用创建。
4.匿名内部类
匿名内部类隐式地继承了一个父类或者实现了一个接口。有时候某个内部类只创建一个对象,我为了不对这个内部类命名,便倾向于使用匿名内部类。由于构造器的名字必须和类名相同,而匿名内部类没有类名,所以匿名类不能有自己的构造器。
对于匿名内部类,我们使用的还是挺多的,像模版方法中的回调函数或叫钩子函数;还有像Andorid的组件的监听器的注册等等,为了方便,一般会采用匿名内部类。
下面看一个Android中的按钮点击事件的注册的例子
1 ((Button) findViewById(R.id.loginButton)).setOnClickListener(new Button.OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 new Thread() { 5 @Override 6 public void run() { 7 // TODO Auto-generated method stub 8 } 9 }.start(); 10 } 11 });
对于这段代码实际上创建了两个匿名内部类:1.Button.OnClickListener;2.Thread。
对于匿名内部类的使用,有一下方面需要注意:
1. 当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法。如果有需要,也可以重写父类中的普通方法。
2. 如果匿名内部类需要访问外部类的局部变量,则外部类的局部变量必须使用final修饰符来修饰。(在JDK8中,我们不用写final修饰符也不会报错,但对于JVM实际依旧是按照final常量来处理)