- 10.1创建内部类
- 10.2链接到外部类
- 10.3使用this与new
- 10.4内部类与向上转型
- 10.5在方法和作用域内的内部类
- 10.6匿名内部类
- 10.7嵌套类
- 10.8为什么需要内部类
- 10.9内部类的继承
- 10.10内部类可以被覆盖吗
- 10.11局部内部类
- 10.12内部类标识符
- 10.13总结
内部类:一个类的定义放在另一个类的定义内部
- 逻辑相关的类组织在一起,并控制位于内部的类的可视性。
与组合是完全不同的概念。
10.1 创建内部类
// 创建内部类
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 readLable(){ 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);
System.out.println(d.readLable());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tasmania");
}
}
// 返回一个指向内部类的引用
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();
Parcel2.Contents c = q.contents(); // 创建内部类对象 outerClassName.InnerClassName
Parcel2.Destination d = q.to("Borneo");
}
}
10.2 创建到外部类
内部类对象拥有一个对外围类对象的引用
package chapter10Innerclasses;
//
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;
}
private class SequenceSelector implements Selector {
private int i = 0;
@Override
public boolean end() {
return i == items.length;
}
@Override
public Object current() {
return items[i];
}
@Override
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.println(selector.current() + " ");
selector.next();
}
}
}
10.3 使用.this与.new
package chapter10Innerclasses;
public class DotThis {
void f(){
System.out.println("DotThis.f()");
}
public class Inner{
public DotThis outer(){
return DotThis.this; // 外部类.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()
*/
public class DotNew {
public class Inner{}
public static void main(String[] args) {
DotNew dn = new DotNew();
DotNew.Inner dni = dn.new Inner(); // 创建某个内部类的对象 不能用外部类名称如DotNew,而是用外部类的对象创建
}
}
package chapter10Innerclasses;
public class Parcel3 {
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 static void main(String[] args) {
Parcel3 p = new Parcel3();
Parcel3.Contents c = p.new Contents();
Parcel3.Destination d = p.new Destination("Tasmania"); // 内部类对象会 暗暗的连接到创建它到外部类对象上。
// 如果创建到是嵌套类(静态内部类),就不需要对外部类对象对引用。这句话没有例子
}
}
10.4 内部类与向上转型
package chapter10Innerclasses;
class Parcle4{
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;
}
@Override
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) {
Parcle4 p = new Parcle4();
Contents c = p.contents(); // 向上转型
Destination d = p.destination("Tasmania");
// Parcle4.PContents pc = p.new PContents(); // 不能访问私有类 不能向下转型
}
}
package chapter10Innerclasses.e6.package1;
public interface Interface01 {
void f();
}
package chapter10Innerclasses.e6.package2;
import chapter10Innerclasses.e6.package1.Interface01;
public class Class2 {
protected class Inner implements Interface01{
@Override
public void f() {
System.out.println("class2.inner.method()");
}
public Inner(){} // Inner 为 protected,强制 构造函数为public
}
}
package chapter10Innerclasses.e6.package3;
import chapter10Innerclasses.e6.package1.Interface01;
import chapter10Innerclasses.e6.package2.Class2;
public class Class3 extends Class2 {
public Interface01 get(){
return new Inner(); // 构造函数为public 才能new
}
public static void main(String[] args) {
new Class3().get().f();
}
}
package chapter10Innerclasses.e7;
public class ClassA {
private int i = 10;
private void methodA(){
System.out.println("ClassA private methodA(),and i = " + i);
}
class Inner{
void methodB(){
i++;
methodA(); // 内部类可以访问 外围类的私有字段和私有方法
System.out.println("ClassA Inner methodB(),and i = " + i);
}
}
public void methodC(){
Inner inner = new Inner();
inner.methodB();
System.out.println("methodC and i = " + i);
}
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.methodC();
}
}
10.5 在方法和作用域内的内部类
内部类作用
- 实现某类型的接口,可以创建并返回对其对引用
- 解决复杂问题,创建一个类辅助解决,不希望它公共可用
局部内部类:方法中的类
package chapter10Innerclasses;
public class Parcel5 {
public Destination destination(String s){
class PDestination implements Destination{ // 方法中的类
private String label;
private PDestination(String whereTo){
label = whereTo;
}
@Override
public String readLabel() {
return label;
}
}
return new PDestination(s); // 返回的是 Destination 的引用
}
public static void main(String[] args) {
Parcel5 p = new Parcel5();
Destination d = p.destination("Tasmania"); // Destination 向上转型
System.out.println(d.readLabel());
}
}
作用域中嵌入内部类
package chapter10Innerclasses;
// 作用域内嵌入一个内部类
public class Parcel6 {
private void interalTracking(boolean b){
if (b){
class TrackingSlip{ // 跟踪单 嵌入在if作用域中,并不是说该类创建是有条件的。它其实是与别的类一起编译的。 超出作用域外,不可用。除此之外,与普通类一样。
private String id;
TrackingSlip(String s){
id = s;
}
String getSlip(){
return id;
}
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
// TrackingSlip ts = new TrackingSlip("slip"); // 不能用在这里,超出作用域
}
public void track(){interalTracking(true);}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
p.track();
}
}
10.6 匿名内部类
实现了接口的匿名类
package chapter10Innerclasses;
public class Parcel7 {
public Contents contents(){
return new Contents() { // 使用默认构造器生成Contents
private int i = 11;
@Override
public int value() {
return i;
}
}; //需要分号
}
public static void main(String[] args) {
Parcel7 p = new Parcel7();
Contents c = p.contents();
}
}
扩展了有非默认构造器的类
package chapter10Innerclasses;
class Wrapping {
private int i ;
Wrapping(int x) {
i = x;
System.out.println("Wrapping constructor x = " + 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);
System.out.println(w.value());
}
}
执行字段初始化
- 通过实例初始化实现构造(匿名类不可能有构造器)