Java中的内部类

1、内部类

将一个类定义置入另一个类定义中。这就叫作“内部类”。
// Creating inner classes
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; }
	}
	
	// Using inner classes looks just like 
	// using any other class, within Parcel1:
	public void ship(String dest) {
		Contents c = new Contents();
		Destination d = new Destination(dest);
	}
	
	public static void main(String[] args) {
		Parcel1 p = new Parcel1();
		p.ship("TianJin");
	}
}
若在ship()内部使用,内部类的使用看起来和其他任何类都没什么分别。在这里,唯一明显的区别就是它的名字嵌套在Parcel1 里面。
更典型的一种情况是,一个外部类拥有一个特殊的方法,它会返回指向一个内部类的句柄。就象下面这样:
// Returning a handle to an inner class
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 cont() {
		return new Contents();
	}
	
	public void ship(String dest) {
		Contents c = cont();
		Destination d = to(dest);
	}
	
	public static void main(String[] args) {
		Parcel2 p = new Parcel2();
		p.ship("TianJin");
		Parcel2 q = new Parcel2();
		// Defining handles to inner classes : 
		Parcel2.Contents c = q.cont();
		Parcel2.Destination d = q.to("BeiJing");
	}
}

若想在除外部类非static 方法内部之外的任何地方生成内部类的一个对象,必须将那个对象的类型设为“外部类名.内部类名”,就象main()中展示的那样。

2、内部类和上塑造型

当我们准备上溯造型到一个基础类(特别是到一个接口)的时候,内部类就开始发挥其关键作用。
// Returning a handle to an inner class
abstract class Contents {
	abstract public int value();
}

interface Destination {
	String readLabel();
}

public class Parcel3 {
	private class PContents extends 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 dest(String s) {
		return new PDestination(s);
	}
	public Contents cont() {
		return new PContents();
	}
	
	public static void main(String[] args) {
		Parcel3 p = new Parcel3();
		Contents c = p.cont();
		Destination d = p.dest("TianJin");
	}
}

在Parcel3 中,一些新东西已经加入:内部类PContents 被设为private,所以除了Parcel3 之外,其他任何东西都不能访问它。PDestination 被设为protected,所以除了Parcel3,Parcel3 包内的类(因为protected 也为包赋予了访问权;也就是说,protected 也是“友好的”),以及Parcel3 的继承者之外,其他任何东西都不能访问PDestination。

3、方法和作用域中的类

下面所有这些都在cust.haoboy.innerscopes 包内发生,结构图如下所示:




(1)Destination.java
package com.haoboy.innerscopes;

public interface Destination {

	String readLabel();
}

(2)Contents.java
package com.haoboy.innerscopes;

public interface Contents {

	int value();
}

(3)Wrapping.java

package com.haoboy.innerscopes;

public class Wrapping {

	private int i;
	public Wrapping(int x) { i = x; }
	public int value() { return i; }
}

注意:Wrapping 有一个要求使用自变量的构建器。
第一个例子展示了如何在一个方法的作用域(而不是另一个类的作用域)中创建一个完整的类:
package com.haoboy.innerscopes;

public class Parcel4 {

	public Destination dest(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) {
		Parcel4 p = new Parcel4();
		Destination d = p.dest("TianJin");
	}
}
PDestination 类属于dest()的一部分,而不是Parcel4 的一部分(同时注意可为相同目录内每个类内部的一个内部类使用类标识符PDestination,这样做不会发生命名的冲突)。因此,PDestination 不可从dest()的外部访问。请注意在返回语句中发生的上溯造型——除了指向基础类Destination 的一个句柄之外,没有任何东西超出dest()的边界之外。当然,不能由于类PDestination 的名字置于dest()内部,就认为在dest()返回之后PDestination 不是一个有效的对象。

下面这个例子展示了如何在任意作用域内嵌套一个内部类:
package com.haoboy.innerscopes;

public class Parcel5 {

	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) {
		Parcel5 p = new Parcel5();
		p.track();
	}
}
TrackingSlip 类嵌套于一个if 语句的作用域内。这并不意味着类是有条件创建的——它会随同其他所有东西得到编译。然而,在定义它的那个作用域之外,它是不可使用的。

下面这个例子展示了如何在一个方法中返回一个匿名类:
package com.haoboy.innerscopes;

public class Parcel6 {

	public Contents cont() {
		return new Contents() {
			private int i = 11;
			public int value() { return i; }
		};	// 这里需要一个分号
	}
	
	public static void main(String[] args) {
		Parcel6 p = new Parcel6();
		Contents c = p.cont();
	}
}
这种奇怪的语法要表达的意思是:“创建从Contents 衍生出来的匿名类的一个对象”。由new 表达式返回的句柄会自动上溯造型成一个Contents 句柄。
匿名内部类的语法其实要表达的是:
class MyContents extends Contents {
private int i = 11;
public int value() { return i; }
}
return new MyContents();

下面这段代码展示了基础类需要含有自变量的一个构建器时做的事情:
package com.haoboy.innerscopes;

public class Parcel7 {

	public Wrapping wrap(int x) {
		return new Wrapping(x) {
			public int value() {
				return super.value() * 47;
			}
		};
	}

	public static void main(String[] args) {
		Parcel7 p = new Parcel7();
		Wrapping w = p.wrap(10);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值