anonymous inner class

本文深入探讨Java中匿名内部类的使用方法,包括无参构造、带参构造、实例初始化及限制,通过具体代码示例展示如何创建和使用匿名内部类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

For example:

// innerclasses/Parcel7.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Returning an instance of an anonymous inner class

public class Parcel7 {
  public Contents contents() { // no-arg constructor
    return new Contents() { // Insert class definition
      private int i = 11;

      @Override
      public int value() {
        return i;
      }
    }; // Semicolon required, upcasting
  }

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

 when use 

$ javac innerclasses/Parcel7.java

the compile error is : 

innerclasses/Parcel7.java:2: error: cannot find symbol
  public Contents contents() {
         ^
  symbol:   class Contents
  location: class Parcel7
innerclasses/Parcel7.java:3: error: cannot find symbol
    return new Contents() { // Insert class definition
               ^
  symbol:   class Contents
  location: class Parcel7
innerclasses/Parcel7.java:15: error: cannot find symbol

    Contents c = p.contents();
    ^
  symbol:   class Contents
  location: class Parcel7
3 errors

this solution is to cd Parcel7.java current directory for compile this java source code.

The result generated three classes: Contents.class, Parcel7.class, Parcel7$1.class(anonymous inner class).

Inner class with an argument:

// innerclasses/Parcel8.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Calling the base-class constructor

public class Parcel8 {
  public Wrapping wrapping(int x) {
    // Base constructor call:
    return new Wrapping(x) { // [1]
      @Override
      public int value() {
        return super.value() * 47;
      }
    }; // [2], compiled class has similar style to Parcel7 anonymoius inner class
  }

  public static void main(String[] args) {
    Parcel8 p = new Parcel8();
    Wrapping w = p.wrapping(10);
  }
}
  • [1] We pass the appropriate argument to the base-class constructor.
  • [2] The semicolon at the end of an anonymous inner class doesn’t mark the end of the class body. Instead, it marks the end of the expression that happens to contain the anonymous class. Thus, it’s identical to the way the semicolon is used everywhere else.

Another inner class with an argument:

// innerclasses/Parcel9.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.

public class Parcel9 {
  // Argument must be final or "effectively final"
  // to use within the anonymous inner class:
  public Destination destination(final String dest) { // method parameter is final
    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");
  }
}

As long as We're assigning a field, the approach in this example is fine. But what if we must perform some constructor-like activity? We can’t have a named constructor in an anonymous class (since there’s no name). With instance initialization, we can, in effect, create a constructor for an anonymous inner class, like this:

// innerclasses/AnonymousConstructor.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Creating a constructor for an anonymous inner class

abstract class Base {
  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) {
      {
        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();
  }
}
/* Output:
Base constructor, i = 47
Inside instance initializer
In anonymous f()
*/

Here, the variable i did not have to be final. While i is passed to the base constructor of the anonymous class, it is never directly used inside the anonymous class.

Here's the "parcel" theme with instance initialization:

// innerclasses/Parcel10.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Using "instance initialization" to perform
// construction on an anonymous inner class

public class Parcel10 {
  public Destination destination(final String dest, final float price) { // note arguments are final
    return new Destination() {
      private int cost;
      // Instance initialization for each 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.395F);
  }
}
/* Output:
Over budget!
*/

Inside the instance initializer we see code that couldn’t be executed as part of a field initializer (that is, the if statement). So in effect, an instance initializer is the constructor for an anonymous inner class. However, it’s limited; we can’t overload instance initializers, so we can have only one of these constructors. Anonymous inner classes are somewhat limited compared to regular inheritance, because they can either extend a class or implement an interface, but not both. And if we do implement an interface, we can only implement one.

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/innerclasses/Parcel7.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/innerclasses/Parcel8.java

4. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/innerclasses/Parcel9.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值