内部类最大的优点就在于它能够非常好的解决多重继承的问题
在《Think in java》中有这样一句话:使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。
1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
3、创建内部类对象的时刻并不依赖于外围类对象的创建。
4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
5、内部类提供了更好的封装,除了该外围类,其他类都不能访问。
我们需要明确一点,内部类是个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不同的类(当然他们之间还是有联系的)。
Java的四种内部类
成员内部类
静态内部类
局部内部类
匿名内部类
成员内部类
定义在另一个类(外部类)的内部,而且与成员方法和属性平级叫成员内部类,……相当于外部类的非静态方法,如果被static修饰,就变成静态内部类了。
内部类的优点是:内部类可以访问外部类的私有成员变量,而不需要new外部类的对象。
class OuterClass {
private String OuterClassname = "OuterClassname";
public class InnerClass {
private String InnerClassName = "InnerClassName";
public void display() {
System.out.println("InnerClassName:" + InnerClassName);
//访问外部类对象时使用外部类名.this.成员方法/属性
System.out.println("OuterClassname:" + OuterClass.this.OuterClassname);
// 变量名不冲突时 也可以直接访问.
System.out.println("OuterClassname:" + OuterClassname);
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}
注意点:
1. 必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量
2. 成员内部类中不能存在static关键字,即,不能声明静态属性、静态方法、静态代码块等。
3. 外部类无法直接访问成员内部类的方法和属性,需要通过内部类的一个实例来访问。
4. 在成员内部类中访问外部类的成员方法和属性时使用:外部类名.this.成员方法/属性。
静态内部类
使用static修饰的成员内部类叫静态内部类。
静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
它的创建是不需要依赖于外围类的。
它不能使用任何外围类的非static成员变量和方法。
class OuterClass {
private String OuterClassname = "OuterClassname";
private static String OuterStaticname = "OuterStaticname";
public class InnerClass {
/* 非静态内部类中不能存在静态成员 */
// public static String staticname = "InnerClassstaticname2";
private String InnerClassName = "InnerClassName";
public void display() {
System.out.println("InnerClassName:" + InnerClassName);
//访问外部类对象时使用外部类名.this.成员方法/属性
System.out.println("OuterClassname:" + OuterClass.this.OuterClassname);
// 变量名不冲突时 也可以直接访问.
System.out.println("OuterClassname:" + OuterClassname);
}
}
public static class StaticInnerClass {
//静态内部类可以使用非静态变量
private String InnerNonStaticsName = "InnerNonStaticsName";
//静态内部类可以使用静态变量
public static String InnerStaticName = "InnerStaticName";
public void display() {
//外围类访问静态内部类:内部类的静态变量
System.out.println(OuterClass.StaticInnerClass.InnerStaticName);
System.out.println("InnerNonStaticsName:" + InnerNonStaticsName);
System.out.println("InnerStaticName:" +InnerStaticName);
// 不可以访问Outer的非静态变量.
// System.out.println("OuterClassname:" + OuterClassname);
// 可以访问Outer的静态变量.
System.out.println("OuterClassname:" + OuterStaticname);
}
}
public static void main(String[] args) {
//静态内部类 可以直接创建实例不需要依赖于外围类
new OuterClass.StaticInnerClass().display();
//非静态内部的创建需要依赖于外围类的实例
new OuterClass().new InnerClass().display();
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}
局部内部类
局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰, 暂时没在代码中用到, 后续有深的理解时再补充.
匿名内部类
备注:
1. 只能使用一次,创建实例之后,类定义会立即消失(想要多次使用就要用到反射的知识了)
2. 匿名内部类是没有访问修饰符的
3. 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。
4. 匿名内部类不能包含static变量/方法
小结:
静态内部类的应用场景是:只可以访问外部类的静态成员变量和静态成员方法。一般是当外部类需要使用内部类,而内部类无需外部类资源,并且内部类可以单独创建的时候会考虑采用静态内部类的设计
成员内部类的应用场景是:它可以访问它的外部类的所有成员变量和方法,不管是静态的还是非静态的都可以。
局部内部类:像局部变量一样,不能被public, protected, private和static修饰。只能访问方法中定义的final类型的局部变量。
匿名内部类:匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。匿名内部类隐式地继承了一个父类或者实现了一个接口。匿名内部类使用得比较多,通常是作为一个方法参数。