在C ++中,您可以在参数中指定函数的返回类型,例如:
C ++
float* myFloat = CollectionClass.ptr<float>();
int* myInt = CollectionClass.ptr<int>();
Java中是否有等效指定返回类型而不添加其他类args?
爪哇
//This doesn't work (due to type erasure)
public <T> T getDate()
{
if (T instanceof Date)
return new Date();
if (T instanceof Calendar)
return new Calendar();
}
Date myDate = getDate<Date>();
答案 0 :(得分:18)
声明一个带有签名public <T> T getDate()
的方法是完美的。
但是,实现返回所需内容的方法是不可能的。方法在运行时所做的不仅仅取决于它的类型参数,因为它不知道它的类型参数。
为了获得对此的直觉,请认识到使用泛型编写的任何代码也可以在不使用泛型的情况下等效编写,只需删除泛型参数并在适当的位置插入强制转换。这就是“类型擦除”的含义。
因此,要了解您的方法是否可以在泛型中使用,只需询问,如果没有泛型,您将如何做到这一点:
public Object getDate()
{
// what would you do here?
}
Date myDate = (Date)getDate();
如果没有Generics就无法做到,你也无法使用Generics。
C ++模板完全不同。对于模板化函数和类,C ++模板为与其一起使用的每个类型参数生成函数或类的“单独副本”。即编译器获取模板化代码并将其“复制并粘贴”到多个版本中,每个版本分开。因此,代码的每个副本都特定于某个类型的参数,因此可以在运行时使用该类型。
这就是为什么C ++模板化代码需要以源代码形式提供才能使用它 - 没有“编译”模板这样的东西。但是,在Java中,可以使用编译的泛型类。 Java中的通用类和方法不会假设它们可以使用的类型。
答案 1 :(得分:9)
好的,现在通过编辑清楚地表明代码是以T
为条件的......
不,在Java中没有任何简单的方法可以使这项工作 - 由于类型擦除,正如你的问题所提到的那样。您可以传递Class<T>
:
public <T> T getDate(Class<T> clazz)
{
// Now use clazz to work out what to do
}
...但你不能做任何,这取决于T
本身在执行时的“价值”,因为这根本就不知道。遗憾的是,泛型在Java中有些贫血:(
编辑:在编辑之前,使代码以T
...
只需要以不同方式指定类型参数:
import java.util.Date;
class Test {
public static <T> T getDate() {
return (T) new Date();
}
public <T> T getDateInstanceMethod() {
return (T) new Date();
}
public static void main (String [] args) {
Date date = Test.<Date>getDate();
// Compiles fine, but is obviously bogus.
String string = Test.<String>getDate();
// And specifying a type argument for an instance method
Test test = new Test();
date = test.<Date>getDate();
}
}
我一直更喜欢“在常规参数之前放置类型参数”方法,但是我们去...
编辑:正如rgettman指出的那样,类型推断无论如何都会为你做正确的事情,因此在很多情况下你实际上并不需要需要来指定类型参数。有时你会这样做。答案 2 :(得分:1)
使用Arrays.asList
时,有时需要指定返回类型。 Java试图根据所有参数的常见超类来“缩小”返回类型,但有时您需要特定类型。例如,
List<Number> list = Arrays.asList(1, 2, 3);
此处,Arrays.asList
返回List<Integer>
,您会收到编译错误。要让它返回List<Number>
,您必须指定泛型类型。
List<Number> list = Arrays.<Number>asList(1, 2, 3);