Как получить название любого класса? - PullRequest
0 голосов
/ 18 ноября 2018

Я пытаюсь сделать функцию расширения для регистрации.Я хочу отправить Any в качестве параметра и получить его имя.Но не могу найти, как получить имя класса Any.Есть идеи по этому поводу?

fun MainActivity.log(claz: Objects,any: Any){
    Log.d("Main", claz.name +  any.toString())
}

Ответы [ 4 ]

0 голосов
/ 08 мая 2019

Мне нужно было что-то похожее для отображения объектов в формате json в качестве объектов, и мне удалось заставить его работать вот так

val depositResponse = convertResponseToObject(response , DepositResponse ::class.java.name) as DepositResponse
val withdrawResponse = convertResponseToObject(response , WithdrawResponse ::class.java.name) as WithdrawResponse
fun convertResponseToObject(response: String?, type: String ): Any{
    try {
        when (type) {
            DepositResponse ::class.java.name -> 
                 return ObjectMapper().readValue(response, DepositResponse ::class.java)
            WithdrawResponse ::class.java.name -> 
                 return ObjectMapper().readValue(response, WithdrawResponse ::class.java)
            else -> throw Exception("Error Mapping the json response")
        }
    }catch(e:Exception){
        throw e
    }
}
0 голосов
/ 18 ноября 2018

Использование yourClassInstance::class.simpleName:

fun MainActivity.log(claz: Objects, any: Any){
    Log.d("Main", "${claz::class.simpleName} ${any::class.simpleName}")
}
0 голосов
/ 18 ноября 2018

Вы можете использовать Class или KClass для этого, но лучше использовать KClass для этого случая. В противном случае вам придется добавить .java в класс, как упоминал Блю Джонс.

Я не уверен какое имя вы хотите. Помните, что может быть несколько классов JVM с одним и тем же именем. Closeable для экземпляра может быть либо java.io.Closeable , либо пользовательской реализацией, если вы также используете библиотеку, которая использует ее по любой практической причине.

Учитывая это, существуют допустимые варианты использования, в которых вы хотите указать полное имя. Полное имя идентично «обычному» имени, за исключением того, что оно также включает пакет. Рассмотрим это для примера:

import java.io.Closeable;

fun main(ar: Array<String>){
    val closeable = Closeable::class
    println(closeable.simpleName)
    println(closeable.qualifiedName)
}

Это напечатало бы:

Closeable
java.io.Closeable

Вам нужно будет выбрать тот, который вы хотите использовать, в зависимости от вашего использования. Если вы тоже хотите пакет, используйте qualifiedName. В противном случае используйте simpleName.

Вы, очевидно, не должны получать уроки, выполняя ClassName::class. Вы также можете сделать то же самое на экземплярах, что означает, что вы можете сделать any::class и использовать это, чтобы получить имя.

Итак, чтобы получить имя, используйте any::class.qualifiedName. Если вы просто хотите, чтобы имя класса исключало пакет, используйте simpleName.

Стоит отметить, что KClass является частью пакета отражения . Поэтому я предполагаю, что он использует отражение в нескольких или во всех вызовах.

Это означает, что вы можете получить SecurityException, если в разрешениях отказано. Я тестировал большую часть этого на try.kotlinlang.org , и я получил SecurityException с лямбда в основном методе при использовании KClass#qualifiedName и KClass#simpleName.

Использование ::class.java исправило это. Так что, если вы испытываете исключения безопасности, используйте class.java. Наименование практически идентично. simpleName есть, но qualifiedName просто name. Какой из них вы выбираете, зависит от вас, но любой из них работает.

Итак, ваш код будет выглядеть так:

println(any::class.qualifiedName) // Alternatively with simpleName
println(any::class.java.name) // Alternatively with simpleName

И, наконец, я вижу, как вы назвали toString() в одном из случаев. Это возвращает полное имя класса с хешем после него. Это тоже вариант, но если вам не нужен хеш, используйте Class или KClass.

Кроме того, я вижу, вы использовали MainActivity.log в качестве своей функции. Я действительно не понимаю, почему. Если у вас есть функция ведения журнала, ограниченная одним классом, поместите ее в объект-компаньон. Объявление функций расширения внутри самого класса также бессмысленно, поскольку вызовы идентичны. Поскольку вы можете редактировать класс, а это единственный класс, о котором мы говорим, вы можете переместить его в объект-компаньон (опционально, сделать его закрытым).

И ваш код может выиграть от использования строковых шаблонов, которые я добавлю в последнем примере. Это должно гарантировать, что места заканчиваются правильно. С вашим текущим кодом нет места для добавления. Я также не могу найти Objects#getName(), поэтому я предполагаю, что это еще одна попытка получить само имя. Однако: Класс Objects при условии, что он java.util.Objects не может быть инициализирован. Это служебный класс. Если вы имели в виду java.lang.Object, используйте вместо него Any. Any примерно такой же, как Object.

Что означает, что ваш класс может выглядеть так:

class MainActivity : Activity() {
    ...
    companion object {
        fun log(claz: Object, any: Any){
            Log.d("Main", "${claz::class.java.name} ${any::class.qualifiedName}") // I'm mixing the calls here to show you that you can use either. You can of course pick which you use.
        }
    }
}
0 голосов
/ 18 ноября 2018
val c = String::class
println(c.simpleName)

$ String
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...