簡體   English   中英

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

[英]JAVA : How to return value in generic function

我正在用 JAVA 泛型概念測試一些小實踐。

我嘗試從通用函數返回一個 List,但 compile 不允許我這樣做。

檢查下面的代碼:

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 增加了這樣的編譯時特性?

謝謝,甘詹。

泛型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();

您需要進行簽名:

public List<String> testReturn()

當您在方法聲明中使用<T> ,它會根據傳入的參數之一告訴編譯器您要在方法中使用泛型類型。因為您沒有傳入任何類型為T參數,所以編譯器無法解析T到一個類型。

您正在指定 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 泛型允許我們將特定 List 的輸入/輸出限制為特定類(以及該類的任何實現)——例如 List 只接受並返回字符串。

例如生成樣本:

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 教程

我認為要問的第一個問題是,當您在方法中顯式創建List<String>時,為什么要聲明返回List<T>的方法? 該示例不會通過使用泛型為您購買任何東西。 您是否正在嘗試解決其他一些情況?

只是為了給您一個快速的教訓,當 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);
}

列表中的字符串和整數是不兼容的類型。 泛型禁止這種不安全的訪問/數據輸入(盡管當你投射某些東西時它總是會相信你)。

通用的“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的對象類型一樣

我認為您將 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>被稱為類型參數,如果在方法中使用 this,則表示這是方法中遇到type T的參數時要使用的type T

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM