How to write a generic method in Java.
In C# I would do this
public static T Resolve<T>()
开发者_开发技巧 {
return (T) new object();
}
Whats the equivalent in Java?
First, your C# example is wrong; it will throw an InvalidCastException
unless typeof(T) == typeof(object)
. You can fix it by adding a constraint:
public static T Resolve<T>() where T : new() {
return new T();
}
Now, this would be the equivalent syntax in Java (or, at least, as close as we can get):
public static <T> T Resolve() {
return (T) new T();
}
Notice the double mention of T
in the declaration: one is the T
in <T>
which parameterizes the method, and the second is the return type T
.
Unfortunately, the above does not work in Java. Because of the way that Java generics are implemented runtime type information about T
is not available and so the above gives a compile-time error. Now, you can work around this constraint like so:
public static <T> T Resolve(Class<T> c) {
return c.newInstance();
}
Note the need to pass in T.class
. This is known as a runtime type token. It is the idiomatic way of handling this situation.
As other commenters have pointed out, you can do this with Java as well - with as much of a possibility to create a casting exception at runtime:
@SuppressWarnings("unchecked")
public static <T> T resolve() {
return (T) new Object();
}
Unless you use the @SuppressWarnings
annotation, however, Java's type erasure comes into play and you will get a compiler warning. The exception will also occur somewhere else: whereever you are trying to use it:
String s = <String>resolve();
will throw the exception.
On the other hand, you probably wanted to use new T()
in C# anyway. This you cannot do in Java. The suggested workaround is to use Class<T>
as a type parameter if you need to rely on type information at runtime. For your example, this would mean that you have to refactor it to this version:
public static <T> T resolve(Class<T> type) {
try {
return type.newInstance();
} catch(Exception e) {
// deal with the exceptions that can happen if
// the type doesn't have a public default constructor
// (something you could write as where T : new() in C#)
}
}
By the way, you can use this also to get rid of the warning in the previous case and to place the runtime exception at a more sensible line:
public static <T> T resolve(Class<T> type) {
return type.cast(new Object());
}
This piece of code will behave exactly like the one you gave as an example - including an exception that occurs when T
is any type different from Object
.
Try this http://java.sun.com/docs/books/tutorial/extra/generics/methods.html
public static <T> T Resolve()
{
return (T) new Object();
}
Be careful about (T)
but I am not sure that this is correct. I know that generic cast causes a lot of problems. I have already spent with it a lot of time...
You want some kind of factory:
public interface MyFactory<T> {
T newInstance();
}
Then that can be passed into where it is needed. In your code:
public static T resolve<T>(MyFactory<T> factory) {
return factory.newInstance();
}
Note: There is absolutely no reason to be using reflection for this!!
精彩评论