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
发布了49 篇原创文章 · 获赞 25 · 访问量 1526

猜你喜欢

转载自blog.csdn.net/weixin_45784666/article/details/104544839
今日推荐