4

In C#, I can put a type constraint on a generic parameter that requires the generic type to have a default parameterless constructor. Can I do the same in Java?

In C#:

    public static T SomeMethodThatDoesSomeStuff<T>() where T : class, new()
    {
            // ... method body ...
    }

The class and new() constraints mean that T must be a class that can be called with the new operator with zero parameters. What little I know of Java generics, I can use extends to name a required super class. Can I use that (or any other supported operation) to achieve the above functionality?

Knickedi
  • 8,742
  • 3
  • 43
  • 45
Rich
  • 36,270
  • 31
  • 115
  • 154
  • Related: http://stackoverflow.com/questions/1927789/why-should-i-care-that-java-doesnt-have-reified-generics – BalusC Sep 27 '11 at 03:15

3 Answers3

9

No; in Java the typical solution is to pass a class, and doc the requirement of 0-arg constructor. This is certainly less static checking, but not too huge a problem

/** clazz must have a public default constructor */
public static <T> T f(Class<T> clazz)
    return clazz.newInstance();
irreputable
  • 44,725
  • 9
  • 65
  • 93
3

No.

Because of type erasure, the type of <T> is not known at runtime, so it's inherently impossible to instantiate it.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 2
    Well somewhat. The problem is that contrary to C# in Java we can't specify constraints on constructors - ie specifying what kind of constructor an interface has to offer. Even with type erasure if we could do this, the above would work just fine and it would be oh so useful. Sadly it doesn't work, which means we have to use reflection to instantiate types and have to specify somewhere in the API "Has to offer argument less public constructor" - bad design flaw that. – Voo Sep 27 '11 at 02:53
  • The type erasure is not exactly a problem. The class is known at compile time so at least such a constraint, if it was present in JLS, could be enforced easily by the compiler – usr-local-ΕΨΗΕΛΩΝ Jan 26 '16 at 16:11
  • @usr-local-ΕΨΗΕΛΩΝ: Yes, but it wouldn't be very useful. – SLaks Jan 26 '16 at 16:23
  • Personally, but that's just my opinion, it would be the opposite. Yesterday we did have such a problem and with a similar constraint we could easier find it out before running the web application – usr-local-ΕΨΗΕΛΩΝ Jan 26 '16 at 16:48
0

Java does not do structural typing, so you cannot constrain T to have a particular constructor or static method. Only subtyping and supertyping restrictions are permitted.

So, pass an appropriate abstract factory. Use of reflection here, or in virtually any case, is highly inappropriate. There is now a now a suitable generic JDK type for this in the form of java.util.function.Supplier.

public static T someMethodThatDoesSomeStuff<T>(
    Supplier<T> factory
) {

Invoke as:

Donkey donkey = someMethodThatDoesSomeStuff(BigDonkey::new);

(The method reference needn't be a constructor.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305