java的四种内部类
成员内部类:
成员内部类没有用static修饰且定义在外层类的类体中。下面程序在OuterClass类中定义了一个成员内部类Inne class OuterClass{ //外层类
class OuterClass{ //外层类 private int x = 200; private void print(){ System.out.println("hello"); } public class InnerClass{ //内部成员类 int y = 300; public int function1(){ //内部成员类及其定义的方法可以访问访问外层类的成员x return x + y; } public void print1(){ print(); } } public void function2(){ InnerClass ic = new InnerClass(); //创建内部类对象 System.out.println(ic.function1()); } public static void main(String[] args){ OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass(); System.out.println(inner.function1()); //输出500 inner.print1(); } } 输出: 500 hello
在内部成员类中可以定义自己的成员变量和方法(如function1()),也可以定义自己的构造方法。成员内部类的访问修饰符可以是private、public、protected或缺省。成员内部类可以看成是外层类的一个成员,因此可以访问外层类的所有成员,包括私有成员。
在外层类的方法中可以直接创建内部类的实例。在外层类的外面要创建内部类的实例必须要先创建一个外层类的对象,因为内部类对象对外层类对象有一个隐含的引用。但是内部类中不可以含有static声明
- 成员内部类中不能定义static变量和static方法
- 成员内部类也可以使用abstract和final修饰,含义与其他类一样
- 成员内部类还可以使用private、public、protected或包可访问修饰符
静态内部类:
与类的其他成员类似,静态内部类使用static修饰,静态内部类也称嵌套类,例如:
class OuterClass{ //外层类 private static int x = 200; //智能调用静态变量 static void print(){ System.out.println("hello"); } public static class InnerClass{ //内部成员类 int y = 300; public int function1(){ //内部成员类及其定义的方法可以访问访问外层类的成员x return x + y; } public void print1(){ OuterClass.print();//只能调用静态方法,若是非静态则不可以被调用 注意此处不能凭空写一个 OuterClass.print(),必需在方法内 } } public static void main(String[] args){ OuterClass.InnerClass inner = new OuterClass.InnerClass(); System.out.println(inner.function1()); //输出500 // System.out.println(inner.y);//x是外部类属性,只能在内部类中调用 inner.print1(); } }
- 静态内部类中可以定义静态成员,而成员内部类不能;
- 静态内部类只能访问外层类的静态成员,成员内部类可以访问外层类的实例成员和静态成员;
- 创建静态内部类的实例不需要先创建一个外层类的实例;相反,创建成员内部类实例,必须先创建一个外层类的实例。
局部内部类:
可以在方法体或语句块内定义类。在方法体或语句块(包括方法、构造方法、局部块、初始化块或静态初始化块)内部定义的类称为局部内部类。
局部内部类不能视为外部类的成员,只对局部块有效,同局部变量一样,在说明它的块之外完全不能访问,因此也不能有任何访问修饰符。下面程序演示了局部内部类的定义。
class OuterClass2 { private String x = "hello"; public void function1(int z) { final String y = "world"; class InnerClass { //局部内部类 public void function2() { System.out.println("x = " + x); System.out.println("y = " + y); System.out.println("z = " + z); } } new InnerClass().function2(); } public static void main(String[]args){ OuterClass2 oc = new OuterClass2(); oc.function1(2019); } }
输出结果: x = hello y = world z = 2019
在OuterClass2类中的function1()方法中定义了一个局部内部类InnerClass,该类只在function1()方法中有效,就像方法中定义的变量一样。在方法体的外面不能创建InnerClass类的对象。在局部内部类中可以访问外层类的实例变量(x)、访问方法的参数(z)以及访问方法的final局部变量(y)。
注意:
局部内部类同方法局部变量一样,不能使用private、protected和public等访问修饰符,也不能使用static修饰,但可以使用final或abstract修饰。
局部内部类可以访问外层类的成员,若要访问其所在方法的参数和局部变量,这些参数和局部变量不能修改。
static方法中定义的局部内部类,可以访问外层类定义的static成员,不能访问外层类的实例成员。
静态内部类实际上是一种外部类,它不存在对外部类的引用,不通过外部类的实例可以创建一个对象。程序中的静态内部类的完整名称为Myouter.MyInner,此时必须使用完整的类名创建对象。因此,有时候将静态内部类称为顶层类。
静态内部类不具有任何对外层类实例的引用,因此静态内部类中的方法不能使用this关键字访问外层类的实例成员,然而这些方法可以访问外层类的static成员。这一点与一般类的static方法的规则相同。
匿名内部类:
定义类的最终目的是创建一个类的实例。但如果某个类的实例只使用一次,可以将类的定义和实例的创建在一起完成,或者在定义类的同时就创建一个实例。以这种方式定义的没有名字的类称为匿名内部类。
注意:
匿名内部类可以继承一个类或实现一个接口,且不需要使用extends或implements关键字。匿名内部类不能同时继承一个类和实现一个接口,也不能实现多个接口。
因为匿名内部类没有名称,所以类体中不能定义构造方法。又因为不知道类名,所以只能在定义类的同时用new关键字创建类的实例。实际上,匿名内部类的定义、创建对象发生在同一地方。
class Animal{ public void eat(){ System.out.println("i like eat anything."); } } class AnimalTest{ public static void main(String[] args){ Animal dog = new Animal(){ @Override public void eat(){ System.out.println(" i like eat bones."); } }; //这里的分号是赋值语句的结束 dog.eat(); } }
这里创建的匿名内部类实际上继承了Animal类,是Animal类的子类,并覆盖了Animal类的eat()方法。同时,代码创建一个匿名类的实例,并用dog指向它。