Archive

Archive for April, 2010

Swing : 将 System.out 重定向到 JTextArea 和 JTextPane

April 30th, 2010 leeing 1 comment

最近在用Swing 来编写图形用户界面,其中一个需求就是将System.out.println 的输出重定向到JTextArea组件中,刚开始使用的是《Java 标准输出重定向到GUI 》里的代码,但是在后台需要大量计算的时候,界面出现无响应的情况。后来又经过一番搜索,在 blogspot 找到了一篇文章: 《 Redirecting System.out and System.err to JTextPane or JTextArea》 ( 被墙了),可以实现实时输出的功能,不会出现缓慢的情况。

在 Swing 中,如果想将System.out和System.err 重定向到 JTextPane或者JTextArea,只需要覆盖OutputStream中的write() 方法来将文件附加到 text pane中。

JTextArea 版本:

  private void updateTextArea(final String text) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        textArea.append(text);
      }
    });
  }

  private void redirectSystemStreams() {
    OutputStream out = new OutputStream() {
      @Override
      public void write(int b) throws IOException {
        updateTextArea(String.valueOf((char) b));
      }

      @Override
      public void write(byte[] b, int off, int len) throws IOException {
        updateTextArea(new String(b, off, len));
      }

      @Override
      public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
      }
    };

    System.setOut(new PrintStream(out, true));
    System.setErr(new PrintStream(out, true));
  }

Read more…

Categories: Java Tags: ,

Scala : “运算符” 重载

April 26th, 2010 leeing No comments

运算符带了双引号,这是因为从技术上来说,Scala 并没有所谓的“运算符”,在这里是指重载符号,如+ ,+- 等等。
在 Scala 中,事实上这些是方法的名字。但是由于 Scala 并不需要点来分隔对象引用和方法名,因而看起来像是运算符。调用 ref1+ref2 其实与 ref1.+(ref2)是等同的,调用的其实是 ref1 的+()方法。

举例如下:

class Complex(val real: Int, val imaginary: Int) {
    def +(operand: Complex) : Complex = {
        new Complex(real + operand.real, imaginary + operand.imaginary)
    }
    override def toString() : String = {
        real + (if (imaginary < 0) "" else "+") + imaginary + "i"
    }
}
val c1 = new Complex(1, 2)
val c2 = new Complex(2, -3)
val sum = c1 + c2
println("(" + c1 + ") + (" + c2 + ") = " + sum)

运行结果:

(1+2i) + (2-3i) = 3-1i

再次强调,Scala 并不存在运算符,所以没有定义运算符优先级,但是同时又定义了方法的优先级。方法的第一个字符用来决定它们的优先级,如果两个同等优先级的字符在同个表达式中出现,那左边的优先。

Read more…

Categories: Scala Tags:

Scala : 交互式应用程序,函数组合

April 26th, 2010 leeing No comments

函数和交互式应用程序

回调(callback)在交互式应用程序中是很常见的。例如一个按钮被点击,并进行一个特定的动作。在Web 应用程序中创建回调是尤其困难的,除非你拥有像Scala这样强大的工具。下面创建一个方法,它生成一个随机的String,以作为一个全局唯一的标识符(GUID)。

scala> def randomName() = "I"+ scala.util.Random.nextLong.abs
randomName: ()java.lang.String

然后定义一个通用的JavaScript trait, 我们不需要刷新它,假设它包含可以在浏览器中运行的JavaScript 命令。

scala> trait JavaScript
defined trait JavaScript

下面用一个能生成 JavaScript的函数来创建一个Map 以关联GUID:

scala> var callbacks: Map[String, () => JavaScript] = Map()
callbacks: Map[String,() => JavaScript] = Map()
scala> def register(f: () => JavaScript) = {
| val name = randomName
| callbacks += name -> f
| <button onclick={"invokeServerCall("""+name+""")"}>ClickMe</button>
| }
register: (f: () => JavaScript)scala.xml.Elem

当用户点击按钮时,会用 GUID 创建一个Ajax HTTP 请求,Servlet 在map中查找GUID,如果GUID存在,这个函数就会被调用并将JavaScript则返回给浏览器,这个功能的代码类型于:

Scala> def handleAjax(guid: String): HttpResponse =
functionMap.get(guid).map(f => f()) match {
case Some(javaScript) => JavaScriptResponse(javaScript)
case _ => Http404Response()
}

上面的代码是 Lift 框架的简化版本,可以看到,这种写法可以让程序员更关注于业务逻辑。

Read more…

Categories: Scala Tags:

Scala : 作用域中的变量,容器

April 25th, 2010 leeing No comments

Functions Bound to Variables in Scope

函数被绑定到创建函数时所在的作用域内中的变量,这样就允许承载状态,例如首先声明一个名为 foo 的变量:

scala> val foo = "dog"
foo: java.lang.String = dog

下面创建一个引用了这个变量的函数:

scala> val whoTo = (s: String) => s+" "+foo
whoTo: (String) => java.lang.String = <function1>

调用这个函数:

scala> whoTo("I love my")
res0: java.lang.String = I love my dog

scala> whoTo("I walk my")
res1: java.lang.String = I walk my dog

函数可以绑定于vars 或 vals ,甚至可以修改vars,首先,创建一个var strs,它是一个 List[String]:

然后创建一个以String为参数并返回String的函数,并且它能修改strs:

scala> var strs: List[String] = Nil
strs: List[String] = List()

scala> val strF = (s: String) => {strs ::= s; s+" Registered"}
strF: (String) => java.lang.String = <function1>

调用这个函数:

scala>  strF("a")
res2: java.lang.String = a Registered

scala> strF("b")
res3: java.lang.String = b Registered

scala> strs
res4: List[String] = List(b, a)

把这个函数作为参数:

scala> List("p", "q", "r").map(strF)
res5: List[java.lang.String] = List(p Registered, q Registered, r Registered)

scala> strs
res6: List[String] = List(r, q, p, b, a)

可以看到每一步都正确地更新了 strs。

Read more…

Categories: Scala Tags:

Scala : Partial Functions 和 Type Parameters

April 21st, 2010 leeing No comments

方法和函数是不同的,在Scala中,除了方法以外,一切都是一个实例。方法被附加到实例之上,并且被实例所调用。Function是实现了 FunctionNN trait (NN是指参数的个数,在 Scala 2.8 的文档中可知,NN 的取值范围是 1~22)的实例。在运行时函数没有什么特别的地方,但在编译阶段,有一些方式可以让编写一个函数使用很少的代码。

Partial Functions

Partial function 是只有部份参数被 apply 的函数,在Scala中,可以从方法中来构建 partially applied function:

scala> def plus(a: Int, b: Int) = "Result is: "+(a + b)
plus: (a: Int,b: Int)java.lang.String

scala> val p = (b: Int) => plus(42, b)
p: (Int) => java.lang.String =

partial function 允许你基于已有的方法或函数来构建新的函数,参数可以用不同的括号来分组:

scala> def add(a: Int)(b: Int) = "Result is: "+(a + b)
add: (a: Int)(b: Int)java.lang.String

这样,就可以用下面的語法来调用:

scala> add(1)(2)
res1: java.lang.String = Result is: 3

通过这个語法,你可以传递一个独立于其它参数的代码快作为参数:

scala> add(1){
| val r = new java.util.Random
| r.nextInt(100)
| }
res2: java.lang.String = Result is: 15

同时,也允许很容易地将一个方法提升为一个partially applied function:

scala> def w42(f: Int => String) = f(42)
w42: (f: (Int) => String)String

scala> w42(add(1))
res5: String = Result is: 43

最后,也可以通过partially applying一个方法将它转换为一个函数:

scala> def f2 = add(1) _
f2: (Int) => java.lang.String

此时,这个函数也能被传递给另一个方法:

scala> w42(f2)
res6: String = Result is: 43

Type Parameters

方法可以拥有类型参数:类型参数定义了其它的类型或方法的返回值类型。但注意函数不能接收类型参数,一个的参数和返回值必须在函数定义时创建。

Read more…

Categories: Scala Tags: