详解 java 内部类
来源:互联网 发布:手机生日蜡烛软件 编辑:程序博客网 时间:2024/04/28 12:50
定义 :将一个类的定义放在另一个类中 .
首先说如何创建一个内部类的实例: 从外部类的非静态方法之外的人一位置创建某个内部类的对象,那么必须像在main()方法中那样,具体的致命这个对象的类型:
OuterClassName.InnerClassName
外部类可以访问内部类中的信息那是没什么疑问的,可是内部类也可以访问外部类的信息,包括私有信息,当生成一个内部类的对象时,此对象与制造它的外围对象(enclosing object)
之间就有了一种联系,所以它能 访问其外围对象的所有成员,而不需要特殊条件。 实现机制:当某个外围类的对象创建了一个内部类对象时,此对象会秘密持有一个对外围对象的引用。
下面给出一个例子
package com.meran.thinkingInJava.innerClass;public class Test1 {private String label="合肥";class Destination{private String label; Destination(String whereTo){ label=whereTo; } String readFatherLabel(){ return Test1.this.label;//父类.this相当于 父类中的this } String readLabel(){ return label; }}public Destination getDest(String label){return new Destination(label);}public void ship(String dest){ Destination dest1=new Destination(dest); System.out.println(dest1.label);}static class Context{private String label="静态内部类不需要内部类对外部类对象的引用";public String getLabel(){return label;};}public static void main(String [] args){Test1 test=new Test1();test.ship("北京");Test1 test1=new Test1();Test1.Destination dest=test1.getDest("上海");Destination dest1=test1.getDest("南京");System.out.println(dest.readLabel());System.out.println(dest1.readFatherLabel()); Destination dest2=test1.new Destination("哈尔滨");//直接创建内部类对象。 Context c=new Context(); System.out.println(c.getLabel());}}
北京上海合肥静态内部类不需要内部类对外部类对象的引用
如上面结果所写, 静态内部类的创建不需要内部类对外部对象的引用。
下面来说下
.this .new
.this 父类对象实例。this 相当于当前父类对象的引用 父类对象实例。new 用于创建内部类。 当类为静态内部类(嵌套类)的时候,不需要.new方法不需要对父类对象的引用。
内部类与向上转型。
当将内部类向上转型为其基类,尤其是转型为一个接口的时候,内部类就有了用武之地(从实现了某个几口的对象,得到对此接口的引用)这是因为内部类-----某接口实现-------能够完全不可见并且不可用。所得的只是指向接口的引用,可以很方便的隐藏实现。
下面一段代码
package com.meran.thinkingInJava.innerClass;/* * 可以看出 destination 方法返回的一个向Destination类型的上转型 */abstract class Destination{abstract String readLabel();}class Context {private String label;public Context(String s){ System.out.println("调用Context构造方法");this.label=s;}public void printLabel(){ System.out.print("父类printLabel被调用打印父类中label"); System.out.println(label);}}public class Test2 { public Context context(String label,final String _label1){ return new Context(label){ String label1; { System.out.println("子类实例化函数被调用"); label1=_label1; } public void printLabel(){ System.out.println("子类printLabel被调用 打印子类中label1"+label1); super.printLabel(); } }; }public Destination destination(final String dest,final float price){return new Destination(){ private int cost; //小括号中代码是对象初始化代码 { cost=Math.round(price); if(cost>100) System.out.println("over budget!"); } private String label=dest; public String readLabel(){return label;}};}public static void main(String []args){Test2 t=new Test2();Destination d=t.destination("Tasmania",101.395F);System.out.println(d.readLabel());Context c=t.context("小明的爸爸", "小明");c.printLabel();} }
over budget!Tasmania调用Context构造方法子类实例化函数被调用子类printLabel被调用 打印子类中label1小明父类printLabel被调用打印父类中label小明的爸爸
Test2中public Context context(String label,final String _label1)方法 返回的是Context 类型的引用,这句话的意思相当于,创建一个继承自Context的匿名类对象。这个类的作用于今夏怒public Context context(String label,final String _label1) 方法内部。 注意这个方法的两个参数, 第一个参数没加 final ,因为它是要被 Context类调用的, 而 _label1这个变量则是被我们的匿名内部类访问的,所以它要被设置为final类型。 在匿名内部类中无法定义构造器,----_-----!!!!!!因为我们连类名都不知道,所以只能调用父类构造器,或者使用实例初始化块,这段代码的作用就相当于构造器。
嵌套类:如果不需要内部类对象与其外部类对象之间有联系,可以把它声明为static类型,就通常称为嵌套类。
潜逃类意味着:1.要创建嵌套类的类的对象,并不需要其外围类的对象 2.不能从嵌套类的对象访问非静态的外围类对象
1。接口内部的类
正常情况下不可以在接口中放任何代码,接口中热不和类都是static 和public的,因为类是static的 只是相当于把潜逃类放到了接口的命名空间中,这样坐可以创建公共代码,为不同接口的实现所共用。
利用内部类实现多重继承
每个内部类都能独立的继承子一个(接口)的实现,所以无论外部类是否已经继承了某(接口的)实现,对内部类没有影响。
接口解决的 “多重继承问题”
interface A{};interface B{};public class x implements A,B{];public class x implements A{B getB{//匿名内部类实现return new B():}}
//实现多继承
class D{}abstract F{}class Z extends D{E makeE(){return new E(){};}}
闭包与回调
闭包(closure)是一个可调用的对象。它记录了一些信息,这些信息来自创建它的作用域(内部类是面向对象的闭包),因为它不但了解外部类信息,还包含一个对外部类的引用,可以调用外部类中的所有字段和方法。
package com.meran.thinkingInJava.innerClass;interface Incrementable{void increment();}class Callee1 implements Incrementable{private int i=0; public void increment(){i++;System.out.println(i);}}class MyIncrement{public void increment(){ System.out.println("Another method");}static void f(MyIncrement mi){mi.increment();};}class Callee2 extends MyIncrement{private int i=0;public void increment(){super.increment();i++;System.out.println(i);}private class Closure implements Incrementable{public void increment(){Callee2.this.increment();}}Incrementable getCallbackReference(){return new Closure();}}class Caller{private Incrementable callbackReference; Caller(Incrementable cbh){callbackReference=cbh;} void go(){callbackReference.increment();}}public class CallBacks {public static void main(String [] args){Callee1 c1=new Callee1();Callee2 c2=new Callee2();MyIncrement.f(c2);Caller caller1=new Caller(c1);Caller caller2=new Caller(c2.getCallbackReference());caller1.go();caller1.go();caller2.go();caller2.go();}}
Another method112Another method2Another method3
这个例子掩饰了外围类实现接口与内部类实现接口间的区别。 Callee2 继承自MyIncrement 后者已经有了一个increment() 方法,并且与incrementable 接口完全不相关。如果Calle2继承了MyIncrement ,就不能为了Incrementable 用途而覆盖 increment()s覆盖increment 方法,于是只能使用内部类独立实现increment。当创建了一个内部类的时候并没有在外围类的接口中添加东西,也没有修改外围接口。
内部类Closure 实现了Incrementable ,以提供一个”钩子“(hook)-------而且是一个安全的钩子。无论谁获得 Incrementable 都只能使用 increment()方法。
Caller 的构造器需要一个Incrementable的引用类型作为参数,然后再以后的某个时刻,Caller对象可以使用此引用回调Callee类
内部类的继承: java 编程思想212.
内部类可以被覆盖么??: 详见213页。
- java内部类详解
- Java内部类详解
- 详解 java 内部类
- java内部类详解
- java内部类详解
- java 内部类详解
- 【java】内部类详解
- java内部类详解
- java 内部类详解
- java内部类详解
- java内部类详解
- Java内部类详解
- java 内部类详解
- java内部类详解
- JAVA内部类详解
- java内部类详解
- java 内部类详解
- java:内部类详解
- 黑马程序员----GUI布局管理器和swing组件
- socket开发中一个小问题
- Topcoder SRM 495 - 513
- 用aspnetpager实现datalist分页(简单使用方法)
- 2011-7-30 20:39:39
- 详解 java 内部类
- Ethernet II帧格式
- Md5(base64)
- ABAP feature, in comparison to other programming languages
- 北京的郊区
- csdn更新了blog之后。。。
- Pthreads笔记
- 初识Linux--Commands(2)
- 初识Linux--Commands(3)