229

假设我有一个具体的 Class1 类,我正在用它创建一个匿名类。

Object a = new Class1(){
        void someNewMethod(){
        }
      };

现在有什么办法可以重载这个匿名类的构造函数。如下图所示

Object a = new Class1(){
        void someNewMethod(){
        }
        public XXXXXXXX(int a){
          super();
          System.out.println(a);
        }
      };

用 xxxxxxxx 处的东西来命名构造函数?

4

10 回答 10

297

来自Java Language Specification,第 15.9.5.1 节:

匿名类不能有显式声明的构造函数。

对不起 :(

编辑:作为替代方案,您可以创建一些最终局部变量,和/或在匿名类中包含一个实例初始化程序。例如:

public class Test {
    public static void main(String[] args) throws Exception {
        final int fakeConstructorArg = 10;

        Object a = new Object() {
            {
                System.out.println("arg = " + fakeConstructorArg);
            }
        };
    }
}

这很糟糕,但它可能只会帮助你。或者,使用适当的嵌套类:)

于 2008-12-12T10:42:54.320 回答
105

这是不可能的,但您可以像这样添加一个匿名初始化程序:

final int anInt = ...;
Object a = new Class1()
{
  {
    System.out.println(anInt);
  }

  void someNewMethod() {
  }
};

不要忘记对匿名类使用的局部变量或参数的最终声明,就像我为 anInt 所做的那样。

于 2008-12-12T10:53:05.127 回答
79

这是解决问题的另一种方法:

public class Test{

    public static final void main(String...args){

        new Thread(){

            private String message = null;

            Thread initialise(String message){

                this.message = message;
                return this;
            }

            public void run(){
                System.out.println(message);
            }
        }.initialise(args[0]).start();
    }
}
于 2010-01-08T07:19:13.070 回答
20

我知道该线程太旧而无法发布答案。但我仍然认为这是值得的。

虽然你不能有一个显式的构造函数,但如果你的意图是调用超类的一个可能受保护的构造函数,那么下面就是你所要做的。

StoredProcedure sp = new StoredProcedure(datasource, spName) {
    {// init code if there are any}
};

StoredProcedure这是一个在 Spring 中通过传递 aDataSource和一个对象来创建对象的示例String

所以底线是,如果你想创建一个匿名类并想调用超类构造函数,那么创建一个签名匹配超类构造函数的匿名类。

于 2015-09-22T11:35:58.620 回答
3

是的,你不能在匿名类中定义构造是正确的,但这并不意味着匿名类没有构造函数。混淆......实际上你不能在匿名类中定义构造,但编译器会为它生成一个构造函数,其签名与其父构造函数相同。如果父级有多个构造函数,匿名将只有一个构造函数

于 2009-07-08T18:45:48.360 回答
3

您可以在接受初始化参数的抽象类中有一个构造函数。Java 规范只规定匿名类,它是(可选的)抽象类或接口实现的后代,不能拥有自己的构造函数。

以下是绝对合法和可能的:

static abstract class Q{
    int z;
    Q(int z){ this.z=z;}
    void h(){
        Q me = new Q(1) {
        };
    }
}

如果您有可能自己编写抽象类,请将这样的构造函数放在那里,并在没有更好解决方案的地方使用流畅的 API。您可以通过这种方式覆盖原始类的构造函数,使用带参数的构造函数创建一个命名的兄弟类,并使用它来实例化您的匿名类。

于 2013-01-31T12:35:08.863 回答
2

如果你不需要传递参数,那么初始化代码就足够了,但是如果你需要从一个 contrcutor 传递参数,有一种方法可以解决大多数情况:

Boolean var= new anonymousClass(){
    private String myVar; //String for example

    @Overriden public Boolean method(int i){
          //use myVar and i
    }
    public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);
于 2012-07-28T01:24:31.080 回答
2

Peter Norvig 的 Java IAQ:不常回答的问题

http://norvig.com/java-iaq.html#constructors - 匿名类构造器

http://norvig.com/java-iaq.html#init - 构造函数和初始化

总结,你可以构造这样的东西..

public class ResultsBuilder {
    Set<Result> errors;
    Set<Result> warnings;

...

    public Results<E> build() {
        return new Results<E>() {
            private Result[] errorsView;
            private Result[] warningsView;
            {
                errorsView = ResultsBuilder.this.getErrors();
                warningsView = ResultsBuilder.this.getWarnings();
            }

            public Result[] getErrors() {
                return errorsView;
            }

            public Result[] getWarnings() {
                return warningsView;
            }
        };
    }

    public Result[] getErrors() {
        return !isEmpty(this.errors) ? errors.toArray(new Result[0]) : null;
    }

    public Result[] getWarnings() {
        return !isEmpty(this.warnings) ? warnings.toArray(new Result[0]) : null;
    }
}
于 2014-11-13T15:31:47.600 回答
1

在匿名类中拥有命名的重载构造函数没有任何意义,因为无论如何都无法调用它。

根据您实际尝试执行的操作,仅访问在类外部声明的最终局部变量,或使用 Arne 所示的实例初始化程序,可能是最佳解决方案。

于 2008-12-12T13:34:39.313 回答
1

在我的例子中,一个本地类(带有自定义构造函数)作为一个匿名类工作:

Object a = getClass1(x);

public Class1 getClass1(int x) {
  class Class2 implements Class1 {
    void someNewMethod(){
    }
    public Class2(int a){
      super();
      System.out.println(a);
    }
  }
  Class1 c = new Class2(x);
  return c;
}
于 2012-05-05T19:14:34.620 回答