繁体   English   中英

为什么这个 java 代码可以工作,但 kotlin 代码不能

[英]why this java code can work but kotlin code can't

public class Generics2 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        List<Integer> list = new ArrayList<>();

        list.add(12);
//这里直接添加会报错
        Class<? extends List> clazz = list.getClass();
        Method add = clazz.getDeclaredMethod("add", Object.class);
//但是通过反射添加是可以的
//这就说明在运行期间所有的泛型信息都会被擦掉
        add.invoke(list, "kl");
        System.out.println(list);
        System.out.println(list.get(0));
        System.out.println(list.get(1));
    }
}

这段代码可以工作。 但是当我将其转换为 kotlin 时。它无法工作并抛出异常。为什么? 我只知道 kotlin 代码有CHECKCAST java/lang/Number ,但为什么 java 代码没有? 这是kotlin的特殊攻略吗?

object Generics {
    @Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
    @JvmStatic
    fun main(args: Array<String>) {
        val list: MutableList<Int> = ArrayList()
        list.add(12)
        //这里直接添加会报错
//        list.add("a");
        val clazz: Class<out MutableList<*>?> = list.javaClass
        val add = clazz.getDeclaredMethod("add", Any::class.java)
        //但是通过反射添加是可以的
//这就说明在运行期间所有的泛型信息都会被擦掉
        add.invoke(list, "kl")
        println(list)
        println(list[0])
        println(list[1])
        println(list.get(1))
    }
}
[12, kl]
12
Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')
    at Generics.main(Generics.kt:22)

来自https://www.baeldung.com/kotlin/generics

6.1. 类型擦除与 Java 一样,Kotlin 的 generics 在运行时被擦除。 也就是说,泛型 class 的实例不会在运行时保留其类型参数。 例如,如果我们创建一个 Set 并将一些字符串放入其中,在运行时我们只能将其视为一个 Set。 让我们创建两个具有两个不同类型参数的集合: val books: Set<String> = setOf("1984", "Brave new world") val primes: Set<Int> = setOf(2, 3, 11)在运行时, Set 和 Set 的类型信息将被删除,我们将它们视为普通 Set。 因此,即使在运行时完全有可能发现该值是一个 Set,我们也无法判断它是一组字符串、整数还是其他东西:该信息已被删除。

那么,Kotlin 的编译器如何阻止我们将 Non-String 添加到 Set 中呢? 或者,当我们从 Set 中获取一个元素时,它如何知道该元素是一个 String? 答案很简单。 编译器负责擦除类型信息,但在此之前,它实际上知道 books 变量包含 String 元素。 因此,每次我们从中获取一个元素时,编译器都会将其转换为字符串,或者当我们要向其中添加一个元素时,编译器会对输入进行类型检查。

所以,这是 kotlin 编译器引入的附加安全功能

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM