2

我正在使用 JAVA 泛型概念测试一些小实用程序。

我尝试从一个通用的函数返回一个列表,但编译不允许我这样做。

检查下面的代码:

package com.test.generic.method;

import java.util.ArrayList;
import java.util.List;


public class Sample_3<T> {

    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 添加了这样的编译时特性?

谢谢,甘扬。

4

5 回答 5

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<String>。您的<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(){ ... }
}

例如

 List<Integer> l = new Sample_3<Integer>().getList();
 List<String> s = new Sample_3<String>().getList();
 List<Calendar> c = new Sample_3<Calendar>().getList();
于 2012-07-18T17:47:18.550 回答
3

您需要进行签名:

public List<String> testReturn()

当您<T>在方法声明中使用时,它会根据传入的参数之一告诉编译器您要在方法中使用泛型类型。因为您没有传入任何带有 type 的参数T,所以编译器无法解析T为类型。

于 2012-07-18T17:40:44.887 回答
1

您正在指定 T 列表的返回类型,但正在返回字符串列表。快速修复是:

public List<String> testReturn(){
  List<String> list = new ArrayList<String>();
  // add stuff to list;
  return list;
}

实际上,泛型的目的是允许您生成您的类(即 Sample),以便您可以创建它的新实例,但指定它为每个实例处理的对象类型。Java 在编译时检查这些泛型。以 List 为例 - 没有泛型,它不关心我放入列表中的对象 - 这意味着我可能会在没有收到警告的情况下将 Double 放入其中,并且我不知道它包含什么样的对象调用 get()。我们可以编写仅限于特定对象的新类或 List 实现——例如,StringList 只能接受字符串——但这会很耗时并且可能难以维护。相反,Java 泛型允许我们将特定列表的输入/输出限制为特定类(以及该类的任何实现) - 例如

例如生成样本:

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 类是否应该限制为处理 Strings 和 List 或者是否应该将其设为通用。

有关更多信息,请查看Java 教程

于 2012-07-18T17:50:55.990 回答
1

List<T>我认为要问的第一个问题是,当您在方法中显式创建 a 时,为什么要声明要返回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

于 2012-07-18T18:04:41.003 回答
0

我认为您将 String 对象放入 List 中,然后创建String 类型的 List

public List<String> testReturn(){
        List<String> list = new ArrayList<String>();
        list.add("Gunjan");
        list.add("Parth");
        list.add("Devang");
        return list; 
    }

泛型可以与类、方法、变量一起使用,但最重要的是使用它来使集合更加类型安全

<T>被称为TypeParameters,如果在方法中使用了this,那么就意味着,在方法中遇到带有.的参数时使用的Type就是this type T

于 2012-07-18T17:42:57.930 回答