11.2 在Scala里使用Java类

在Scala里可以直接使用Java类。如果要用的Java类是标准JDK的一部分,直接用就是了。如果它不在java.lang里,就要导入类的包。下面用到了java.utiljava.lang.reflect包:

WorkingWithScriptsAndClasses/UseJDKClasses.scala

  1. import java.util.Date
  2. import java.lang.reflect._
  3. println("Today is " + new Date())
  4. val methods = getClass.getMethods()
  5. methods.foreach { method: Method => println(method.getName()) }

如果想用的Java类是你自己创建的,或是来自第三方,请确保scalac的classpath指向字节码的位置。假定我们有如下的Java文件:

WorkingWithScriptsAndClasses/InvestmentType.java

  1. //Java code
  2. package investments;
  3. public enum InvestmentType {
  4. SHORT_TERM,
  5. BOND,
  6. STOCK,
  7. REAL_ESTATE,
  8. COMMODITIES,
  9. COLLECTIBLES,
  10. MUTUAL_FUNDS
  11. }

WorkingWithScriptsAndClasses/Investment.java

  1. //Java code
  2. package investments;
  3. public class Investment {
  4. private String investmentName;
  5. private InvestmentType investmentType;
  6. public Investment(String name, InvestmentType type) {
  7. investmentName = name;
  8. investmentType = type;
  9. }
  10. public int yield() { return 0; }
  11. }

在Scala代码里使用这些类,同使用Scala类是一样的。下面是一个在Scala里创建Investment实例的例子:

WorkingWithScriptsAndClasses/UseInvestment.scala

  1. import investments._
  2. object UseInvestment {
  3. def main(args: Array[String]) {
  4. val investment = new Investment("XYZ Corporation", InvestmentType.STOCK)
  5. println(investment.getClass())
  6. }
  7. }

假设上面Java文件编译成的字节码位于名为classes/investments的目录下,可以这样编译Scala文件:

  1. scalac -classpath classes UseInvestment.scala

编译完成后这样运行代码:

  1. scala -classpath classes:. UseInvestment

另外,也可以用java运行:

  1. java -classpath \
  2. /opt/scala/scala-2.7.4.final/lib/scala-library.jar:classes:. UseInvestment

输出如下:

  1. class investments.Investment

Investment类的yield()方法需要小心使用。如果Java代码有方法或字段的名字(比如traityield等)与Scala的关键字冲突,调用它们会导致Scala编译器死掉。比如,下面的代码是不行的:

  1. val theYield1 = investment.yield //ERROR
  2. val theYield2 = investment.yield() //ERROR

幸运的是,Scala提供了一个解决方案。把冲突的变量/方法放到反引号里,就可以绕开这个问题。改一下代码就可以让上面的两个调用工作了:

  1. val theYield1 = investment.`yield`
  2. val theYield2 = investment.`yield`()