第10章内部类

一、概述

 

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);
  }
}

 

十二、内部类的覆盖

 

 

你可能感兴趣的:(内部类)