如何用Java编写泛型方法

时间:2010-01-10 13:33:23

标签: c# java generics

如何用Java编写泛型方法。

在C#中我会这样做

    public static T Resolve<T>()
    {
        return (T) new object();
    }

Java中的等价物是什么?

4 个答案:

答案 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());
}

这段代码的行为与您给出的代码完全相同 - 包括TObject不同的任何类型时发生的异常。

答案 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();
}

注意:绝对没有理由使用反射!!