Java泛型02 5.自定義泛型 5.1自定義泛型類 基本語法: class 類名<T,R...>{//…表示可以有多個泛型 成員 } 註意細節: 普通成員可以使用泛型(屬性、方法) 使用泛型的數組不能初始化 靜態方法中不能使用類的泛型 泛型類的類型,是在創建類的對象時確定的(因為創建對象時,需要指 ...
Java泛型02
5.自定義泛型
5.1自定義泛型類
基本語法:
class 類名<T,R...>{//…表示可以有多個泛型
成員
}
註意細節:
- 普通成員可以使用泛型(屬性、方法)
- 使用泛型的數組不能初始化
- 靜態方法中不能使用類的泛型
- 泛型類的類型,是在創建類的對象時確定的(因為創建對象時,需要指定確定類型)
- 如果在創建對象時沒有指定類型,預設為Object
例子:
// Tiger後面有泛型,所以我們把 Tiger稱為自定義泛型類
class Tiger<T,R,M>{// T,R,M是泛型的標識符,一般是單個的大寫字母;泛型的標識符可以有多個
String name;
R r; // 普通成員可以使用泛型(屬性、方法),這裡是屬性使用泛型
M m;
T t;
// 使用泛型的數組不能初始化,因為數組在new的時候不能確定T的類型,就無法在記憶體開闢空間
T[] ts ;
public Tiger(String name) {
this.name = name;
}
public Tiger(R r, M m, T t) {// 構造器使用泛型
this.r = r;
this.m = m;
this.t = t;
}
//因為靜態是和類相關的,在來載入的時候,對象還沒有創建
//所以如果靜態方法和靜態屬性使用到泛型,JVM就無法完成初始化
//因此靜態方法和靜態屬性不能使用泛型
// static R r2;
// public static void m1(M m){
//
// }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public R getR() {
return r;
}
public void setR(R r) { // 方法使用泛型
this.r = r;
}
public M getM() { // 返回類型 使用泛型
return m;
}
public void setM(M m) {
this.m = m;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
@Override
public String toString() {
return "Tiger{" +
"name='" + name + '\'' +
", r=" + r +
", m=" + m +
", t=" + t +
", ts=" + Arrays.toString(ts) +
'}';
}
}
練習:說明自定義泛型代碼是否正確,並說明原因
package li.generic.customgeneric;
import java.util.Arrays;
public class CustomGeneric_ {
public static void main(String[] args) {
//T=Double , R=String , M=Integer
Tiger<Double,String ,Integer> g = new Tiger<>("john");//ok
g.setT(10.9);//ok
// g.setT("yy");//錯誤,類型不對
System.out.println(g);
//這裡沒有指定泛型類型,全部預設為Object類型
//T=Object , R=Object , M=Object
Tiger g2 = new Tiger("join~~");
g2.setT("yy");//ok,因為T為Object類型,“yy”為String類型,是Object的子類
System.out.println("g2="+g2);
}
}
5.2自定義泛型介面
基本語法:
interface 介面名<T,R...>{
}
註意細節:
- 介面中,靜態成員不能使用泛型(這個和泛型類的規定一樣)
- 泛型介面的類型,在繼承介面或者實現介面時確定
- 沒有指定類型,就預設為Object類
例子:
package li.generic.customgeneric;
public class CustomInterfaceGeneric {
public static void main(String[] args) {
}
}
interface IUsb<U,R>{
//U name; //這裡的介面屬性預設前面加上了static final,介面中,靜態成員不能使用泛型
//普通方法中,可以使用介面泛型
R get(U u);
void hi(R r);
void run(R r1,R r2,U u1,U u2);
//在jdk8中,可以在介面中使用預設方法,也是可以使用泛型的
default R method(U u){
return null;
}
}
// 在繼承介面時,指定泛型介面的類型
interface IA extends IUsb<String,Double>{ }
//當我們去實現IA介面時,因為IA在繼承IUsb介面時,指定了U為String類型,R為 Double類型
//因此,在實現IUsb方法的時候,使用String替換U,使用Double替換R
class AA implements IA{
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double aDouble) {
}
@Override
public void run(Double r1, Double r2, String u1, String u2) {
}
}
//實現介面時,直接指定泛型介面的類型
//給U指定了Integer,給R指定了Float
//所以當我們實現IUsb方法時,會使用Integer替換U,使用Float替換R
class BB implements IUsb<Integer,Float>{
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float aFloat) {
}
@Override
public void run(Float r1, Float r2, Integer u1, Integer u2) {
}
}
//沒有指定類型,則預設為Object
class CC implements IUsb{//等價於 class CC implements IUsb<Object,Object>{
@Override
public Object get(Object o) {
return null;
}
@Override
public void hi(Object o) {
}
@Override
public void run(Object r1, Object r2, Object u1, Object u2) {
}
}
5.3自定義泛型方法
基本語法:
修飾符 <T,R...> 返回類型 方法名(參數列表){
}
註意細節:
- 泛型方法,可以定義在普通類中,也可以定義在泛型類中
- 當泛型方法被調用時,類型會確定
public void eat(E e){}
,修飾符後面沒有<T,R...> 則eat方法不是泛型方法,只是使用了泛型
例子:
package li.generic.customgeneric;
import java.util.ArrayList;
public class CustomMethodGeneric {
public static void main(String[] args) {
Car car = new Car();
car.fly("寶馬", 100);//當調用方法時,傳入參數,編譯器就會確定類型
// class java.lang.String
//class java.lang.Integer
System.out.println("==========");
car.fly(300, 100.7);//當調用方法時,傳入參數,編譯器就會確定類型
//class java.lang.Integer
//class java.lang.Double
System.out.println("==========");
//fish的T=String,R=ArrayList
Fish<String, ArrayList> fish = new Fish<>();
fish.hello(new ArrayList(),11.3f);
//class java.util.ArrayList
//class java.lang.Float
}
}
//泛型方法,可以定義在普通的類中,也可以定義在泛型類中
class Car {//普通類
public void run() {//普通方法
}
//<T,R>就是泛型,是提供給fly方法使用的
public <T, R> void fly(T t, R r) {//泛型方法
System.out.println(t.getClass());
System.out.println(r.getClass());
}
}
class Fish<T, R> {//泛型類
public void run() {//普通方法
}
public <U, M> void eat(U u, M m) {//泛型方法
}
//說明:下麵的hi方法不是泛型方法,因為修飾符後面沒有表示符<T,R...>
//是hi方法使用了類聲明的泛型
public void hi(T t) { }
//泛型方法可以使用類聲明的泛型,也可以使用自己聲明的泛型
public <K> void hello(R r,K k){//R是類聲明的標識符,K則是方法自己聲明的標識符
System.out.println(r.getClass());
System.out.println(k.getClass());
}
}
5.4泛型方法練習
下麵代碼是否正確,如果有錯誤,修改正確,並說明輸出什麼?
package li.generic.customgeneric;
public class CustomMethodGenericExercise {
public static void main(String[] args) {
Apple<String, Integer, Double> apple = new Apple<>();//ok
apple.fly(10);//ok 10會被自動裝箱,輸出Integer
apple.fly(new Dog());//ok 輸出Dog
}
}
class Apple<T, R, M> {
public <E> void fly(E e) {//泛型方法
System.out.println(e.getClass().getSimpleName());
}
// public void eat(U u) {}//錯誤,因為U沒有聲明
public void run(M m) {
}
}
class Dog {
}