Android学习记录043_java泛型与kotlin泛型

一、java泛型

package generically;


public class Main {

    public static void main(String[] args) {
        GenericType<Fruit> genericTypeFruit = new GenericType<>();
        GenericType<Apple> genericTypeApple = new GenericType<>();
        GenericType<Orange> genericTypeOrange = new GenericType<>();
        GenericType<HongFushi> genericTypeHongFushi = new GenericType<>();


        System.out.println("=============GenericType<? extends Apple>=============");
        //因为Fruit不是Apple的子类,所以 generically.GenericType<generically.Fruit>无法转换为generically.GenericType<? extends generically.Apple>
//        print1(genericTypeFruit); //不兼容的类型: generically.GenericType<generically.Fruit>无法转换为generically.GenericType<? extends generically.Apple>
        print1(genericTypeHongFushi);
        print1(genericTypeApple);
        //泛型的上界
        GenericType<? extends Apple> extendsVariable = new GenericType<>();
        /**
         * ?extends Apple当作类型的时候为什么调用setData不能传递参数?
         * 因为?extends Apple处于方法入参的位置,此时会导致类型转换异常。例如声明了extendsVariable这个变量,假设可以调用setData给
         * extendsVariable对象中的data属性赋值为new HongFushi(),因为data类型为?extends Apple这就代表着data类型最高为Apple类型(也可以
         * 是Apple的任意子类型),如果传入HongFushi那data的类型要是LanFushi,兄弟类型之间的类型转换就不行;如果传入Apple那data类型是LanFushi
         * ,父类型转换为子类型也不行。综合上述问题简而言之就是?extends Apple处于方法入参的位置时,无法确定方法所需参数具体类型,所以?extends Apple
         * 处于方法入参的位置时没有办法给该方法传参
         *
         */
//        extendsVariable.setData(new Object());// 不兼容的类型: java.lang.Object无法转换为capture#1, 共 ? extends generically.Apple
//        extendsVariable.setData(new HongFushi()); // 不兼容的类型: generically.HongFushi无法转换为capture#1, 共 ? extends generically.Apple
//        extendsVariable.setData(new Apple()); //不兼容的类型: generically.HongFushi无法转换为capture#1, 共 ? extends generically.Apple
//        extendsVariable.setData(new Fruit()); //不兼容的类型: generically.HongFushi无法转换为capture#1, 共 ? extends generically.Apple

        /**
         * ?extends Apple当作方法返回值类型的时候为什么都用Apple来接收?
         * ?extends Apple代表着类型最高为Apple,所以拿extendsVariable.getData()这个方法来说,该方法的返回值要么Apple类型的
         * 子类,要么就是其自身,但是由无法确定具体类型。由于java自身的特性使得子类强转为父类是被允许的,所以都用Apple来接收就避免
         * 了类型转换异常。其实也可以用Object来接收,因为Apple也是继承至Object,不过这样的话就没太大意义了
         */
        Apple apple = extendsVariable.getData();


        System.out.println("=============GenericType<? super Apple>=============");
//        print2(genericTypeFruit);
        // 因为HongFushi不是Apple的超类,所以不能强转
//        print2(genericTypeHongFushi); // 不兼容的类型: generically.GenericType<generically.HongFushi>无法转换为generically.GenericType<? super generically.Apple>
        print2(genericTypeApple);

        //泛型的下界
        GenericType<? super Apple> superVariable = new GenericType<>();
        /**
         * ?super Apple当作类型的时候为什么调用setData能传递参数?
         * 因为?super Apple处于方法入参的位置,编译器可以找到兜底的类就是Apple,所有传给setData方法的参数都是Apple类型的子类或其自身。
         * 例如声明了superVariable这个变量,假设调用setData方法给superVariable对象的data赋值为new HongFushi(),因为data类型为? super Apple这就代表着
         * data的类型至少是Apple类型,那么HongFushi做为Apple类型的子类强转为Apple类型是可以的。要是传递Fruit类型的对象给setData的话,那Fruit对象
         * 是无法强转为Apple类型。
         */
        superVariable.setData(new HongFushi());
        superVariable.setData(new Apple());
//        superVariable.setData(new Fruit());//不兼容的类型: generically.Fruit无法转换为capture#1, 共 ? super generically.Apple


        /**
         * ?super Apple当作方法返回值类型的时候为什么都用Object来接收?
         * ?super Apple代表着类型最低为Apple,所以拿superVariable.getData()这个方法来说,该方法的返回值要么Apple类型的
         * 父类,要么就是其自身,但是无法确定具体类型。由于java自身的特性使得父类强转为子类是不被允许的,但是在java中所有的类都是
         * 继承至Object类所以只能用Object来接收。否则将会出现父类型转化为子类型的强转、兄弟类型之间的强转,这些情况是不被允许的。
         */
        Object object = superVariable.getData();
    }

    public static void print1(GenericType<? extends Apple> data) {
        Apple apple = data.getData();
    }

    public static void print2(GenericType<? super Apple> data) {
        Object object = data.getData();
    }
}

/**
 * 泛型类
 * @param <T>
 */
class GenericType<T> {
    private T data;

    public void setData(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
}


二、kotlin泛型

package com.study


open class Fruit()
open class Apple() : Fruit()
open class HongFushi() : Apple()
open class Orange() : Fruit()

class GenericType<T> {
    private  var data: T? = null

    fun setData(data: T) {
        this.data = data
    }

    fun getData(): T? = data
}

/**
 * java的? extends T不能直接使用在声明泛型的地方
 */
class GenericOutType<out T> {
    private  var data: T? = null

    /**
     * 如果用out修饰泛型T的话,那么泛型T是不被允许出现在方法入参的位置上的
     */
//    fun setData(data: T) {
//        this.data = data
//    }

    fun getData(): T? = data
}


/**
 * java的? super T不能直接使用在声明泛型的地方
 */
class GenericInType<in T> {
    private  var data: T? = null


    fun setData(data: T) {
        this.data = data
    }

    /**
     * 如果用in修饰泛型T的话,那么泛型T是不被允许出现在方法返回值类型上面的
     */
//    fun getData(): T? = data
}


fun main() {

    val genericTypeFruit = GenericType<Fruit>()
    val genericTypeApple = GenericType<Apple>()
    val genericTypeOrange = GenericType<Orange>()
    val genericTypeHongFushi = GenericType<HongFushi>()

//    print1(genericTypeFruit) // Type mismatch: inferred type is GenericType<Fruit> but GenericType<out Apple> was expected
    print1(genericTypeApple)
    /**
     * 泛型的协变:GenericType<T>的泛型类,其中HongFushi是Apple的子类型,同时GenericType<HongFushi>又是GenericType<Apple>的子类型,
     * 那么我们就可以称GenericType在T这个泛型上是协变的。
     */
    print1(genericTypeHongFushi)

    /**
     * 下面这两种声明变量的方式是不被允许的
     */
//    val outVariable = GenericType<out Apple>() //Projections are not allowed on type arguments of functions and properties
//    val inVariable = GenericType<in Apple>() //Projections are not allowed on type arguments of functions and properties

    /**
     * 泛型的逆变:GenericType<T>的泛型类,其中Fruit是Apple的父类型,同时GenericType<Fruit>又是GenericType<Apple>的子类型,
     * 那么我们就可以称GenericType在T这个泛型上是逆变的。
     */
    print2(genericTypeFruit)
    print2(genericTypeApple)

}

/**
 * 类似java中的? extends Apple
 */
fun print1(data: GenericType<out Apple>) {
    val apple:Apple? = data.getData()
}

/**
 * 类似java中的? super Apple
 */
fun print2(data: GenericType<in Apple>) {
    val `object`:Any? = data.getData()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值