How to create an instance of type T?

P

prowyh

I want to write a generic method that return the specified object
constructed with type parameter T and the parameter of type String.
Here is the code:

public class TTest
{
public static void main(String[] args) throws Exception
{
GClass<Integer> i = new GClass<Integer>();
int a = i.getValue("345").valueOf();

GClass<Double> d = new GClass<Double>();
double b = d.getValue("345.5").valueOf();
}
}

class GClass<T>
{
public T getValue(String p) throws Exception
{
// create and instance of type T or a Class class of type T
// construct the object with p by reflection
// return the object
}
}

well, we can do the same thing by default(T) or
Activator.CreateInstance<T>() in C#. But how can I do that in Java?

Any hints appreciated. Thanks.
 
J

Joshua Cranmer

prowyh said:
I want to write a generic method that return the specified object
constructed with type parameter T and the parameter of type String.
Wherefore?

class GClass<T>
{
public T getValue(String p) throws Exception
{
// create and instance of type T or a Class class of type T
// construct the object with p by reflection
// return the object
}
}

You'll need to modify the code here somewhat:
class GClass<T> {
private Class<T> clazz;

public GClass<T>(Class<T> clazz) {
this.clazz = clazz;
}

public T getValue(String p) throws Exception {
return clazz.getConstructor(String.class).newInstance(p);
}
}

Beware: reflection is slow.
 
D

Daniel Pitts

prowyh said:
I want to write a generic method that return the specified object
constructed with type parameter T and the parameter of type String.
Here is the code:

public class TTest
{
public static void main(String[] args) throws Exception
{
GClass<Integer> i = new GClass<Integer>();
int a = i.getValue("345").valueOf();

GClass<Double> d = new GClass<Double>();
double b = d.getValue("345.5").valueOf();
}
}

class GClass<T>
{
public T getValue(String p) throws Exception
{
// create and instance of type T or a Class class of type T
// construct the object with p by reflection
// return the object
}
}

well, we can do the same thing by default(T) or
Activator.CreateInstance<T>() in C#. But how can I do that in Java?

Any hints appreciated. Thanks.

interface Factory<T> {
T create();
}

Foo = new GClass<Foo>(new Factory<Foo>() { public T create() {return new
Foo(); } ).getValue("Bar");


You shouldn't use reflection unless you know very much what you are doing.

Also, note that Java doesn't have reified generic types, so you can't
get the Class object of your "T" parameter unless you have the caller
pass it in for you. If you can avoid it by using the idiom above
(called the factory pattern), it would be better. If you really wanted
to use reflection, then you could *also* create a ReflectionBasedFactory
<T> class that takes a Class<? extends T> object and uses reflection on
that to instantiate a class.
 
D

Daniel Pitts

Joshua said:
You'll need to modify the code here somewhat:
class GClass<T> {
private Class<T> clazz;

public GClass<T>(Class<T> clazz) {
this.clazz = clazz;
}

public T getValue(String p) throws Exception {
return clazz.getConstructor(String.class).newInstance(p);
}
}

Beware: reflection is slow.
Not *that* slow. Granted, slower than normal object instantiation, but
every Java release they seem to enhance the speed of reflection.
 
P

prowyh

Thanks for all of your responses. I'm frustrated that it is impossible
to create an instance of type T due to the type erasure of Java.

Or maybe I do not express my idea clearly. All I want is the following
class:

class InputClass
{
public <T> T getValue() throws Exception
{
String str = getInputFromConsole();
T v = null;

// v = new T(str);
// how to do this?

return v;
}
}

well, client can call InputClass's getValue() with Integer, or Double,
or something else that I don't know.

My idea is that if I can get the instance (or Class class) of type T,
I can get object v by call T's valueOf() method. If I can not get the
instance (or Class class) of type T, the class will be like:

class InputClass
{
public Integer getIntegerValue()
{
String str = getInputFromConsole();
return new Integer(str);
}

public Double getDoubleValue()
{
String str = getInputFromConsole();
return new Double(str);
}

// other getXxxValue()...
}

It's almost useless and very ugly!
 
P

Peter Duniho

Thanks for all of your responses. I'm frustrated that it is impossible
to create an instance of type T due to the type erasure of Java.

I don't understand why you wrote that. You got at least two suggestions
for how to accomplish this. I agree with Daniel that you should avoid
reflection if you can, but based on your description is seems that you
need this to work in a general case where you can't ensure that your
generic type parameter implements a specific interface (per his example).

But even in that case, Joshua's suggestion should work just fine. The
code will throw an exception unless the type being used has a constructor
that takes a string, in which case it will return a new instance of the
type, just as you're asking for.

Was there something about Joshua's suggestion you didn't understand? Did
you try using the code he posted? Is there something specific about his
suggestion that doesn't work for you?

Pete
 
S

Stefan Ram

prowyh said:
Thanks for all of your responses. I'm frustrated that it is impossible
to create an instance of type T due to the type erasure of Java.

You can move the type parameter to »InputClass«, name a
subclass and then read the actual type argument at runtime:

class B< T >{ /* ... */ }

class C extends B< java.lang.Double >{}
class D extends B< java.lang.Integer >{}
class E extends B< java.lang.Character >{}

public class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println
( ( ( java.lang.reflect.ParameterizedType )
C.class.getGenericSuperclass() ).
getActualTypeArguments()[ 0 ]); }}

class java.lang.Double

An early text expressing this idea is:

http://gafter.blogspot.com/2006/12/super-type-tokens.html

In

<[email protected]>

Ralf Ullrich presents two other ideas for the same purpose.

With reflection, you then can create instances of this type,
if they have an appropriate constructor with a string
argument.

However, I don't think I would do this, for what you want
to do.
public Double getDoubleValue()
It's almost useless and very ugly!

I believe this still is not what you actually want to achieve.

If the type of the number is given by the input, then use
a factory method, like:

Value value = getNextValue();

Where »Value« is the supertype of all possible types.

If the type of the number is given by your expectation,
then use this. For example, if you expect a double, use

Double d = getNextDouble();

If the type is given neither by the input nor by the
expectation of the source code, how is it given, then?

Java has static typing, which sometimes gets in the way and
requires some redundancy in the source code (like
»getNextDouble«, »getNextInt«, ...). This is not considered
ugly in Java. See

http://download.java.net/jdk7/docs/api/java/util/Scanner.html
http://download.java.net/jdk7/docs/api/java/util/Arrays.html

.--------------------------------------------------.
| When one has chosen Java, one wants it this way. |
'--------------------------------------------------'

Otherwise one would have chosen Ruby or so.
 
P

prowyh

Peter, maybe you can not understand what I mean.

Stefan's solution that use supertype of all possible T's can solve the
problem, but it is achieved by inheritance, not by generic.

In fact, I just want to test the ability of Java generic.

In C#, I can have a perfect solution:

// C# solution
class InputClass<T>
{
public T GetValue()
{
string str = GetInputFromConsole();

T v = default(T); // critical !!!
MethodInfo[] mis = v.GetType().GetMethods();
foreach (MethodInfo m in mis)
{
ParameterInfo[] pis = m.GetParameters();
if (m.Name == "Parse" && pis.Length == 1)
{
object[] o = {str};
v = (T)m.Invoke(v, o); // T has method Parse(string
s)
break;
}
}

return v;
}
}

so, you can make invocations as following:

InputClass<int> o = new InputClass<int>();
int k = o.GetValue();

InputClass<double> oo = new InputClass<double>();
double d = oo.GetValue();

This solution can not be achieved in Java due to its type erasure.

By the way, let's look at Jusha's solution. It can be simplified as:

GClass
{
public static <T> T getValue(Class<T> clazz) throws Exception
{
String p = getInputFromConsole();
return clazz.getConstructor(String.class).newInstance(p);
}
}

so, you can make invokcations as following:

Integer o = GClass.<Integer>getValue(Integer.class);
Double oo = GClass.<Double>getValue(Double.class);
Foo ooo = GClass.<Foo>getValue(Foo.class);

but you can not do:

Integer o = GClass.<Integer>getValue();
Double oo = GClass.<Double>getValue();
Foo ooo = GClass.<Foo>getValue();
 
D

Daniel Pitts

prowyh said:
Peter, maybe you can not understand what I mean.

Stefan's solution that use supertype of all possible T's can solve the
problem, but it is achieved by inheritance, not by generic.

In fact, I just want to test the ability of Java generic.

In C#, I can have a perfect solution:

// C# solution
class InputClass<T>
{
public T GetValue()
{
string str = GetInputFromConsole();

T v = default(T); // critical !!!
MethodInfo[] mis = v.GetType().GetMethods();
foreach (MethodInfo m in mis)
{
ParameterInfo[] pis = m.GetParameters();
if (m.Name == "Parse" && pis.Length == 1)
{
object[] o = {str};
v = (T)m.Invoke(v, o); // T has method Parse(string
s)
break;
}
}

return v;
}
}

so, you can make invocations as following:

InputClass<int> o = new InputClass<int>();
int k = o.GetValue();

InputClass<double> oo = new InputClass<double>();
double d = oo.GetValue();

This solution can not be achieved in Java due to its type erasure.

By the way, let's look at Jusha's solution. It can be simplified as:

GClass
{
public static <T> T getValue(Class<T> clazz) throws Exception
{
String p = getInputFromConsole();
return clazz.getConstructor(String.class).newInstance(p);
}
}

so, you can make invokcations as following:

Integer o = GClass.<Integer>getValue(Integer.class);
Double oo = GClass.<Double>getValue(Double.class);
Foo ooo = GClass.<Foo>getValue(Foo.class);

but you can not do:

Integer o = GClass.<Integer>getValue();
Double oo = GClass.<Double>getValue();
Foo ooo = GClass.<Foo>getValue();
However you *can* do
Integer o = GClass.getValue(Integer.class);
Foo foo = GClass.getValue(Foo.class);

What's wrong with that?
 
P

prowyh

However you *can* do
Integer o = GClass.getValue(Integer.class);
Foo foo = GClass.getValue(Foo.class);

What's wrong with that?

You are right. I *can* do
Integer o = GClass.getValue(Integer.class);

For a pair value, I *must* do
Pair<Integer, Foo> o = GClass.getValue(Integer.class, Foo.class);

So, in Java, I *must* pass T's (and U's in Pair case) Class.
This may be the final solution for the problem, though not elegant,
but this is a personal taste.

Thanks, Daniel Pitts, Joshua Cranmer, Roedy Green, Peter Duniho, and
Stefan Ram. Thanks for your postings.
 
E

Eric Sosman

prowyh said:
Thanks for all of your responses. I'm frustrated that it is impossible
to create an instance of type T due to the type erasure of Java.

Or maybe I do not express my idea clearly. All I want is the following
class:

class InputClass
{
public <T> T getValue() throws Exception
{
String str = getInputFromConsole();
T v = null;

// v = new T(str);
// how to do this?

return v;
}
}

well, client can call InputClass's getValue() with Integer, or Double,
or something else that I don't know.

How does the client make this call? That is, where in
the call does the client specify that T is an Integer or a
Double or an EnterpriseWarpEngineDiagnosticAssessmentMessage?

InputClass iclass = new InputClass();
Object thing = iclass.getValue(); // what is T?
 
P

prowyh

     How does the client make this call?  That is, where in
the call does the client specify that T is an Integer or a
Double or an EnterpriseWarpEngineDiagnosticAssessmentMessage?

        InputClass iclass = new InputClass();
        Object thing = iclass.getValue(); // what is T?
As your quoted code snippet, the client must make call like:
InputClass iClass = new InputClass();
Integer o = iclass.<Integer>getValue();

Sure, the InputClass makes nonsense, since you *can not* get instance
of T. The client should call GClass's getValue() as follows:
Integer o = GClass.getValue(Integer.class);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top