当前位置: 首页 > Thinking in Java > 正文

第10章–内部类_匿名内部类

匿名内部类,因为没有名字,所以不可能有构造方法.

因而,匿名内部类一般就只有一个实例. 

匿名内部类,只能借助于接口或者其他常规类的构造函数来实现.

匿名内部类通常作为函数的返回值或者参数.

1. 借助于接口实现的匿名内部类

public interface Contents
{
  int value();
} 

public class Parcel7
{
  public Contents contents()
  {
    
    //借助于Contents接口,创建一个匿名内部类的唯一实例
    //该实例必须要 实现 借助的 接口Contents
    return new Contents()
    { 
      private int i = 11;

      public int value()
      {
        TT();
        return i;
        
      }
      
      //改方法只能在匿名内部类内部使用
      public void TT()
      {
        
      }
    }; //这个分号不能少
    
  }

  public static void main(String[] args)
  {
    Parcel7 p = new Parcel7();
    Contents c = p.contents();
  }
} 

2. 借助于 常规类的 构造函数 生成匿名内部类的唯一对象

   这种方式生成的内部类,其实相当于把协助生成匿名内部类唯一对象的

   那个常规类当成一个接口来使用(可以使用常规类的public方法),同时生成的匿名内部类唯一实例可以使用

   那个常规类的protected方法以及friend方法(方法前面什么都不加).

   但是匿名内部类自己内部新增的public方法 不能被使用,所以这中方式 与继承也不用.

   介于 实现接口和继承之间.

//协助生成内部类唯一对象的 常规类 

public class Wrapping
{
  private int i;

  public Wrapping(int x)
  {
    i = x;
  }

  public int value()
  {
    return i;
  }
  
  //protected方法
  protected void testProtected()
  {
    System.out.println("testProtected()");
  }
  
  //friend 方法
   void testFriend()
  {
    System.out.println("testFriend()");
  }
   
   static void  testStatic()
   {
     System.out.println("testStatic()");
   }
}

当做返回值的匿名内部类.

public class Parcel8
{
  public Wrapping wrapping(int x)
  {
    // 通过借助常规类的构造函数方法实现的匿名内部类,介于继承和实现接口之间:
    return new Wrapping(x) 
    //匿名内部类 的对象 要么作为 方法返回值; 要么作为方法的参数;
    //这样 匿名内部类 总是作为一个已知的类的子类 或者 已知接口的实现类(这里 都涉及到向上转型)
    //所以 创建匿名内部类 的语法 总是 new 基类() {类定义}  或 new 接口() {类定义}
    //匿名内部类 不可能有构造器(因为匿名内部类没有名字)  所以匿名内部类只能使用 默认构造器来创建对象
    { // 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);
    w.testFriend(); //什么都不加的方法
    w.testProtected(); //protected方法
    w.testStatic(); //静态方法
  }
} 
/**
* 这里必须要传递一个参数x给构造函数的原因
* 1. 如果 类一个参数构造器都没有,则编译器会自动加一个默认构造器(即无参构造器)
* 2. 假如 类 已经有一个构造器,则编译器不会再自动加上默认构造器
* 3. 导出类的构造器必须首先要调用基类的构造器,
*    如果基类没有默认构造器(比如 上面的Wrapping 只有一个构造器Wrapping(int x)),
*    则导出类的构造器必须首先要显式的调用基类的构造器,因此上面内部类定义时必须传入参数x给
*    基类的构造器Wrapping(int x)
*  
*  总之,如果导出类的构造器没有首先显式的调用基类的构造器,则编译器会自动让导出类调用基类的默认
*  构造器,如果基类没有默认构造器,则导出类必须首先显式的调用基类的其他构造器,否则编译不通过.
*/

3. 匿名内部类中直接使用了外部的对象,比如定义匿名内部类的函数的参数,那么这个参数必须是final的.

public class Parcel9
{
  private int iTmp = 3;
  
  public Destination destination(final String dest)
  {
    return new Destination()
    {
      private String label = dest; 
      //局部内部类直接使用了 函数的参数,则参数必须为final的.
      public int iTmpInner = iTmp; 
      //局部内部类使用 外围类 字段 iTmp, iTmp 不 需要 是final的(内部类中自动拥有外围类的引用)
      
      public String readLabel()
      {
        iTmpInner++;
        return label;
      }
    };
  }

  public static void main(String[] args)
  {
    Parcel9 p = new Parcel9();
    Destination d = p.destination("Tasmania");
  }
} 

4. 匿名内部类没有构造函数,可以使用初始化块完成初始化.

 

   下面的例子中,传递给匿名内部类的参数i 不需要 是final的,因为i没有直接在匿名内部类中使用,

   而是传递给匿名内部类的基类使用.

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没有直接在匿名内部类中使用,
    //而是传递给匿名内部类的基类使用.
    {
      private int cost;
      {
        cost = 100;//匿名内部类, 初始化块中的初始化,
        System.out.println("Inside instance initializer");
      }

      public void f()
      {
        System.out.println("In anonymous f()");
      }
      
      public void g() 
      //匿名内部类,继承了基类,即使自己新增了一个方法g(),返回的唯一的匿名内部类的对象也无法使用这个新增的方法
      //所以,匿名内部类的继承 其实 相当于实现接口
      {
        System.out.println("In anonymous g()");
      }
    };
  }

  public static void main(String[] args)
  {
    Base base = getBase(47);
    base.f();
  }
}

 

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2360.html | 边城网事

该日志由 边城网事 于2013年07月22日发表在 Thinking in Java 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 第10章–内部类_匿名内部类 | 边城网事
关键字: ,

第10章–内部类_匿名内部类 暂无评论

发表评论

快捷键:Ctrl+Enter