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

JAVA:如何在泛型函数中返回值,java,generics,Java,Generics,我正在用JAVA泛型概念测试一些小的实践 我试图从一个泛型函数返回一个列表,但compile不允许我这样做 检查以下代码: package com.test.generic.method; 导入java.util.ArrayList; 导入java.util.List; 公共类样本3{ 公共列表测试返回(T){ List=newarraylist(); 列表。添加(t); 退货清单; } 公共静态void main(字符串a[]{ 字符串s=“Gunjan”; 样本_3样本=新样本_3(); L

我正在用JAVA泛型概念测试一些小的实践

我试图从一个泛型函数返回一个列表,但compile不允许我这样做

检查以下代码:

package com.test.generic.method;
导入java.util.ArrayList;
导入java.util.List;
公共类样本3{
公共列表测试返回(T){
List=newarraylist();
列表。添加(t);
退货清单;
}
公共静态void main(字符串a[]{
字符串s=“Gunjan”;
样本_3样本=新样本_3();
List=(List)sample.testReturn(sample);
for(字符串ab:列表){
系统输出打印LN(ab);
}
}
}
它给出了
ClassCastException

如何从泛型函数返回列表? 为什么JAVA添加了这样的编译时特性

谢谢,
Gunjan.

您需要签名:

public List<String> testReturn()
公共列表testReturn()

当您在方法声明中使用
时,它会告诉编译器您希望基于传入的一个参数在方法中使用泛型类型。因为您没有传递任何类型为
T
的参数,编译器无法将
T
解析为类型。

我认为您正在将字符串对象放入列表中,然后创建类型字符串的列表

public List<String> testReturn(){
        List<String> list = new ArrayList<String>();
        list.add("Gunjan");
        list.add("Parth");
        list.add("Devang");
        return list; 
    }
公共列表testReturn(){
列表=新的ArrayList();
列表。添加(“Gunjan”);
列表。添加(“第方”);
列表。添加(“德旺”);
退货清单;
}
泛型可以与类、方法、变量一起使用,但它的最重要的用途是使集合更加类型安全


称为类型参数,如果在方法中使用该参数,则意味着,当遇到类型为T
的参数时,该类型将在方法中使用。因此,您可以执行以下操作:

public List<T> testReturn(T t){
        List<T> list = new ArrayList<T>();
        list.add(t); 
        return list; 
    }
公共列表testReturn(T){
列表=新的ArrayList();
列表。添加(t);
退货清单;
}
这将允许您执行以下操作:

List<String> a = testReturn("A");
List<Integer> b = testReturn(1);
List a=testReturn(“a”);
列表b=测试返回(1);
代码的问题在于,方法的意图并不是真正的泛型——编写该方法是为了返回一个列表。代码中的
实际上不会影响任何东西

回应你的进一步质询— 您已经编写了以下内容:

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);

}
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);
}
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);
    }
}
公共类示例\u 3{
公共列表测试返回(T){
List=newarraylist();
列表。添加(t);
退货清单;
}
公共静态void main(字符串a[]{
字符串s=“Gunjan”;
//这是错误的-示例_3类不是泛型的。它没有获取泛型类型参数。
样本_3样本=新样本_3();
//这也是错误的,因为方法是泛型的,所以得到的“T”与得到的“T”相同
//进入方法。此处字符串输出类型与方法的输入类型不匹配,
//您在这里将其设置为示例_3对象
List=(List)sample.testReturn(sample);
}
您的泛型参数T设置可以变化的类型。您可以在方法级别(如上所述)或类级别执行此操作:

public class Sample_3<T> {
   public List<T> getList(){ ... }
}
公共类示例\u 3{
公共列表getList(){…}
}
e、 g

List l=新样本_3().getList();
列表s=新样本_3().getList();
列表c=新样本_3().getList();

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

public List<String> testReturn(){
  List<String> list = new ArrayList<String>();
  // add stuff to list;
  return list;
}
公共列表testReturn(){
列表=新的ArrayList();
//在列表中添加内容;
退货清单;
}
实际上,泛型的目的是允许您泛化类(即示例)因此,您可以创建它的新实例,但指定它为每个实例处理什么类型的对象。Java在编译时检查这些泛型。以列表为例—没有泛型,它不关心我将哪些对象放入列表—这意味着我可能会在没有得到警告的情况下放入一个Double,并且我不知道是什么类型的O调用get()时包含的对象。我们可以编写新的类或列表实现,这些类或实现仅限于特定对象(例如,StringList只能接受字符串),但这将非常耗时,并且可能很难维护。相反,Java泛型允许我们将特定列表的输入/输出限制为特定类(以及该类的任何实现)-例如,List只接受和返回字符串

e、 g.要使样本通用化:

public class Sample<T> {
  public List<T> makeEmptyList(){
    return new ArrayList<T>();
  }
}
公共类示例{
公共列表makeEmptyList(){
返回新的ArrayList();
}
}
也可以在静态方法中指定泛型,但必须将泛型类型作为对象或类引用传入:

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>();
}
publicstaticlist-makeAndAddToList(T){
列表=新的ArrayList();
列表。添加(t);
退货清单;
}
公共静态列表makeEmptyList(类clazz){
返回新的ArrayList();
}
在您的例子中,不清楚您的示例类是否应该限制为处理字符串和列表,或者是否应该将其设置为泛型


要了解更多信息,请查看。

我认为要问的第一个问题是,当您在方法中显式创建
列表时,为什么要声明返回
列表的方法?该示例不会通过使用泛型为您带来任何好处。您是否正在尝试解决其他情况

为了给您上一课,当Java编译类时,会从字节码中删除泛型。因此,在编辑器中最初可能是这样的:

public <T> List<T> testReturn(){
}
public List<String> 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);
}
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);
    }
}