Java學習總結:21

泛型

泛型的引出

例:向下轉型的錯誤示範

package Project.Study.Genericity;

class Point{					//定義座標類
    private Object x;			//可以保存任意數據
    private Object y;			//可以保存任意數據

    public Object getX() {
        return x;
    }

    public Object getY() {
        return y;
    }

    public void setX(Object x) {
        this.x = x;
    }

    public void setY(Object y) {
        this.y = y;
    }
}
public class Test {
    public static void main(String args[]){
        Point p=new Point();				//實例化Point類數據
        p.setX("東經100度");				//設置座標數據
        p.setY(10);							//設置座標數據
        System.out.println("x座標:"+p.getX()+"y座標"+p.getY());
        //根據設置好的座標取出數據進行操作
        String x=(String)p.getX();			//取出座標數據
        String y=(String)p.getY();			//取出座標數據
        System.out.println("x座標:"+x+"y座標"+y);
    }
}
//結果
//Exception in thread "main" java.lang.ClassCastException: class //java.lang.Integer cannot be cast to class java.lang.String //(java.lang.Integer and java.lang.String are in module java.base of //loader 'bootstrap')
//	at Project.Study.Genericity.Test.main(Test.java:30)
//x座標:東經100度y座標10

例:使用泛型減少轉型操作

package Project.Study.Genericity;
//此時的T在Point類定義上只表示一個標記,在使用時需要爲其設置具體的類型
class Point<T>{		
    private T x;		//此屬性的類型不知道,由Point類使用時的動態決定
    private T y;		//此屬性的類型不知道,由Point類使用時的動態決定

    public T getX() {
        return x;
    }

    public T getY() {
        return y;
    }

    public void setX(T x) {
        this.x = x;
    }

    public void setY(T y) {
        this.y = y;
    }
}
public class Test {
    public static void main(String args[]){
        Point<String> p=new Point<String>();		//實例化Point類數據,設置泛型爲String
        p.setX("東經100度");
        p.setY("北緯20度");
        System.out.println("x座標:"+p.getX()+"y座標"+p.getY());
        String x=p.getX();							//取出座標數據,不再需要強制類型轉換
        String y=p.getY();							////取出座標數據,不再需要強制類型轉換
        System.out.println("x座標:"+x+"y座標"+y);
    }
}
//結果
//x座標:東經100度y座標10
//x座標:東經100度y座標10

提示:一個類中可以定義多個泛型標記。

class Point<P,R>{
	public R fun(P p){
		return null;
	}
}

需要注意的是,如果要想使用泛型,那麼它能夠採用的類型只能夠是類,即不能是基本類型,只能是引用類型。

通配符

例:通配符"?"的使用

package Project.Study.Genericity;

class Message<T>{
    private T msg;
    public void setMsg(T msg){
        this.msg=msg;
    }

    public T getMsg() {
        return msg;
    }
}
public class Test1 {
    public static void main(String args[]){
        Message<Integer>message1=new Message<>();
        Message<String>message2=new Message<>();
        message1.setMsg(30);
        message2.setMsg("Hello World");
        fun1(message1);							//引用傳遞
        fun2(message2);
    }
    public static void fun1(Message<?> temp){	//不能設置,但是可以取出
        System.out.println(temp.getMsg());
    }
    public static void fun2(Message temp){		//默認使用Object作爲泛型類型,可以在方法中隨意修改對象內容(即使類型不符合),這種做法是不嚴謹的
    	temp.setMsg(100);
        System.out.println(temp.getMsg());
    }
}
//結果
//30
//100

由上fun2(),必須使用通配符"?"來制約這種任意修改數據問題的操作。所以"?"設置的泛型類型只表示可以取出,但是不能設置,一旦設置了內容,程序編譯就會出現錯誤提示。

“? extends 類”:設置泛型上限,可以在聲明和方法參數上使用;

? extends Number:意味着可以設置Number或者是Number的子類(Integer、Double、…)

例:設置泛型的上限

package Project.Study.Genericity;

class Message<T extends Number>{	//設置泛型上限,只能是Number或Number子類
    private T msg;
    public void setMsg(T msg){
        this.msg=msg;
    }

    public T getMsg() {
        return msg;
    }
}
public class Test1 {
    public static void main(String args[]){
        Message<Integer>message1=new Message<>();				//Integer是Number子類
        message1.setMsg(30);
        fun1(message1);											//引用傳遞
    }
    public static void fun1(Message<? extends Number> temp){	//定義泛型上限
        System.out.println(temp.getMsg());
    }
}
//結果
//30

“? super 類”:設置泛型下限,方法參數上使用;

? super String:意味着只能設置String或它的父類Object。

例:設置泛型的下限

package Project.Study.Genericity;

class Message<T>{				//定義泛型
    private T msg;
    public void setMsg(T msg){
        this.msg=msg;
    }

    public T getMsg() {
        return msg;
    }
}
public class Test1 {
    public static void main(String args[]){
        Message<String>message1=new Message<>();
        message1.setMsg("Hello World");						//設置屬性內容
        fun1(message1);										//引用傳遞
    }
    public static void fun1(Message<? super String> temp){	//定義泛型下限
        System.out.println(temp.getMsg());
    }
}
//結果
//Hello World

泛型接口

任何情況下如果要使用接口,就必須定義相應的子類,而對於使用了泛型的接口子類而言,有以下兩種實現方式。

實現方式一:在子類繼續設置泛型標記

例:

package Project.Study.Genericity;

interface IMessage<T>{      //定義泛型接口
    public void print(T t);
}
class MessageImpl<S>implements IMessage<S>{ //在子類繼續設置泛型,此泛型也作爲接口中的泛型類型
    public void print(S t){
        System.out.println(t);
    }
}
public class Test2 {
    public static void main(String[] args){
        IMessage<String>msg=new MessageImpl<String>();
        msg.print("HelloWorld");
    }
}
//結果
//HelloWorld

實現方式二:在子類不設置泛型,而爲父類接口明確地定義一個泛型類型。

package Project.Study.Genericity;

interface IMessage1<T>{
    public void print(T t);
}
class MessageImpl1 implements IMessage1<String>{
    public void print(String t){
        System.out.println(t);
    }
}
public class Test3 {
    public static void main(String [] args){
        IMessage1<String>msg=new MessageImpl1();
        msg.print("HelloWorld");
    }
}
//結果
//HelloWorld

泛型方法

package Project.Study.Genericity;

public class Test4 {
    public static void main(String [] args){
        String str=fun("HelloWorld");
        System.out.println(str.length());
    }

    /**
     * 此方法爲泛型方法,T的類型由傳入的參數類型決定
     * 必須在方法返回值前明確定義泛型標記
     * @param t 參數類型,同時也決定了返回值類型
     * @param <T>
     * @return  直接返回設置進來的內容
     */
    public static <T>T fun(T t){
        return t;
    }
}
//結果
//10
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章