【问题标题】:Scala Generic Parameter Type passed to Java Generic container传递给 Java 通用容器的 Scala 通用参数类型
【发布时间】:2013-04-30 07:48:36
【问题描述】:

问题:如何将通用类型从 Scala 传递到 Java,以便 JavaContainer 中的下一个代码不会像这样失败:

I'm instance of SomeClass
Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    at main.java.JavaContainer.print(JavaContainer.java:19)
    at main.scala.Main$.print(Main.scala:13)
    at main.scala.Main$.main(Main.scala:17)
    at main.scala.Main.main(Main.scala)

对于这个问题,我有一个给定的(并且不可能从外部 Jar 更改 Java 类)我们称之为:JavaContainer

import java.lang.reflect.ParameterizedType;
public /* You can remove the final marking, the problem is still there */ final class JavaContainer<T> {
  private Class<T> clazz;
  public JavaContainer(Class<T> clazz) {
    this.clazz = clazz;
  }

  public void print() {
    /* This one works */
    try {
      T unknown = clazz.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      e.printStackTrace();
    }
    /* This one isn't */
    Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    System.out.println(persistentClass.getName());
  }
}

我还有一个 Java 类,将用作类型参数:SomeClass

public class SomeClass {
    public SomeClass() {
        System.out.println("I'm instance of SomeClass");
    }
}

现在我想创建一个名为 ScalaContainerScala

import main.java.{JavaContainer, SomeClass}

class ScalaContainer[T]()(implicit m:Manifest[T]) {
  val clazz = m.runtimeClass.asInstanceOf[Class[T]]
  val javaContainer : JavaContainer[T] = new JavaContainer[T](clazz)
}

我们在 Main 对象中也有我​​们的 main 方法。

object Main {

  def print{
    val main = new ScalaContainer[SomeClass]()
    main.javaContainer.print()
  }

  def main(args: Array[String]) {
    print
  }
}

【问题讨论】:

  • JavaContainer 似乎天生就坏了。调用getClass().getGenericSuperclass() 的行似乎假定T 将由扩展类解决(例如,Guava 的TypeToken 工作方式)。但是JavaContainer 被标记为final 所以这是不可能的。
  • 转载没有最后的标记,所以不是这样的。
  • 我认为你不明白我在说什么。需要有一个扩展JavaContainer&lt;SomeConcreteType&gt; 的类,以便T 可以被具体化为SomeConcreteType。写JavaContainer 的人是货物崇拜编程。
  • 问题是,当我在“Java 世界”中时,我可以传递任何我想要的东西,但是当类型来自“Scala 世界”时,情况并非如此,或者我错过了一些东西.

标签: java scala generics reflection


【解决方案1】:

Hrmmm.. 我正在尝试描绘您的代码以及它在做什么。这让我想起了将 Hibernate 与通用 DAO 一起使用,我已经做了很多,所以我想说你应该看看 http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/reflect/TypeToken.html,它会按照你设置的方式打印 SomeClass。这里还有TypeTools https://github.com/jhalterman/typetools

认为如果我正确理解您的问题,这应该会让您走上正确的道路。

【讨论】:

  • 你猜对了,这与 DAO 有关,尽管它不是休眠的,而是Morphia。有一个 BasicDao 类有这种行为,我为这个问题简化了这个。
  • 啊,我明白了。然后我肯定会检查 TypeToken。您可以直接使用它,也可以只看它是如何实现的。这是我在制作 daos 时能够解决类型擦除问题的方法之一。
  • 重点是我不想更改 Morphia 代码,我正在从 Scala 类中传递我可以更改的通用参数。即使我将它包装在 Scala 中,我认为这无论如何都会发生,因为代码失败是我无法企及的。无论如何我都会试一试。
  • 啊,我现在明白了。我不知道 java 片不是在你的控制之下。现在这困扰着我......我无法让它工作:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多