Java 内部类
1、内部类定义:
将一个类的声明和定义放在另一个类的内部。
内部类相当于外部类的类成员,可以访问外部类的成员变量、方法和其它内部类。
2、为什么使用内部类?
“Think in Java“中写道:使用内部类最吸引人的原因是每个内部类都能独立地继承一个类或实现一个接口,所以无论外部类是否已经继承了某个类或者实现了某个接口,对内部类没有影响。而且,内部类对象创建时刻并不依赖外部类对象的创建,内部类和外部类之间没有令人迷惑的“is a”关系,就是一个独立的实体。
内部类提供了更好的封装,除了所在的外部类,其他类都不能访问。
3、内部类的4种形态:
静态内部类:
非静态内部类:成员内部类,局部内部类,匿名内部类。
4、静态内部类:Static Inner
静态内部类跟静态方法一样,只能访问外部类的静态成员。而如果在外部类的静态方法中访问内部类,只能访问静态内部类。(成员之间的静态互访原则)
静态内部类和非静态内部类之间最大的一个区别是,非静态内部类在编译完成后会隐含地保存一个引用,该引用指向创建它的外部类。但是,静态内部类没有这样的引用,意味着静态内部类的对象创建不依赖外部类的对象创建,因此不能访问外部类任何的非静态成员。同时只有静态内部类可以声明静态的成员变量,非静态内部类不可以。
/*静态内部类实例的创建并不依赖外部类实例的创建*/ OuterClass.StaticInner sInner=new OuterClass.StaticInner(); sInner.execute();
5、成员内部类:Member Inner
就是普通内部类,可以访问外部类的静态与非静态的方法和成员变量。
可以在成员内部类中定义与外部类中变量同名的成员变量,这样会隐藏外部类中的变量。如果需要在外部内中访问被隐藏的变量,需要通过外部类的类名来调用。
注意两点:
- 成员内部类中不能存在任何static的变量和方法。
- 成员内部类依附于外部类,成员内部类对象的创建依附于外部类对象的创建。
来看看怎么创建成员内部类的对象:
/*先创建外部类的对象,再创建成员内部类的对象*/ /*然后我们可以使用这个内部类的对象的方法了*/ OuterClass.InnerClass innerClass=new OuterClass().new InnerClass();
6、局部内部类:Local Inner
嵌套在方法作用域中的内部类。
在解决复杂问题时,创建这样一个类来辅助,又不希望它是公共可用的。
局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法中被使用,不能在它的方法域外创建它的实例。
局部内部类的声明不能被定义为public、protected、private或者static。只能访问方法中声明的final类型的变量(即finnal局部变量)。
7、匿名内部类:Anonymous Inner
一种特殊的局部内部类,没有类名,没有class关键字,也不能使用extends和implements等关键字修饰。
匿名内部类不能是抽象类,必须实现它的抽象父类或者接口的所有抽象方法。
因为没有类名,所以匿名内部类只能被使用一次,通常用来简化代码编写。
使用匿名内部类的前提条件:继承一个父类或者实现一个接口,其实就是使用的时候通过new来生成父类或者接口的实例,然后再直接定义类体。
匿名内部类使用过程中要注意:
- 必须继承一个类or实现一个接口,但不能同时发生;
- 不能定义构造函数;
- 不能存在静态变量或方法;
- 不能是抽象的,必须实现父类或者接口的所有抽象方法。
package test; public class AnonymousInner { public static void main(String[] args) { Outer out=new Outer(); out.instanceMethod(); } } interface Action{ void doAction(); } class BaseClass{ private int data; public BaseClass(int data){ this.data=data; } public int getData(){ return data; } } class Outer{ public void instanceMethod(){ //这里的匿名实现类实现Action接口,创建一个实例 Action action= new Action(){ public void doAction(){ System.out.println("a simple anoynous class demo"); } }; action.doAction(); //这里的匿名实现类从BaseClass派生,并创建一个实例 new BaseClass(5){ public void printData(){ System.out.println("data="+getData()); } }.printData(); } }