泛型(類型參數):泛型設計編寫代碼意味着代碼可以被不同類型的對象重用,【個人理解:將類型參數化,實際調用類型由實例化對象或方法調用的對象爲準】
泛型基礎定義演示:
package Generic;
/**
* 測試泛型,泛型擦除 屬性類型: 子類中由子類確定。 基類中由基類確定 方法重寫: 隨基類確定
*
* @author Administrator
*
*/
public class GenericTest {
public static void main(String[] args) {
// 創建中學類
Middle<String, String> middle = new Middle<>();
// see方法需要傳入String對象
middle.see("中學生在看");
// 查看屬性id是String類型,子類中屬性由子類類型
middle.getId();
Primary<String, String> primary = new Primary<>();
// Priamry類進行了類型擦除,see方法需要傳入Object對象,重寫的方法由基類確定
primary.see("小學生在看");
// 查看屬性id是String類型
primary.getId();
// 調用泛型方法,傳入一個字符串,確定了泛型方法的類型
Exam exam = new Exam();
exam.exam("exam");
Middle<Object, Object> middleMath = new Middle<Object, Object>();// 使用Object類替換類型
Middle middleMathTest = new Middle();// 泛型擦除後,使用Object替換,但是不會進行類型檢查,所以傳入的不會報錯
// exam.examMath(middleMath);
// 報錯,需要的是參數類型是String類型的中學生類型,但是傳入的是參數類型是Object類型的學生類型
exam.examMath(middleMathTest);
Student<String, Student> ploymorphic = new Middle<String, Student>();
// 泛型:類型參數不能使用多態,報錯
// Student<String,Student> ploymorphicone = new Middle<String,Middle>();
Middle<String, String> array = new Middle<String, String>();
// 泛型不能使用數組,但是可以聲明泛型數組,若需要賦值,需要類型轉換
// Middle<String, String>[] array = new Middle<String,String>[] ();
String[] str = new String[] {"a","b","c"};
//如果需要使用泛型數組功能選用類型轉換
Array<String> array1 = new Array<String>(str);
int length = array1.arry.length;
System.out.println(length);
}
}
class Exam {
/**
* 泛型方法的定義
*
* @param stu
* 傳入界定參數
*/
public <T> void exam(T stu) { // 泛型方法
System.out.println("這是一次測試");
}
public void examMath(Middle<String, String> stu) { // 泛型方法
System.out.println("這是一次測試");
}
}
class Array<T> {
Object[] arry = new Object[10];
/**
* 構造器傳入指定類型的參數類型的數組,將產生一個Array實例的對象,其arry屬性是指定類型的數組,可以設置方法調用
* @param arry
*/
@SuppressWarnings("hiding")
public <T> Array(T[] arry) {
this.array();
}
/**
* 使用Object類接受輸入類,將其強制轉換成相應的類型
* @return強制轉型返回函數類型
*/
@SuppressWarnings("unchecked")
private T array(){
return (T)this.arry;
}
}
泛型類定義:
ackage Generic;
/**
* 泛型類,使用類型變量T,T1 ,定義爲基類【抽象類】
*
* @author Administrator
*
* @param <T>
* @param <T1>
*/
public abstract class Student<T, E> {
private T name; // 引用泛型類型,聲明屬性
public Student() { // 空構造器
}
public Student(T name) {// 帶參構造器
super();
this.name = name;
}
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
/*泛型方法
public abstract void run(T obj);// 抽象方法
public abstract <E> String see(E obj);// 抽象方法,帶泛型抽象方法
}
泛型方法定義:
泛型變量的限定:
泛型類的繼承:
package Generic;
/**
*
* 繼承泛型Man,Man未進行泛型擦除
*
* @author Administrator
*
* @param <T>泛型:【參數類型】
* @param <T1>泛型:【參數類型】
*/
public class Middle<T, E> extends Student<T, E> {
private T id;
public Middle() { // 空構造器
}
public Middle(T id) {// 帶參構造器
super();
this.id = id;
}
public Middle(T id, T name) {// 帶參構造器
super(name);
this.id = id;
}
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
@Override
public void run(T obj) {// 重寫run方法
System.out.println(obj);
}
@SuppressWarnings("hiding")
@Override
public <E> String see(E obj) {// 重寫see方法
System.out.println(obj);
return null;
}
}
泛型擦出:
package Generic;
/**
* 繼承泛型類Man,但是基類進行泛型擦除後,若泛型沒有進行泛型限定,會用默認用Object類替換類型變量.
*
* @param id學生的id
* @param name學生的姓名
*/
class Primary<T, E> extends Student{
private T id;
public Primary() {
}
public Primary(T id) {
super();
this.id = id;
}
@SuppressWarnings("unchecked")
public Primary(T id, T name) {
super(name);
this.id = id;
}
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
public void run(Object obj) {// 重寫run方法,Man類進行了泛型擦除,因無限定,提供一個自動類型:Obeject
System.out.println(obj);
}
@Override
public String see(Object obj) { // 重寫run方法,Man類進行了泛型擦除,因無限定,提供一個自動類型:Obeject
// TODO Auto-generated method stub
return null;
}
}
泛型橋方法的使用(當使用泛型擦除後,子類對父類繼承的方法存在兩個一個是Object類型替換的,還有一個是子類本身泛型參數定義的參數,需要在父類繼承繼承方法重寫,將兩個方法合併):
泛型調用遺留代碼:
泛型的約束和侷限性: