JAVA:如何在泛型函数中返回值

时间:2012-07-18 17:38:44

标签: java generics

我正在使用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。

5 个答案:

答案 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>