`

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

 

十二、内部类的覆盖

 

 

分享到:
评论

相关推荐

    第11章 内部类(Inner class).ppt

    本章我们将深入探讨内部类的种类、用法以及其优势。 1. **成员内部类**: - 成员内部类就像普通类的成员变量一样,可以是静态或非静态的。静态内部类与普通的静态成员类似,不依赖于外部类的实例,而非静态内部类...

    thinkingInJava10:内部类

    《思考Java10:内部类》 在Java编程语言中,内部类是一个强大的特性,它允许我们在一个类的内部定义另一个类。这种设计模式在处理复杂的问题时特别有用,例如事件处理、封装特定功能或者创建匿名类。让我们深入探讨...

    数据结构课件:第10章 内部排序.ppt

    内部排序的方法多种多样,根据不同的策略可以分为五类: 1. **插入类排序**:如直接插入排序,它通过将无序序列中的一个或多个记录插入到已排序的部分,逐渐扩大有序序列的长度。在一趟插入排序中,会将当前元素与...

    JAVA 面向对象程序设计第8章 内部类和泛型.pptx

    为了遍历 ListArray 中的所有元素,我们可以定义一个内部类,实现之前定义的 Foreach 接口,这个内部类将作为 ListArray 的迭代器。 ```java public class ListArray implements Foreach { private int capacity; ...

    Java语言基础入门教程 Java开发编程基础课程 第8章 内部类和异常处理 共18页.pptx

    ### Java语言基础入门教程:内部类与异常处理 #### 一、内部类概述 内部类是在另一个类的内部定义的类。它具有多种类型,并且能够访问外部类的私有成员,这使得内部类在实现特定功能时非常灵活且强大。 #### 二、...

    Java语言基础入门教程 Java开发编程基础课程 第12章 内部类和异常处理 共18页.pptx

    ### Java语言基础入门教程:内部类与异常处理 #### 一、内部类概述 内部类是在另一个类的内部定义的类。它具有多种类型,并且能够访问外部类的私有成员,这使得内部类在实现特定功能时非常灵活且强大。 #### 二、...

    数据结构:第10章 内部排序.ppt

    数据结构:第10章 内部排序.ppt

    java第七章高级类特性.rar

    2. **内部类**:Java允许在类内部定义其他类,包括成员内部类、局部内部类、匿名内部类和静态内部类。这种设计允许更紧密的封装和更复杂的逻辑结构,例如事件监听器的实现。 3. **枚举(Enum)**:枚举是Java中的一...

    财务管理第10章内部审计-王宝庆.pptx

    财务管理第10章内部审计-王宝庆.pptx

    数据结构课件:第10章 内部排序 (2).ppt

    数据结构课件:第10章 内部排序 (2).ppt

    java面向对象程序设计课程每章ppt(共15章+复习1章).zip

    第10章 static修饰符.pptx 第10章 枚举.pptx 第11章 异常和断言.pptx 第12章 JDK8中的日期.pptx 第12章 字符串、日期.pptx 第13章 容器和泛型.pptx 第14章 流与文件(1).pptx ...第9章 内部类.pptx

    Java编程思想笔记(全)

    #### 第 10 章 内部类 第十章介绍了内部类的概念。内部类是在另一个类的内部定义的类,它可以访问外部类的成员变量甚至是私有变量。本章讨论了成员内部类、局部内部类、静态内部类以及匿名内部类的不同应用场景和...

    数据结构(严蔚敏)第十章:内部排序

    内部排序通常包括比较型排序和非比较型排序两大类,比较型排序基于元素之间的比较,如冒泡排序、插入排序、选择排序等;非比较型排序则不依赖于元素间的比较,如计数排序、桶排序、基数排序等。 2. **基本排序算法*...

    联想维修站的内部发行资料

    联想维修站的内部发行资料 第一部分 总则 第一章 电脑维修的基本原则...第十一章 兼容类故障 第三部分 附录 硬盘基本知识 挽救硬盘的几个方法 硬盘逻辑锁巧解 WINDOWS蓝色当机画面解读 实用的端口大全(中文版)

    数据结构第八章内部排序.pdf

    "数据结构第八章内部排序" 数据结构第八章内部排序是指在内存中对数据进行排序的算法和技术。本章主要介绍了内部排序的评价指标、稳定性、关键字相同的元素经过排序后相对顺序是否发生改变等概念,并对插入排序、...

    重庆大学数据结构第10章 内部排序.ppt

    【内部排序分类】根据排序过程中对存储器的使用,内部排序可以分为两大类: 1. **直接插入排序**:是最基本的排序方式之一。它的工作原理是逐步将新记录插入到已排序的序列中,以扩展有序区域。例如,**直接插入排序...

    数据结构教学课件:第10章 内部排序.ppt

    数据结构教学课件的第10章主要探讨了内部排序这一主题。内部排序是指当待排序的记录数量不大,能够全部存储在内存中进行排序的一种处理过程。在计算机科学和数据处理领域,排序是一个基本且重要的操作,它涉及到将一...

Global site tag (gtag.js) - Google Analytics