1

I'm new to Scala. I need help in resolving this issue.
I have built a project which is written in Scala and I'm trying to integrate it with a Java project. I have taken the dependency on the build scala jar in my Java project in eclipse. However when I call a method in the Scala jar I get ClassCastException when running the application:

Below is the exception I get

Exception in thread "main" java.lang.ClassCastException: com.rockymadden.stringmetric.phonetic.MetaphoneAlgorithm cannot be cast to com.rockymadden.stringmetric.StringFilter at com.rockymadden.stringmetric.phonetic.MetaphoneAlgorithm.compute(MetaphoneAlgorithm.scala:10) at org.gobe.search.dictionary.test.PhoneticTest.main(PhoneticTest.java:16)

What can I do to fix this ?

public static void main(String[] args) {
    MetaphoneMetric metric = new MetaphoneMetric();
    DummyImplicit di = new DummyImplicit();
    MetaphoneAlgorithm algo = new MetaphoneAlgorithm();
    char[] rr = {'h', 'e', 'l', 'l', 'o'};
    System.out.println(algo.compute(rr, di));
}

In the above code "MetaphoneMetric" , "DummyImplicit" are part of Scala Jar I generated.
Logic of Metaphone algorithm can be found at http://pastebin.com/d7CXjDtx

4

3 回答 3

3

查看代码,您MetaphoneAlgorithm的定义为:

class MetaphoneAlgorithm extends StringAlgorithm[...] { this: StringFilter =>
 ...
}

重要的是this: StringFilter =>。由于StringAlgorithm尚未实现StringFilter,因此需要混合这种 self 类型来创建MetaphoneAlgorithm.

在斯卡拉你会做:

val algo = new MetaphoneAlgorithm with StringFilter

编辑:正如@a​​im 回答的那样,这正是MetaphoneAlgorithm.apply()返回的结果。这可能就是你想要的。

或者您将创建一个新类:

class MyAlgo extends MetaphoneAlgorithm with StringFilter

// and then
val algo = new MyAlgo

如果您希望能够MetaphoneAlgorithm with StringFilter在 java 端创建一个:

查看您的StringFiltertrait,它应该是 java 端的接口。

编辑:可悲的是,它将StringFilter变成一个抽象类。提供与 java 的兼容性的方法是StringFilter完全抽象:

trait StringFilter extends Filter[String] with StringFilterable {
  override def filter(charArray: Array[Char]): Array[Char]
}

以及Filtertrait,然后定义MetaphoneAlgorithm.apply()为返回:

def apply(): MetaphoneAlgorithm = new MetaphoneAlgorithm with StringFilter
  with DefaultStringFilter

作为您的DefaultStringFilter默认StringFilter实现(当前在 中StringFilter,它也实现在 中定义的方法Filter)。

通过这种更改,这在 java 端成为可能:

public class MyAlgo extends MetaphoneAlgorithm implements StringFilter {
  /* implement StringFilter here */
}

main然后在你的方法中实例化那个。

这有点混乱,但允许您StringFilter在 java 端定义自定义实现。


错误消息本身来自将(未写入的)this转换为StringFilter,因此我可以理解为什么该错误令人惊讶。

附带说明一下,有趣的是,MetaphoneAlgorithm考虑到它不可能工作,它可以让您直接实例化该类。我不确定这是否可以避免,但这是另一个有趣的 scala/java 兼容性问题。

于 2013-07-29T09:26:10.277 回答
1

请检查:

Predef.DummyImplicit di = new Predef.DummyImplicit();
MetaphoneAlgorithm algo = MetaphoneAlgorithm.apply();
char[] rr = {'h', 'e', 'l', 'l', 'o'};
System.out.println(Arrays.toString(algo.compute(rr, di).get()));
于 2013-07-29T09:25:33.020 回答
0

您已MetaphoneAlgorithm使用自类型注释定义:

class MetaphoneAlgorithm { this: StringFilter =>

这意味着该类不能被使用,除非它具有StringFilter混入(例如new MetaphoneAlgorithm() with MyCoolStringFilter)的特征。

由于您没有在示例中执行此操作,而您只是在构造一个 plain MetaphoneAlgorithm,因此代码无效。Scalac 会让它编译,但是 Java 编译器不理解 Scala 的注释,这些注释告诉它为什么这不起作用 - 所以你在运行时会出错。

事实上,我认为在纯 Java 代码中根本不可能做到这一点,因为您无法创建一个混入 trait* 的匿名类。如果你打算在 Java 中使用 Scala 类,那么考虑你希望 Java 用户调用什么接口是有意义的,然后确保你不要用它做任何太 Scala-y 的事情。

*好吧,如果你真的有动力,我想你可能会这样做,但你必须看看 Scala 如何在字节码级别编译 mixin,然后尝试模仿它。它会非常脆弱,而且不值得。

于 2013-07-29T09:26:10.633 回答