Java泛型是Java SE 5中引入的一項改進機制,它是Java語言中的一種特殊類型,主要用於對類和方法進行泛化處理。Java泛型可以對任意類型進行泛化處理,從而使得程序的通用性更強,代碼實現更加簡潔優雅。本文將從多個方面對Java泛型做詳細的闡述。
一、JAVA中泛型的經典解釋
泛型就是參數化類型。未使用泛型時,我們通常使用Object對象來表示任何類型的數據,例如:
public static void main(String[] args) { List list = new ArrayList(); //未使用泛型 list.add("hello"); String str = (String) list.get(0); //需要強制轉換 }
在上面的例子中,我們需要將Object類型轉換為String類型,這樣不僅繁瑣,而且容易出現類型轉換異常。Java泛型的出現可以很好地解決這個問題:
public static void main(String[] args) { List<String> list = new ArrayList<>(); //使用泛型 list.add("hello"); String str = list.get(0); //不需要強制轉換 }
使用泛型後,我們可以直接獲得String類型的值,不需要進行類型轉換,代碼更加簡潔、安全可靠。
二、泛型的類型參數
Java泛型的核心概念就是泛型類型參數,即在定義類或方法時所使用的類型表示符。在Java中,泛型類型參數使用尖括弧(<…>)來表示,例如:
public class MyList<E> { private List<E> list = new ArrayList<>(); public void add(E e) { list.add(e); } public E get(int index) { return list.get(index); } }
在上面的例子中,我們定義了一個包含泛型類型參數E的類MyList,然後使用List<E>來定義類的成員變數,從而實現對泛型類型E的使用。
泛型類型參數可以用於方法中的參數、返回值和局部變數,例如:
public <T> T getValue(T t) { return t; }
在上面的例子中,我們定義了一個泛型方法getValue,使用泛型類型參數T來表示方法的參數和返回值類型。例如,調用getValue(“hello”)方法將返回字元串”hello”。
三、通配符?的使用
通配符?是Java泛型中一個比較重要的概念,它可以代表任何類型的實例,例如:
public static double sum(List<? extends Number> list) { double result = 0; for (Number num : list) { result += num.doubleValue(); } return result; }
在上面的例子中,我們定義了一個靜態方法sum,該方法接收一個List<? extends Number>類型的參數,並遍歷該列表中的所有元素,累加它們的double值,並返回累加結果。通配符?的作用在於可以適配任何類型的列表,比如List<Double>、List<Integer>等。
通配符?還可以用於上下界限定,例如:
List<? extends Number> list = new ArrayList<>(); list.add(1); //編譯報錯
在上面的例子中,我們定義了一個List<? extends Number>類型的列表,該列表不能添加任何元素,因為這違反了上界限定,而我們無法確定該列表具體是什麼類型。
四、常見泛型面試題
1. 什麼是Java泛型?
Java泛型是一種特殊的類型,可以對類和方法進行泛化處理,從而讓程序的通用性更強,代碼實現更加簡潔優雅。
2. 泛型與多態的區別是什麼?
泛型是Java SE 5中引入的一項改進機制,是一種編譯時概念,而多態是Java的基本特性,是一種運行時概念。泛型是對類型進行泛化處理,使得同一份代碼可以適應不同類型的數據,而多態是通過父類或介面來引用子類或實現類的對象,從而實現代碼的重用和靈活性。
3. Java泛型中的上下界限定有哪些?
Java泛型中的上下界限定主要有三種:
- <? extends T>:表示通配符的上界限定,代表T或T的子類。
- <? super T>:表示通配符的下界限定,代表T或T的父類。
- <T extends Comparable<T>>:表示泛型類型參數T需要實現Comparable介面。
4. 什麼是泛型擦除?
泛型擦除是Java泛型中的一種特殊機制,它是在編譯時實現的。泛型擦除的作用在於使得泛型類型參數在運行時被擦除,從而避免了在運行時對類型進行判斷的開銷。例如,在編譯後,List<String>和List<Integer>都變成了List<Object>。
5. 如何解決泛型類型擦除所帶來的問題?
為了解決泛型類型擦除所帶來的問題,Java提供了一些解決方案,例如:
- 使用泛型通配符來限制類型。
- 使用反射獲取泛型類型參數。
- 使用泛型輔助庫,例如Google的Guava庫。
五、代碼示例
下面是一個關於Java泛型的完整示例:
public class Main { public static void main(String[] args) { List<String> stringList = new ArrayList<>(); stringList.add("hello"); stringList.add("world"); System.out.println(join(stringList, ", ")); //輸出"hello, world" List<Integer> integerList = new ArrayList<>(); integerList.add(1); integerList.add(2); System.out.println(join(integerList, " + ")); //輸出"1 + 2 = 3" List<Double> doubleList = new ArrayList<>(); doubleList.add(1.2); doubleList.add(3.4); System.out.println(join(doubleList, " + ")); //輸出"1.2 + 3.4 = 4.6" } public static <E> String join(List<E> list, String separator) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < list.size(); i++) { if (i > 0) { sb.append(separator); } sb.append(String.valueOf(list.get(i))); } if (list.size() > 1) { sb.append(" = "); } if (list.size() > 0) { sb.append(String.valueOf(sum(list))); } return sb.toString(); } public static <E extends Number> double sum(List<E> list) { double result = 0; for (Number num : list) { result += num.doubleValue(); } return result; } }
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/242030.html