1简介
内部类简单理解就是在外部类里面定义类。内部类是一个编译的概念,在外部类Outer里面定义内部类Inner,编译后会生成outer.Class和Outer$Inner.class两个class文件。
2分类
(1)成员内部类
成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取。
成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的。
public class Outer { public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.print("通过外部类对象new内部类对象");
// 推荐使用此方法 // inner = outer.getInner(); // inner.print("编写外部类的成员方法获取内部类对象"); } public Inner getInner() { return new Inner(); } public class Inner { public void print(String str) { System.out.println(str); } } }
在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类(通常称为嵌套类)。静态内部类只能访问外部类的静态成员或方法。
静态内部类与普通内部类区别主要有以下两点:
- 静态内部类可以有静态成员和方法,而普通内部类不行。
- 静态内部类的对象,并不需要其外围类的对象。
//普通内部类创建对象 OutClass oc = new OutClass(); OutClass.InnerClass inner = oc.new InnerClass(); //静态内部类创建对象 OutClass.InnerClass inner = new OutClass.InnerClass();
(2)局部内部类
局部内部类,是指内部类定义在方法和作用域内。
public class Outer { public static void main(String[] args) { Outer outer = new Outer(); ImplInner inner = outer.getInner(); inner.print("定义在方法的局部内部类"); } public ImplInner getInner() { public class Inner implement ImplInner { public void print(String str) { System.out.println(str); } } return new Inner(); } }
当然,上述代码中有一个前提,就是先要有个ImplInner 接口。
(3)匿名内部类
匿名内部类就是没有名字的内部类。有两种场景经常要使用匿名内部类:
- 监听器
- 直接new一个接口(或抽象类),由于没有具体实现类,常用的做法是直接在类体实现所有抽象方法。
public class Outer { public static void main(String[] args) { Outer outer = new Outer(); Inner inner = outer.getInner("Inner", "gz"); System.out.println(inner.getName()); } public Inner getInner(final String name, String city) { return new ImplInner() { private String nameStr = name; public String getName() { return nameStr; } }; } } //注释后,编译时提示类Inner找不到 /* interface ImInner { String getName(); } */
注意getInner方法的形参,当所在的方法的形参需要被内部类里面使用时,该形参必须为final。这里可以看到形参name已经定义为final了,而形参city 没有被使用则不用定义为final。为什么要定义为final呢?
但其实该变量实际上仍然是final的。(外形变了,内涵没变)public class InheritInner extends WithInner.Inner { // InheritInner() 是不能通过编译的,一定要加上形参 InheritInner(WithInner wi) { wi.super(); } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner obj = new InheritInner(wi); } } class WithInner { class Inner { } }
c)内部类的成员属性和外部类重了,会不会屏蔽?
当然不会,可以通过Outer.this.xxx。
d)匿名内部类没有构造函数怎么进行初始化?
代码块。
关于内部类问题,更多详细内容请参考:http://blog.51cto.com/android/384844
3为什么使用内部类
说了那么多,我们为什么要使用内部类?没什么用的话学他干啥~。
用内部类是因为内部类与所在外部类有一定的关系,往往只有该外部类调用此内部类,所以没有必要专门用一个Java文件存放这个类。
使用内部类还有如下几个优点:
public class Outer { public ImplInner getInner() { public class Inner implement ImplInner { public void print(String str) { System.out.println(str); } } return new Inner(); } }
下面是别人的业务代码Test
public class Test{ public static void main(String[] args) { Outer outer = new Outer(); ImplInner obj= outer.getInner(); obj.print("定义在方法的局部内部类"); } }
调用者甚至连内部类的类名都没有看见,直接从外部类的成员方法获得就行了。