1

I'm looking for a way to return a new instance of a type which extends an abstract class in Java, ideally without reflection from a static method.

So I want be able to call:

SomeClass anInstanceOfSomeClass = Builder.build<SomeClass>()

I hoped I could do something like:

public class Builder {

    public static <T extends SomeBaseClass> T build() {                             
        return new T(); // cannot instantiate type T            
    }

}

I've seen a few examples using Supplier but they tend to be based on either a non static, using a generic class rather than a method and/or require passing in the ctor as a param which seems a bit more complex syntactically.

Feels like this should be simple but coming from C# I'm not too familiar with the best way to achieve this in Java. Any thoughts appreciated.

dougajmcdonald
  • 19,231
  • 12
  • 56
  • 89
  • Generic types like `T` are compile time only, not runtime. Because of that it will not be able to be accessed after compilation. – James Conway Jan 11 '19 at 08:02
  • A) I suggest you do some research about java generics to understand its limitations B) you also want to read about java naming conventions, method names go camelCase() C) remind yourself about that "research prior asking questions" thing ;-) – GhostCat Jan 11 '19 at 08:11
  • @GhostCat Hello, for me it is not really a duplicate. That is much simpler than referenced duplicates. While there is probably a better dup but still we have to find it ;) – davidxxx Jan 11 '19 at 08:15
  • 1
    Question is closed. So here a comment as answer. I think that what you are looking for is : `public static T build(Supplier supplier) { return supplier.get(); }` And use it such as : `SomeClass anInstanceOfSomeClass = Builder.build(SomeClass::new);` – davidxxx Jan 11 '19 at 08:26
  • @davidxxx aha! this is the version I was looking for, thanks. Feel free to pop it down as the answer – dougajmcdonald Jan 11 '19 at 09:06
  • @GhostCat A) yes I'm trying to do that hence the question. B) agreed, but not really the focus of the question. C) That I have done, but as davidxxx mentions, both the docs and the other SO questions I've found are more complex. Or don't address the desire to have a static method, or expect the class not the method to be generic, or use reflection. – dougajmcdonald Jan 11 '19 at 09:14
  • @GhostCat for example, the accepted answer here uses reflection https://stackoverflow.com/questions/1090458/instantiating-a-generic-class-in-java there is no accepted answer here and the versions using supplier (which is what I wanted) assume a non static implementation https://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java – dougajmcdonald Jan 11 '19 at 09:17
  • Well. If you really have to trouble turning a that one supplier example into one that uses static... then I think you are overburdening yourself at this point. – GhostCat Jan 11 '19 at 09:36

2 Answers2

2

You would have to pass actual class you want to create. T becomes Object on runtime so JVM would have no idea what type it should create (just hypothetically)

public static <T extends SomeBaseClass> T build(Class<T>clazz) {                             
         return clazz.newInstance();
    }

And the call would be as simple as you would expect

SomeClass anInstanceOfSomeClass = Builder.build(SomeClass.class);

Stick to Java's naming convention (ClassName and methodName)

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • The question asks without reflection. Note also that `newInstance()` is deprecated At last I think that Supplier would make things much simpler (exception handling for example that you don't show here). – davidxxx Jan 11 '19 at 08:22
  • This is I think the neatest solution I've seen thus far, albeit using the `newInstance()` method – dougajmcdonald Jan 11 '19 at 09:05
  • @davidxxx what would be an alternative? Collection of class specific suppliers ?? :( – Antoniossss Jan 11 '19 at 09:11
  • Ahh just checked and I can see it will be just depracated in favor of getConstructor().newInstance() - not much of a change (fortunetly) ;) – Antoniossss Jan 11 '19 at 09:13
  • @Antoniossss Why a collection of class ? We don't need to refer class in the param of it is conveyed by the inference of the declared type of the the variable. – davidxxx Jan 11 '19 at 09:15
  • @davidxxx ye I can see your answer and I like it. Didnt think of constructor reference as a supplier. – Antoniossss Jan 11 '19 at 09:16
2

Supplier is fine here :

public static <T extends SomeBaseClass> T build(Supplier<T> supplier){ 
   return supplier.get(); 
} 

It avoids reflection and exception handling.

And use it such as :

SomeClass anInstanceOfSomeClass = Builder.build(SomeClass::new); 
davidxxx
  • 125,838
  • 23
  • 214
  • 215