Java知識點總結(Java泛型)
@(Java知識點總結)[Java, Java泛型]
[toc]
泛型
泛型就是引數化型別
- 適用於多種資料型別執行相同的程式碼
- 泛型中的型別在使用時指定
- 泛型歸根到底就是“模版”
優點:使用泛型時,在實際使用之前型別就已經確定了,不需要強制型別轉換。
泛型主要使用在集合中
import java.util.ArrayList;
import java.util.List;
public class Demo01 {
// 不使用泛型,存取資料麻煩
public static void test1(){
List list = new ArrayList();
list.add(100);
list.add("zhang");
/*
* 從集合中獲取的資料是Object型別,Object型別是所有型別的根類,但是在具體使用的時候需要
* 型別檢查,型別轉化,處理型別轉化異常
* 使用麻煩
*/
Object o = list.get(1);
if (o instanceof String) {
String s = (String)o;
}
System.out.println(o);
}
// 使用泛型
public static void test2(){
List<String> list = new ArrayList<String>();
//list.add(100); 放資料時安全檢查,100不是String型別,不能存放
list.add("存資料安全,取資料省心");
String s = list.get(0); //取出來的資料直接就是泛型規定的型別
System.out.println(s);
}
public static void main(String[] args) {
test1();
test2();
}
}
自定義泛型
泛型字母
- 形式型別引數(formal type parameters)即泛型字母
-
命名泛型字母可以隨意指定,儘量使用單個的大寫字母(有時候多個泛型型別時會加上數字,比如T1,T2)
常見字母(見名知意)- T Type
- K V Key Value
- E Element
- 當類被使用時,會使用具體的實際型別引數(actual type argument)代替
泛型類
- 只能用在成員變數上,只能使用引用型別
泛型介面
- 只能用在抽象方法上
泛型方法
- 返回值前面加上 <T>
/**
* 自定義泛型類
*
* 定義"模版"的時候,泛型用泛型字母:T 代替
* 在使用的時候指定實際型別
*
* @author Administrator
* @param <T>
*/
public class Student<T> {
private T javase;
//private static T javaee; // 泛型不能使用在靜態屬性上
public Student() {
}
public Student(T javase) {
this();
this.javase = javase;
}
public T getJavase() {
return javase;
}
public void setJavase(T javase) {
this.javase = javase;
}
}
/**
* 自定義泛型的使用
* 在宣告時指定具體的型別
* 不能為基本型別
* @author Administrator
*
*/
class Demo02 {
public static void main(String[] args) {
//Student<int> Student = new Student<int>(); //不能為基本型別,編譯時異常
Student<Integer> student = new Student<Integer>();
student.setJavase(85);
System.out.println(student.getJavase());
}
}
/**
* 自定義泛型介面
*
* 介面中泛型字母只能使用在方法中,不能使用在全域性常量中
*
* @author Administrator
* @param <T>
*/
public interface Comparator<T1,T2> {
//public static final T1 MAX_VALUE = 100; //介面中泛型字母不能使用在全域性常量中
//T1 MAX_VALUE;
public static final int MAX_VALUE = 100;
void compare(T2 t);
T2 compare();
public abstract T1 compare2(T2 t);
}
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
/**
* 非泛型類中定義泛型方法
* @author Administrator
*
*/
public class Method {
// 泛型方法,在返回型別前面使用泛型字母
public static <T> void test1(T t){
System.out.println(t);
}
// T 只能是list 或者list 的子類
public static <T extends List> void test2(T t){
t.add("aa");
}
// T... 可變引數 ---> T[]
public static <T extends Closeable> void test3(T...a) {
for (T temp : a) {
try {
if (null != temp) {
temp.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws FileNotFoundException {
test1("java 是門好語言");
test3(new FileInputStream("a.txt"));
}
}
泛型的繼承
/**
* 泛型繼承
*
* 保留父類泛型 ----》泛型子類
* 不保留父類泛型 -----》子類按需實現
*
* 子類重寫父類的方法,泛型型別隨父類而定 子類使用父類的屬性,該屬性型別隨父類定義的泛型
*
* @author Administrator
*
* @param <T1>
* @param <T2>
*/
public abstract class Father<T1, T2> {
T1 age;
public abstract void test(T2 name);
}
// 保留父類泛型 ----》泛型子類
// 1)全部保留
class C1<T1, T2> extends Father<T1, T2> {
@Override
public void test(T2 name) {
}
}
// 2) 部分保留
class C2<T1> extends Father<T1, Integer> {
@Override
public void test(Integer name) {
}
}
// 不保留父類泛型 -----》子類按需實現
// 1)具體型別
class C3 extends Father<String, Integer> {
@Override
public void test(Integer name) {
}
}
// 2)沒有具體型別
// 泛型擦除:實現或繼承父類的子類,沒有指定型別,類似於Object
class C4 extends Father {
@Override
public void test(Object name) {
}
}
/**
* 泛型擦除
* 類似於Object,不等於Object
* @author Administrator
*
*/
public class Demo03 {
public static void test(Student<Integer> student){
student.setJavase(100);
}
public static void main(String[] args) {
// 泛型擦除
Student student = new Student();
test(student);
Student<Object> student2 = new Student<Object>();
//test(student2); //編譯異常
}
}
萬用字元
萬用字元(Wildcards)
- T、K、V、E 等泛型字母為有型別,型別引數賦予具體的值
- ?未知型別 型別引數賦予不確定值,任意型別
- 只能用在宣告型別、方法引數上,不能用在定義泛型類上
/**
* 泛型的萬用字元 型別不確定,用於宣告變數或者形參上面
*
* 不能使用在類上 或者 new 建立物件上
* @author Administrator
*
*/
public class Demo04 {
// 用在形參上
public static void test(List<?> list) {
List<?> list2; // 用在宣告變數上
list2 = new ArrayList<String>();
list2 = new ArrayList<Integer>();
list2 = new ArrayList<Object>();
}
public static void main(String[] args) {
test(new ArrayList<String>());
test(new ArrayList<Integer>());
}
}
extends/super
上限(extends)
指定的類必須是繼承某個類,或者實現了某個介面(不是implements),即<=
- ? extends List
下限(super)
即父類或本身
- ? super List
import java.util.ArrayList;
import java.util.List;
/**
* extends:泛型的上限 <= 一般用於限制操作 不能使用在新增資料上,一般都是用於資料的讀取
*
* supper:泛型的上限 >= 即父類或自身。一般用於下限操作
*
* @author Administrator
* @param <T>
*/
public class Test<T extends Fruit> {
private static void test01() {
Test<Fruit> t1 = new Test<Fruit>();
Test<Apple> t2 = new Test<Apple>();
Test<Pear> t3 = new Test<Pear>();
}
private static void test02(List<? extends Fruit> list) {
}
private static void test03(List<? super Apple> list) {
}
public static void main(String[] args) {
// 呼叫test02(),測試 extends <=
test02(new ArrayList<Fruit>());
test02(new ArrayList<Apple>());
test02(new ArrayList<ReadApple>());
// test02(new ArrayList<Object>()); Object 不是 Fruit 的子類 ,編譯不通過
// 呼叫test03() ,測試super >=
test03(new ArrayList<Apple>());
test03(new ArrayList<Fruit>());
//test03(new ArrayList<ReadApple>()); ReadApple < apple,所以不能放入
}
}
class Fruit {
}
class Apple extends Fruit {
}
class Pear extends Fruit {
}
class ReadApple extends Apple {
}
泛型巢狀
從外向裡取
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 泛型巢狀
* @author Administrator
*
*/
public class Demo05 {
public static void main(String[] args) {
Student2<String> student = new Student2<String>();
student.setScore("優秀");
System.out.println(student.getScore());
//泛型巢狀
School<Student2<String>> school = new School<Student2<String>>();
school.setStu(student);
String s = school.getStu().getScore(); //從外向裡取
System.out.println(s);
// hashmap 使用了泛型的巢狀
Map<String, String> map = new HashMap<String,String>();
map.put("a", "張三");
map.put("b", "李四");
Set<Entry<String, String>> set = map.entrySet();
for (Entry<String, String> entry : set) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
public class School<T> {
private T stu;
public T getStu() {
return stu;
}
public void setStu(T stu) {
this.stu = stu;
}
}
public class Student2<T> {
T score;
public T getScore() {
return score;
}
public void setScore(T score) {
this.score = score;
}
}
其他
import java.util.ArrayList;
import java.util.List;
/**
* 泛型沒有多型
* 泛型沒有陣列
* JDK1.7對泛型的簡化
* @author Administrator
*
*/
public class Demo06 {
public static void main(String[] args) {
Fruit fruit = new Apple(); // 多型,父類的引用指向子類的物件
//List<Fruit> list = new ArrayList<Apple>(); //泛型沒有多型
List<? extends Fruit> list = new ArrayList<Apple>();
//泛型沒有陣列
//Fruit<String>[] fruits = new Fruit<String>[10];
//ArrayList底層是一個Object[],它放資料的時候直接放,取資料的時候強制型別轉化為泛型型別
/*public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}*/
/*E elementData(int index) {
return (E) elementData[index];
}*/
//JDK1.7泛型的簡化,1.6編譯通不過
List<Fruit> list2 = new ArrayList<>();
}
}