【问题标题】:How to call T eq(Object) method of Java interface from Scala?如何从Scala调用Java接口的T eq(Object)方法?
【发布时间】:2011-08-31 21:47:24
【问题描述】:

Scala 定义了一个 AnyRef 类,它在编译后被解释为 Java 的 Object 类。然而,从语言的角度来看,AnyRef 类并不完全等同于 Object,因为它引入了几个新方法,例如 eq(),它接受 AnyRef 并返回布尔值并比较引用的身份

如果 Java 中有一个类,它本身定义了具有不同结果类型的 eq() 方法,并且该类实现的接口也具有此方法:

public interface I {
    String eq(Object that);
}

public class A implements I {
    public String eq(Object that) {return "";}
}

如果通过接口引用调用,Scala 代码将无法访问其 eq 方法

val i: I = new A
val a = new A
val b = Some(1)           //whatever actually
val s1: String = a.eq(b)   //compiles OK
val s2: String = i.eq(b)   //compilation error

Scala 在这里知道的 eq 方法是 AnyRef 类中的 eq 方法被“粘合”到接口 I,它来自 Java,没有该方法,但它自己的 eq() 方法具有不同的结果类型。 我可以解释这种行为,但是当我不得不调用这个 Java eq() 方法而无法修改 Java 第三方库的代码时,我无法解决现实生活中的任务。 也就是说,我说的是 Liferay 及其动态查询 API 和名为 com.liferay.portal.kernel.dao.orm.Property 的接口。它有一个 eq() 方法,接受 Object 并返回 Criterion。此代码无法在 Scala 中编译:

val query = DynamicQueryFactoryUtil.forClass(classOf[BookmarksEntry])
.add(PropertyFactoryUtil.forName("folderId").eq(new Long(folderId)))

因为 eq 不会被正确解释。 顺便提一下,Property 类有另一个重载的 eq() 方法,它以 DynamicQuery 作为参数。这个重载可以从 Scala 访问。

你知道有什么方法可以从 Scala 调用 Java 接口的 eq(Object) 方法吗?

使用的 Scala 版本是 2.8.1

【问题讨论】:

  • 你试过a.eq(b.asInstanceOf[Object])吗?
  • 对我有用,没有编译错误,并且调用了正确的方法。
  • 不幸的是它没有帮助。我更新了描述,这里还有一个界面在起作用
  • @Lex,抱歉,已解决问题,感谢您的努力
  • 我不是反思方面的专家,但您能以这种方式获得这种方法吗?

标签: java scala


【解决方案1】:

有趣的问题:我以前没见过这个。我不知道如何在 Scala 中解决它,或者即使有可能。然而,在这种情况下,您能做的最好的事情就是在 Java 中创建一个包装器。例如:

public class Eq {
    static public String eq(I obj, Object that) {
        return obj.eq(that);
}

然后您只需拨打Eq.eq(x, y) 而不是x.eq(y)

【讨论】:

  • 是的,如果没有直接的 Scala 方式,它真的会这样结束。我会等待其他想法并将其标记为正确答案。谢谢!
【解决方案2】:

你可以通过反射来做到这一点,但我不知道这是否是你想要的,因为它有点难看。

FWIW,你可以这样做:

i.getClass().getMethod("eq", classOf[Object]).invoke(i, "a").asInstanceOf[String]

【讨论】:

  • 我的上帝。不得不做这样的事情是很可悲的。但它有效。
【解决方案3】:

我一定不能掌握一切,因为它看起来太明显了。如果(i:I).eq(o): String 不起作用但A.eq(o): String 起作用,为什么这不起作用?

scala> i.asInstanceOf[A].eq(b)
res2: java.lang.String = str

所以

val query = DynamicQueryFactoryUtil.forClass(classOf[BookmarksEntry])
  .add(PropertyFactoryUtil.forName("folderId").asInstanceOf[XYZ]
  .eq(new Long(folderId)))

(将XYZ替换为实例化的任何具体类,例如com.liferay.portal.dao.orm.hibernate.PropertyImpl

【讨论】:

  • Property 是一个接口,而不是一个类(参见docs.liferay.com/portal/5.1/javadocs/portal-kernel/com/liferay/…
  • @Alexey Romanov,Property 的具体子类是在运行时生成的吗?
  • 具体类驻留在一个 JAR 中,我不想依赖它来保持适当的分层和松散耦合。从技术上讲,您的解决方案有效,@huynhil,但一般来说,实现类可能是未知的、变化的或运行时生成的
猜你喜欢
  • 2012-04-09
  • 1970-01-01
  • 2019-12-27
  • 2018-05-03
  • 2010-11-11
  • 2015-10-31
  • 2018-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多