1. 程式人生 > >Java常用物件API——泛型

Java常用物件API——泛型

泛型

jdk1.5出現的安全機制。

好處:
1,將執行時期的問題ClassCastException轉到了編譯時期。
2,避免了強制轉換的麻煩。

<>:什麼時候用?當操作的引用資料型別不確定的時候。就使用<>。將要操作的引用資料型別傳入即可.
其實<>就是一個用於接收具體引用資料型別的引數範圍。

在程式中,只要用到了帶有<>的類或者介面,就要明確傳入的具體引用資料型別 。

泛型技術是給編譯器使用的技術,用於編譯時期。確保了型別的安全。

import java.util.ArrayList;
import java.
util.Iterator; public class GenericDemo { /** * @param args */ public static void main(String[] args) { int[] arr = new int[4]; ArrayList<String> al = new ArrayList<String>();//泛型:明確傳入的只能是String型別 al.add("abc");//public boolean add(Object obj) al.add("hahah"); // al.add(4);//al.add(new Integer(4));放不進去了
Iterator<String> it = al.iterator(); while(it.hasNext()){ String str = it.next(); System.out.println(str); } } }

執行時,會將泛型去掉,生成的class檔案中是不帶泛型的,這個稱為泛型的擦除
為什麼擦除呢?為了相容執行的類載入器。

泛型的補償:在執行時,通過獲取元素的型別進行轉換動作。使用者不必再強制轉換了。

泛型在集合中的應用

例子:

import java.util.Iterator;
import java.
util.TreeSet; import cn.itcast.p2.bean.Person; import cn.itcast.p3.comparator.ComparatorByName; public class GenericDemo2 { /** * @param args */ public static void main(String[] args) { //泛型:傳入Person類 TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName()); ts.add(new Person("lisi8",21)); ts.add(new Person("lisi3",23)); ts.add(new Person("lisi",21)); ts.add(new Person("lis0",20)); Iterator<Person> it = ts.iterator(); while(it.hasNext()){ Person p = it.next(); System.out.println(p.getName()+":"+p.getAge()); } } }
//ComparatorByName.java  這個比較器通過名稱排序
import java.util.Comparator;

import cn.itcast.p2.bean.Person;

public class ComparatorByName implements Comparator<Person> {

	@Override
	public int compare(Person o1, Person o2) {
		
		int temp = o1.getName().compareTo(o2.getName());
		return temp==0? o1.getAge()-o2.getAge(): temp;
	}

}

執行結果:(對Person物件按名稱排序)
在這裡插入圖片描述

泛型類

在jdk1.5後,使用泛型來接收類中要操作的引用資料型別。
泛型類。什麼時候用?當類中的操作的引用資料型別不確定的時候,就使用泛型來表示。

public class Tool<QQ>{//泛型類
	private QQ q;

	public QQ getObject() {
		return q;
	}

	public void setObject(QQ object) {
		this.q = object;
	}
public class GenericDefineDemo3 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		Tool<Student> tool = new Tool<Student>();
		
	    tool.setObject(new Worker());//在編譯時就報錯

		Student stu = tool.getObject();

		
	}

}

泛型方法


    public class Tool<QQ>{
	private QQ q;

	public QQ getObject() {
		return q;
	}

	public void setObject(QQ object) {
		this.q = object;
	}
	
	
	/**
	 * 將泛型定義在方法上。
	 * @param str
	 */
	public <W> void show(W str){
		System.out.println("show : "+str.toString());
	}
	public void print(QQ str){
		System.out.println("print : "+str);
	}
	
	/**
	 * 當方法靜態時,不能訪問類中定義的泛型。
	 * 如果靜態方法使用泛型,只能將泛型定義在方法上。 泛型必須寫在返回值型別的前面,靜態修飾符的後面
	 * @param obj
	 */
	public static <Y> void method(Y obj){
		System.out.println("method:"+obj);
	}
}

public class GenericDefineDemo4 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		
		Tool<String> tool = new Tool<String>();
		
		tool.show(new Integer(4));
		tool.show("abc");
		tool.print("hahah");

		Tool.method("haha");//呼叫靜態方法
		Tool.method(new Integer(9));
	}
	

}

在這裡插入圖片描述

泛型介面

public class GenericDefineDemo5 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		InterImpl in = new InterImpl();
		in.show("abc");
		
		InterImpl2<Integer> in2 = new InterImpl2<Integer>();//實現子類物件的時候才知道具體的型別
		in2.show(5);
	}
}

//泛型介面,將泛型定義在介面上。 
interface Inter<T>{
	public void show(T t);
}


class InterImpl2<Q> implements Inter<Q>{ //實現介面的時候繼續定義泛型
	public void show(Q q){
		System.out.println("show :"+q);
	}
}




class InterImpl implements Inter<String>{//實現介面,明確引數型別
	public void show(String str){
		System.out.println("show :"+str);
	}
}

泛型限定

泛型的萬用字元:? 用來代表未知型別。

演示1:?萬用字元

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class GenericAdvanceDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ArrayList<String> al = new ArrayList<String>();
		
		al.add("abc");
		al.add("hehe");
		
		ArrayList<Integer> al2 = new ArrayList<Integer>();
		
		al2.add(5);
		al2.add(67);
		
		printCollection(al);
		printCollection(al2);
	}

	/**
	 * 迭代並列印集合中元素。
	 * @param al
	 */
	public static void printCollection(Collection<?> al) {	//萬用字元的使用
	
		Iterator<?> it = al.iterator();
		
		while(it.hasNext()){

			System.out.println(it.next().toString());
		}
		
	}

}

執行結果:
在這裡插入圖片描述

演示2:? extends E (上限)

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;

public class GenericAdvanceDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//建立3個ArrayList,分別存Worker,Student,String
		ArrayList<Worker> al = new ArrayList<Worker>();
		
		al.add(new Worker("Work",30));
		al.add(new Worker("Work",34));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		
		al2.add(new Student("stu1",11));
		al2.add(new Student("stu2",22));
		ArrayList<String> al3 = new ArrayList<String>();
		
		al3.add("stu3331");
		al3.add("stu33332");
		
		printCollection(al2);
		printCollection(al);
		//printCollection(al3);編譯不通過 因為String不是Person的子類
	}

	/**
	 * 迭代並列印集合中元素。
	 * 
	 * 可以對型別進行限定:
	 * ? extends E:接收E型別或者E的子型別物件。上限!
	 * 
	 * ? super E :接收E型別或者E的父型別。下限!
	 * @param al
	 */
	public static void printCollection(Collection<? extends Person> al) {//泛型的限定 只接收Person的子類
		Iterator<? extends Person> it = al.iterator();
		
		while(it.hasNext()){

			Person p = it.next();
			
			System.out.println(p.getName()+":"+p.getAge());
		}	
	}	
}

執行結果:
在這裡插入圖片描述

演示3:? super E(下限)

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;


public class GenericAdvanceDemo2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ArrayList<Person> al = new ArrayList<Person>();
		
		al.add(new Person("Person",30));
		al.add(new Person("Person",34));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		
		al2.add(new Student("stu1",11));
		al2.add(new Student("stu2",22));
		ArrayList<String> al3 = new ArrayList<String>();
		
		al3.add("stu3331");
		al3.add("stu33332");
		
		printCollection(al2);
		printCollection(al);
		//printCollection(al3);編譯不通過 
	}
	//? super E :接收E型別或者E的父型別。下限!
	public static void printCollection(Collection<? super Student> al){
		Iterator<? super Student> it = al.iterator();
		
		while(it.hasNext()){
			
			System.out.println(it.next());
		}
	}

}

執行結果:
在這裡插入圖片描述

上限的體現

一般在儲存元素的時候都是用上限,因為這樣取出都是按照上限型別來運算的。不會出現型別安全隱患。
比如TreeSet的addAll方法:
在這裡插入圖片描述

下限的體現

什麼時候用下限呢?通常對集合中的元素進行取出操作時,可以使用下限。
例如:

class TreeSet<Worker>
 {
  		Tree(Comparator<? super Worker> comp);
  }