一、成员内部类
1.可以把一个内部类看做是一个成员。成员内部类可以无条件访问外部类的所有成员属性和成员方法。
class OutterClass {//外部类 private int in = 0; static int inn=4; public OutterClass(int in) { this.in = in; } class InnerClass { //内部类 public void output() { System.out.println(in); System.out.println(inn); } } }
2.当成员内部类拥有和外部类同名的成员变量或者方法时,默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问。
OutterClass(外部类).this.成员
3.外部类访问内部类,必须创建一个成员内部类的对象,再通过指向这个对象的引用来访问。
class OutterClass { private int in = 0; static int inn=4; public OutterClass(int in) { InnerClass inner=new InnerClass(); //创建一个成员内部类的对象 this.in=inner.innerNum; //再通过指向这个对象的引用来访问 } class InnerClass { //内部类 public int innerNum=1; public void output() { System.out.println(in); System.out.println(inn); int a=OutterClass.this.inn; } } }
4.成员内部类是依附于外部类而存在的。也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
创建成员内部类的一般方式为:
public class classa { public static void main(){ OutterClass oc=new OutterClass(3); OutterClass.InnerClass in=oc.new InnerClass(); } }
二、局部内部类
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰的。
class OutterClass{ public OutterClass(int in){ class InnerClass{ int innerNum = 1; } } }
规则一:局部内部类类似方法的局部变量,所以在类外或者类的其他方法中不能访问这个内部类,但这并不代表局部内部类的实例和定义了它的方法中的局部变量具有相同的生命周期。
规则二:只能在方法内部,类(局部内部类)定义之后使用,不存在外部可见性问题,因此没有访问修饰符。
规则三:不能在局部内部类中使用可变的局部变量。
规则四:可以访问外围类的成员变量。如果是static方法,则只能访问static修饰的成员变量。
规则五:可以使用final 或 abstract修饰。
三、静态内部类
又叫静态嵌套类或嵌套类。是使用static关键字修饰的内部类。
一般形式为
public class Outter { /** 嵌套类,public等四种访问修饰符均可修饰*/ public static class Inner { /** 嵌套类内部*/ } }
接口中的形式
public interface OutInterface { /** 嵌套类,在接口中定义的任何类都自动的是public和static的,因此这两个关键字都可以省略*/ class Inner { public void print() { System.out.println("print()"); } } }
声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用outer.inner,即不需要创建外部类,也不需要创建内部类。
public class classa { public static void main(){ Outter.Inner in=new Outter.Inner(); } }
规则一:不能从嵌套类中访问外部类的非静态成员。这一点与Java基础语法中对静态非静态语法的相关描述完全一致。
规则二:与普通内部类不同,嵌套类实例化不需要依赖外部类对象,与外部类没有必然联系。
规则三:与普通内部类的区别如下:
普通内部类只能包含非静态变量、非静态方法、非嵌套类。
静态嵌套类可以包含静态和非静态变量、静态和非静态方法、静态和普通内部类。
规则四:嵌套类可以定义在接口中,并作为接口的一部分来使用。
实例:
/** 接口*/ public interface OutInterface { void method_1(); void method_2(); /** 嵌套类*/ class Inner { public void print() { System.out.println("print something..."); } } } /** 实现类 */ public class OutInterfaceImpl implements OutInterface { private OutInterface.Inner inner = new Inner(); @Override public void method_1() { inner.print(); } @Override public void method_2() { inner.print(); } public static void main(String[] args) { OutInterface oif = new OutInterfaceImpl(); oif.method_1(); oif.method_2(); } }
四、匿名内部类
由于匿名内部类不利于代码的重用,因此,一般在确定此内部类只会使用一次时,才会使用匿名内部类。
形式:
public class OutterClass { public Runnable task() { return new Runnable() { @Override public void run() { System.out.println("匿名内部类..."); } }; } }
五、闭包和回调
闭包(Closure)是一种能被调用的对象,它保存了创建它的作用域的信息。JAVA并不能显式地支持闭包,但是在JAVA中,闭包可以通过“接口+内部类”来实现。
例如:一个接口程序员和一个基类作家都有一个相同的方法work,相同的方法名,但是其含义完全不同,这时候就需要闭包。
class Writer {//作家基类 void work(){}; } interface programmer{//程序员接口 void work(); }
闭包实现代码如下:
public class WriterProgrammer extends Writer { @Override public void work(){ //写作 } public void code(){ //写代码 } class ProgrammerInner implements programmer{ @Override public void work(){ code(); } } }
在子类中定义了遵循程序员接口规则的内部类,然后使用内部类实现程序员的work()方法回调code()方法,在子类中直接实现父类作家的work()方法。
六、内部类的作用
- 内部类可以很好的实现隐藏。
一般的非内部类,是不允许有 private 与protected权限的,但内部类可以 - 内部类拥有外围类的所有元素的访问权限
- 可是实现多重继承
- 可以避免修改接口而实现同一个类中两种同名方法的调用。
参考1:https://www.jianshu.com/p/367b138fe909
参考2:https://blog.csdn.net/u014745069/article/details/80201440