Java编程思想(2nd)学习笔记(8)-2 (转)[@more@]

二. Inner classes(内隐类)

1. 内隐类的基本用法

1) 如果要在外围class的non-static函数之外产生一个inner class对象,得以OuterClassName.InnerClassName的形式指定该对象的型别。而在non-static函数内则不用。

public class ExplicitStatic{

class Contents{

private int i = 11;

public int value() { return i; }

}

class Destination{

private String label;

Destination(String whereTo){

label = whereTo;

}

String readLabel() { return label; }

}

public Destination to(String s){

//在outer class的non-static函数中可直接产生inner class对象

return new Destination(s); //(1

}

public Contents cont(){

return new Contents(); //(1

}

public void ship(String dest){

//在outer class的non-static函数中可直接通过InnerClassName

//来指定对象型别

Contents c = cont();

Destination d = to(dest);

System.out.println(d.readLabel());

}

public static void main(String[] args){

ExplicitStatic p = new ExplicitStatic();

p.ship("Tanzania");

ExplicitStatic q = new ExplicitStatic();

//在outer class的非non-static函数内产生inner class对象

ExplicitStatic.Contents c = q.cont();

ExplicitStatic.Destination d = q.to("Borneo");

//不能在static函数直接生成inner class对象

// new Contents();

}

}

2) 对于non-static inner class,在外围class的non-static函数可以通过new产生一个inner class对象,如上面的(1)处。但要在非non-static函数产生一个inner class对象,则一定要关联到其enclosing class的某个对象。

3) inner class的向上转型

当把一个inner class对象向上转型成为interface时,我们得到的只是一个reference。

interface Destination{

String readLabel();

}

interface Contents{

int value();

}

class Parcel3{

private class PContents implements Contents{

private int i = 11;

public int value() { return i; }

}

protected class PDestination implements Destination{

private String label;

PDestination(String whereTo){

label = whereTo;

}

public String readLabel() { return label; }

}

public Destination to(String s){

return new PDestination(s);

}

public Contents cont(){

return new PContents();

}

}

public class ExplicitStatic{

public static void main(String[] args){

Parcel3 p = new Parcel3();

//把inner class对象向上转型

Contents c = p.cont();

Destination d = p.to("Borneo");

}

}

虽然我们不能在ExplicitStatic class无法调用Pcontents class,但我们把一个Pcontents class对象向上转型为Contents,就可对之进行调用。

4) inner class的作用域为定义该inner class的SCOpe内。但inner class可在它的作用域之外被继承(见4)。

interface Contents{

int value();

}

class Parcel3{

//PContents1 class的作用域为Parcel3 class内

private class PContents1 implements Contents{

private int i = 11;

public int value() { return i; }

}

public Contents cont1(){

return new PContents1();

}

public Contents cont2(){

//PContents2 class的作用域为函数cont2内

class PContents2 implements Contents{

private int i = 11;

public int value() { return i; }

}

return new PContents2();

}

//不能在函数cont2外使用PContents2 class

/*

public Contents cont22(){

return new PContents2();

}

*/

public Contents cont3(boolean b){

if(b){

//PContents3 class的作用域为当前if内

class PContents3 implements Contents{

private int i = 11;

public int value() { return i; }

}

return new PContents3();

}

//不能在if外使用PContents3 class

//return new PContents3();

return null;

}

}

public class ExplicitStatic{

public static void main(String[] args){

Parcel3 p = new Parcel3();

Contents c1 = p.cont1();

Contents c2 = p.cont2();

Contents c3 = p.cont3(true);

}

}

2. 内隐类与外围enclosing class的连接关系

2.1 non-static inner class

1) inner class可以访问enclosing class的所有成员(包括private成员),就像inner class自己拥有这些成员一样。即inner class天生具有对enclosing class的所有成员的访问权力。

2) Inner class对象被产生时,一定要关联到其enclosing class的某个对象(这个enclosing class对象就是Inner class对象的制造者)。建构inner class对象的同时,得有其enclosing class对象的reference才行。

原因:因为inner class可以访问enclosing class的所有成员,那么当产生一个inner class时,编译器会自动为inner class对象添加一个指向enclosing class对象的reference(这个reference是隐藏的)。所以Inner class被产生时,一定要关联到其enclosing class的某个对象。

3) 同一个enclosing class对象产生出来的inner class对象访问的是同一个enclosing class对象中的成员。

interface Destination{

String readLabel();

}

interface Contents{

int value();

}

class Parcel3{

int i1 = 10;

private String s1 = "Parcel3_";

Parcel3(String s){

s1 += s;

}

private class PContents implements Contents{

//可调用enclosing class的成员 1

private int i2 = i1;

private String s2 = s1;

PContents(int num){

System.out.println("" + num + ": i2 = " + i2 + ",s2 = " + s2);

}

public int value() { return 1; }

}

public Contents cont(int i){

return new PContents(i);

}

}

public class ExplicitStatic{

public static void main(String[] args){

Parcel3 p1 = new Parcel3("1");

Contents c1 = p1.cont(1);

Contents c2 = p1.cont(2);

Parcel3 p2 = new Parcel3("2");

c2 = p2.cont(3);

c2 = p1.cont(4);

}

}

结果为:

1: i2 = 10,s2 = Parcel3_1

2: i2 = 10,s2 = Parcel3_1

3: i2 = 10,s2 = Parcel3_2

4: i2 = 10,s2 = Parcel3_1

在(1)在inner class调用了enclosing class的成员。结果表明,同一个enclosing class对象p1产生的inner class对象调用的是同一个enclosing class对象中的成员,如结果中的1、2、4。

2.2  Static inner classes(静态内隐类)

1) 产生Static inner classes对象时,不需要同时存在一个enclosing class对象

2) 只能在Static inner classes对象中访问enclosing class中的静态成员。

interface Contents{

int value();

}

class Parcel1{

private static String s1 = "Parcel3_";

private String s11 = “Parcel3_”;

Parcel1(String s){

s1 += s;

}

protected static class PContents implements Contents{

//只能访问enclosing class中的s1

String s2 = s1;

//s11不是static成员,不能访问

//String 22 = s11;

PContents(int num){

System.out.println("" + num + ":s2 = " + s2);

}

public int value() { return 1; }

}

public static Contents cont(int i){

return new PContents(i);

}

}

public class ExplicitStatic{

public static void main(String[] args){

Parcel1 p1 = new Parcel1("1");

Contents c1 = p1.cont(1);

c1 = Parcel1.cont(2);  //(1)

Parcel1 p2 = new Parcel1("2");

c1 = p2.cont(3);

c1 = Parcel1.cont(4); //(1)

}

}

因为内隐类Pcontents class是静态的,所以在(1)处不通过enclosing class对象而是通过静态函数来直接产生其对象。

2.3 无论inner class被嵌套置放的层次有多深,且所有outer class的成员都可

被它访问。

class MNA{

private void f() {}

class A{

private void g() {}

class B{

void h(){

g();

f();

}

}

}

}