10.1 创建内部类
如果想从外部类的非静态方法之外的任意位置创建某一个内部类的对象,那么需要遵循以下格式,OuterClassName.InnerClassName 对象= new OuterClassName.InnerClassName( )
10.2 链接到外部类
内部类拥有其外围类所有成员的访问权限,包括私有成员
10.3 使用.this 和.new
若要生成外部类的对象,可以使用 外部类名.this 的方法,它将返回外部类对象的一个引用
需要告知某个外部类去创建一个内部类对象,那么可以通过使用 外部类对象.new 内部类类名的方式,如DotNew.Inner dni=dn.new Inner( )
声明内部类对象,可以采用外部类类名.内部类类名 的方式,但是若要创建内部类的对象,则必须采用外部类对象.内部类类名的方式
若创建的是嵌套类(静态内部类),他不需要外部对象的引用,但是普通的内部类却需要
10.5 在方法或作用域中创建内部类
//: innerclasses/Parcel5.java
// Nesting a class within a method.
public class Parcel5 {
public Destination destination(String s) {
class PDestination implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
}
return new PDestination(s);
}
public static void main(String[] args) {
Parcel5 p = new Parcel5();
Destination d = p.destination("Tasmania");
}
} ///:~
//: innerclasses/Parcel6.java
// Nesting a class within a scope.
public class Parcel6 {
private void internalTracking(boolean b) {
if(b) {
class TrackingSlip {
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() { return id; }
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
// Can't use it here! Out of scope:
//! TrackingSlip ts = new TrackingSlip("x");
}
public void track() { internalTracking(true); }
public static void main(String[] args) {
Parcel6 p = new Parcel6();
p.track();
}
} ///:~
注,方法内部类在方法的作用域之外,内部类是不可用的,
10.6 .匿名内部类
page3rd,通过实例初始化可以达到匿名内部类创建一个构造器的效果(再看)
如果定义一个匿名内部类,并且希望他使用外部定义的对象,那么编译要求传进来的参数需要是final的
//: innerclasses/Parcel9.java
// An anonymous inner class that performs
// initialization. A briefer version of Parcel5.java.
public class Parcel9 {
// Argument must be final to use inside
// anonymous inner class:
public Destination destination(final String dest) {
return new Destination() {
private String label = dest;
public String readLabel() { return label; }
};
}
public static void main(String[] args) {
Parcel9 p = new Parcel9();
Destination d = p.destination("Tasmania");
}
} ///:~
匿名类实现工厂模式,试与前面一章接口中的工厂模式相比较
//: innerclasses/Factories.java
import static net.mindview.util.Print.*;
interface Service {
void method1();
void method2();
}
interface ServiceFactory {
Service getService();
}
class Implementation1 implements Service {
private Implementation1() {}
public void method1() {print("Implementation1 method1");}
public void method2() {print("Implementation1 method2");}
public static ServiceFactory factory =
new ServiceFactory() {
public Service getService() {
return new Implementation1();
}
};
}
class Implementation2 implements Service {
private Implementation2() {}
public void method1() {print("Implementation2 method1");}
public void method2() {print("Implementation2 method2");}
public static ServiceFactory factory =
new ServiceFactory() {
public Service getService() {
return new Implementation2();
}
};
}
public class Factories {
public static void serviceConsumer(ServiceFactory fact) {
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(Implementation1.factory);
// Implementations are completely interchangeable:
serviceConsumer(Implementation2.factory);
}
} /* Output:
Implementation1 method1
Implementation1 method2
Implementation2 method1
Implementation2 method2
*///:~
10.7 普通的内部类不能包含static域或方法,也不能包含嵌套类,但是嵌套类(静态内部类)却可以(再看)
嵌套类意味着:1.要创建嵌套类对象,并不需要其外围类的对象
2.嵌套类只能访问外围类中的静态部分
10.7.1 接口的内部可放置嵌套类(static)
//: innerclasses/TestBed.java
// Putting test code in a nested class.
// {main: TestBed$Tester}
public class TestBed {
public void f() { System.out.println("f()"); }
public static class Tester {
public static void main(String[] args) {
TestBed t = new TestBed();
t.f();
}
}
} /* Output:
f()
*///:~
10.7.2 从对层嵌套类中访问外部类的成员
不管一个类是第几层嵌套类,他可以访问外围类的所有成员
//: innerclasses/MultiNestingAccess.java
// Nested classes can access all members of all
// levels of the classes they are nested within.
class MNA {
private void f() {}
class A {
private void g() {}
public class B {
void h() {
g();
f();
}
}
}
}
public class MultiNestingAccess {
public static void main(String[] args) {
MNA mna = new MNA();
MNA.A mnaa = mna.new A();
MNA.A.B mnaab = mnaa.new B();
mnaab.h();
}
} ///:~
10.8 相比外围类实现接口,使用内部类实现接口的好处,"每个内部类都能独立的继承自一个(接口的)实现,无论外围类是否继承了某个实现,对内部类是没有影响的",这也是内部类最为吸引人的原因。
内部类使得多重继承的方案得到完整,接口解决了部分问题,而内部类有效的实现了"多重继承",即内部类允许继承多个非接口类型,如类或抽象类
如果拥有的是普通类或抽象类,而不是接口,那么就只能使用内部类才能实现多层继承(有Demo)
试通过以下两个程序,体会内部类在这方面的好处
//: innerclasses/MultiInterfaces.java
// Two ways that a class can implement multiple interfaces.
package innerclasses;
interface A {}
interface B {}
class X implements A, B {}//单一类
class Y implements A {
B makeB() { //内部类
// Anonymous inner class:
return new B() {};
}
}
public class MultiInterfaces {
static void takesA(A a) {}
static void takesB(B b) {}
public static void main(String[] args) {
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
takesB(y.makeB());
}
} ///:~
//: innerclasses/MultiImplementation.java
// With concrete or abstract classes, inner
// classes are the only way to produce the effect
// of "multiple implementation inheritance."
package innerclasses;
class D {}
abstract class E {}
class Z extends D {
E makeE() { return new E() {}; }//相当于类Z实现了两种类型
}
public class MultiImplementation {
static void takesD(D d) {}
static void takesE(E e) {}
public static void main(String[] args) {
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
} ///:~
内部类的其他特性,详见书,共四条
1.内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类的信息相互独立
2.在单个外围类中,可以让多个内部类实现同一个接口,或继承同一个类
3.创建内部类对象的时刻,并不依赖外围类对象的创建
4.内部类没有令人迷惑的is-a关系,他只是一个独立的实体
10.8.2 内部类与控制框架(内部类有利于控制框架的实现)
10.9 内部类的继承(不理解)
//: innerclasses/InheritInner.java
// Inheriting an inner class.
class WithInner {
class Inner {}
}
public class InheritInner extends WithInner.Inner {
//! InheritInner() {} // Won't compile
InheritInner(WithInner wi) {
wi.super();
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi);
}
} ///:~
InheritInner当要生成构造器时,使用默认构造器,并不好,而且不能只是传递一个外围类的引用,此外,必须在构造器内使用以下语法:enclosingClassReference.super(),这样才提供了必要的引用,程序才能编译通过
10.11 局部内部类
//: innerclasses/LocalInnerClass.java
// Holds a sequence of Objects.
import static net.mindview.util.Print.*;
interface Counter {
int next();
}
public class LocalInnerClass {
private int count = 0;
Counter getCounter(final String name) {
// A local inner class:
class LocalCounter implements Counter {
public LocalCounter() {
// Local inner class can have a constructor
print("LocalCounter()");
}
public int next() {
printnb(name); // Access local final
return count++;
}
}
return new LocalCounter();
}
// The same thing with an anonymous inner class:
Counter getCounter2(final String name) {
return new Counter() {
// Anonymous inner class cannot have a named
// constructor, only an instance initializer:
{
print("Counter()");
}
public int next() {
printnb(name); // Access local final
return count++;
}
};
}
public static void main(String[] args) {
LocalInnerClass lic = new LocalInnerClass();
Counter
c1 = lic.getCounter("Local inner "),
c2 = lic.getCounter2("Anonymous inner ");
for(int i = 0; i < 5; i++)
print(c1.next());
for(int i = 0; i < 5; i++)
print(c2.next());
}
} /* Output:
LocalCounter()
Counter()
Local inner 0
Local inner 1
Local inner 2
Local inner 3
Local inner 4
Anonymous inner 5
Anonymous inner 6
Anonymous inner 7
Anonymous inner 8
Anonymous inner 9
*///:~
局部内部类和匿名内部类的名字在方法之外,均是不可见的,他们实现了同样的功能,那么使用局部内部类而不使用匿名内部类,的理由是需要命名构造器或重载构造器,以及需要不止一个内部类对象