- 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());
}
}
-
执行字段初始化
package chapter10Innerclasses;
public class Parcel9 {
public Destination destination(final String dest){ // 参数必须final JDK 8编译器会自动加上,可以把class文件反编译出来看看,编译期会自动加上final关键字
// dest = "test";
//
// String finalDest = dest; //Local variable a defined in an enclosing scope must be final or effectively final
return new Destination() { // 匿名类 初始化 是Parcel5的简化版
private String label = dest;
@Override
public String readLabel() {
System.out.println("dest is " + dest);
return label;
}
};
}
public static void main(String[] args) {
Parcel9 p = new Parcel9();
Destination d = p.destination("Tasmania");
System.out.println(d.readLabel());
}
}
-
通过实例初始化实现构造(匿名类不可能有构造器)
package chapter10Innerclasses;
abstract class Base{
public Base(int i){
System.out.println("Base constructor.i = " + i);
}
public abstract void f();
}
public class AnonymousConstructor {
public static Base getBase(int i ){
return new Base(i){ // 变量i 不一定是final 因为i 是被传递给匿名类的基类的构造器,它不会在匿名类内部被直接使用
{
System.out.println("Inside instance initializer");
}
@Override
public void f() {
System.out.println("In anonymous f()");
}
};
}
public static void main(String[] args) {
Base base = getBase(47);
base.f();
}
}
/*
Base constructor.i = 47
Inside instance initializer
In anonymous f()
*/
package chapter10Innerclasses;
// 实例初始化
public class Parcel10 {
public Destination destination(final String dest,final float price){
return new Destination() { // 实现接口
private int cost;
// 为每个object 初始化实例
{
cost = Math.round(price);
if (cost > 100)
System.out.println("Over budget");
}
private String label = dest;
@Override
public String readLabel() {
return label;
}
};
}
public static void main(String[] args) {
Parcel10 p = new Parcel10();
Destination d = p.destination("Tasmania",101.295F);
d.readLabel();
}
}
作业12
package chapter10Innerclasses.e12;
public class ClassA {
private int i = 10;
private void methodA(){
System.out.println("ClassA private methodA(),and i = " + i);
}
public void methodC(){
new Object(){
void methodB(){
i++;
methodA(); // 内部类可以访问 外围类的私有字段和私有方法
System.out.println("ClassA Inner methodB(),and i = " + i);
}
}.methodB(); //匿名内部类 实例的方法
System.out.println("methodC and i = " + i);
}
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.methodC();
}
}
10.6.1 再访工厂方法
package chapter10Innerclasses;
interface Service{
void method1();
void method2();
}
interface ServiceFactory{ // 生成某个接口的对象
Service getService();
}
class Implementation1 implements Service {
private Implementation1(){} // 构造方法 为private
@Override
public void method1() {
System.out.println("Implementation1.method1()");
}
@Override
public void method2() {
System.out.println("Implementation1.method2()");
}
public static ServiceFactory factory = new ServiceFactory(){ // 工厂对象为 static 字段对象
@Override
public Service getService() {
return new Implementation1();
}
};
}
//class Implementation1Factory implements ServiceFactory {
//
// @Override
// public Service getService() {
// return new Implementation1(); //生成接口的某个实现的对象
// }
//}
class Implementation2 implements Service {
private Implementation2(){}
@Override
public void method1() {
System.out.println("Implementation2.method1()");
}
@Override
public void method2() {
System.out.println("Implementation2.method2()");
}
public static ServiceFactory factory = new ServiceFactory() {
@Override
public Service getService() {
return new Implementation2();
}
};
}
//class Implementation2Factory implements ServiceFactory {
//
// @Override
// public Service getService() {
// return new Implementation2();
// }
//}
public class Factories {
public static void serviceConsumer(ServiceFactory fact){
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(Implementation1.factory);
serviceConsumer(Implementation2.factory);
}
}
/*
Implementation1.method1()
Implementation1.method2()
Implementation2.method1()
Implementation2.method2()
*/
package chapter10Innerclasses;
interface Game{boolean move();}
interface GameFactory{
Game getGame();}
class Checkers implements Game { //西洋跳棋
private int moves = 0;
private static final int MOVES =3;
@Override
public boolean move() {
System.out.println("Checkers move " + moves);
return ++moves != MOVES;
}
public static GameFactory checkersFactory = new GameFactory(){
@Override
public Game getGame() {
return new Checkers();
}
};
}
//class CheckersFactory implements GameFactory {
//
// @Override
// public Game getGame() {
// return new Checkers();
// }
//}
class Chess implements Game {
private int moves = 0;
private static final int MOVES =4;
@Override
public boolean move() {
System.out.println("Chess " + moves);
return ++moves != MOVES;
}
public static GameFactory chessFactory = new GameFactory() {
@Override
public Game getGame() {
return new Chess();
}
};
}
//class ChessFactory implements GameFactory {
//
// @Override
// public Game getGame() {
// return new Chess();
// }
//}
public class Games {
public static void playGame(GameFactory factory){
Game s = factory.getGame();
while (s.move())
;
}
public static void main(String[] args) {
playGame(Checkers.checkersFactory);
playGame(Chess.chessFactory);
}
}
/*
Checkers move 0
Checkers move 1
Checkers move 2
Chess 0
Chess 1
Chess 2
Chess 3
*/
优先使用类,而不是接口
10.7嵌套类
- 内部类 对象 隐式 保留一个引用 指向创建它的外围类对象
- 但
- static 嵌套类:不需要其外围类的对象
- 不能从嵌套类的对象中 访问 非静态的 外围类对象
- 普通内部类 字段方法 放在类的外部层次 不能有static 数据和字段
- 嵌套类 可以包含
package chapter10Innerclasses.e18;
public class E18 {
static class NestedClass{
void f(){
System.out.println("NestedClass.f()");
}
}
public static void main(String[] args) {
NestedClass ne = new NestedClass(); // 嵌套类内直接使用类名
ne.f();
}
}
class other { // 类作用域之外,通过outer class.nested class
void f(){
E18.NestedClass ne =new E18.NestedClass();
}
}
package chapter10Innerclasses.e19;
public class E19 {
class Inner1{
class Inner2{
void f(){}
}
Inner2 makeInner2(){return new Inner2();}
}
Inner1 makeInner1(){return new Inner1();}
static class Nested1{
static class Nested2{
void f(){}
}
void f(){}
}
public static void main(String[] args) {
new E19.Nested1().f(); // 调用类,不用() 实例化需要生成对象
new E19.Nested1.Nested2().f();
E19 x1 = new E19();
E19.Inner1 x2 = x1.makeInner1();
E19.Inner1.Inner2 x3 = x2.makeInner2();
x3.f();
}
}
/*
生成的class文件名称
E19$Inner1$Inner2.class E19$Nested1.class
E19$Inner1.class E19.class
E19$Nested1$Nested2.class
*/
10.7.1接口内部的类
创建某些公共代码,被某接口所有不同实现所共用。
package chapter10Innerclasses;
public interface ClassInInterface {
void howdy();
class Test implements ClassInInterface{ // 嵌套类可以作为 接口的一部分,放到接口的类 自动都是public static。
// 类是static ,只是将嵌套类 置于接口的命名空间内,不违反接口规则。甚至可以在内部类中,实现外围接口
@Override
public void howdy() {
System.out.println("howdy!");
}
public static void main(String[] args) {
new Test().howdy();
}
}
}
package chapter10Innerclasses;
public class TestBed {
public void f(){
System.out.println("f()");
}
public static class Tester{
public static void main(String[] args) {
TestBed t = new TestBed();
t.f();
}
}
}
//每个类中 都写个main()测试 ,缺点: 带着编译后都额外代码
//嵌套类 放置测试代码,生成两个类
// TestBed$Tester.class 执行java TestBed$Tester.class $ 转义
//TestBed.class
// 产品打包前删除 TestBed$Tester.class
package chapter10Innerclasses.e20;
interface Outer{
class Inner{
public void g(){
System.out.println("Inner.g()");
}
}
}
public class E20 implements Outer { //即使接口本身没有什么用,但接口中的类仍旧有用。
public static void main(String[] args) {
E20 e20 = new E20();
Outer.Inner in = new Outer.Inner();
in.g();
}
}
package chapter10Innerclasses.e21;
interface I{
void f();
class C{ //包含嵌套类的接口
static void g(I i){ // static方法,调用接口中的方法
System.out.println("calling I.f");
i.f();
}
}
}
public class E21 {
public static void main(String[] args) {
I impl = new I(){ // 实现接口
@Override
public void f() {
}
};
I.C.g(impl); // 将实现的实例传递给这个方法
}
}
10.7.2从多层嵌套类中访问外部类的成员
package chapter10Innerclasses;
// 嵌套类 能访问 外围层的所有成员,包括私有,如下例 g() f()
class MNA{
private void f(){}
class A{
private void g(){}
public class B{
void h(){
g();
f();
}
}
}
}
public class MultiNestingAccess {
public static void main(String[] args) {
MNA mna = new MNA();
MNA.A mnaa = mna.new A(); // .new语法能产生正确的作用域,不必在调用构造器时限定类名
MNA.A.B mnaab = mnaa.new B();
mnaab.h();
}
}
10.8为什么需要内部类
内部类提供 某种进入其外围类的窗口
- 内部类继承自某个类或实现某个接口
- 内部类的代码 操作 创建它的外围类的对象。
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
package chapter10Innerclasses;
// 两种方法 一个类 实现 多个接口
interface A{}
interface B{}
class X implements A,B{}
class Y implements A{
B makeB(){
return new B(){}; //匿名内部类
}
}
public class MultiInterfaces {
static void takesA(A a){}
static void takesB(B a){}
public static void main(String[] args) {
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
takesB(y.makeB());// 通过使用内部类实现接口
}
}
package chapter10Innerclasses;
// 拥有具体的类或抽象类,而不是接口。只能 内部类 实现多重继承。
// 若不需要解决 多重问题,可以用其他方式编码
class D{}
abstract class E{}
class Z extends D{
E makeE(){return new E(){};} //内部类 实现多重继承
}
public class MultiImplementation {
static void takesD(D d){}
static void takesE(E e){}
public static void main(String[] args) {
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
}
内部类的其他特性:
可以有多个实例,每个实例都有自己的状态信息,与外围类对象信息相互独立
单个外围类,可以多个内部类以不同方式实现一个接口或继承同一个类
练习22
package chapter10Innerclasses.e22;
//
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 Sequence outer(){ // 对外部类 Sequence 的引用
return Sequence.this;
}
}
public Selector selector(){
return new SequenceSelector();
}
public boolean check(){
return this == ((SequenceSelector)selector()).outer(); //校验 SequenceSelector 为私有
}
// 逆序
private class ReverseSelector implements Selector{
private int i = items.length -1;
@Override
public boolean end() {
return i == 0;
}
@Override
public Object current() {
return items[i];
}
@Override
public void next() {
if(i>0) i--;
}
public Sequence outer(){ // 对外部类 Sequence 的引用
return Sequence.this;
}
}
public Selector reverseSelector(){return new ReverseSelector();}
public boolean checkReverse(){
return this == ((ReverseSelector)reverseSelector()).outer(); //校验
}
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();
}
System.out.println(sequence.check());
//逆序
Selector rs = sequence.reverseSelector();
while (!rs.end()){
System.out.println(rs.current() + "");
rs.next();
}
System.out.println(sequence.checkReverse());
}
}
package chapter10Innerclasses.e23;
interface U {
void method1();
void method2();
void method3();
}
class A {
int i = 0;
A(int i) {
this.i = i;
}
public U getU() { // 创建一个匿名内部类,生成指向U的引用
return new U() {
@Override
public void method1() {
System.out.println("A method1 ,i = " + i);
}
@Override
public void method2() {
System.out.println("A method2 ,i = " + i);
}
@Override
public void method3() {
System.out.println("A method3 ,i = " + i);
}
};
}
}
class B {
private U[] ua; // U的数组,此例子中用A产生的对象来填充
public B(int size) {
ua = new U[size];
}
public boolean add(U u, int index) {
for (int i = 0; i < ua.length; i++) {
if (ua[i] == null){
ua[index] = u;
return true;
}
}
return false; // 找不到空位
}
public boolean setNull(int i) {
if (i<0 || i>= ua.length)
return false; // 越界 抛出异常
ua[i] = null;
return true;
}
void callMethods() {
for (int i = 0; i < ua.length; i++) {
if (ua[i] != null) {
ua[i].method1();
// ua[i].method2();
// ua[i].method3();
}
}
}
}
public class E23 {
public static void main(String[] args) {
int size = 3;
B b = new B(size);
for (int i = 0; i < size; i++) {
A a = new A(i);
b.add(a.getU(), i);
}
b.callMethods();
b.setNull(0);
b.callMethods();
}
}
/*
A method1 ,i = 0
A method1 ,i = 1
A method1 ,i = 2
A method1 ,i = 1
A method1 ,i = 2
*/
10.8.1闭包与回调
闭包的定义:
- 可调用的对象。记录了来自创建于它的作用域的信息。
内部类:面向对象的闭包
- 包含外围类对象的信息
- 自动拥有外围类对象的引用
- 内部类可以操作包括private成员
package chapter10Innerclasses;
/*闭包 回调
闭包 用一个类把另一个类包装起来。其构造比内部类复杂。作用有二
1闭包 能保护内部类里面的变量安全,不会被外部访问
2 能维持一个变量一直存活在内存中,不被CG掉
回调
同步调用
异步调用
回调 与异步 区别,以后补
*/
//创建个接口,包含一个函数
interface Incrementable{
void increment();
}
// 接口中没有上面特别的地方,实现这个接口,直接覆盖方法。
class Callee1 implements Incrementable{
private int i;
@Override
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();} //测试一下increment方法而已
}
//如果必须继承上面的MyIncrement的话,那上面已经有了具体的方法实现。把它覆盖,则上面的功能就不能用了
class Callee2 extends MyIncrement{
private int i = 0;
public void increment(){// 同样写类这个方法,覆盖父类方法,中间还调用父类方法
super.increment();
i++;
System.out.println(i);
}
//闭包具体实现 内部类实现类接口,并直接调用外部类的方法作为具体实现。
private class Closure implements Incrementable{
@Override
public void increment() {
// 具体 外围的方法,否则 会 无限回调
Callee2.this.increment(); //调用外部类的方法
}
}
//钩子getCallbackReference方法, 返回内部类的对象,实现内部和外部的链接。
//只有Callee2的对象可以访问
Incrementable getCallbackReference(){return new Closure();}
}
// 专门调用函数的 调用者
// 唤醒作用,通过接受不同的接口对象,实现不同的操作。
// 等待接受一个内部类对象,来产生回调。
class Caller{
private Incrementable callbackReference;
Caller(Incrementable cbh){callbackReference = cbh;}
void go(){callbackReference.increment();}
}
public class Callbacks {
public static void main(String[] args) {
Callee1 c1 = new Callee1();
Callee2 c2 = new Callee2();
// MyIncrement.f(c2);
System.out.println("------");
Caller caller1 = new Caller(c1);
Caller caller2 = new Caller(c2.getCallbackReference()); //
caller1.go();
caller1.go();
System.out.println("------");
caller2.go();
caller2.go();
}
}
/*
other operation
1
------
1
2
------
other operation
2
other operation
3
*/
10.8.2内部类与控制框架
package chapter10Innerclasses.controller;
// 要控制的事件
// 基于时间去执行控制,使用抽象类代替实际接口
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start(){ // 没有包含在构造器内,可以允许重启
eventTime = System.nanoTime() + delayTime;
}
public boolean ready(){ //何时可以运行action方法了 在导出类中 可以覆盖ready()方法,使得Event能够基于时间以外的其他因素而触发
return System.nanoTime() >= eventTime; //当前时间 大于 延时时间,说明已经准备完毕
}
public abstract void action(); // 重复事件,则在action中调用start方法
}
package chapter10Innerclasses.controller;
// 控制系统的可重用的框架
import java.util.ArrayList;
import java.util.List;
public class Controller {
private List<Event> eventlist = new ArrayList<Event>();
public void addEvent(Event c) {
eventlist.add(c);
}
public void run() {
while (eventlist.size() > 0)
//对eventList做一个拷贝,免得改动了原来的数据
for(Event e: new ArrayList<Event>(eventlist))
if (e.ready()){
System.out.println(e);
e.action();
eventlist.remove(e);
}
}
}
package chapter10Innerclasses.controller;
//{Args:5000}
/*
功能:控制框架的实现,
1、控制框架的完整实现是由单个的类创建的,从而使得实现的细节被封装了起来。内部类用来表示解决问题所必须的各种不同的action
2、内部类能够很容易地访问外围类的任意成员,所以可以避免这种实现变得笨拙。
*/
public class GreenhouseControl extends Controller {
private boolean light = false;
public class LightOn extends Event {// //由于event是抽象类,所以必须实现构造函数和抽象函数
public LightOn(long delayTime) {
super(delayTime);
}
@Override
public void action() {
//
light = true;
}
public String toString() {
return "Light is on";
}
}
public class LightOff extends Event {
public LightOff(long delayTime) {
super(delayTime);
}
@Override
public void action() {
//
light = false;
}
public String toString() {
return "Light is off";
}
}
private boolean water = false;
public class WaterOn extends Event //由于event是抽象类,所以必须实现构造函数和抽象函数
{
public WaterOn(long delayTime) {
super(delayTime);
}
@Override
public void action() {
water = true;
}
public String toString() {
return "Greenhouse is on";
}
}
public class WaterOff extends Event //由于event是抽象类,所以必须实现构造函数和抽象函数
{
public WaterOff(long delayTime) {
super(delayTime);
}
@Override
public void action() {
water = false;
}
public String toString() {
return "Greenhouse is off";
}
}
private String thermostat = "Day";
public class ThermostatDay extends Event //由于event是抽象类,所以必须实现构造函数和抽象函数
{
public ThermostatDay(long delayTime) {
super(delayTime);
}
@Override
public void action() {
thermostat = "Day";
}
public String toString() {
return "Thermostat on day setting";
}
}
public class ThermostatNight extends Event //由于event是抽象类,所以必须实现构造函数和抽象函数
{
public ThermostatNight(long delayTime) {
super(delayTime);
}
@Override
public void action() {
thermostat = "Night";
}
public String toString() {
return "Thermostat on night setting";
}
}
public class Bell extends Event {
public Bell(long delayTime) {
super(delayTime);
}
@Override
public void action() {
addEvent(new Bell(delayTime));
}
public String toString() {
return "Bing!";
}
}
public class Restart extends Event {
private Event[] eventList;
public Restart(long delayTime, Event[] eventList) {
super(delayTime);
this.eventList = eventList;
for (Event e : eventList)
addEvent(e);
}
@Override
public void action() {
for (Event e : eventList) {
e.start(); // rerun 每个event
}
start(); // rerun 这个事件
addEvent(this);
}
public String toString() {
return "Restarting system!";
}
}
public static class Terminate extends Event {
public Terminate(long delayTime) {
super(delayTime);
}
@Override
public void action() {
System.exit(0);
}
public String toString() {
return "Terminate system!";
}
}
//配置 并 执行系统
public static void main(String[] args) {
GreenhouseControl gc = new GreenhouseControl();
gc.addEvent(gc.new Bell(900));
Event[] eventList ={
gc.new ThermostatNight(0),
gc.new LightOn(200),
gc.new LightOff(200),
gc.new WaterOn(600),
gc.new WaterOff(800),
gc.new ThermostatDay(1400),
};
gc.addEvent(gc.new Restart(2000,eventList));
if(args.length == 1)
gc.addEvent(new GreenhouseControl.Terminate(new Integer(args[0])));
gc.run();
}
}
内部类的继承
package chapter10Innerclasses;
//内部类的继承
class WithInner{
class Inner{}
}
public class InheritInner extends WithInner.Inner{
InheritInner(WithInner wi){
wi.super(); //这个看不懂
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi);
}
}
此练习已吐血
package chapter10Innerclasses.e26;
class WithInner {
class Inner {
Inner(int i) {
System.out.println("Inner i:" + i);
}
}
}
class WithInner2 {
class Inner2 extends WithInner.Inner {
public Inner2(WithInner wnd, int i) {
wnd.super(i);
}
}
public static void main(String[] args) {
WithInner wi = new WithInner();
WithInner2 wi2 = new WithInner2();
Inner2 i2 = wi2.new Inner2(wi, 47);
}
}
public class E26 {
}
10.10内部类可以被覆盖吗
package chapter10Innerclasses;
// 内部类不能像方法那样被覆盖
// 继承某个外围类时,相同的内部类,是两个完全独立的实体,各自在自己的命名空间内。
class Egg{
private Yolk y;
protected class Yolk{
public Yolk(){
System.out.println("Egg.Yolk()");
}
}
public Egg(){
System.out.println("New Egg()");
y = new Yolk();
}
}
public class BigEgg extends Egg{
public class Yolk{
public Yolk(){
System.out.println("BigEgg.Yolk()");
}
}
public static void main(String[] args) {
new BigEgg();
}
}
/*
New Egg()
Egg.Yolk()
*/
package chapter10Innerclasses;
// 内部类不能想方法那样被覆盖
// 但 内部类如果明确继承某个内部类,也是可以的。
class Egg2{
protected class Yolk{
public Yolk(){
System.out.println("Egg2.Yolk()");
}
public void f(){
System.out.println("Egg2.Yolk().f()");
}
}
private Yolk y = new Yolk();
public Egg2(){
System.out.println("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(){
System.out.println("BigEgg2.Yolk()");
}
public void f(){
System.out.println("BigEgg2.Yolk.f()");
}
}
public BigEgg2(){insertYolk(new Yolk());} // 向上转型
public static void main(String[] args) {
Egg2 egg2 = new BigEgg2();
egg2.g(); // 调用新的f()
}
}
/*
Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
BigEgg2.Yolk.f()
*/
局部内部类
局部内部类:在方法和及方法的作用域内的类
不能有访问说明符,因为它不是外围类的一部分。
但可以访问当前代码块的常量,以及外围类的所有成员。
package chapter10Innerclasses;
interface Counter {
int next();
}
public class LocalInnerClass {
private int count = 0;
// 局部内部类
Counter getCounter(final String name) {
class LocalCounter implements Counter {
LocalCounter() {
System.out.println("LocalCounter() 构造器");
}
@Override
public int next() {
System.out.print(name); // 访问local final
return count++;
}
}
return new LocalCounter();
}
// 匿名内部类
Counter getCounter2(final String name) {
return new Counter() { // 匿名内部类 没有带名字的构造器,只有一个实例的初始化
{
System.out.println("Counter");
}
@Override
public int next() {
System.out.print(name); // 访问local final
return count++;
}
};
}
public static void main(String[] args) {
LocalInnerClass lic = new LocalInnerClass();
Counter c1 = lic.getCounter("局部内部类"),
c2 = lic.getCounter2("匿名内部类");
for (int i = 0; i < 5; i++)
System.out.println(c1.next());
for (int i = 0; i < 5; i++)
System.out.println(c2.next());
}
}
/*
LocalCounter() 构造器
Counter
局部内部类0
局部内部类1
局部内部类2
局部内部类3
局部内部类4
匿名内部类5
匿名内部类6
匿名内部类7
匿名内部类8
匿名内部类9
*/
局部内部类和匿名内部类实现的功能,具有相同的行为和能力。
- 匿名内部类:用于实例初始化
- 局部内部类:
- 理由1:需要一个已经命名的构造器,或者需要重载构造器。
- 理由2:需要不止一个该内部类的对象。
10.12内部类标识符
每个类都生成.class文件
- Out.class
- Out$1.class 匿名类
- Out$1Inner2.class局部内部类
- Out$Inner3.class内部类嵌套