首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

面向 Java 开发人员的 Scala 指南 增强 Scitter 库-4

面向 Java 开发人员的 Scala 指南 增强 Scitter 库-4

兼容性但是,这又产生一个有趣的问题:从 Java 代码调用这个方法有多容易?毕竟,如果这个库的主要目标之一是维护与 Java 代码的兼容性,那么我们需要确保 Java 代码在使用它时不至于太麻烦。
我们首先通过我们的好朋友 javap 检验一下 Scitter 类:
清单 10. 哦,没错,Java 代码……我现在想起来了……
1
2
3
4
5
6
7
8
9
C:\>javap -classpath classes com.tedneward.scitter.Scitter
Compiled from "scitter.scala"
public class com.tedneward.scitter.Scitter extends java.lang.Object implements s
cala.ScalaObject{
    public com.tedneward.scitter.Scitter(java.lang.String, java.lang.String);
    public scala.List friendsTimeline(scala.Seq);
    public boolean verifyCredentials();
    public int $tag()       throws java.rmi.RemoteException;
}




这时我心中有两点担心。首先,friendsTimeline() 带有一个 scala.Seq 参数(这是我们刚才用过的重复参数特性)。其次,friendsTimeline() 方法和 Scitter 对象中的    publicTimeline() 方法一样(如果不信,可以运行 javap 查证),返回一个元素列表 scala.List。这两种类型在 Java 代码中有多好用?
最简单的方法是用 Java 代码而不是 Scala 编写一组小型的 JUnit 测试,所以接下来我们就这样做。虽然可以测试 Scitter 实例的构造,并调用它的 verifyCredentials() 方法,但这些并不是特别有用 — 记住,我们不是要验证 Scitter 类的正确性,而是要看看从 Java 代码中使用它有多容易。为此,我们直接编写一个测试,该测试将获取 “friends timeline” — 换句话说,我们要实例化一个 Scitter 实例,并且不使用任何参数来调用它的 friendsTimeline() 方法。
这有点复杂,因为需要传入 scala.Seq 参数 —scala.Seq 是一个 Scala 特性,它将映射到底层 JVM 中的一个接口,所以不能直接实例化。我们可以尝试典型的 Java null 参数,但是这样做会在运行时抛出异常。我们需要的是一个 scala.Seq 类,以便从 Java 代码中轻松地实例化这个类。
最终,我们还是在 mutable.ListBuffer 类型中找到一个这样的类,这正是在 Scitter 实现本身中使用的类型:
清单 11. 现在我明白了自己为什么喜欢 Scala……
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.tedneward.scitter.test;

import org.junit.*;
import com.tedneward.scitter.*;

public class JavaScitterTests
{
  public static final String testUser = "TESTUSER";
  public static final String testPassword = "TESTPASSWORD";
   
  @Test public void getFriendsStatuses()
  {
    Scitter scitter = new Scitter(testUser, testPassword);
    if (scitter.verifyCredentials())
    {
      scala.List statuses =
        scitter.friendsTimeline(new scala.collection.mutable.ListBuffer());
      Assert.assertTrue(statuses.length() > 0);
    }
    else
      Assert.assertTrue(false);
  }
}




使用返回的 scala.List 不是问题,因为我们可以像对待其他 Collection 类一样对待它(不过我们的确怀念 Collection 的一些优点,因为 List 上基于 Scala 的方法都假设您将从 Scala 中与它们交互),所以,遍历结果并不难,只要用上一点 “旧式” Java 代码(大约 1995 年时候的风格):
清单 12. 重回 1995,又见 Vector……
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.tedneward.scitter.test;

import org.junit.*;
import com.tedneward.scitter.*;

public class JavaScitterTests
{
  public static final String testUser = "TESTUSER";
  public static final String testPassword = "TESTPASSWORD";

  @Test public void getFriendsStatuses()
  {
    Scitter scitter = new Scitter(testUser, testPassword);
    if (scitter.verifyCredentials())
    {
      scala.List statuses =
        scitter.friendsTimeline(new scala.collection.mutable.ListBuffer());
      Assert.assertTrue(statuses.length() > 0);
      
      for (int i=0; i<statuses.length(); i++)
      {
        Status stat = (Status)statuses.apply(i);
        System.out.println(stat.user().screenName() + " said " + stat.text());
      }
    }
    else
      Assert.assertTrue(false);
  }
}




这将我们引向另一个部分,即将参数传递到 friendsTimeline() 方法。不幸的是,ListBuffer 类型不是将一个集合作为构造函数参数,所以我们必须构造参数列表,然后将集合传递到方法调用。这样有些单调乏味,但还可以承受:
清单 13. 现在可以回到 Scala 吗?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.tedneward.scitter.test;

import org.junit.*;
import com.tedneward.scitter.*;

public class JavaScitterTests
{
  public static final String testUser = "TESTUSER";
  public static final String testPassword = "TESTPASSWORD";
   
  // ...

  @Test public void getFriendsStatusesWithCount()
  {
    Scitter scitter = new Scitter(testUser, testPassword);
    if (scitter.verifyCredentials())
    {
      scala.collection.mutable.ListBuffer params =
        new scala.collection.mutable.ListBuffer();
      params.$plus$eq(new Count(5));
      
      scala.List statuses = scitter.friendsTimeline(params);

      Assert.assertTrue(statuses.length() > 0);
      Assert.assertTrue(statuses.length() == 5);
      
      for (int i=0; i<statuses.length(); i++)
      {
        Status stat = (Status)statuses.apply(i);
        System.out.println(stat.user().screenName() + " said " + stat.text());
      }
    }
    else
      Assert.assertTrue(false);
  }
}




所以,虽然 Java 版本比对应的 Scala 版本要冗长一点,但是到目前为止,从任何要使用 Scitter 库的 Java 客户机中调用该库仍然非常简单。好极了。
返回列表