定义 :将一个类的定义放在另一个类中 .
首先说如何创建一个内部类的实例: 从外部类的非静态方法之外的人一位置创建某个内部类的对象,那么必须像在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 method 1 1 2 Another method 2 Another method 3
这个例子掩饰了外围类实现接口与内部类实现接口间的区别。 Callee2 继承自MyIncrement 后者已经有了一个increment() 方法,并且与incrementable 接口完全不相关。如果Calle2继承了MyIncrement ,就不能为了Incrementable 用途而覆盖 increment()s覆盖increment 方法,于是只能使用内部类独立实现increment。当创建了一个内部类的时候并没有在外围类的接口中添加东西,也没有修改外围接口。
内部类Closure 实现了Incrementable ,以提供一个”钩子“(hook)-------而且是一个安全的钩子。无论谁获得 Incrementable 都只能使用 increment()方法。
Caller 的构造器需要一个Incrementable的引用类型作为参数,然后再以后的某个时刻,Caller对象可以使用此引用回调Callee类
内部类的继承: java 编程思想212.
内部类可以被覆盖么??: 详见213页。