如何用Java编写泛型方法。
在C#中我会这样做
public static T Resolve<T>()
{
return (T) new object();
}
Java中的等价物是什么?
答案 0 :(得分:11)
首先,您的C#示例是错误的;它将抛出InvalidCastException
,除非typeof(T) == typeof(object)
。您可以通过添加constraint:
public static T Resolve<T>() where T : new() {
return new T();
}
现在,这将是Java中的等效语法(或者,至少,尽可能接近):
public static <T> T Resolve() {
return (T) new T();
}
请注意声明中的T
的双重提及:一个是T
<T>
,其中参数化方法,第二个是返回类型T
。
不幸的是,上述内容在Java中不起作用。由于Java泛型的实现方式,T
的运行时类型信息不可用,因此上面给出了编译时错误。现在,你可以像这样解决这个约束:
public static <T> T Resolve(Class<T> c) {
return c.newInstance();
}
请注意需要传入T.class
。这被称为runtime type token。这是处理这种情况的惯用方法。
答案 1 :(得分:2)
正如其他评论者指出的那样,你也可以用Java做到这一点 - 尽可能在运行时创建一个强制转换异常:
@SuppressWarnings("unchecked")
public static <T> T resolve() {
return (T) new Object();
}
但是,除非您使用@SuppressWarnings
注释,否则Java的类型擦除会起作用,您将收到编译器警告。异常也会发生在其他地方:无论你试图使用它还是什么:
String s = <String>resolve();
将抛出异常。
另一方面,你可能想在C#中使用new T()
。这是你无法用Java做的。如果您需要在运行时依赖类型信息,建议的解决方法是使用Class<T>
作为类型参数。对于您的示例,这意味着您必须将其重构为此版本:
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#)
}
}
顺便说一句,您也可以使用它来摆脱前一种情况中的警告,并将运行时异常置于更合理的界限:
public static <T> T resolve(Class<T> type) {
return type.cast(new Object());
}
这段代码的行为与您给出的代码完全相同 - 包括T
与Object
不同的任何类型时发生的异常。
答案 2 :(得分:1)
试试这个http://java.sun.com/docs/books/tutorial/extra/generics/methods.html
public static <T> T Resolve()
{
return (T) new Object();
}
小心(T)
,但我不确定这是否正确。我知道通用演员会导致很多问题。我已经花了很多时间......
答案 3 :(得分:0)
你想要某种工厂:
public interface MyFactory<T> {
T newInstance();
}
然后可以将其传递到需要的地方。在您的代码中:
public static T resolve<T>(MyFactory<T> factory) {
return factory.newInstance();
}
注意:绝对没有理由使用反射!!