我正在使用JAVA泛型概念测试一些小实用。
我尝试从一个通用的函数返回一个List,但是编译不允许我这样做。
检查以下代码:
package com.test.generic.method;
import java.util.ArrayList; import java.util.List;
公共类Sample_3 {
public <T> List<T> testReturn(T t) {
List<T> list = new ArrayList<T> ();
list.add(t);
return list;
}
public static void main(String a[]) {
String s = "Gunjan";
Sample_3 sample = new Sample_3<String>();
List<String> list =(List<String>) sample.testReturn(sample);
for(String ab : list){
System.out.println(ab);
}
}
}
它给出了ClassCastException。 如何从通用函数返回列表? 为什么JAVA添加了这样的编译时功能?
谢谢, Gunjan。
答案 0 :(得分:5)
The
泛型的目的是让你自由指定。所以你可以这样做:
public List<T> testReturn(T t){
List<T> list = new ArrayList<T>();
list.add(t);
return list;
}
然后允许你这样做。
List<String> a = testReturn("A");
List<Integer> b = testReturn(1);
您的代码的问题是您的方法的意图不是真正的通用 - 编写该方法以返回List&lt; String&gt;。代码中的<T>
实际上不会影响任何内容。
回答你的进一步问题 - 你写了以下内容:
public class Sample_3 {
public <T> List<T> testReturn(T t) {
List<T> list = new ArrayList<T> ();
list.add(t);
return list;
}
public static void main(String a[]) {
String s = "Gunjan";
// this is wrong - the Sample_3 class is not generic. It does not get a generic type parameter.
Sample_3 sample = new Sample_3<String>();
// this is also wrong. Since the method is generic the "T" you get is the same as the "T" that
// goes into the method. Here your String output type does not match the input type of the method,
// which you've set here as a Sample_3 object
List<String> list =(List<String>) sample.testReturn(sample);
}
您的通用参数T设置可以变化的类型。你可以在方法层面上,如上所述,或者在班级层面上做到这一点:
public class Sample_3<T> {
public List<T> getList(){ ... }
}
e.g。
List<Integer> l = new Sample_3<Integer>().getList();
List<String> s = new Sample_3<String>().getList();
List<Calendar> c = new Sample_3<Calendar>().getList();
答案 1 :(得分:3)
您需要签名:
public List<String> testReturn()
在方法声明中使用<T>
时,它会告诉编译器您希望根据传入的参数之一在方法中使用泛型类型。因为您没有传入类型为{{{ 1}},编译器无法将T
解析为类型。
答案 2 :(得分:1)
您正在指定T列表的返回类型,但是返回String列表。快速解决方法是:
public List<String> testReturn(){
List<String> list = new ArrayList<String>();
// add stuff to list;
return list;
}
实际上,泛型的目的是允许您生成类(即Sample),以便您可以创建它的新实例,但指定它为每个实例处理的对象类型。 Java在编译时检查这些泛型。以List为例 - 没有泛型,它不关心我放入列表中的对象 - 这意味着我可能会在没有得到警告的情况下放入Double,而且我不知道它包含什么类型的Object调用get()。我们可以编写限于特定对象的List的新类或实现 - 例如StringList只能接受字符串 - 但这很费时并且可能难以维护。相反,Java泛型允许我们将特定List的输入/输出限制为特定类(以及该类的任何实现) - 例如List仅接受并返回字符串。
e.g。生成样本:
public class Sample<T> {
public List<T> makeEmptyList(){
return new ArrayList<T>();
}
}
您还可以在静态方法中指定泛型,但必须将泛型类型传递给 - 作为对象或类引用:
public static <T> List<T> makeAndAddToList(T t){
List<T> list = new ArrayList<T>();
list.add(t);
return list;
}
public static <T> List<T> makeEmptyList(Class<T> clazz){
return new ArrayList<T>();
}
在您的情况下,不清楚您的Sample类是否应该限制处理字符串和列表,或者它是否应该是通用的。
有关详细信息,请查看Java tutorial。
答案 3 :(得分:1)
我认为要问的第一个问题是,当您在方法中明确创建List<T>
时,为什么要声明返回List<String>
的方法?这个例子不会通过使用泛型来购买任何东西。您是否正在尝试解决其他情况?
为了给你一个快速的教训,当Java编译你的类时,从字节码中删除泛型。那么,在你的编辑器中最初看起来像这样:
public <T> List<T> testReturn(){
}
public List<String> testReturn2(){
}
在编译为字节码后看起来像这样:
public List testReturn(){
}
public List testReturn2(){
}
这称为类型擦除。泛型的目的是允许编译时参数检查,从而在运行时删除异常。将产生运行时错误的非通用代码示例如下:
List list = new ArrayList();
list.add("Hello World");
list.add(Integer.valueOf(42));
for (int i = 0; i < list.size(); i++) {
String str = (String) list.get(i);
}
List中的String和Integer是不兼容的类型。泛型禁止这种不安全的访问/数据输入(虽然它会在你投射东西时总是相信你。)
通用的'display()'方法如下所示:
public static void main(String a[]) {
List<String> list = new ArrayList<String>();
list.add("Gunjan");
list.add("Shah");
new Sample_2().display(list);
}
public <T> void display(List<T> list) {
for (T t : list) {
System.out.println(t);
}
}
在泛型方法中使用泛型时,必须引用通用值,就好像它们是名为T
答案 4 :(得分:0)
我认为你将String对象放在List中,然后创建 String类型列表。
public List<String> testReturn(){
List<String> list = new ArrayList<String>();
list.add("Gunjan");
list.add("Parth");
list.add("Devang");
return list;
}
泛型可以与类,方法,变量一起使用,但最重要的用途可以使集合更安全类型
<T>
被称为类型参数,如果在方法中使用它,则意味着,这是在遇到带type T
的参数时在方法中使用的类型。 / p>