Java内部类

内部类详解

内部类的基本使用

//例子1
public class DotThis {
  void f() { System.out.println("DotThis.f()"); }
  public class Inner {
    public DotThis outer() {
      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();
    DotThis.Inner dti = dt.inner();
    dti.outer().f();
  }
} /* Output:
DotThis.f()
*///:~
//例子2
public class DotNew {
  public class Inner {}
  public static void main(String[] args) {
    DotNew dn = new DotNew();
    DotNew.Inner dni = dn.new Inner();
  }
} ///:~
  1. 内部类自动拥有对其外围类所有成员的访问权.
  2. 如果我们需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this.
  3. 如果我们要创建内部类的对象,要使用外部类的对象来创建该内部类的对象.使用点.new 语法.

内部类"高级"用法

下面的两个例子展示了在方法里面创建内部类与在作用域里面创建内部类.
//局部内部类  1
public class Parcel5 {
//PDestination类是destination()方法的一部分,而不是Parcel5的一部分,
//所以在destination()方法之外不能访问PDestination
	public Destination destination(String s) {
		class PDestination implements Destination {
			private String label;

			private PDestination(String whereTo) {
				label = whereTo;
			}

			public String readLabel() {
				return label;
			}
		}
		//向上转型,返回了Destination,它是基类.
		return new PDestination(s);
	}

	public static void main(String[] args) {
		Parcel5 p = new Parcel5();
		Destination d = p.destination("Tasmania");
	}
}

//例子2 在作用域里面嵌套一个内部类
public class Parcel6 {
	private void internalTracking(boolean b) {
		if (b) {
			class TrackingSlip {
				private String id;
				TrackingSlip(String s) {
					id = s;
					System.out.println("+TrackingSlip");
				}
				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();
	}
} 
匿名内部类
public interface Contents {
  int value();
}

//例子1
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()方法将返回值的生成与表示这个返回值的类的定义结合在了一起!
		Contents c = p.contents();
	}
}

//例子2 
public class Parcel7b {
	class MyContents implements Contents {
		private int i = 11;

		public int value() {
			return i;
		}
	}

	public Contents contents() {
		return new MyContents();
	}

	public static void main(String[] args) {
		Parcel7b p = new Parcel7b();
		//我们使用了默认的构造器来生成了Contents
		Contents c = p.contents();
	}
}
//例子3
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) {
		//基本构造函数调用:
		return new Wrapping(x) { // 传递构造函数参数
			public int value() {
				return super.value() * 47;
			}
		}; // 这里的分号表示的不是内部类的结束,而是表示改表达式的结束,只不过是这个表达式正巧包含了匿名内部类罢了
	}

	public static void main(String[] args) {
		Parcel8 p = new Parcel8();
		//
		Wrapping w = p.wrapping(10);
	}
}
//例子4
public class Parcel9 {
	//必须是final类型的
	// 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");
	}
}
//例子5
public class Parcel10 {
  public Destination
  destination(final String dest, final float price) {
    return new Destination() {
      private int cost;
      // 
      {
        cost = Math.round(price);
        if(cost > 100)
          System.out.println("Over budget!");
      }
      private String label = dest;
      public String readLabel() { return label; }
    };
  }	
  public static void main(String[] args) {
    Parcel10 p = new Parcel10();
    Destination d = p.destination("Tasmania", 101.395F);
  }
} /* Output:
Over budget!
*///:~
  1. 例子1中得出一种奇怪的语法:创建一个继承自Contents的匿名对象.通过new表达式返回的引用被自动向上转型为对Contents的引用.
  2. 例子4中,如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数的引用是final的.
  3. 例子5中,匿名类中不可能有命名构造器,但是通过实例初始化,就可以达到为匿名内部类创建一个构造器的效果.
内部类的继承
class WithInner {
  class Inner {}
}
//这里InheritInner只继承自内部类,而不是外围类
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);
  }
}

因为内部类的构造器必须连接到指向其外围类的引用,所以在继承内部类的时候,事情会变得复杂一点.
指向外围类对象的"秘密的"引用必须被初始化.而在导出类中不再存在可连接的默认对象.

内部类可以被覆盖吗?

答案是肯定.

class Egg2 {
	protected class Yolk {
		public Yolk() {
			print("Egg2.Yolk()");
		}

		public void f() {
			print("Egg2.Yolk.f()");
		}
	}

	private Yolk y = new Yolk();

	public Egg2() {
		print("New Egg2()");
	}
	//
	public void insertYolk(Yolk yy) {
		y = yy;
	}

	public void g() {	
		y.f();
	}
}

public class BigEgg2 extends Egg2 {
//继承了内部类,并且覆盖了其中的方法
	public class Yolk extends Egg2.Yolk {
		public Yolk() {
			print("BigEgg2.Yolk()");
		}

		public void f() {
			print("BigEgg2.Yolk.f()");
		}
	}

	public BigEgg2() {
		insertYolk(new Yolk());
	}

	public static void main(String[] args) {
		Egg2 e2 = new BigEgg2();
		e2.g();
	}
} 	/*
	 * Output: Egg2.Yolk() New Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f()
	 */// :~
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值