一、概述
package com.test; /** * * 可以将一个类的定义放在另一个类的内部,这就是内部类。 * * 在拥有外部类对象之前是不可能创建内部类对象的。 * 但是,如果创建的是嵌套类(静态内部类),就不需要外部类对象了。 * @author Administrator * */ public class Parcel2 { 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 = contents(); Destination d = to(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Parcel2 p = new Parcel2(); p.ship("Tasmania"); Parcel2 q = new Parcel2(); // Defining references to inner classes: Parcel2.Contents c = q.contents(); Parcel2.Destination d = q.to("Borneo"); } }
二、访问外围类的成员
package com.test; interface Selector { boolean end(); Object current(); void next(); } public class Sequence { private Object[] items; private int next = 0; public Sequence(int size) { items = new Object[size]; } public void add(Object x) { if (next < items.length) items[next++] = x; } /** * 内部类自动拥有对其外部类所有成员的访问权,无论是公共还是私有的 * @author Administrator * */ private class SequenceSelector implements Selector { private int i = 0; public boolean end() { return i == items.length; } public Object current() { return items[i]; } public void next() { if (i < items.length) i++; } } public Selector selector() { return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) sequence.add(Integer.toString(i)); //创建内部类对象,并返回其引用 Selector selector = sequence.selector(); while (!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } } }
三、使用this和new
public class DotThis { private int i=0; public void setI(int i){ this.i=i; } void f() { System.out.println("DotThis.f()"+i); } public class Inner { public DotThis outer() { //通过this可以生成外围类对象的引用 return DotThis.this; // A plain "this" would be Inner's "this" } } public Inner inner() { return new Inner(); } public static void main(String[] args) { DotThis dt = new DotThis(); dt.setI(10); DotThis.Inner dti = dt.inner(); dti.outer().f(); } }package com.test;
public class DotNew { public class Inner { } public static void main(String[] args) { DotNew dn = new DotNew(); //使用new可以在外面创建内部类的对象 //不能使用类名,必须使用对象名创建 DotNew.Inner dni = dn.new Inner(); } }
四、内部类向上转型
下面的代码可以很方便地隐藏实现的细节
class Parcel4 { 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) { Parcel4 p = new Parcel4(); Contents c = p.contents(); Destination d = p.destination("Tasmania"); // Illegal -- can't access private class: //! Parcel4.PContents pc = p.new PContents(); } }
五、在方法作用域内的内部类
public class Parcel5 { /** * 在方法的内部创建类,称为局部内部类 * * @param s * @return */ 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"); System.out.println(d.readLabel()); } } /** * 在任意的作用域嵌入内部类 * @author Administrator * */ 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(); } }
六、匿名内部类
/** * 使用了默认的构造器 * @author Administrator * */ public class Parcel7 { public Contents contents() { return new Contents() { // Insert a class definition private int i = 11; public int value() { return i; } }; // Semicolon required in this case } public static void main(String[] args) { Parcel7 p = new Parcel7(); Contents c = p.contents(); } }
public class Wrapping { private int i; public Wrapping(int x) { i = x; } public int value() { return i; } } public class Parcel8 { public Wrapping wrapping(int x) { // Base constructor call: return new Wrapping(x) { // Pass constructor argument. public int value() { return super.value() * 47; } }; // Semicolon required } public static void main(String[] args) { Parcel8 p = new Parcel8(); Wrapping w = p.wrapping(10); } }/**
* 如果想在匿名内部类中使用外围类的对象 * 那么对象的引用必须是final的 * 当时传递给匿名内部类构造器的参数不必是final的 * * 可以在匿名内部类中进行实例化 * @author Administrator * */ public class Parcel9 { // Argument must be final to use inside // anonymous inner class: public Destination destination(final String dest) { return new Destination() { {System.out.println("sss");} private String label = dest; public String readLabel() { return label; } }; } public static void main(String[] args) { Parcel9 p = new Parcel9(); Destination d = p.destination("Tasmania"); } }
六、嵌套类
/** * 将内部类声明为static,这样的内部类通常称为嵌套类 * 普通内部类对象隐式地保存了一个外围类对象的引用,而内部类没有 * 特点: * 1.创建嵌套类的对象不需要外围类对象; * 2.不能从嵌套类的对象中访问非静态的外围类对象 * 3.普通内部类不能含有static成员; * 4.普通内部类内部也不能声明嵌套类; * @author Administrator * */ public class Parcel11 { 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 ParcelDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } // Nested classes can contain other static elements: 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 ParcelDestination(s); } public static Contents contents() { return new ParcelContents(); } public static void main(String[] args) { Contents c = contents(); Destination d = destination("Tasmania"); } }
七、接口内部类
/** * 嵌套类可以放到接口中 * 接口中得任何类都自动为public、static * 甚至可以在嵌套类中实现外围接口 * @author Administrator * */ public interface ClassInInterface { void howdy(); class Test implements ClassInInterface { public void howdy() { System.out.println("Howdy!"); } public static void main(String[] args) { new Test().howdy(); } } }
八、多层嵌套内部类
class MNA { private void f() { } class A { private void g() { } public class B { void h() { g(); f(); } } } } /** * 多层内部类 * 它可以透明地访问所有嵌入它的外围类的所有成员 * @author Administrator * */ 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(); } }
九、为什么需要内部类
interface A { } interface B { } class X implements A, B { } class Y implements A { B makeB() { // Anonymous inner class: return new B() { }; } } /** * 为什么需要内部类? * 每个内部类都能独立地继承一个实现,所以无论外围类是否已经继承了某个实现,对于内部类都没有影响; * 内部类使得多重继承的解决方案变得完整 * 接口解决了部分问题,内部类有效地实现了多重继承 * @author Administrator * */ 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()); } }
十、闭包与回调
interface Incrementable { void increment(); } // Very simple to just implement the interface: class Callee1 implements Incrementable { private int i = 0; public void increment() { i++; System.out.println(i); } } class MyIncrement { public void increment() { System.out.println("Other operation"); } static void f(MyIncrement mi) { mi.increment(); } } // If your class must implement increment() in // some other way, you must use an inner class: class Callee2 extends MyIncrement { private int i = 0; public void increment() { super.increment(); i++; System.out.println(i); } /** * 已经继承了MyIncrement类,就不能为了Incrementable的 * 用途而覆盖Increment方法,于是只能使用内部类独立地实现 * Incrementable * @author Administrator * */ private class Closure implements Incrementable { public void increment() { // Specify outer-class method, otherwise // you'd get an infinite recursion: Callee2.this.increment(); } } Incrementable getCallbackReference() { return new Closure(); } } class Caller { private Incrementable callbackReference; Caller(Incrementable cbh) { callbackReference = cbh; } void go() { callbackReference.increment(); } } /** * 闭包(closure),是一个可调用的对象,它记录了一些信息,这些信息来自于创建 * 它的作用域。通过这个定义,可以看出内部类是面向对象的闭包,因为它不仅包含外 * 围类的对象的信息,还自动拥有指向外围类对象的引用,在此作用域内,内部类有权 * 操作所有的成员,包括private。 * @author Administrator * */ 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(); } }
十一、内部类的继承
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); } }
十二、内部类的覆盖