什么是内部类
将一个类的定义放在另一个类的内部,就称之为内部类
创建内部类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Parcel1 { 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) { return new Destination(s); } public Contents contents () { return new Contents(); } public void ship (String dest) { Contents c = new Contents(); Destination d = new Destination(dest); System.out.println(d.readLabel()); } public static void main (String args[]) { Parcel1 p = new Parcel1(); p.ship("Tasmania" ); } }
可以使外部类有一个方法,该方法返回一个指向内部类的引用,就像在to()和contents()方法
连接到外部类
内部类拥有其外围类的所有元素的访问权;
内部类的对象可以访问其外为对象的所有成员
.this与.new
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class DotThis { void f () {System.out.println("DoThis.f()" );} public class Inner { public DotThis outer () { return DotThis.this ; } } public Inner inner () {return new Inner();} public static void main (String args[]) { DotThis dt = new DotThis(); DotThis.Inner dti = dt.inner(); dti.outer().f(); } }
2. .new告知某些其他对象,去创建其某个内部类的对象;
1 2 3 4 5 6 7 public class DotNew { public class Inner {} public static void main (String args[]) { DotNew dn = new DotNew(); DotNew.Inner dni = dn.new Inner(); } }
内部类的向上转型
将内部类向上转型为其基类,尤其是转型为一个接口时;内部类就有了用武之地;从实现了某个接口的对象,得到对此接口的引用,与向上转型为这个对象的基类,实质上是一样的;
1 2 3 4 5 6 7 public interface Destination { String readLabel () ; } public interface Contents { int value () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Parcel { private class PContents implements Contents { private int i = 11 ; public int value () {return i;} } protected class PDestination implements Destination { private String label; private PDestination (String whereTo) { label = whereTo; } public String readLabel () {return label;} } public Destination destination (String s) { return new PDestination(s); } public Contents contents () { return new PContents(); } } public class TestParcel { public static void main (String args[]) { Parcel p = new Parcel(); Contents c = p.contents(); Destination d = p.destination("Tasmania" ); } }
在方法和作用域内的内部类
可以在一个方法或者一个作用域内部定义内部类;
有两个理由这么做:
1.实现了某个类型的接口,于是可以创建并返回对其引用
2.要解决一个问题,于是创建一个类来辅助解决方案,但又不希望这个类是公用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Parcel { public Destination destination (String s) { class PDestination implements Destination { private String label; private PEestination (String whereTo) { label = whereTo; } public String readLabel () {return label;} } return new PDestination(s); } public static void main (String args[]) { Parcel p = new Parcel(); Destination d = p.destination("Tasmania" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Parcel { 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(); } } public void track () {internalTracking(true );} public static void main (String args[]) { Parcel p = new Parcel(); p.track(); } }
匿名内部类
没有名字的类;作为实现了某个接口或基类的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Parcel { public Contents contents () { return new Contents(){ private int i = 11 ; public int value () {return i;} }; } public static void main (String args[]) { Parcel p = new Parcel(); Contents c = p.contents(); } }
注意点:
1.若基类需要一个带有参数的构造器;则给匿名类一个参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Parcel { public Wrapping wrapping (int x) { return new Wrapping(x){ public int value () { return super .value()*47 ; } }; } public static void main (String args[]) { Parcel p = new Parcel(); Wrapping w = p.wrapping(10 ); } }
Wrapping基类如下:
1 2 3 4 5 public class Wrapping { private int i; public Wrapping (int x) {i = x;} public int value () {return i;} }
2.若希望匿名类可以使用一个定义在外部的对象,则需要将该参数声明为final;//代码太多懒得写了……
工厂方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 interface Service { void method1 () ; void metiod2 () ; } interface ServiceFactory { Service getService () ; } class Implementation1 implements Servie { private Implementation1 () {} public void method1 () { ... } public void method2 () { ... } public static ServiceFactory factory = new ServiceFactory(){ publc Service getService () { return new Implementation1(); } }; } class Implementation2 implements Servie { private Implementation1 () {} public void method1 () { ... } public void method2 () { ... } public static ServiceFactory factory = new ServiceFactory(){ publc 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(Implemention1.factory); serviceConsumer(Implemention2.factory); } }
嵌套类
将内部类声明为static;由此,内部类对象与外部类对象之间没有了联系
It means:
1.要创建嵌套类的对象,不需要其外部类的对象
2.不能从嵌套类的对象中访问非静态的外部类对象
普通的内部类的字段和方法只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段;也不能包含嵌套类
但是嵌套类就可以包含这些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class Parcel { private static class ParcelContents implements Contents { private int i = 11 ; public int value (return i;) } protected static class ParcelDestination implements Destination { private String label; private ParceDestination (String whereTo) { label = whereTo; } public String readLabel () {return label;} public static void f () { static int x = 10 ; static class AnotherLevel { public static void f () {} static int x = 10 ; } } public static Destination destination (String s) { return new ParcelContents(); } public static Contents contents () { return new ParcelContents(); } public static void main (String args[]) { Contents c = contents(); Destination d = destination("Tasmania" ); } } }
接口内部的类
用于进行测试
从多层嵌套类中访问外部类的成员
一个内部类无论被嵌套多少层,其依旧可以透明的访问所有它嵌入的外围类的所有成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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(); } }
闭包和回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package closure;interface Incrementable { void increment () ; } class MyIncrement { public void increment () {System.out.println("Other operation" );} static void f (MyIncrement mi) {mi.increment();} } class Callee1 implements Incrementable { private int i = 0 ; public void increment () { i++; System.out.println(i); } } 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(); } }
输出:
Other operation
1
1
2
Other operation
2
Other operation
3
内部类与控制框架
略
内部类的继承
eg:
1 2 3 4 5 6 7 8 9 10 11 12 13 class WithInner { class Inner {} } public class InheritInner extends WithInner .Inner { InheritInner(WithInner wi){ wi.super (); } public static void main (String args[]) { WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } }
内部类可以被覆盖吗
不能被覆盖的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Egg { private Yolk y; protected class Yolk { public Yolk () { ... } } public Egg () { ... y = new Yolk(); } } public class BigEgg extends Egg { public class Yolk { pubic Yolk () {...} } public static void main (String args[]) { new BigEgg(); } }
能被覆盖的情况
必须使用extends
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Egg { private Yolk y; protected class Yolk { public Yolk () { ... } } public Egg () { ... y = new Yolk(); } } public class BigEgg extends Egg { public class Yolk extends Egg .Yolk { pubic Yolk () {...} } public static void main (String args[]) { new BigEgg(); } }
局部内部类与匿名类的区别
一个有名字一个没有名字
内部类标识符
Xxx&Xxx.java
资料:《Thking in java》