В чем разница между классом <*> и классом <T> - PullRequest
0 голосов
/ 27 января 2019

У меня есть два способа написания своих функций, как показано ниже:

private fun createFragment(fragmentClass: Class<*>, fragmentArgs: Bundle?): Fragment {
    try {
        val fragment = fragmentClass.newInstance() as Fragment
        fragment.arguments = fragmentArgs
        return fragment
    } catch (exception: Exception) {
        throw RuntimeException(exception.message)
    }
}

И это

private fun <T>createFragment(fragmentClass: Class<T>, fragmentArgs: Bundle?): Fragment {
    try {
        val fragment = fragmentClass.newInstance() as Fragment
        fragment.arguments = fragmentArgs
        return fragment
    } catch (exception: Exception) {
        throw RuntimeException(exception.message)
    }
}

Я не знаю, в чем отличие создания этого Class<*> против класса`.Чем они отличаются друг от друга?Что лучше?

Примечание: я понимаю, что это лучше сделать, используя reified Например, вообще не нужно использовать Class.Но я просто хочу понять без reified, в чем разница между использованием Class<*> против Class<T>

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Оба результата привели к одному и тому же декомпилированному коду Java

private final Fragment createFragment(Class fragmentClass, Bundle fragmentArgs) {
  try {
     Object var10000 = fragmentClass.newInstance();
     if (var10000 == null) {
        throw new TypeCastException("null cannot be cast to non-null type android.support.v4.app.Fragment");
     } else {
        Fragment fragment = (Fragment)var10000;
        fragment.setArguments(fragmentArgs);
        return fragment;
     }
  } catch (Exception var4) {
     throw (Throwable)(new RuntimeException(var4.getMessage()));
  }
}

Так что они одинаковы.Как и то, что говорит @Willi Mentzel, мы должны использовать Class<T>, только если нам нужно T.Один пример, как показано ниже (например, возвращает тип), что мы можем получить точно такой же тип

private fun <T>createFragmentX(fragmentClass: Class<T>, fragmentArgs: Bundle?): T {
    try {
        val fragment = fragmentClass.newInstance()
        (fragment as Fragment).arguments = fragmentArgs
        return fragment
    } catch (exception: Exception) {
        throw RuntimeException(exception.message)
    }
}
0 голосов
/ 27 января 2019

* называется проекция звезды .Вы используете его, когда вам нужно указать универсальный тип, но не волнует, что это такое (возможно, потому, что вам это не нужно).


Поскольку этот вопрос не связан каким-либо особым образомДля класса Class<T> позвольте мне показать вам, как это работает, на простом примере:

Рассмотрим эту простую функцию, которая принимает List и печатает его:

fun printList(l: List) { println(l) }

Она выигралане компилируется со следующей ошибкой:

Ожидается один аргумент типа для интерфейса List<out E>

Я мог бы исправить это так:

fun <T> printList(l: List<T>) { println(l) }

но это утомительно, потому что на самом деле мне плевать на T, и мне это не нужно.

А вот и звездная проекция в игре:

fun printList(l: List<*>) { println(l) }

Это будетcompile, короток и лаконичен.


Итак, в вашем конкретном примере вы должны использовать Class<*>, потому что вам просто не нужно T.

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