内部类
- 内部类:定义在一个类内部的类
内部类的对象能访问它所处类的私有属性
内部类能隐藏起来不为同一个包中其他类访问
内部类提供了更好的封装,只有外部类能访问内部类
内部类可以独立继承一个接口,不受外部类是否继承接口影响
内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private
利于回调函数的编写
- 用$符号分割内部类和外部类
- 实例化内部类必须先有一个外部类实例存在,然后通过外部类实例来实例化内部类。
- 注意:
内部类是一个相对独立的实体,与外部类不是is-a关系,变异之后会生成两个class文件
内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素
外部类可以通过内部类引用间接访问内部类元素
四种分类:
成员内部类 成员内部类也是最普通的内部类,它是外部类的一个成员,所以他是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。 在成员内部类中要注意两点: 成员内部类中不能存在任何static的变量和方法 成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类 |
方法/局部内部类 方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是它们的作用域不同,方法内部类只能在该方法中被使用,出了该方法就会失效。 对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。 注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的 class People{ public People() {
} } class Man{ public Man(){
}
public People getWoman(){ class Woman extends People{ //局部内部类 int age =0; } return new Woman(); } } |
匿名内部类 匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,初次之外,还有一些地方需要注意: 匿名内部类是没有访问修饰符的。 匿名内部类必须继承一个抽象类或者实现一个接口 匿名内部类中不能存在任何静态成员或方法 匿名内部类是没有构造方法的,因为它没有类名。 一般使用匿名内部类的场景是,要继承或实现的接口只有一个抽象方法,比如添加一个监听器: 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成员变量和方法,而内部类则都可以 public class OuterClass { private static String outerName; public int age; static class InnerClass1{ /* 在静态内部类中可以存在静态成员 */ public static String _innerName = "static variable"; public void display(){ /* * 静态内部类只能访问外部类的静态成员变量和方法 * 不能访问外部类的非静态成员变量和方法 */ System.out.println("OutClass name :" + outerName); } } class InnerClass2{ /* 非静态内部类中不能存在静态成员 */ public String _innerName = "no static variable"; /* 非静态内部类中可以调用外部类的任何成员,不管是静态的还是非静态的 */ public void display(){ System.out.println("OuterClass name:" + outerName); System.out.println("OuterClass age:" + age); } } public void display(){ /* 外部类能直接访问静态内部类静态元素 */ System.out.println(InnerClass1._innerName); /* 静态内部类可以直接创建实例不需要依赖于外部类 */ new InnerClass1().display(); /* 非静态内部的创建需要依赖于外部类 */ OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2(); /* 非静态内部类的成员需要使用非静态内部类的实例访问 */ System.out.println(inner2._innerName); inner2.display(); } public static void main(String[] args) { OuterClass outer = new OuterClass(); outer.display(); } } |