8
votes

Consider the following constructor for the class Foo (which for the sake of clarity is not a generic class):

public <T> Foo(T obj) { }

This is valid syntax for constructors, just like with normal generic methods.

But what is the use of this syntax? Typically generic methods provide type safety for their return type, and can benefit from type inference by the compiler. For example:

Pair<String, Integer> stringInt = Pair.of("asfd", 1234);

But a call to a constructor always returns an instance of its declaring class, so its type parameters have no effect on the return type. The constructor above could just be replaced with its erasure:

public Foo(Object obj) { }

Of course generics aren't only about type safety for return types. The constructor might just want to constrain the type of argument(s) being passed in. However, the above reasoning still applies for a bounded type parameter:

public <N extends Number> Foo(N number) { }

public Foo(Number number) { } //same thing

Even nested type parameters with bounds are handled using wildcards:

public <N extends Number, L extends List<N>> Foo(L numList) { }

public Foo(List<? extends Number> numList) { } //same thing

So what is a legitimate use case for having a generic constructor?

5

5 Answers

6
votes

Here's a possible one, adapted from functional programming. Suppose we have a Stream type that has some internal state, repeatedly yielding new elements until it returns null. The outside callers don't care what the internal state type of the stream type is, so you might get something like

class Stream<E> {
  <S> Stream(S initialState, StepFunction<E, S> stepFun) {
    ...
  }
}

without the recipient having to know what the internal state type is.

5
votes

One thing I can think off of the top of my head is that you can ensure that bounds are fulfilled in the same way across multiple parameters.

Take an obviously stupid and contrived but valid constructor that copies a list from a source to a target:

public <T> Foo (List<T> listA, List<T> listB) {
    listA.addAll(listB);
}

Using wildcards here would quickly become pretty nasty and probably not do what you want anyway. It would also be a totally arbitrary restriction to disallow it. So it makes sense to me that the language spec allows it.

2
votes

One use case that I can think of is when you want to constrain a constructor argument to more than one type. Only the generic syntax allows you to declare a constructor taking a List of Numbers that also implements RandomAccess:

public <L extends List<? extends Number> & RandomAccess> Foo(L raNumList) { }

...

Foo f1 = new Foo(new ArrayList<Integer>());
Foo f2 = new Foo(new LinkedList<Integer>()); //compiler error
1
votes

You can enforce certain constraints for the constructor parameters. E.g. the following code requires two parameters which implement the interfaces InterfaceA and InterfaceB.

<T extends InterfaceA & InterfaceB > Foo(T t1, T t2) {

}
1
votes

The main use is to ensure that type constraints are met between multiple parameters. Here's an example that puts a bunch of components on an assembly line in the right order:

public <T> AssemblyLine(T[] starting, List<T> components) {
  T[] a = components.toArray(starting);
  Arrays.sort(a);
  this.conveyorBelt.add(a);
}

Here the <T> ensures that T[] and List<T> hold the same type T, and not (say), Integer[] and List<string>.