通配符和泛型接口简单使用

1. 通配符的引出

在程序中追加了泛型之后,可以避免ClassCastException 的问题,但是又会产生新的情况:参数的统一的问题。
举例:方法中的参数类型与接收到的参数类型不匹配

public class TestMessage{

    public static void main(String[] args) {
        Message<Integer> message = new Message<>();
        message.setMessage(20);
        //fun(message);   与fun()方法中的类型不匹配,报红
    }

    //此处方法参数的Message泛型类型是String
    private static void fun(Message<String> message) {
        System.out.println(message.getMessage());
    }
}

class Message<T> {
    private T message;

    public void setMessage(T message){
        this.message = message;
    }

    public T getMessage(){
        return this.message;
    }

    @Override
    public String toString() {
        return "TestMessage{" +
                "message=" + message +
                '}';
    }
}

那么为了解决上述问题,可以接受所有的泛型类型,又不能让用户随意修改,这种情况下就要使用 通配符 来处理
举例:使用通配符

public class TestMessage{

    public static void main(String[] args) {
        Message<Integer> message = new Message<>();
        message.setMessage(20);
        fun(message);

        Message<String> message1 = new Message<>();
        message1.setMessage("hello");
        fun(message1);
    }

    //其中?可以表示任意类型,但是因为不确定类型,所以无法进行修改
    private static void fun(Message<?> message) {
        //message.setMessage(100);  无法修改
        System.out.println(message.getMessage());
    }
}

1.2. 泛型上限

在通配符的基础上,又产生了两子通配符。泛型上限和泛型下限

  • ? extends 类:设置泛型上限
    比如:? extends Number :因为存在继承关系,所以?表示子类,而Number就是它的上限。它表示只能够设置Number或者其子类,例如:Integer、Double
  • 泛型上限既可以使用在类上,又可以使用在方法上

举例1:方法使用泛型上限

public class TestMessage{

    public static void main(String[] args) {
        
        Message<String> message1 = new Message<>();
        message1.setMessage("hello");
        fun(message1);
    }

    // 因为String类被final修饰,所以没有子类,此处只能放String 
    private static void fun(Message<? extends String> message) {
        System.out.println(message.getMessage());
    }
}

举例2:方法使用泛型上限

public class TestMessage{

    public static void main(String[] args) {

        Message<String> message = new Message<>();
        message.setMessage("hello");
        fun(message);

        Message<StringBuffer> message1 = new Message<>();
        message1.setMessage(new StringBuffer().append("hello").append("world"));
        fun(message1);
    }
        
    private static void fun(Message<? extends CharSequence> message) {
        System.out.println(message.getMessage());
    }
}

以下是CharSequence的已知实现类:
在这里插入图片描述
举例:类使用泛型上限

public class Point6 <T extends CharSequence>{
    private T x;
    private T y;

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

    public void setY(T y){
        this.y = y;
    }
    public T getY(){
        return this.y;
    }

    @Override
    public String toString() {
        return "Point6{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }

    public static void main(String[] args) {
        Point6<String> p1 = new Point6<>();
        p1.setX("hello");
        System.out.println(p1);

        Point6<StringBuffer> p2 = new Point6<>();
        p2.setY(new StringBuffer().append("hello").append(" world"));
        System.out.println(p2);
    }
}

1.3. 泛型下限

  • ? super 类 :设置泛型下限
    比如:< ? super Integer >, ? 表示的是Integer , Number , Object

举例:使用泛型下限

public class TestMessage{

    public static void main(String[] args) {

        Message<String> message = new Message<>();
        message.setMessage("hello");
        fun(message);
    }

    private static void fun(Message<? super String> message) {
        message.setMessage("world");   //此处可以进行修改!!!
        System.out.println(message.getMessage());
    }
}

总结:

  1. 上限可以用在声明,不能修改;
  2. 下限只能用在方法参数中,不能使用在泛型类中,可以修改内容

2. 泛型接口

  • 泛型除了定义在类中,也可以定义在接口里面,这种情况成为泛型接口。
  • 泛型接口定义和泛型类区别不大
  • 泛型接口的实现类:
    • 可以继续是接口的泛型类
    • 不是泛型类,接口处可以指定具体类型
  • 定义一个泛型接口:
interface IMessage<T> {    //在接口上定义了泛型
		public void print(T t);
}

举例:使用泛型接口

public interface IMessage<T> {
    void print(T t);

    public static void main(String[] args) {
        IMessage<String> qq = new QQMessage();
        qq.print("hello");

        MsnMessage<Integer> msn = new MsnMessage<>();
        msn.print(100);
    }
}

//继承原来的类型
class QQMessage implements IMessage<String>{
    @Override
    public void print(String t) {

    }
}

//指定新的类型
class MsnMessage<T> implements IMessage<T>{
    @Override
    public void print(T t) {

    }
}

举例:使用匿名内部类

public interface IMessage<T> {
    void print(T t);

    public static void main(String[] args) {
        new IMessage<String>() {
            @Override
            public void print(String str) {
                System.out.println(str);
            }
        }.print("hello");
    }
}

猜你喜欢

转载自blog.csdn.net/mi_zhi_lu/article/details/90724291