Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generic constructors syntax and purpose

Tags:

java

generics

Java constructors can be generic: http://docs.oracle.com/javase/tutorial/java/generics/methods.html

However I can't find a good example of how to declare and invoke generic constructor. Moreover I don't understand the purpose of generic constructor as type parameter's scope is limited to constructor.

Having class with generic constructor:

public class MyClass {

    public <T> MyClass(T data) {
        // ...
    }

}

we invoke it as:

MyClass obj = new <Integer>MyClass(12);

So my questions are:

  1. What is the purpose of generic constructor? Can you show an example from JDK or your own example?

  2. Why statement like

    Integer val = new <String>Integer(100);
    

is compiled without error even when class Integer doesn't have generic constructor?

like image 787
ako Avatar asked Oct 04 '14 14:10

ako


1 Answers

One purpose of a generic constructor can be the same as for some generic methods: To make sure that several arguments refer to the same type.

Consider the following example (yes, it's a bit contrived, but should show the point) :

import java.util.ArrayList;
import java.util.Collection;

public class GenericConstructorTest 
{
    public static void main(String[] args)
    {
        Collection<String> strings = new ArrayList<String>();
        ClassWithParam c0 = new <String>ClassWithParam("String", strings);
    }
}

class ClassWithParam
{
    public <T> ClassWithParam(T data, Collection<T> collection) 
    {
        collection.add(data);
    }
}

It does not matter for the class or its constructor which type exactly is used there. It's only important to know that the collection that was given as the second argument can take elements of the type that was given as the first argument.

(I'd like to show a more realistic, practical example, but think that it's rather rarely necessary to parameterize a constructor this way, and one could even consider that this is just a "side effect" of the possibility to parameterize methods, and the fact that there is no reason to explicitly disallow this for constructors...)


EDIT As per request in the comment, and example where the given arguments are atually used. It's still rather contrived. More realistic examples could be structurally similar and refer to some sorts of listeners, but would involve much more code:

public class GenericConstructorTest 
{
    public static void main(String[] args)
    {
        Callback<String> callback = new Callback<String>();
        ClassWithParam c0 = new <String>ClassWithParam("String", callback);
        c0.execute();
    }
}

class ClassWithParam
{
    private Runnable runnable;

    public <T> ClassWithParam(final T data, final Callback<T> callback) 
    {
        runnable = new Runnable()
        {
            @Override
            public void run()
            {
                callback.call(data);
            }
        };
    }

    void execute()
    {
        runnable.run();
    }
}

class Callback<T>
{
    void call(T t)
    {
        System.out.println("Called with "+t);
    }
}

The second example that you posted

Integer val = new <String>Integer(100);

does not compile in Eclipse with Java 7. It complains

The constructor Integer(int) of type Integer is not generic; it cannot be parameterized with arguments

In Java 8, this is allowed, although it still issues a warning:

Unused type arguments for the non generic constructor Integer(int) of type Integer; it should not be parameterized with arguments

(If this difference is what you're actually interested in, you might consider asking this as a separate question)

like image 73
Marco13 Avatar answered Nov 05 '22 09:11

Marco13