【Java】内部类

来源:互联网 发布:weka中的数据预处理 编辑:程序博客网 时间:2024/06/05 05:44

这里只记录内部类中的静态和非静态。不论是哪一种,最终都是编译为两个.class文件。

非静态内部类class没有static修饰符,在使用的时候必须注意,必须先生成一个外部类的实例才能创建内部类的实例,这是因为每一个内部类的实例都有一个指向外部类实例的引用,在内部类使用外部类的引用可以OuterClassName.this。在创建内部类实例时,语法为OuterClassName.innerClassName in = outerInstanceName.new InnerClassName()。可以看出,内部类实例必须依附于一个外部类实例。那么内部类的作用是什么?很常见的一个是间接实现多继承,java中是不允许多继承的,通常我们还是使用接口,但是内部类提供了另一种选择吧,当然能用接口还是接口。内部类提供的间接多继承,本质上是一种组合。

相当于在一个需要多继承的类内部,新建几个内部类实现不同父类,然后可以创建这些内部类的实例来使用它们父类的方法,也可以重写,这是一种利用内部类+组合的方法实现的多继承。

class F1{public void f1(){System.out.println("F : f1");}}class F2{public void f2(){System.out.println("F : f2");}}public class Outer {private String name = "ly";private class Inner1 extends F1{String s = Outer.this.name;}private class Inner2 extends F2{public void f2(){System.out.println("Inner2 : f2");}}public void f(){new Inner1().f1();new Inner2().f2();}public static void main(String args[]){Outer o = new Outer();o.f();}}


还有一种内部类是静态内部类,内部类class用statc修饰。这样的类就不是依附于外部类了,而是一个独立的类,不可以访问外部类的非静态成员。可以直接实例化。值得注意的是,这个类的实例化的时机是当他被真正用到的时候,如果只有外部类被使用,那么静态内部类是不会实例化的。

public class Case8 {static class StatcInner{public StatcInner(){System.out.println("con");}public void f(){System.out.println("inner");}}public static void main(String args[]){//StatcInner inner = new StatcInner();Case8 a = new Case8();}}
不管静态还是非静态,上述延迟特性都是成立的。

可以使用上述延迟加载的特性来构建单例模式,这就是静态内部类的重要用处。

public class Singleton {private Singleton(){}static class SingletonGen{private static Singleton instance = new Singleton();}public static Singleton getInstance(){return SingletonGen.instance;}}
可以看到,这里本质上还是使用了懒汉式的单例模式,如果直接使用懒汉式,那么不管用不用实例,只要用到这个类就会创建单例,可能会有开销问题。但是如果把懒汉放在静态内部类里面,就可以使用静态内部类延迟的特性,把创建的时机尽可能的拖后,拖到要使用单例的时候,这就是使用静态内部类的好处。注意private关键字的使用。

这个设计基本实现了与双重检验相同的效果,延迟+单例。但是这两个无法解决序列化和反射的问题。之后再讨论解决办法。

阅读全文
0 0