泛型的比喻_通配符?水_标识符T橡皮泥

背景: 泛型太痛苦了,无中生有.从0构建,比喻效果.

: ? <> E T ,这些东西太让人头痛了,就是抽象的东西,就算使用3天,我也要把这个东西弄清楚,否则极为难受.

小殊 💙 : 有什么我可以帮你的吗? 我会在一旁听你讲的.

: 好的,一步一步来.不着急.我必须弄清楚了.

: start —>

名称解释:

泛型:广泛的类型

通配符:通用匹配的符号

就像橡皮泥一样. <?>

// 不可以
?car = operate();

为什么会这样呢?底层原理是什么?

T 是一个 确定的 类型,通常用于泛型类和泛型方法的定义,?是一个 不确定 的类型,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。

? 不是一个类型,举个例子.T是橡皮泥,?是水. 上尚若水,水是无形的. 可以幻化任何形状,就如同灵魂一般.就是一种能量.

可以使用玄幻比喻吗? 好,按照这个确定,我们开始对代码的演绎.

我有一个父类 Animal 和几个子类,如狗、猫等,现在我需要一个动物的列表,我的第一个想法是像这样的:

List<Animal> listAnimals

但是老板的想法确实这样的:

List<? extends Animal> listAnimals
static int countLegs (List<? extends Animal > animals ) {
    int retVal = 0;
    for ( Animal animal : animals )
    {
        retVal += animal.countLegs();
    }
    return retVal;
} 
static int countLegs1 (List< Animal > animals ){
    int retVal = 0;
    for ( Animal animal : animals )
    {
        retVal += animal.countLegs();
    }
    return retVal;
} 
public static void main(String[] args) {
    List<Dog> dogs = new ArrayList<>();
     // 不会报错
    countLegs( dogs );
    // 报错
    countLegs1(dogs);
} 

所以,作用明白了吗? 水比橡皮泥更加强大.水用来方法里面. 每一个抽象的东西,必须给一个具象的对象进行对应.

<? extends Animal> 这是代表继承动物的类吗? ,是的. 水只能幻化动物的形状,这个72变,36变极为相似.

dog继承了动物. dog是儿子,所以就是 ? 增加了子类, supper增加了父类? 多了可以调用的类型.

参考


private <'K' extends A, E extends B> E test(K arg1, E arg2){
    E result = arg2;
    arg2.compareTo(arg1);
    //.....
    return result;
}

’ 是因为没有办法所以添加的

这个操作是为了,增加多个的限制范围.这很像数轴.以添加.

在这里插入图片描述


dst 类型 “大于等于” src 的类型,这里的“大于等于”是指 dst 表示的范围比 src 要大,因此装得下 dst 的容器也就能装 src 。

上界通配符主要用于读数据,下界通配符主要用于写数据。

区别1:通过 T 来 确保 泛型参数的一致性

// 通过 T 来 确保 泛型参数的一致性
public <T extends Number> void
test(List<T> dest, List<T> src)

//通配符是 不确定的,所以这个方法不能保证两个 List 具有相同的元素类型
public void
test(List<? extends Number> dest, List<? extends Number> src)

不保证两个list具有相同元素是什么意思? 上面代码就不能保证泛型的作用,需要强制转换,所以使用?不合理?

区别2:类型参数可以多重限定而通配符不行

在这里插入图片描述

使用 & 符号设定多重边界(Multi Bounds),指定泛型类型 T 必须是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子类型,此时变量 t 就具有了所有限定的方法和属性。

对于通配符来说,因为它不是一个确定的类型,所以不能进行多重限定。

为什么不能多重限定? 可以单限定,因为java不允许多重继承吗? 接口是可以多重继承的.没有关系.

extends 后面如果是接口. 代表什么,这些接口的子类(接口),包括实现类吗?

接口是可以在后面加 = 类. 这种操作的.


区别3:通配符可以使用超类限定而类型参数不行

类型参数 T 只具有 一种 类型限定方式:

T extends A

但是通配符 ? 可以进行 两种限定:

? extends A
? super A

Class’’ 和 Class’<?>’ 区别

// 通过反射的方式生成  multiLimit
// 对象,这里比较明显的是,我们需要使用强制类型转换
MultiLimit multiLimit = (MultiLimit)
Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();

对于上述代码,在运行期,如果反射的类型不是 MultiLimit 类,那么一定会报 java.lang.ClassCastException 错误。

对于这种情况,则可以使用下面的代码来代替,使得在在编译期就能直接 检查到类型的问题

在这里插入图片描述

 public class Test3{
	public static <T> T createInstance(Class<T> clazz) throws IllegalAccessException, InstanttationException{
		return clazz.newInstance(); 
    }
	public static void main(String[] args) throws IllegalAccessException, InstanttationException{
		A a=createInstance(A.class); 
		B b=createInstance(B.class);
	}
}
class A{}
class B{}

这段代码就比较复杂了,慢慢分析一波. 泛型方法.

T 什么操作? 类型是一个泛型? 假如 返回的是一个 a的对象,所以,这一块 T 就是类似String ,前面必须加上,否则是不是有点不伦不类,这个地方不像普通的写一个类型. 其实很简单, 这种单独使用,很少的.

使用比喻来说: <>是什么意思? 过滤器

( <> T )两个,总是觉得一脸懵逼.一定要确认清楚.

Class A.class .每个class都是泛型,因为类型肯定不确定. 为什么不使用Class 呢? 不能代表.所有类型吗?

有什么深意?

Class a 这个和 List ls 对比一下.

a.newInstance(); 
ls.get()
    List 和 Class 一样,就是一种类型 <>泛型,简单的组合.

任重道远呀. 有一点眉目,但是. 还是很混乱.


看这个,是不是有很多问号.

/**
 * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
 * 即:class FruitGenerator<T> implements Generator<T>{
 * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class"
 */
class FruitGenerator<T> implements Generator<T>{
    @Override
    public T next() {
        return null;
    }
}

这是声明类的.所以没有 T.

泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。

 //同时这也印证了泛型通配符章节所描述的,?是一种类型实参,可以看做为Number等所有类的父类
 

泛型类中的泛型方法 只有一个这种东西

 class GenerateTest<T>{
        public void show_1(T t){
            System.out.println(t.toString());
        }

        //在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型。可以类型与T相同,也可以不同。
        //由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,编译器也能够正确识别泛型方法中识别的泛型。
        public <E> void show_3(E t){
            System.out.println(t.toString());
        }
}

可变参数的学习

public <T> void printMsg( T... args){
    for(T t : args){
        Log.d("泛型测试","t is " + t);
    }
}

T… 是不是有很多问号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值