2016-12-16 1 views
1

Я использую Kotlin для написания чего-то, что работает с API-интерфейсами отражения Java. Мой ввод - Class<*>, и мне нужно решить, является ли этот тип двойным или целочисленным, но мне нужно поддерживать оба примитива и типы с нулевыми значениями в ящике, которые использует Java.Как сравнить класс <*> с примитивным типом Java в коробке без предупреждений компилятора kotlin

Эта игрушка пример делает то, что я пытаюсь сделать:

when(type) { 
    java.lang.Double::class.java, Double::class.java -> TypesEnum.DOUBLE 
    java.lang.Integer::class.java, Int::class.java -> TypesEnum.INT 
    else -> throw IllegalArgumentException("type") 
} 

Но такой подход порождает следующие предупреждения от Котлин компилятора:

Внимание: (22, 13) Котлин : Этот класс не должен использоваться в Котлине. Используйте kotlin.Double вместо этого. Предупреждение: (23, 13) Котлин: Этот класс не должен использоваться в Котлине. Вместо этого используйте kotlin.Int.

Однако Int?::class.java ошибка синтаксиса, the approaches suggested on an earlier question требуют KClass вместо Class<*>.kotlin extension method аварий на некоторых из моих входов). Каков правильный способ Котлина выполнить такой контроль?


Edit: Дальнейшее исследование (запрос на ответ @ voddan в) показал, что эта проблема является симптомом более общей немного странностей в типе отражения Котлин в:

fun main(args: Array<String>) { 
    // ::class.java of Kotlin's own Double type is just double 
    println(Double::class)       // -> class kotlin.Double 
    println(Double::class.java)      // -> double 

    // But starting from Java's nullable java.lang.Double gives an entirely different result 
    println(java.lang.Double::class)     // -> class kotlin.Double 
    println(java.lang.Double::class.java)    // -> class java.lang.Double 
    println(java.lang.Double::class.java.kotlin)  // -> class kotlin.Double 
    println(java.lang.Double::class.java.kotlin.java) // -> class java.lang.Double 

    // Suggested by @mfulton26; works. 
    println(Class.forName("java.lang.Double"))  // -> class java.lang.Double 
} 

Так что, похоже, не все class kotlin.Double s созданы равными. Я играл с листами и вспомогательными переменными, и результаты кажутся очень последовательными.

ответ

3
  1. Class.kotlin должен работать. Если он «сбой на некоторых [ваших] входах», то я рекомендую подать вопрос here.
  2. Вы можете использовать Class.forName(String). чтобы избежать предупреждений компилятора. например Class.forName("java.lang.Integer").
  3. Вы можете suppress предупреждение.
  4. Вы можете использовать KClass.javaObjectType и KClass.javaPrimitiveType:

    when (type) { 
        Double::class.javaObjectType, Double::class.javaPrimitiveType -> TypesEnum.DOUBLE 
        Int::class.javaObjectType, Int::class.javaPrimitiveType -> TypesEnum.INT 
        else -> throw IllegalArgumentException("type") 
    } 
    
+0

'Class.kotlin' работает на try.kotlinlang.org, но не моя система, так что это, безусловно, правильный ответ, и моя среда перепутана. – Dan

+0

'Class.forName (" java.lang.Double "). Kotlin' соответствует' Double :: class' в блоке if, но только на kotlin 1.0.4 и выше. У меня была старая версия. – Dan

1

Int? не является классом, но тип, а это означает, что ссылка этого типа является эфир int, Integer или null.

Int::class.java должен дать вам java.lang.Integer Я думаю.

я не могу проверить это прямо сейчас, но IMO преобразования Class в KClass это лучший вариант:

when(type.kotlinClass) { 
    Double::class -> TypesEnum.DOUBLE 
    Int::class -> TypesEnum.INT 
    else -> throw IllegalArgumentException("type") 
} 
+0

'Int :: class.java' просто' int', не 'java.lang.Integer'. Отредактированный вопрос с большим количеством экспериментов. – Dan

+0

Да, но 'type.kotlin' должен возвращать' Int' независимо от исходного типа – voddan

Смежные вопросы