227
votes

Lets say I have a concrete class Class1 and I am creating an anonymous class out of it.

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

Now is there any way I could overload the constructor of this anonymous class. Like shown below

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

With something at xxxxxxxx to name the constructor?

10
It's worth reading DoubleBraceInitializationKen Kin
In case parent has constructor: stackoverflow.com/questions/20807148/…Vadzim

10 Answers

288
votes

From the Java Language Specification, section 15.9.5.1:

An anonymous class cannot have an explicitly declared constructor.

Sorry :(

EDIT: As an alternative, you can create some final local variables, and/or include an instance initializer in the anonymous class. For example:

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

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

It's grotty, but it might just help you. Alternatively, use a proper nested class :)

102
votes

That is not possible, but you can add an anonymous initializer like this:

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

  void someNewMethod() {
  }
};

Don't forget final on declarations of local variables or parameters used by the anonymous class, as i did it for anInt.

78
votes

Here's another way around the problem:

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();
    }
}
16
votes

I know the thread is too old to post an answer. But still i think it is worth it.

Though you can't have an explicit constructor, if your intention is to call the constructor of the super class, then the following is all you have to do.

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

This is an example of creating a StoredProcedure object in Spring by passing a DataSource and a String object.

So the Bottom line is, if you want to create an anonymous class and want to call the super class constructor then create the anonymous class with a signature matching the super class constructor.

3
votes

You can have a constructor in the abstract class that accepts the init parameters. The Java spec only specifies that the anonymous class, which is the offspring of the (optionally) abstract class or implementation of an interface, can not have a constructor by her own right.

The following is absolutely legal and possible:

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

If you have the possibility to write the abstract class yourself, put such a constructor there and use fluent API where there is no better solution. You can this way override the constructor of your original class creating an named sibling class with a constructor with parameters and use that to instantiate your anonymous class.

2
votes

Yes , It is right that you can not define construct in an Anonymous class but it doesn't mean that anonymous class don't have constructor. Confuse... Actually you can not define construct in an Anonymous class but compiler generates an constructor for it with the same signature as its parent constructor called. If the parent has more than one constructor, the anonymous will have one and only one constructor

2
votes

If you dont need to pass arguments, then initializer code is enough, but if you need to pass arguments from a contrcutor there is a way to solve most of the cases:

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);
2
votes

Peter Norvig's The Java IAQ: Infrequently Answered Questions

http://norvig.com/java-iaq.html#constructors - Anonymous class contructors

http://norvig.com/java-iaq.html#init - Construtors and initialization

Summing, you can construct something like this..

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;
    }
}
1
votes

It doesn't make any sense to have a named overloaded constructor in an anonymous class, as there would be no way to call it, anyway.

Depending on what you are actually trying to do, just accessing a final local variable declared outside the class, or using an instance initializer as shown by Arne, might be the best solution.

1
votes

In my case, a local class (with custom constructor) worked as an anonymous class:

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