在 那些角括號是什麼東西 看過泛型(Generic)的基礎,接下來再深入探討一下。考慮你要製作一個節點物件,節點可內含的物件可以指定其型態(就如同List、Set等內含元素可指定型態),你可以使用泛型語法如下進行定義:
class Node<T> {
Node<T> next;
private T value;
T getValue() {
return value;
}
void setValue(T value) {
this.value = value;
}
}
你使用<>括住一個代表型態的名稱,之後就可以先使用該名稱來宣告變數,名稱所代表的型態是未定的,你要在建立物件時指定型態,例如指定型態為String:
public class Main {
public static void main(String[] args) {
Node<String> first = new Node<String>();
first.setValue("Justin");
first.next = new Node<String>();
first.next.setValue("momor");
}
}
在上例中,將Node定義中的T指定為String,所以getValue()傳回String,而setValue()方法可以接受String,value的型態也是String。你也可以指定別的型態:
public class Main {
public static void main(String[] args) {
Node<Integer> first = new Node<Integer>();
first.setValue(100);
first.next = new Node<Integer>();
first.next.setValue(200);
}
}
在上例中,將Node定義中的T指定為Integer,所以getValue()傳回Integer,而setValue()方法可以接受Integer,value的型態也是Integer。泛型也可以用在方法定義上,例如在 多維矩陣轉一維矩陣 的例子中,若想讓方法更一般化,則可以如下撰寫:
class ArrayUtil {
@SuppressWarnings(value={"unchecked"})
public static <T> T[] toOneByColumn(T[][] array) {
T[] arr = (T[]) Array.newInstance(
array[0].getClass().getComponentType(),
array.length * array[0].length);
for(int row = 0; row < array.length; row++) {
for(int column = 0; column < array[0].length; column++) {
arr[row + column * array.length] = array[row][column];
}
}
return arr;
}
}
public class Main {
public static void main(String[] args) {
Integer[][] arr1 = {
{1, 2, 3},
{4, 5, 6}
};
for(Integer i : ArrayUtil.<Integer>toOneByColumn(arr1)) {
System.out.println(i);
}
String[][] arr2 = {
{"one", "two", "three"},
{"four", "five", "six"}
};
for(String s : ArrayUtil.<String>toOneByColumn(arr2)) {
System.out.println(s);
}
}
}
泛型也可以用來宣告不定長度引數,例如:
public class Main {
public static void main(String[] args) {
Main.<Integer>show(1, 2);
Main.<String>show("one", "two", "three");
}
static <T> void show(T... values) {
for(T v : values) {
System.out.println(v);
}
}
}
在定義介面時,也可以使用泛型,例如在 神奇的 foreach 看過的 java.util.Iterator[E]:
package java.util;
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
Iterator[E]可以在使用時宣告A的型態,一個在 神奇的 foreach 看過的例子如下:
import java.util.*;
public class Some implements Iterable<String>{
private String[] strs;
private int index;
public Some(int length) {
strs = new String[length];
}
public void add(String element) {
strs[index++] = element;
}
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index;
public boolean hasNext() {
return index < strs.length;
}
public String next() {
return strs[index++];
}
public void remove() {
strs[index] = null;
}
};
}
}