java中的内部类

java中的内部类

本博客参考<< thinking in java >>第10章内部类,总结了本人不熟悉的知识点或者重要的知识点.

创建内部类

  • 只需要简单地将类的定义置于外围类内部.

链接到外部类

  • 内部类能够访问外围对象的所有成员,而不需要任何条件.而且内部类具有外部类所有成员的访问权(包括private).为什么呢?这是因为内部类对象会秘密地捕获一个指向外围类的引用.
  • 非static的内部类只能在外部类对象存在时候才可以被创建.(在下一部分中的代码会说明这一点)

使用.this和.new

  • .this:在内部类中通过使用OuterClass.this.就可以生成外部类对象的引用.

  • .new:具体用法见下

      public class OuterClass {
          class InnerClass{
              int val = 1;
              InnerClass(){
                  System.out.println("In innerclass's construction");
              }
          }
      
          void test(){
              InnerClass i = new InnerClass();
              System.out.println(i.val);
          }
      
          InnerClass getInnerClass(){
              return new InnerClass();
          }
      
          public static void main(String[] args) {
              OuterClass o = new OuterClass(); // outerclass must be initialed first
              InnerClass i = o.new InnerClass(); // .new usage
              InnerClass i2 = o.getInnerClass(); // another way to get the instance of innerclass
          }
    

    }

内部类和向上转型

  • 当将内部类向上转型为其基类,尤其是一个接口的时候,内部类就有了用武之地,因为这个实现了接口的内部类完全不可见,所得到的只是指向基类或接口的引用,可以很方便地隐藏实现细节.

      public class TestCast {
    
          private class InnerClass implements Base{
              private String str;
              public void otherMethod(){
                  System.out.println("hah");
              }
              private InnerClass(String str){
                  this.str = str;
              }
              @Override
              public void say() {
                  System.out.println("sya something : " + str);
              }
          }
      
          Base getBase(String str){
              return new InnerClass(str);
          }
      
          public static void main(String[] args) {
              TestCast t = new TestCast();
              Base b = t.getBase("hello");
          }
    

    }

局部内部类

  • 可以在方法内定义一个类.

匿名内部类

  • 在匿名内部类中,如果你的基类需要一个有参数的构造器时,只要简单地传递合适的参数给基类的构造器即可.

      public class TestPass {
          public Wrapping wrapping(int x){
              return new Wrapping(x){
                  public int getValue(){
                      return super.getValue() * 2;
                  }
              };
          }
      
          public static void main(String[] args) {
              TestPass t = new TestPass();
              Wrapping w = t.wrapping(2);
              System.out.println(w.getValue());// output 4
          }
      }
    
      public class Wrapping {
          private int i;
          public Wrapping(int i){
              this.i = i;
          }
          public int getValue(){
              return i;
          }
      }
    
  • 如果要定义一个匿名内部类,并且想使用一个外部定义的对象,那么这个参数引用需要是final的.(貌似jdk8后不用final修饰这个变量,但是这个变量也是不能改变的,这个final称为effectively final)

      public void test(String str){
          return new A(){
              private String word = str;
              public String say(){ return word;}
          };
      }
    
  • 由于匿名类中不可能有命名的构造器(因为根本没有名字),但是通过实例初始化,可以使得匿名类中创建一个构造器类似的效果.

      public class TestInit {
          public Base getBase(){
              return new Base() {
                  {
                      System.out.println("In base init block!");
                  }
                  @Override
                  public void say() {
                      System.out.println("base say");
                  }
              };
          }
      
          public static void main(String[] args) {
              TestInit t = new TestInit();
              Base b = t.getBase(); // output : In base init block!
          }
      }
    

嵌套类

  • 不需要内部类对象和外部类对象之间有联系,可以将内部类声明为static,这通常称为嵌套类.嵌套类意味着:①要创建这个static的内部类并不需要外部类对象.②不能从嵌套类的对象中访问非静态的外围类对象(嵌套类中没有这个特殊的this引用).
  • 接口内部的类:正常情况下不可以在接口中放置任何代码,但是嵌套类可以作为接口的一部分,因为接口中的任何域都是static和public的,而放在接口中的这个类会变成static,你甚至可以让这个嵌套类实现这个接口.

内部类的继承

  • 指向外部类中的秘密引用必须在构造器中被初始化.

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

内部类的覆盖

  • 如果A类中有个protected的内部类InnerClass,B类继承了A类并且也定义了一个内部类InnerClass,事实发现后者并不会覆盖前者的类,两个内部类是完全独立的两个实体.当然,如果B类中的InnerClass明确表示extends A.InnerClass, 那么可以覆盖其中的方法.

内部类标识符

  • 内部类会生成一个.class文件已包含他们的Class对象信息,这些文件的命名规则:如果是局部内部类,那么命名为OuterClassName$InnerClassName.class;如果是匿名内部类,那么会生成OuterClassName$num.class,其中num为一个数字.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值