技术开发 频道

再读Think In Java接口篇


    这里内部类并没有表现出多大的优点,毕竟java里的权限控制,只要给类授予package权限就可以实现类的隐藏。但是当你将它上传到基类或是接口时,内部类还是有自己的特性的,这样任何人都看不到或访问到内部类了,于是隐藏实现变的非常容易,你所能得到的只是基类或是interface的reference。呵呵,不过要先在单独的文件里定义公用接口,这就是内部类的上传。

    在方法和作用域里的内部类,内部类可以创建在方法的内部,甚至是任意一个作用域里,下面就将给你介绍内部类的使用:这里先创建两个接口供下面的代码使用,
interface Students{int getXkrs{};}//Students接口 interface KsCj{String getKcm();}//kscj接口 (1) 在方法作用域里创建一个完整类,这被称为“本地内部类”, public class StudyCourse1{ public KsCj getkcm(String tempkcm){ class PKsCj implements KsCj{ private String kcm ; PKsCj(String tempkcm){ kcm = tempkcm; } String getKcm(){return kcm;} } return new PKsCj(tempkcm); } public static void main(String[] args){ StudyCourse1 st = new StudyCourse1(); KsCj ksCj = st.getkcm(“computer”); } }
    (2) 任意一个作用域定义内部类
    (3) 匿名内部类
public class StudyCourse2{ public Students getRs(){ return Student(){ private int num =20; public int getXkrs{ return num;} }; } public static void main(String[] args){ StudyCourse2 stuCo = new StudyCourse2(); Students students = stuCo.getRs(); //输出人数 System.out.println(students.getXkrs()); } }
    (4) 一个继承了“某个有着非默认的构造函数”的类的匿名类,其实这和继承了默认的构造函数的类的匿名类没有什么区别,这需要直接将参数传给基类的构造函数。
    (5) 一个进行数据成员初始化的匿名类,你可以在定义匿名类的数据成员的时候对其初始化,如果要用到外面的对象,那编译器就会要这个参数的reference是final的。示例:
public class StudyCourse1{ public KsCj getkcm(final String tempkcm){ return new KsCj(){ private String kcm = tempkcm ; String getKcm(){return kcm;} } public static void main(String[] args){ StudyCourse1 st = new StudyCourse1(); KsCj ksCj = st.getkcm(“computer”); } }
    如果只是想对数据成员赋值,这种做法是可以的。但是如果你想进行“类似构造函数的操作”那该怎么办呢? 下面我们讲的就是解决方法。
    (6) 通过实例初始化来构建的匿名类,你不能在匿名内部类里创建构造函数,因为它根本没有名字,但是有了“实例初始化”,你就能在事实上创建一个匿名类的构造函数.下面就用我们以前学的知识,写下面这个示例:
abstract class Base { public Base(String name){ System.out.println("base constructor name is" +name); } public abstract void f(); } public class AnonymousConstrutor { public static Base getBase(String name){ return new Base(name){ //对象实例化 { System.out.println("inside constuctor inliaze"); } public void f(){System.out.println("anonymous method");} }; } public static void main(String[] args) { Base ba = getBase(" lqh"); ba.f(); } }
    运行结果:
    base constructor name is lqh
    inside constuctor inliaze
    anonymous method
    结合我们将的匿名类和抽象类的知识,就能很清楚结果的由来。
    说到这里,我们知道了内部类还只是隐藏名字和组织代码的方式,但是内部类还有一种用法,如果你创建了一个内部类,那么这个内部类的对象就与创建它的“宿主类的对象”产生某种关系,这样它就能访问宿主类对象的成员了(包括所有元素)。那么内部类是怎么和宿主类对象联系的呢?
    (1) 引用宿主类的对象
    要获取宿主类对象的reference,可以宿主类名字后面加一个点再加this类表示宿主类对象的reference.如果还要创建内部类的对象,你就必须在new表达式里给出宿主类对象的reference.
    (2)在多层嵌套的类里向外访问
    内部类可以透明的访问它的各级宿主类的成员,不管嵌套的层次有多深。
public class MNA { private void f(){System.out.println("hello");} //内部类1 class A{ private void g(){} //内部类2 class b{ void h(){ //内部类1(二级宿主类)的method g(); //一级宿主类的method f(); } } } }
    如果你不需要这种“内部类对象和宿主类对象之间的”联系,那么你就可以把内部类定义为static的,这通常被称为“嵌套类”。嵌套类的特征:
    (1) 无须宿主类对象就能创建嵌套类的对象。
    (2) 不能在嵌套类对象里面访问非static宿主类对象。
    嵌套类还有一点不同,普通的内部类不能有static数据,static方法和嵌套类,这些在嵌套类里都可以有。而且嵌套类还可以作为interface的一部分出现,这并不违背interface的规则。
    假如你创建了这样一个内部类,其宿主类继承了另一个内部类的宿主类,并且这个内部类是继承的宿主类的内部类的重写,像这样覆写宿主类方法似的覆写内部类是起不到任何作用的。这是因为两个内部类是相互独立的两个实体,他们都有各自独立名字空间。
    内部类的标识符,由于每个类都生成一个.class文件,以“存储该如何创建这个类的对象”相关信息,内部类也不例外,这种“文件/类”的名字有很严格的规定:宿主类的名字,加上“$”在加上内部类的名字。说到这里,我们就清楚了内部类最吸引人的地方:每个内部类都可以独立的继承某个“实现(implementation)”。因此,内部类是不受“宿主类是否已经继承了别的实现”的约束。
    Closure是一种能调用的现象,它记录了创建它的那个作用域信息,内部类就是一种面向对象的closure,因为它不仅保存了宿主类的所有信息,而且自动保存了指向那个宿主类对象的reference,并能操作宿主类对象的成员,即便他们是private的。
0
相关文章