Java 内部类

内部类包括 成员内部类方法内部类、*静态内部类匿名内部类*。

内部类的作用

由于内部类的实现和外部类没有关系,内部类可自由继承其他类,所以在某一程度上实现了类的多重继承。

使得代码逻辑更紧凑,比如可以将一些相关性强的代码用内部类实现。

有些类往往只实例化一次,可以使用匿名内部类,这样也不会造成类的泛滥。

匿名内部类还能获取不在同一个包的 proteced 方法。

代码示例

成员内部类

IAnimal.java

publicinterfaceIAnimal{voidsleep(Stringname);voideat(Stringname);}

IProgrammer.java

publicinterfaceIProgrammer{voidcoding();}

Person.java

publicclassPersonimplementsIAnimal{privateintage;privateStringname;publicPerson(intage,Stringname){this.age=age;this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}@Overridepublicvoidsleep(Stringname){System.out.println(name+"睡觉");}@Overridepublicvoideat(Stringname){System.out.println(name+"吃东西");}publicvoidcoding(){newXiaoMing().coding();}classXiaoMingimplementsIProgrammer{publicvoidxiaoMingSleep(){sleep(name);// 访问外部类的成员变量及方法}publicvoidxiaoMingEat(){eat(name);// 访问外部类的成员变量及方法}@Overridepublicvoidcoding(){System.out.println(age+"岁开始写代码");}}publicstaticvoidmain(String[]args){Personp=newPerson(12,"小明");Person.XiaoMingming=p.newXiaoMing();p.coding();ming.xiaoMingSleep();ming.xiaoMingEat();}}

运行 main() 方法,控制台打印出

可以看出内部类使用了外部类的成员变量及方法。

外部类也实现了 coding(),间接实现了多重继承。

静态内部类

静态内部类在实现单例模式时候经常使用到,示例:SingletonTest.java

publicclassSingletonTest{privateSingletonTest(){}privatestaticclassSingletonTestHolder{privatestaticSingletonTestsingletonTest=newSingletonTest();}publicstaticSingletonTestgetInstance(){returnSingletonTestHolder.singletonTest;}}

通过静态初始化类来实现单例模式,是线程安全的,利用 ClassLoader 来确保只有一个单例。

匿名内部类

一般作为接口和抽象的一种实现,通常只实例化一次。

比较常见的是我们实现 Runnable 接口和继承 Thread 类,都会用到匿名内部类。ThreadTest.java

publicclassThreadTest{publicstaticvoidmain(String[]args){newThread(){@Overridepublicvoidrun(){System.out.println("Thread ...");}}.start();Runnablerunnable=newRunnable(){@Overridepublicvoidrun(){System.out.println("runnable ...");}};newThread(runnable).start();}}

如果要实现 Runnable 接口,那么我们需要定义一个类,而在上述代码中,我们并没有去指明 class XXX implentments Runnable 这样一个类,我们创建了一个匿名类,来实现接口或者实现抽象方法。这在安卓中会大量用到,Java 中的话,用得其实并没有很多。

匿名类还有一个作用,就是可以访问跨包类中的 protected 方法。这个有点意思。比如在我们包 com.yhx.javabasic 中有个 HelloWorld.java

publicclassHelloWorld{protectedvoidsay(){System.out.println("Hello ...");}publicvoidsing(){System.out.println("sing ...");}}

在另一个包 com.yhx.com.yhx.anonymous 中有个类AnonymousTest.java,我们现在要想访问 HelloWorld.java 中的 say() 方法,怎么办呢?AnonymousTest.java

publicclassAnonymousTest{publicstaticvoidmain(String[]args){HelloWorldhelloWorld=newHelloWorld();helloWorld.sing();helloWorld.say();// 错误,不能调用不同包之间的 protected 方法}}

可以看到,由于 protected 关键字限制了作用域为同一个包内,所以在包外调用 protected方法时,就会出错。这个时候可以用匿名类来实现。更改上述方法,改之后的代码如下:

publicclassAnonymousTest{publicstaticvoidmain(String[]args){HelloWorldhelloWorld=newHelloWorld();helloWorld.sing();newHelloWorld(){voidcallHelloWorldSay(){super.say();}}.callHelloWorldSay();}}

控制台打印出:

这样就可以实现调用跨包之间的 protected 方法。

注意事项

非 static 内部类,不能用 static 修饰属性或方法。因为非静态类只有在实例化之后才能加载到 jvm 内存中。

你可能感兴趣的:(Java 内部类)