首页 > 编程学习 > 浅学习泛型

浅学习泛型

发布时间:2022/11/10 7:31:32

浅学习泛型

  • 一、什么是泛型
  • 二、泛型方法
  • 三、泛型接口
  • 四、通配符
    • 1、通配符
    • 2、上限通配符
    • 3、下限通配符
    • 4、类型擦除


一、什么是泛型

泛型:就是指在类定义时不会设置类中的属性或方法参数的具体类型,而是在类使用时(创建对象)再进行类型的定义。会在编译期检查类型是否错误。

类声明后的<>中这个T被称为类型参数,用于指代任意类型,实际上这个T只是个代表,写什么都可以。表示此时的value1,value2都是在类定义时没有明确类型,只有在使用时才告知编译器类型。出于规范,类型参数用单个的大写字母来代替

T:代表任意类
E:表示Element的意思,或是异常

	@Data
	class people<A, B> {
	    A value1;
	    B value2;
	}

    @Test
    void test1() {
        people<String,Long> people = new people();
        people.setValue1("sb");
        people.setValue2(1L);
        log.info(people.toString());//people(value1=sb, value2=1)
    }

二、泛型方法

表示此方法是个泛型方法,有一个类型参数,不是返回值,只是告知编译器这是一个泛型的声明

@Data
@Slf4j
class people<A, B> {
    A value1;
    B value2;

    //此处的泛型方法指的是有自己的类型参数,这里的A和类上的A不是同一个
    public <A> void test(A t) {
        log.info(String.valueOf(t));
    }
}
    @Test
    void test2() {
        people<String, Long> people = new people();
        people.setValue1("sb");
        people.setValue2(1L);
        log.info(people.toString());//people(value1=sb, value2=1)

        people.test(100L);
    }

三、泛型接口

子类在实现接口时有两种选择,①要么继续保留泛型,②要么定义子类时明确类型

interface INew<T>{
    T getName(T t);
}

class INewImpl1<T> implements INew<T>{

    @Override
    public T getName(T o) {
        return o;
    }
}

class INewImpl2 implements INew<String>{

    @Override
    public String getName(String o) {
        return o;
    }
}

四、通配符

1、通配符

<?> 一般用在方法参数,表示可以接受该类所有类型的泛型变量。
	@Data
	@Slf4j
	class Message<T, K> {
	    T value1;
	    K Value2;
	
	    public void fun(Message<?, ?> sb) {
	        log.info("value1===={}", sb.getValue1());
	        log.info("value1===={}", sb.getValue2());
	    }
	}

    @Test
    void test3() {
        Message message = new Message();
        message.setValue1("aaa");
        message.setValue2(222);
        message.fun(message);

        Message message2 = new Message();
        message2.setValue1(111);
        message2.setValue2("bbb");
        message2.fun(message);
    }

2、上限通配符

<? extends 类> 表示?可以指代任何类型,但是该类型必须是后面类的子类。
可以是类本身,或者子类,除此之外其他类型都不可以。

	@Data
	@Slf4j
	class Message2<T, K> {
	    T value1;
	    K Value2;
	
	    public void fun(Message2<? extends String, ? extends Integer> sb) {
	        log.info("value1===={}", sb.getValue1());
	        log.info("value1===={}", sb.getValue2());
	    }
	}

    @Test
    void test4() {
        Message2<String, Integer> message = new Message2<>();
        message.setValue1("aaa");
        message.setValue2(222);
        message.fun(message);

        Message2<Object, Object> message2 = new Message2();
        message2.setValue1(111);
        message2.setValue2("bbb");
        message2.fun(message2);
    }

在这里插入图片描述

3、下限通配符

<? super 类> 此时?表示可以指代任意类型,但是该类型必须是后面类的父类。

此时表示?必须是String及其父类,所有此时?只能指代String或Object。

注意:下限通配符可以调用对象的setter方法设置一个具体的属性值,无论?是什么类型,规定好的下限类型一定可以通过向上转型变为父类。

	@Data
	@Slf4j
	class Message3<T, K> {
	    T value1;
	    K Value2;
	
	    public void fun(Message3<? super String, ? super Integer> sb) {
	        log.info("value1===={}", sb.getValue1());
	        log.info("value1===={}", sb.getValue2());
	    }
	}

    @Test
    void test5() {
        Message3<String, Integer> message = new Message3<>();
        message.setValue1("aaa");
        message.setValue2(222);
        message.fun(message);

        Message3<Object, Object> message2 = new Message3<>();
        message2.setValue1(111);
        message2.setValue2("bbb");
        message2.fun(message2);

        Message3<Integer, String> message3 = new Message3<>();
        message3.setValue1(111);
        message3.setValue2("bbb");
        message3.fun(message3);
        
    }

在这里插入图片描述

4、类型擦除

类型擦除:所有泛型类型参数,若没有设置泛型上限,则编译之后统一擦除为Object类型,若设置了泛型上限,则编译之后统一擦除为相应的泛型上限。

Copyright © 2010-2022 dgrt.cn 版权所有 |关于我们| 联系方式