一: 为何使用内部类:
- 内部类提供了更好的封装,只有外部类能访问内部类
- 内部类可以独立继承一个接口,不受外部类是否继承接口影响(多重继承的一种实现方案)
- 内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private
- 利于回调函数的编写 ???
二:内部类与外部类的联系
1:内部类是一个相对独立的实体
内部类是一个编译时概念,编译后外部类及其内部类会生成两个独立的class文件: OuterClass.class
和OuterClass$InnerClass.class
,我用javac
编译器对上面的OuterClass
进行编译: D:>javac OuterClass.class
编译后的结果:
2:内部类可以直接访问外部类的成员,反之外部类不可以直接访问内部类成员(但是可以间接访问,看下一条)
内部类可以直接访问外部类属性,尽管外部类属性是用private修饰的这是因为在创建外部类时,内部类会自动捕获一个外部类的引用(外部类的一个this指针),所以内部类访问外部类元素,实际上是通过他所持有外部类引用访问的,在java中,我们可以通过OuterClass.this
来获得外部类的引用。
3:外部类可以通过内部类引用间接访问内部类元素
三:创建内部类
1:在外部类外面(或外部类main方法)创建内部了对象
OuterClass outerClass = new OuterClass(); OuterClass.InnerClass innerClass = outerClass.new InnerClass();
或者
uterClass.InnerClass innerClass=new OuterClass().new InnerClass();
2:在外部类里面创建内部类
InnerClass innerClass=new InnerClass()
四:内部类种类:
成员内部类、方法内部类、匿名内部类、静态内部类
成员内部类
成员内部类也是最普通的内部类,它是外部类的一个成员,所以他是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
在成员内部类中要注意两点:
- 成员内部类中不能存在任何static的变量和方法(why ??, 理解成为java的规定吧。)
- 成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
方法内部类
方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是它们的作用域不同,方法内部类只能在该方法中被使用,出了该方法就会失效。 对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。
匿名内部类
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,初次之外,还有一些地方需要注意:
- 匿名内部类是没有访问修饰符的(只是临时用一下,所以不用访问修符)。
- 匿名内部类必须继承一个抽象类或者实现一个接口(一般是在某一个需要一个接口作为参数的函数调用中,用匿名内部类)
- 匿名内部类中不能存在任何静态成员或方法(make sense)。
- 匿名内部类是没有构造方法的,因为它没有类名(make sense)。
public class Button { public void click(){ //匿名内部类,实现的是ActionListener接口 new ActionListener(){ public void onAction(){ System.out.println("click action..."); } }.onAction(); } //匿名内部类必须继承或实现一个已有的接口 public interface ActionListener{ public void onAction(); } public static void main(String[] args) { Button button=new Button(); button.click(); } }
静态内部类
关键字static
可以修饰成员变量、方法、代码块,其实它还可以修饰内部类,使用static
修饰的内部类我们称之为静态内部类。静态内部类与非静态内部类之间存在一个最 大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。所以:
- 静态内部类的创建是不需要依赖于外围类,可以直接创建(静态内部类可以实例化!静态内部类可以实例化!静态内部类可以实例化!)。
-
静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以。