Java内部类

来源:互联网 发布:pop3端口号 编辑:程序博客网 时间:2024/04/29 19:58

所谓的内部类,就是将一个类定义到另一个类的定义内部。这里引入一个词——嵌套类,嵌套类包括静态嵌套类和非静态嵌套类(内部类),这里的非静态嵌套类就是内部类,而嵌套类呢在接下来的介绍中会讲到。

对于内部类(非静态嵌套类),可以分为三种:

(1) 局部内部类

(2) 匿名内部类

(3) 成员内部类

接下来看看内部类的创建方式:

一、创建局部内部类。

public class LocalInnerClass {private static final String LABEL = "LocalInnerClass";class LocalClass{public LocalClass(){System.out.println("LocalClass()");}public String getLabel(){return LABEL;}}public LocalClass getLocalClass(){return new LocalClass();}public static void main(String[] args){LocalInnerClass lic = new LocalInnerClass();/* * 创建内部类对象的格式为:外部类.内部类  内部类的引用 = 外部类实例化对象的引用.返回内部类引用的方发(或者).new 内部类; * */LocalInnerClass.LocalClass localclass = lic.getLocalClass();//LocalInnerClass.LocalClass localclass2 = lic.new LocalClass();System.out.println(localclass.getLabel());}}运行结果:LocalClass() LocalInnerClass


局部内部类的特点:局部内部类不能有访问说明符,如public、protected、private等,这是因为局部内部类不是外围类的一部分;但是它可以访问当前代码块内的常亮以及此外围类的所有成员。


二、创建匿名内部类。

package Inner;/* * 定义的一个接口 * */public interface Ainterface {String readString();int value();}package Inner;public class Anonymousinnerclass {public Ainterface getAinterface(){/* * 匿名内部类的定义 * */return new Ainterface(){private int i = 100;private String string = "Anonymousinnerclass";public String readString(){return string;}public int value(){return i;}};}public static void main(String[] args){Anonymousinnerclass aic = new Anonymousinnerclass();Ainterface ai = aic.getAinterface();System.out.println(ai.readString()+","+ai.value());}}运行结果:Anonymousinnerclass,100

对于上面的例子,很多刚学Java的人都会奇怪,getAinterface()方法将返回值的生成与表示这个返回值的类的定义结合了在一起!而这就是匿名内部类。下面我们就简化一下上面的匿名内部类,通过语法的简化形式,相信大家能更理解。

上面例子的简化形式:


public class TestAnonymous {class MyAnonymous implements Ainterface{private int i = 100;private String string = "Anonymousinnerclass";public String readString(){return string;}public int value(){return i;}}/* * 向上转型为Ainterface * */public Ainterface getAinterface(){return new MyAnonymous();}public static void main(String[] args){TestAnonymous ta = new TestAnonymous();Ainterface atf = ta.getAinterface();System.out.println(atf.readString()+","+atf.value());}}运行结果:Anonymousinnerclass,100

三、创建成员内部类。

/* * 成员内部类都有访问说明符,如public、private、protected等修饰 * 成员内部类是可以访问外部类的静态与非静态的方法和成员变量的。 * */public class MemberInnerClass {private int x = 10;public void value(){}/* * 成员内部类的创建 * */public class MemberClass{/* * 可以在内部类中定义于外部类同名的成员变量于方法 * */private int x = 100;public void value(){System.out.println("内部类_x:"+this.x);System.out.println("外部类_x:"+MemberInnerClass.this.x);}}public static void main(String[] args){MemberInnerClass mic = new MemberInnerClass();MemberInnerClass.MemberClass mc = mic.new MemberClass();mc.value();}}运行结果:内部类_x:100外部类_x:10

四、创建嵌套类

将内部类声明为static,从而不需要内部类对象与外围类对象之间存在联系,就称之为嵌套类。嵌套类的static有何含义?对于普通内部类,其对象隐式地保存了一个引用,并指向了创建他的外围类的对象,而嵌套类则不是这样。
对嵌套类:
1.要创建嵌套类的对象,并不需要其外围类的对象。
2.不能从嵌套类的对象中访问非静态类的外围类对象。
嵌套类和普通内部类还有一个区别。普通内部类的字段和方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和字段,也不能包含嵌套类。而嵌套类则可以包含所有这些东西。内部类会通过一个特殊的this引用可以链接到其外围类的对象,嵌套类就没有这个特殊的this引用,这就使得它类似于一个static方法。

示例:

public interface Destination {String readLabel();}public class Parcel11 {/* * 嵌套类不同于内部类,嵌套类可以包含static,但内部类则不能 * */private static class ParcelDestination implements Destination{private String label;private ParcelDestination(String whereTo){label = whereTo;}public String readLabel(){return label;}public static void f(){}static int x = 10;/* * 嵌套类内部再定义一个嵌套类 * */static class AnotherLevel{public static void f(){}static int x = 10;}}public static Destination destination(String s){return new ParcelDestination(s);}public static void main(String[] args){Destination d = destination("This insertinnerclass ");System.out.print(d.readLabel());}}运行结果:This insertinnerclass 


接下来,深入总结一下内部类的一些重要知识点:
(1)使用.this与.new
如果要在内部类中生成对外部类对象的引用,可以使用外部类的名字后面紧跟着圆点和this。这样产生的引用自动地具有正确的类型,这一点在编译期就被知晓并受到检查,因此没有任何运行时的开销。
下面示例展示了如何使用.this:

/* * 使用内部类的.this * */public class DoThis {void fun(){System.out.print("DoThis.fun()");}class Inner{public DoThis outer(){return DoThis.this;}}public Inner inner(){return new Inner();}public static void main(String[] args){DoThis dothis = new DoThis();DoThis.Inner inner = dothis.inner();inner.outer().fun();}}结果:DoThis.fun() 
而.new,之前已经介绍过了,是用于创建内部类对象的方法之一,也就是外部类引用.new 内部类()。

2)定义匿名内部类的条件
内部类必须继承一个父类或者实现一个接口,其中父类又包括普通类与抽象类。
下面就来展示这三种情况:


继承普通类

public class Wrapping {//定义的普通类private int i;public Wrapping(int x){i = x;}public int value(){return i;}}public class SympleClass {public Wrapping wrapping(int x){return new Wrapping(x){public int value(){return x;}};}public static void main(String[] args){SympleClass sc = new SympleClass();Wrapping w = sc.wrapping(100);System.out.println(w.value());}}结果:100


继承抽象类

public abstract class Wrapping2 {public abstract int value();}public class SympleClass {private int x = 100;public Wrapping2 wrapping2(){return new Wrapping2(){public int value(){return x;}};}public static void main(String[] args){SympleClass sc = new SympleClass();Wrapping2 w = sc.wrapping2();System.out.println(w.value());}}结果:100


实现接口

package Inner;/* * 定义的一个接口 * */public interface Ainterface {String readString();int value();}package Inner;public class Anonymousinnerclass {public Ainterface getAinterface(){/* * 匿名内部类的定义 * */return new Ainterface(){private int i = 100;private String string = "Anonymousinnerclass";public String readString(){return string;}public int value(){return i;}};}public static void main(String[] args){Anonymousinnerclass aic = new Anonymousinnerclass();Ainterface ai = aic.getAinterface();System.out.println(ai.readString()+","+ai.value());}}运行结果:Anonymousinnerclass,100

(3)那为什么需要内部类呢?

在《Think in Java》中,每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的、可继承多个具体的或抽象的类的能力,一些设计与编程问题就难以解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效的实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(类与抽象类)。

总结一下节点:

(1)解决了多继承的问题

(2)多个内部类可以以不同的方式实现同一接口,继承同一个类。

(3)创建内部类对象的时刻并不依赖于对外围类对象的创建。

(4)内部类并没有“is-a”关系,它就是一个独立的实体。

(5)内部类提供了更好的封装,除了外围类,其他类都不能访问。

但对于内部类的使用,我们必须要清楚什么时候能用,什么时候不能用。相信随着对Java的深入学习,我们能够更好的识别什么情况下应该使用接口,什么情况下使用内部类,或者同时使用二者。



                                             
1 0