代码之家  ›  专栏  ›  技术社区  ›  Elye

班级和班级的区别是什么?

  •  2
  • Elye  · 技术社区  · 7 年前

    我有两种方法来写我的函数,如下所示

    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<*> VS类。它们之间有什么不同?哪个更好?

    注:我知道这是做得更好的使用 reified 例如,不需要使用 Class 完全。但我只想理解没有 神化 ,使用之间有什么不同 类& lt;*& gt; VS Class<T>

    2 回复  |  直到 7 年前
        1
  •  5
  •   Willi Mentzel user670265    7 年前

    * 被称为 star-projection .当您必须指定一个泛型类型,但不关心它是什么类型时(可能是因为您不需要它)。


    因为这个问题与 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) }
    

    这将编译,简短而简洁。


    因此,在您的特定示例中,您应该使用 Class<*> 因为你根本不需要 T .

        2
  •  0
  •   Elye    7 年前

    两者都导致了完全相同的反编译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()));
      }
    }
    

    所以它们是一样的。就像@wili 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)
        }
    }