A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 321哈哈哈 中级黑马   /  2017-10-12 01:39  /  574 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

内部类允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。
内部类看起来像一种代码隐藏机制;同时它了解外围类,并能与之通信。
Private(成员)内部类:
可以完全阻止任何依赖于类型的编码??
(将内部类向上转型为基类或者接口,通过方法返回的只是指向基类或接口的引用,就像new了一个接口对象)(这时扩展接口没有价值)
(甚至无法实现向下转型,因为无法访问该类名)
完全隐藏了实现的细节(private修饰)
嵌套类:
static修饰的(成员)内部类
内部类对象与其外围类对象没有联系(没有保存外部类对象的引用,要创建嵌套类对象并不需要其外部类对象)
不能从嵌套类的对象中访问非静态的外围类成员
普通内部类中不能有static成员(也不能有嵌套类);嵌套类可以包含所有这些东西
局部内部类
定义在方法中(甚至只存在于方法的一个作用域内)
匿名(局部)内部类:(类的定义和创建对象一举完成)
可以继承有非默认构造方法的类(一样传参)
不可能有构造器,可以在类内添加字段初始化(或者构造代码块)来替代
字段初始化所需要的值作为所在方法的参数传入,该形参要声明为final??
局限是不能重载这种“构造器”
可以扩展类或实现接口,但不能两者兼备
为什么需要内部类
内部类使得多重继承的解决方案变得完整(接口解决了部分问题)
每个内部类都能独立的继承类(实现接口)
通过内部类可以继承多个非接口类型
内部类还有的其他特性:
内部类可以有多个实例,每个实例都有自己独立的状态信息
在单个外部类中,可以让多个内部类以不同方式实现同一个接口(继承同一个类)
内部类并没有令人迷惑的is - a”关系(当外部类不满足某个is - a测试,但需要继承那个类,可以让内部类继承)
这些特性本身是相当直观的,但这些特性的使用是设计阶段考虑的问题。
当见到这些语言特性的实际应用时,就最终理解它们了。
Tip
典型的情况是,外部类有一个方法,返回一个指向内部类对象的引用。
如果想从外部类的非静态方法之外的任意位置创建某个内部类对象,必须指明完整类型:外部类.内部类
能访问其外围对象的所有成员,就像他们自己拥有似的
因为,当某个外围类对象创建了一个内部类对象时,内部类对象必定会秘密地捕捉一个指向那个外围类对象的引用,所以在拥有外部类对象之前是不可能创建内部类对象的
内部类(非static时)对象只能在于其外部类对象相关联的情况下才能被创建
所以创建内部类对象时,必须在new表达式中提供对其外部类对象的引用(使用.new语法),同时给外部类对象一个消息,创建其内部类对象的消息,像命令它调用自己的成员方法一样。
如果要在内部类里获得对外部类对象的引用:使用外部类名.this
这个this是外部类的一个隐式成员
只写this获得的是指向内部类对象的引用
*接口内部的类
自动的是public static
通过这样,可以创建某些公共代码,使得它们可以被某个接口的所有不同实现所公用??
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();
    }
  }
} /* Output:
Howdy!
*///:~
使用嵌套类来放置测试代码(main方法,方便得测试每个类)
会生成一个独立的类TestBed$Tester.class(执行java TestBed$Tester 可以测试)
发布产品时,将这个class文件删除(相当于源码中 类里面没写测试的内部类)
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();
    }
  }
} /* Output:
f()
*///:~
*多层嵌套类
可以透明得访问它所嵌入的外部类的所有成员
创建多层嵌套的内部类对象的标准写法:.new能产生正确的作用域,所以不必在调用构造器时写完整类名
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();
    MNA.A.B mnaab = mnaa.new B();
    mnaab.h();
  }
} ///:~
闭包与回调
闭包(closure)是一个对象。它记录了一些信息,这些信息来自于创建它的作用域。
内部类对象自动包含外部类对象的引用,可以自由使用外部类的信息,是一个闭包。
通过内部类提供闭包(内部类对象),来实现回调(callback),比指针更灵活、安全。
本例中也能看出interface是如何允许接口与接口的实现完全独立的(private内部类实现接口;public方法提供闭包,即接口引用)
interface Incrementable {
  void increment();
}
//接口和类中有相同的方法,所以下面的Callee2使用的内部类来实现多重继承
class MyIncrement {
  public void increment() {
          System.out.println("Other operation");
  }
}       
// 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);
  }
  
  //该内部类对象就是一个闭包(包含了外部类对象的信息)
  private class Closure implements Incrementable {
    public void increment() {
      //这个this是指向Callee2对象(被回调)的引用
            //由此提供了闭包的“钩子”(hook)功能
//该闭包只能调用increment方法,是个安全的钩子
      Callee2.this.increment();
    }
  }
  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) {
    Callee2 c2 = new Callee2();
    Caller caller2 = new Caller(c2.getCallbackReference());
    caller2.go();//使用闭包回调
    caller2.go();
  }       
}
*内部类的继承
子类和被继承的内部类一样,其构造方法必须连接到指向其外围类对象的引用??
所以在继承内部类时:外围类引用必须被初始化;导出类中不再存在可连接的默认对象(所以下例中的wi.super()不能省略)??
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);
  }
} ///:~
*内部类可以被重写吗
如下例所示,导出类和基类中同名的两个内部类是完全独立的两个实体,各自在自己的命名空间内??,互不影响,没有“重写”
(继承后父类空间存在于子类空间中。父类的内部类的作用域是父类空间,父类可以使用,但如果是开放权限的内部类,子类也能使用)??
// An inner class cannot be overriden like a method.
// 内部类不能像父类方法一样被重写
import static net.mindview.util.Print.*;
class Egg {
  private Yolk y;
  protected class Yolk {
    public Yolk() { print("Egg.Yolk()"); }
  }
  public Egg() {
    print("New Egg()");
    y = new Yolk();
  }
}       
public class BigEgg extends Egg {
  public class Yolk {
    public Yolk() { print("BigEgg.Yolk()"); }
  }
  public static void main(String[] args) {
    new BigEgg();
  }
} /* Output:
New Egg()
Egg.Yolk()
*///:~
明确继承内部类是可以的:
// Proper inheritance of an inner class.
import static net.mindview.util.Print.*;
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()
*///:~

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马