一、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()
}