Accessing constructor of an anonymous class
Asked Answered
I

10

237

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?

Involutional answered 12/12, 2008 at 10:34 Comment(2)
It's worth reading DoubleBraceInitializationVase
In case parent has constructor: #20807648Dingbat
M
311

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 :)

Morven answered 12/12, 2008 at 10:42 Comment(8)
Arne, i believe him he didnt copy it. he knows enough of java to be fair enough to give credit when he would have copied it i think.Halfwitted
OMG, did someone blamed THE Jon Skeet for copying?Regnal
How would I be able to call a method in the superclass of Test from within println, when that method is overridden?Faceharden
@Zom-B: It's not clear exactly what you mean - I suspect it's worth you asking a new question with an example of what you're trying to achieve.Morven
ah, I wanted to override the superclass constructor... then I understood that no explicitly declared ctor means no overriding whatsoever, too. I suppose.Ricoriki
Is there a reason why the variable had to be final?Fledgy
@banarun: Yes - because otherwise it couldn't be used in an anonymous inner class. Now as of Java 8, local variables can be "effectively final" so this would still work in Java 8 without being explicitly final... but you still couldn't change it afterwards.Morven
@user..maybe arne blamed Jon first so that people dont think he copied it from Jon..i'm not saying he copied it, but he could've said it to protect himselfTeresiateresina
M
110

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.

Mertiemerton answered 12/12, 2008 at 10:53 Comment(1)
It's actually very much like a constructor. I can access protected members of an abstract base class. Everything else can be done in code before instantiating of the anonymous class.Speciosity
D
88

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();
    }
}
Dr answered 8/1, 2010 at 7:19 Comment(5)
Nice solution, but the use of Thread here makes it somewhat misleading at first (for a moment I thought you were created a separate thread to initialize stuff!)Pugh
Note that after t is defined you can't call t.initialise() unless this function is defined in the class/interface type.Vociferous
@AramKocharyan That makes it work even more like a constructor.Engird
I love this solution! It makes it obvious that the initialise() method is called after the Thread constructor. It was (at least to me) on the other hand not obvious that with the instance initializer this is always guaranteed.Taeniafuge
similar to java - How to pass parameters to anonymous class? - Stack OverflowEngender
P
22

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 a, possibly protected, 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.

Perfectionist answered 22/9, 2015 at 11:35 Comment(0)
H
3

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

Hsinking answered 8/7, 2009 at 18:45 Comment(0)
E
3

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.

Exaggerated answered 31/1, 2013 at 12:35 Comment(1)
(raison detre of anonymous classes) How to have that code within a function?Abbreviated
C
2

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);
Calamanco answered 28/7, 2012 at 1:24 Comment(1)
If I understand your code anonymousClass should inherit from String (setVar is type of String and returns this), but String is not extendable. I guess setVar should return what anonymousClass extends from.Intratelluric
S
2

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;
    }
}
Sipple answered 13/11, 2014 at 15:31 Comment(1)
I didn't know Peter Norvig, a Scientific of Google, it is probably one of his early work, it is about java 1.1! Interesting on an historic point of view :)Conquer
D
1

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.

Dorchester answered 12/12, 2008 at 13:34 Comment(2)
The language could easily turn the "normal" constructor arguments into arguments for the anonymous class, if desired. The syntax for the constructor declaration would probably look pretty weird though...Morven
couldn't it just say to declare the constructor like if it were the base class constructor? i don't see problems with thatHalfwitted
A
1

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;
}
Aerodonetics answered 5/5, 2012 at 19:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.