Skip to content

Latest commit

 

History

History
217 lines (179 loc) · 5.11 KB

泛型.md

File metadata and controls

217 lines (179 loc) · 5.11 KB

泛型

介紹

  • 泛型類: 具有一個或多個類型變量的類,稱之為泛型類
class A<T> {}
  • 在創建泛型類實例時,需要為其類型變量賦值 A<String> a = new A<String>();

    • 如果創建實例時,不給類型變量賦值,那麼會有一個警告
  • 泛型方法: 具有一個或多個類型變量的方法,稱之為泛型方法

    class A<T> {
        public T fun(T t1) {}
    }

    fun() 方法不是泛型方法,他是泛型類中的一個方法 public <T> fun(T t1) {} -> 他是泛型方法

    • 泛型方法與泛型類沒甚麼關係,泛型方法不一定非要在泛型類中。
  • 泛型在類中或方法中使用

    • 泛型類中使用泛型
      • 成員類型
      • 返回值和參數類型
      • 局部變量的引用上
class A<T> {
    private T bean; //泛型可在成員變量上使用
    public T fun(T t) {} //泛型還可以在局部變量的引用類型上使用
    public void fun2() { //泛型還可以在局部變量的引用類型上使用
        T b = ...
        new T(); //不行!
    }
}
  • 泛型的繼承和實現

    class A<T> {}
    class AA extends A<String> {} //不是泛型類,父類是
    • 繼承泛型類
      • 子類不是泛型類: 需要給父類傳遞類型常量
        • 當給父類傳遞的類型常量為 String 時,那麼在父類中所有 T 都會被 String 替換
      • 子類是泛型類: 可以給父類傳遞類型常量,也可以傳遞類型變量
    class AA1<T> extends A<T> {}
    
    class AA3<E> extends A<E> {}

Example

package generic.test.demo;

import org.junit.Test;

public class Demo1 {
	@Test
	public void fun1() {
		AA3<Long> aa3 = new AA3<Long>();
	}
}

class A<T> {
	private T t;

	public T fun1() {
		return t;
	}

	public void fun2(T t) {
		this.t = t;
	}
}

class AA1 extends A<Integer> {

}

class AA2 extends A<String> {

}

class AA3<E> extends A<E> {

}

泛型的通配符

  • 通配符使用的場景: 方法的形參

  • 通配符的優點: 使方法更加通用

  • 通配符的分類: 無界通配: ? 子類限定: ? extends Object 父類限定: ? super Integer

  • 通配符卻點 使變量使用上不再方便 無界: 參數和返回值為泛型的方法,不能使用 子類: 參數為泛型的方法不能使用 父類: 返回值為泛型的方法不能使用

  • 比較通配符 boolean addAll(Collection<E> c)

    List<Number> numList = new ArrayList<Number>(); List<Integer> intList = new ArrayList<Integer>(); numList.addAll(intList); //addAll(Collection<? extends Number> c), 傳遞的是 List<Integer>

Example

package generic.test.demo;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class Demo2 {
	@Test
	public void fun1() {
		Object[] objs = new Object[10];
		List list = new ArrayList();
		
		String[] strs = new String[10];
		List<String> strList = new ArrayList<String>();
		
		Object[] objArray = new String[10];
		objArray[0] = new Integer(100); //ArrayStoreException
//		List<Object> objList = new ArrayList<String>();\
		/*
		 * 泛型引用和創建兩端,給出的泛型變量必須相同
		 */
	}
	
	public void fun2() {
		List<Integer> integerList = new ArrayList<Integer>();
		print(integerList);
		
		List<String> stringList = new ArrayList<String>();
		print(stringList);
	}
	
	/*
	 * 其中的 ? 就是通配符
	 * 通配符只能出現在左邊,即不能在 new 時使用通配符
	 */
	/*
	 * ? 表示一個不確定的類型,他的值會在調用時確定下來
	 */
	public void print(List<? extends Object> list) {
		/*
		 * 當使用通配符時,對泛型類中的參數為泛型的方法起到了副作用,不能再使用
		 */
//		list.add("hello");	
		/*
		 * 當使用通配符時,泛型類中返回值為泛型的方法也作廢了
		 */
		Object s = list.get(0);
		/*
		 * 通配符好處,可以使泛型類型更加通用,尤其是在方法調用時形參使用通配符
		 */
	}
	
	@Test
	public void fun3() {
		List<Integer> intList = new ArrayList<Integer>();
		print1(intList);
		
		List<Long> longList = new ArrayList<Long>();
		print1(intList);
	}
	
	/*
	 * 給通配符添加了限定
	 *  只能傳遞 Number 或其子類型
	 *  子類通配對通用性產生了影響,但使用了形參更加靈活
	 */
	public void print1(List<? extends Number> list) {
//		list.add(new Integer(100));
		/*
		 * 返回值為泛型的方法
		 */
		Number number = list.get(0);
	}
	
	@Test
	public void fun4() {
		List<Integer> intList = new ArrayList<Integer>();
		print2(intList);
		
		List<Number> numList = new ArrayList<Number>();
		print2(numList);
		
		List<Object> objList = new ArrayList<Object>();
		print2(objList);
	}
	
	/*
	 * 給通配符添加了限定
	 * 	只能傳遞Integer類型,或其父類型
	 */
	public void print2(List<? super Integer> list) {
		/*
		 * 參數為泛型的方法可以使用
		 */
		list.add(new Integer(100));
		/*
		 * 返回值為泛型的方法,還是不能使用
		 */
		Object obj = list.get(0);
	}
}