zoukankan      html  css  js  c++  java
  • Java编程思想读书笔记 第十章 内部类

    非静态内部类作用:

    1. 最基本的作用:名字隐藏和组织代码
      • 用例:内部类不访问外部类的元素时可以直接new。(bad style!)
      • 用例:通过外部类的非静态方法返回内部类的引用,这样隐含了内部类对象和其对应的外部类对象的关系(需要先创建外部类对象,然后通过外部类对象创建内部类对象)。
      • 注意:内部类访问内部类的元素时,直接new内部类编译会报错
        No enclosing(外围的) instance of type xxx is accessible
    2. 链接到外部类:访问其外围类所有成员的访问权
      • 实现机制:普通内部类(非静态)对象和外部类对象之间存在联系。创建内部类对象时,该对象保存指向其外部类对象的引用。
      • 用例:"迭代器"设计模式

    非静态内部类使用:

    1. 外部类类名 + .this

      • 用法:返回内部类对象引用的外部类对象
    2. 外部类对象 + .new

      • 用法:返回内部类的引用,告知其它对象或静态方法中使用
      // Creating an inner class directory using the .new syntax
      
      public class DotNew {
          public class Inner {}
          public static void main(String[] args) {
              DotNew dotNew = new DotNew();
              DotNew.Inner inner = dotNew.new Inner();
          }
      }
      
    3. 权限修饰符

      1. 私有内部类,隐藏内部类信息。接口的实现不可见也不可用,仅能得到指向基类或者接口的引用。
      2. 保护内部类,自己、子类、同一个包中的类可以访问
      // 接口所有成员自动是public的
      interface Destination {
          String readLabel();
      }
      
      interface Contents {
          int value();
      }
      
      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) {
                  this.label = whereTo;
              }
              public String readLabel() { return this.label; }
          }
          public Destination destination(String s) {
              PDestination pDestination =  new PDestination(s);
              // Exercise 8: 外部类是否可以访问内部类的private元素
              // 答:外部类访问内部类的private对象就像访问自己的private对象一样
              // 理由:编译器对内部类实现时,生成两个类,对于private变量的访问,编译器会生成一个accessor函数.
              System.out.println(pDestination.label);
              return pDestination;
          }
          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");
              // The type Parcel4.PContents is not visible
              // 不能向下转型成private内部类,因为名字不可访问
              // ! Parcel4.PContents pc = p.new PContents();
          }
      }
      
      • 注意:嵌套类(内部静态类)不需要对外部对象的引用
      // Exercise 8: 外部类是否可以访问内部类的private元素
      // 答:可以,外部类访问内部类的private对象就像访问自己的private对象一样
      // 实现机制:编译器对内部类实现时,生成两个类,对于private变量的访问,编译器会生成一个 accessor函数.
      

    方法和作用域内的内部类

    1. 目的

      • 实现了某种类型的接口,可以创建并返回对其的引用
      • 创建一个类以解决问题,但不希望这个类是公共可用的
    2. 局部内部类

      • 在方法内部定义类
      • 局部内部类可以嵌入某个作用域内(如if作用域),则在作用域外不可访问
    3. 匿名内部类

      • 创建继承/实现自公共类/接口的匿名类的对象
      // Returning an instance of an anonymous inner class.
      
      // 普通类被当作“公共”接口来使用
      class Wrapping {
          private int i;
          public Wrapping(int x) { i = x; }
          public int value() { return i; }
      }
      
      
      public class Parcel7 {
          public Contents contents() {
              // 创建一个实现/继承自Contents的匿名类的对象,且使用默认的构造器
              return new Contents() {
                  private int i = 11;
                  public int value() { return i; }
              };
          }
      
          public Wrapping wrapping(int x) {
              // Base constructor call:
              return new Wrapping(x) {    // Pass constructor argument
                  public int value() {
                      return super.value() * 47;
                  }
              };
          }
      
          public static void main(String[] args) {
              Parcel7 parcel7 = new Parcel7();
              Wrapping wrapping = parcel7.wrapping(4);
              System.out.println(wrapping.value());
          }
      }
      
      public class Parcel9 {
          // Argument must be final to use inside
          // anonymous inner class:
          public Destination destination(final String dest) {
              return new Destination(){
                  private String label = dest;
                  @Override
                  public String readLabel() {
                      return label;
                  }
              };
          }
          public static void main(String[] args) {
              Parcel9 p = new Parcel9();
              Destination d = p.destination("Tasmania");
              System.out.println(d.readLabel());
          }
      }
      
      • 匿名内部类、局部内部类:若要使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的

      Java编译器实现的只是capture-by-value,并没有实现capture-by-reference

          interface AnnoInner(){addXYZ();}
          public class Outer {
              public AnnoInner getAnnoInner(final int x) {
                  final int y = 100;
                  return new AnnoInner(){
                      // 编译器相当于拷贝外部自由变量的副本到匿名类
                      // int copyX=x;
                      // int copyY=y;
                      int z = 100;
                      public int addXYZ() {
                          return x + y + z;
                      }
                  }
              }
          }
      

      • 利用实例初始化,以达到为匿名内部类创建一个构造器的效果
      • 注意:匿名内部类既可以扩展类,也可以实现接口,但不能同时扩展类和实现接口,且如果是实现接口,也只能实现一个接口

    嵌套类

    不需要内部类对象与其外部类对象之间有联系。

    1. 意义
      • 要创建嵌套类的对象,并不需要其外围类的对象
      • 不能从嵌套类的对象中访问非静态的外围类对象
      • 嵌套类可包含static数据和字段,但普通内部类不行
  • 相关阅读:
    Uri编码,包括javascript前端与C#服务器端
    HttpWebResponse类
    HTTP报文
    HTTP权威指南阅读记录
    XMPP通讯开发-1
    开源安卓播放器:Dolphin Player 简单分析
    Spring MVC框架
    Median of Two Sorted Arrays (找两个序列的中位数,O(log (m+n))限制) 【面试算法leetcode】
    C语言指针5分钟教程
    2013中国互联网安全大会---关于季昕华老师的分享(不喜请勿入!)
  • 原文地址:https://www.cnblogs.com/Willendless/p/11708746.html
Copyright © 2011-2022 走看看