原文請戳此處!!!
1. 普通泛型
class Point<T>{ //此處可以隨便寫標識符號,T只是Type的簡稱
private T var; // var的類型由T指定,也就是:由外部指定
public T getVar(){ //返回值得類型也是由外部決定的
return var;
}
public void setVar(T var){ //設置的類型也由外部決定
this.var = var;
}
}
public class GenericsDemo01{
public static void main(String args[]){
Point<String> p = new Point<String>(); //此處決定了類Point<T>裏面的var類型爲String類型
p.setVar("forfan06"); //設置字符串
System.out.println(p.getVar().length()); //此處分兩步,一是取得字符串;二是獲得字符串長度
}
}
-----------------------------------------------------------------------------------------------------------
class Notepad<K, V>{ //指定了兩個泛型類型T和V,當然,此處的T和V可以換成其他字符。但是爲了方便識別,一般取一個有意義單詞的大寫首字母
private K key; // 此處的T和V均是由外部決定的
private V value;
public K getKey(){
return this.key;
}
public V getValue(){
return this.value;
}
public void setKey(K key){
this.key = key;
}
public void setValue(V value){
this.value = value;
}
}
public class GenericsDemo02{
public static void main(String args[]){
Notepad<String, Integer> t = null; //定義了兩個泛型類型的對象。
t = new Notepad<String, Integer>(); //裏面的key和value分別爲String和Integer類型。
t.setKey("飯飯"); //設置對象t的內容
t.setValue(20);
System.out.print("姓名:" + t.getKey()); //獲取對象t的屬性
System.out.println(", 年齡:" + t.getValue());
}
}
2. 通配符
class Info<T>{
private T var; //定義泛型變量,由外部決定
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){ //直接打印
return this.var.toString();
}
}
public class GenericsDemo03{
public static void main(String args[]){
Info<String> i = new Info<String>(); //使用String類型爲泛型類型
i.setVar("forfan06");
fun(i);
}
public static void fun(Info<?> info){ //此處Info<?>裏面沒有明確指明泛型類型,說明可以接受任意的泛型對象。
System.out.println("內容是:" + info);
}
}
更好的驗證通配符的作用:增加Info<Integer>如下代碼:也可以正常運行!!!
class Info<T>{
private T var; //定義泛型變量,由外部決定
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){ //直接打印
return this.var.toString();
}
}
public class GenericsDemo03{
public static void main(String args[]){
Info<String> i = new Info<String>(); //使用String類型爲泛型類型
i.setVar("forfan06");
fun(i);
Info<Integer> s = new Info<Integer>();
s.setVar(28);
fun(s);
}
public static void fun(Info<?> info){ //此處Info<?>裏面沒有明確指明泛型類型,說明可以接受任意的泛型對象。
System.out.println("內容是:" + info);
}
}
上面程序若修改爲:
class Info<T>{
private T var; //定義泛型變量,由外部決定
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){ //直接打印
return this.var.toString();
}
}
public class GenericsDemo03{
public static void main(String args[]){
Info<String> i = new Info<String>(); //使用String類型爲泛型類型
i.setVar("forfan06");
fun(i);
Info<Integer> s = new Info<Integer>();
s.setVar(28);
fun(s);
}
public static void fun(Info<T> info){ //此處Info<?>裏面沒有明確指明泛型類型,說明可以接受任意的泛型對象。
System.out.println("內容是:" + info);
}
}
則會出現編譯錯誤!!!!!!!!!!!!
GenericsDemo03.java:22: error: cannot find symbol
public static void fun(Info info){
^
symbol: class T
location: class GenericsDemo03
1 error
編譯錯誤
3. 受限泛型
上限:
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo04{
public static void main(String args[]){
Info<Integer> i1 = new Info<Integer>(); //聲明Integer類的泛型對象
Info<Float> i2 = new Info<Float>(); //聲明Float類的泛型對象
i1.setVar(27); //設置整數(小數), 自動裝箱!!
i2.setVar(10.53f);
fun(i1);
fun(i2);
}
public static void fun(Info<? extends Number> temp){ //只能接受Number類及其子類的實例!!!!
System.out.print(temp + "、");
}
}
下限:
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo04{
public static void main(String args[]){
Info<String> i1 = new Info<String>();
Info<Object> i2 = new Info<Object>();
i1.setVar("forfan06");
i2.setVar(new Object());
fun(i1);
fun(i2);
}
public static void fun(Info<? super String> temp){ //只能接收String類或其父類(Object類)類型的泛型
System.out.print(temp + "、");
}
}
4. 泛型無法向上轉型
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo05{
public static void main(String args[]){
Info<String> i1 = new Info<String>();
Info<Object> i2 = null;
i2 = i1; //此句會出錯:error: incompatible types
}
}
運行得到錯誤:
GenericsDemo05.java:17: error: incompatible types
i2 = i1; //此句會出錯:incompatible types
^
required: Info
found: Info
1 error
編譯錯誤
- 此時Info<String> i1, Info<Object> i2中,i2已經不是i1的基類了!!!所以不存在向上轉型這一說法!!!!!
5. 泛型接口
interface Info<T>{ //在接口中定義泛型
public T getVar(); //定義抽象方法,抽象方法的返回值就是泛型類型
}
class InfoImpl<T> implements Info<T>{ //定義泛型接口的子類
private T var;
public InfoImpl(T var){ //通過構造方法設置屬性內容
this.var = var;
}
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var = var;
}
}
public class GenericsDemo06{
public static void main(String args[]){
Info<String> i = null; //聲明接口對象,泛型T此時爲String類型
i = new InfoImpl<String>("forfan06"); //通過子類實例化對象
System.out.println("內容:" + i.getVar());
}
}
interface Info<T>{ //在接口中定義泛型
public T getVar(); //定義抽象方法,抽象方法的返回值就是泛型類型
}
class InfoImpl implements Info<String>{ //定義泛型接口的子類
private String var;
public InfoImpl(String var){ //通過構造方法設置屬性內容
this.var = var;
}
public String getVar(){
return this.var;
}
public void setVar(String var){
this.var = var;
}
}
public class GenericsDemo06{
public static void main(String args[]){
Info i = null; //聲明接口對象
i = new InfoImpl("forfan06"); //通過子類實例化對象
System.out.println("內容:" + i.getVar());
}
}
6. 泛型方法
聲明格式:
[訪問權限] <泛型標識> 泛型標識 方法名稱([泛型標識 參數名稱])
class Demo{
public <T> T fun(T t){ //可以接收任意類型的數據
return t; //直接把參數返回
}
}
public class GenericsDemo07{
public static void main(String args[]){
Demo d= new Demo();
String str = d.fun("forfan06");
int i = d.fun(28); //傳遞數字,自動裝箱
System.out.println(str);
System.out.println(i);
}
}
7. 通過泛型方法返回泛型類型實例
class Info<T extends Number>{ //指定上限,只能是數字類型。(只能是Number類的子類)
private T var;
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var = var;
}
public String toString(){ //覆寫Object類中的toString()方法
return this.var.toString();
}
}
public class GenericsDemo08{
public static void main(String args[]){
Info<Integer> i = fun(30);
System.out.println(i.getVar());
}
public static <T extends Number> Info<T> fun(T param){ //方法中傳入或返回的泛型類型由調用方法時所設置的參數類型決定
Info<T> temp = new Info<T>(); //根據傳入的數據類型實例化Info
temp.setVar(param); //將傳遞的內容設置到Info對象的var屬性中
return temp; //返回實例化對象
}
}
8. 使用泛型統一傳入的參數類型
class Info<T>{
private T var;
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var = var;
}
public String toString(){
return this.var.toString();
}
}
public class GenericsDemo09{
public static void main(String args[]){
Info<String> i1 = new Info<String>();
Info<String> i2 = new Info<String>();
i1.setVar("forfan06");
i2.setVar("你好!");
add(i1,i2);
}
public static <T> void add(Info<T> i1, Info<T> i2){
System.out.println(i1.getVar() + " " + i2.getVar());
}
}
9. 泛型數組
public class GenericsDemo10{
public static void main(String args[]){
Integer i[] = fun1(1, 2, 3, 4, 5, 6); //返回泛型數組
fun2(i);
}
public static <T> T[] fun1(T...arg){ //接收可變參數
return arg; //返回泛型數組
}
public static <T> void fun2(T param[]){ //輸出
System.out.println("接收泛型數組:");
for(T t:param){
System.out.print(t + "、");
}
}
}
此時運行會得到以下警告:
GenericsDemo10.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
出現上面警告是因爲用到了JAVA5.0的泛型,而5.0的泛型不做類型檢查,例如ArrayList = a new ArrayList(); a.add("hello");這樣會出現警告!解決方法有以下幾種:
- 在方法的前面加上@SuppressWarnings("unchecked")
- 聲明泛型類型,例如ArrayList<Object> a = new ArrayList<Object>();
- 使用1.4兼容JDK來編譯, javac -source 1.4 Test.java
- 也可以查看警告信息,javac Xlint:unchecked Test.java。這樣會顯示詳細的警告信息。
10. 泛型的嵌套設置
class Info<T, V>{
private T var;
private V value;
public Info(T var, V value){
this.setVar(var);
this.setValue(value);
}
public void setVar(T var){
this.var = var;
}
public void setValue(V value){
this.value = value;
}
public T getVar(){
return this.var;
}
public V getValue(){
return this.value;
}
}
class Demo<S>{
private S info;
public Demo(S info){
this.setInfo(info);
}
public void setInfo(S info){
this.info = info;
}
public S getInfo(){
return this.info;
}
}
public class GenericsDemo11{
public static void main(String args[]){
Demo<Info<String, Integer>> d = null; //將Info作爲Demo的泛型類型
Info<String, Integer> i = null; //Info指定兩個泛型類型
i = new Info<String, Integer>("forfan06", 30); //實例化Info對象
d = new Demo<Info<String, Integer>>(i); //在Demo類中設置Info類的對象
System.out.println("內容一:" + d.getInfo().getVar());
System.out.println("內容二:" + d.getInfo().getValue());
}
}
泛型方法不一定要通過參數來確定泛型準確類型,可以只通過返回值,比如:
public static <E> ArrayList<E> new ArrayList(){
return new ArrayList<E>();
}
public List<PrepaidHistory> queryHistories(Long skyid, PrepaidHistoryType type, Date from, Date end){
...
return Lists.newArrayList();
}
這樣Lists.newArrayList();
智能的知道返回類型爲PrepaidHistory