内部类的好处
可以使用外部类的元素
class Demo extends B{ private String a; class Test{ public void test() { System.out.println(a); } } }
匿名内部类可以加private protected修饰,隐藏对象
public class Demo { public static void main(String[] args){ A a = new A(); //实现隐藏 Instance in = a.getIn(); } } interface Instance{} class A{ public B getIn(){ return new B(); } private class B implements Instance{ } }
可以实现多重继承
class A { public String name() { return "小明"; } } class B { public int age() { return 18; } } class Test { private class test1 extends A { } private class test2 extends B { } public String name() { return new test1().name(); } public int age() { return new test2().age(); } public static void main(String args[]) { Test mi = new Test(); System.out.println("姓名:" + mi.name()); System.out.println("年龄:" + mi.age()); } }
避免修改接口而实现同一个类中两种同名方法的调用
你的类要继承一个类,还要实现一个接口,可是你发觉你继承的类和接口里面有两个同名的方法怎么办?
未使用内部类的情况
interface A{ void test(); } class B{ void test(){ System.out.println("B"); } } class Demo extends B implements A{ @Override public void test() { //这种方法就调用不到B类的方法了 } }
使用内部类的情况
interface A{ void test(); } class B{ void test(){ System.out.println("B"); } } class Demo extends B{ //使用内部类来实现接口 class Test implements A{ @Override public void test() { } } }
成员内部类:
public class Demo { public static void main(String[] args){ A a = new A(); // A.B b = a.new B(); //创建内部类,通常不建议这样调用 // b.print(); a.Bprint(); //通过接口来创建内部类,并调用类的方法 } } class A{ //成员内部类 public void Bprint(){ B b = new B(); b.print(); } //成员内部类,建议设置私有.内部调用 private class B{ public void print(){ System.out.println("测试"); } } }
方法内部类:
public class Demo { public static void main(String[] args){ A a = new A(); a.Aprint(); } } class A{ //方法内部类 public void Aprint(){ int x = 1; // x++; //由于内部类调用了局部变量x,所以x不能修改; System.out.println(x); class B{ public void print(){ System.out.println("测试"+x); //一旦方法内部类中调用了局部变量,该变量默认是final,不可以被修改; } } B b = new B(); //方法内部类只能在该方法内实例化 b.print(); } }
解释:为什么方法内部类中类调用局部变量,该变量必须修饰为final(在jdk1.8之后,可以不用加,解释器会默认加上)?
当上面的Aprint方法结束了。方法直接出栈,栈中里面的局部变量清空,但是对象(内部类),可能GC垃圾回收机制,还没有将对象回收掉。而对象有调用着局部变量,此时就会报错,所以必须将该局部变量修饰为final,放在堆的常量区,这个即使方法出栈了,局部变量也不会被清空,而修饰了finnal的局部变量,则不能在进行修改操作了。
注意:没有被类调用的变量不会默认为final,可以进行修改操作;
内部类中可以使用不加final的静态变量
静态内部类:
静态内部类不依赖对象,所以开发项目的时候优先考虑
使用静态内部类不用担心内存泄漏的问题;
public class Demo { public static void main(String[] args){ A.B b = new A.B(); b.print(); } } class A{ //静态内部类 ,不能调用非静态的方法和属性; static class B{ public void print(){ System.out.println("静态内部类"); } } }
匿名内部类:
继承式匿名内部类
接口式匿名内部类
参数式匿名内部类
注意事项:
1、不能有构造方法(没有名字),只能有一个实例
2、不能定义任何静态成员,静态方法(内部类依赖对象,对象和静态是没有关系的)
3、不能是private static protected public (没有类,没办法加修饰符)
4、一定是是在new后面,用其隐含实现一个接口或者继承一个类
5、匿名内部类是局部的,所以局部内部类的所有的限制都对其生效
public class Demo { public static void main(String[] args){ print1(); print2(); print3(new C(){ public void print(){ System.out.println("参数式内部类"); } }); } public static void print1(){ A a = new A(){ public void print(){ System.out.println("继承式内部类"); } };//注意一定要有分号; a.print(); } public static void print2(){ B b = new B(){ public void print(){ System.out.println("接口式内部类"); }; }; b.print(); } public static void print3(C c){ c.print(); } } abstract class A{ public abstract void print(); } interface B{ void print(); } abstract class C{ //interface class C{} 一样 public abstract void print(); }
总结:
每个内部类能独立的继承或一个(接口)的实现,所以无论外部类是否是否已经继承了某个(接口的)实现,对于内部类没有影响。
并且内部类为多继承的实现,提供了解决方案;
public class Demo { public static void main(String[] args){ C c = new C(); c.print(); } } abstract class A{ } abstract class B{ public abstract void print(); } class C extends A{ class D extends B{ public void print(){ System.out.print("测试"); } } public void print(){ D d = new D(); d.print(); } }