- 浏览: 308242 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
suxiaojack:
15题,就是拿杨辉三角填充空格,答案应该是C(38,19)吧? ...
Project Euler解题汇总 013 ~ 022 -
songhaikang:
这篇文章挺好的,跟着你的步骤很快就可以入门了。非常感谢。
[转贴]Derby入门 —— (1) -
Eastsun:
呵呵,我没有Android的机器,所以兴趣不大
使用Java写的GVmaker虚拟机(开源) -
crapricorn:
那个版本的用不了虚拟键盘啊 呵呵 我们的手机没有实体键盘呀 所 ...
使用Java写的GVmaker虚拟机(开源) -
Eastsun:
crapricorn 写道希望sun侠能做出个android平 ...
使用Java写的GVmaker虚拟机(开源)
原文地址:Java.next #2: Java Interop
翻 译:Eastsun
本文是Java.next系列的第二部分。在这一部分,我们来看Java.next语言如何与Java进行互操作。
在所有这些Java.next语言中,与Java互操作都是很简单的一件事。这得归功于Java虚拟机规范,它使得JVM上的其它语言能够很容易的反射以及调用Java代码。
一个Swing的例子
作为与Java互操作的第一个例子,考虑通过调用Swing API创建一个应用程序,使其包含:
● 一个窗口
● 一个按钮
● 点击按钮时弹出一个模式对话框
作为参照,这里先给出使用原始Java代码给出的实现:
接下来,我将使用Java.next中的语言来实现这个Swing应用。对于这些代码,有两点需要注意的地方:
■ 在这个例子中,我根据这些语言与Java语法差异从小到大的顺序呈现代码。这样做使得我们能从熟悉东西自然过渡到陌生的事物。
■ 下面这些实现并不是这些语言的最佳实践。它们被刻意简化,使得我们能将注意力集中在与Java的互操作上。在接下来的文章中,我将更多的展现这些语言的习惯用法。
Groovy的实现
Groovy是Java.next语言中与Java最相似的,下面是Groovy的实现代码:
与Java的实现对比一下可以发现,它们几乎一样。只不过省略了一些冗余的代码结构。Groovy版本使得我们能够忽略:
◇ 分号
◇ 类型声明
◇ 大部分括号
◇ 属性的Getter与Setter
Groovy版本的最大优势体现在事件监听器上,它展现了:
◇ 多行字符串(使用"""界定)
◇ 使用${}往字符串里插入it.actionCommand
◇ 不需要匿名内部类,简单的传递一个匿名函数
在SwingBuilder项目中可以看到如何用更符合Groovy习惯用法去使用Swing。
我们可以得出一个显而易见的结论:在Groovy中与Java互操作相当简单。
Scala的实现
接下来,让我们看看Scala的版本:
Scala版本与Groovy相对Java具有许多相同的优点:
◇ 更少的类型声明
◇ 更少的分号
◇ 更少的括号
我们还可以看到Scala独有的一些性质:
◇ 在Scala中import通配符是_而不是熟悉的*。*号具有其它意义
◇ Scala能够单行引入同一个package中的多个class
◇ 因为我们只需要一个实例,所以我们用object声明而不是class
◇ 该object继承了JFrame,Scala允许我们使用内嵌的方式调用JFrame的构造函数,而不必再单独声明一个构造函数
与Groovy一样,最大的不同是事件监听器。Scala同样允许我们简单的传入一个匿名函数,而不需要使用匿名内部类。
看起来很强大,只不过这儿我做了一个小小的弊。Scala是强类型语言,它不会自动将一个函数类型转换为一个ActionListener。因此上面的代码还不能被编译通过。幸运的是,Scala的隐式转换功能让我们拥有这个能力:强类型加上一个便利的类型系统。所有我们要做的是告诉Scala这个转换是合法的:
将上面的代码放到适当的位置,我们就能够在需要ActionListener的地方传入一个函数。
已经有多个将Swing包装为Scala的项目。使用这些库,你能够书写更加简洁的代码。作为示例,你可以参看ScalaGUI。
JRuby的实现
现在来看看JRuby的情形:
如果与之前Groovy的代码进行对比,你会发现它们几乎具有相同的特点:
◇ 更少的类型声明
◇ 更少的分号
◇ 更少的括号
◇ 简洁的属性访问(没有getter与setter)
◇ 多行字符串(使用END界定)
◇ 使用${}往字符串里插入it.actionCommand
相比而言,JRuby的ActionListener实现比Groovy稍微简单一点。JRuby能够自动根据block生成ActionListener:
在JRuby的例子中,我依照Ruby的命名方式来使用Java方法名:
Java程序员习惯Camel命名方式。为了便利,JRuby同时支持这两种命名方式:
由于Ruby语言的灵活性,鼓励试验不同的语法与Java交互,可以参看JRUBY-903以了解相关历史。如果想了解更符合JRuby习惯用法的Swing使用方式,可以看Profligacy 项目。
结论:在JRuby中,与Java互操作很简单。
Clojure的实现
这儿是Clojure的版本:
Clojure是一种Lisp方言,因此其语法与其它几种有着本质上的不同。这一点就得花上几个小时来讨论,但我们现在的焦点是与Java的互操作,所以我将这一点留给这系列以后文章来讨论。现在,让我们把注意力放到与Java互操作上来。
导入Java类是件很容易的事。import之后跟着一串参数,第一项是package,其余的是要导入到当前名字空间的class。注意,这样允许我们在一行中导入多个class。
创建一个Java实例也很简单,使用(class. &args)的形式:
有多种途径来调用Java类中的方法。你可以使用(.methodName obj &args)的方式来调用单个方法。对于静态方法,使用(class/method &args)的方式:
在Java中,可以通过x.y().z()的方式使用链式调用。在Clojure中你可以使用(.. x (y) (z))的方式:
最后的三个方法调用都是在frame对象上。使用Clojure的doto,你能够在一个对象上执行多次操作并避免每次都要重写这个对象:
与其它几个例子一样,事件监听器是最有趣的部分。在Clojure中,proxy能够动态创建Java实例,并允许你实现所需的接口与方法。
同JRuby一样,相对Groovy这个解决方案更具有普适性,同时需要使用更多的语法。同样,你能够构建自己的语法结构。
结论:在Clojure中与Java互操作很简单。
结论
在上面的例子中,我演示了Java.next可以方便的与Java互操作。每一个例子都使用了比Java更少的代码来操作Swing库。更重要的是,Java.next的版本抓住了问题的本质并简化了形式。
与Java的无缝衔接并不是衡量Java.next语言的首要标准,因为它们都做得很好。这里并没有体现出这些语言在复杂情形下的表现,但我认为它们与Java互操作的问题已经得到了根本的解决。
Java.next系列的前两篇文章中,我采用了接近Java语言的风格来展示Java.next语言的特性。有了这些基础,是时候去使用Java.next各自的习惯用法了。在本系列文章接下来的部分,我们将会看到Java.next语言如何支持领域特定语言。
翻 译:Eastsun
本文是Java.next系列的第二部分。在这一部分,我们来看Java.next语言如何与Java进行互操作。
在所有这些Java.next语言中,与Java互操作都是很简单的一件事。这得归功于Java虚拟机规范,它使得JVM上的其它语言能够很容易的反射以及调用Java代码。
一个Swing的例子
作为与Java互操作的第一个例子,考虑通过调用Swing API创建一个应用程序,使其包含:
● 一个窗口
● 一个按钮
● 点击按钮时弹出一个模式对话框
作为参照,这里先给出使用原始Java代码给出的实现:
// Java import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.JOptionPane; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class Swing { public static void main(String[] args) { JFrame frame = new JFrame("Hello Swing"); JButton button = new JButton("Click Me"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { JOptionPane.showMessageDialog(null, String.format("<html>Hello from <b>Java</b><br/>" + "Button %s pressed", event.getActionCommand())); } }); frame.getContentPane().add(button); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } }
接下来,我将使用Java.next中的语言来实现这个Swing应用。对于这些代码,有两点需要注意的地方:
■ 在这个例子中,我根据这些语言与Java语法差异从小到大的顺序呈现代码。这样做使得我们能从熟悉东西自然过渡到陌生的事物。
■ 下面这些实现并不是这些语言的最佳实践。它们被刻意简化,使得我们能将注意力集中在与Java的互操作上。在接下来的文章中,我将更多的展现这些语言的习惯用法。
Groovy的实现
Groovy是Java.next语言中与Java最相似的,下面是Groovy的实现代码:
// Groovy import javax.swing.JFrame import javax.swing.JButton import javax.swing.JOptionPane import java.awt.event.ActionListener frame = new JFrame("Hello Swing") button = new JButton("Click Me") button.addActionListener({ JOptionPane.showMessageDialog(null, """<html>Hello from <b>Groovy</b> Button ${it.actionCommand} pressed""") } as ActionListener) frame.contentPane.add button frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE frame.pack() frame.visible = true
与Java的实现对比一下可以发现,它们几乎一样。只不过省略了一些冗余的代码结构。Groovy版本使得我们能够忽略:
◇ 分号
◇ 类型声明
◇ 大部分括号
◇ 属性的Getter与Setter
Groovy版本的最大优势体现在事件监听器上,它展现了:
◇ 多行字符串(使用"""界定)
◇ 使用${}往字符串里插入it.actionCommand
◇ 不需要匿名内部类,简单的传递一个匿名函数
在SwingBuilder项目中可以看到如何用更符合Groovy习惯用法去使用Swing。
我们可以得出一个显而易见的结论:在Groovy中与Java互操作相当简单。
Scala的实现
接下来,让我们看看Scala的版本:
// Scala (almost right, see below) import javax.swing._ import java.awt.event.{ActionEvent, ActionListener} object HelloWorld extends JFrame("Hello Swing") { def showButtonMessage(msg: String) = JOptionPane.showMessageDialog(null, String.format("""<html>Hello from <b>Scala</b>. Button %s pressed""", Array(msg))); def main(args: Array[String]) { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) val button = new JButton("Click Me") button.addActionListener((e:ActionEvent) => showButtonMessage(e.getActionCommand.toString)) getContentPane add button pack setVisible(true) } }
Scala版本与Groovy相对Java具有许多相同的优点:
◇ 更少的类型声明
◇ 更少的分号
◇ 更少的括号
我们还可以看到Scala独有的一些性质:
◇ 在Scala中import通配符是_而不是熟悉的*。*号具有其它意义
◇ Scala能够单行引入同一个package中的多个class
◇ 因为我们只需要一个实例,所以我们用object声明而不是class
◇ 该object继承了JFrame,Scala允许我们使用内嵌的方式调用JFrame的构造函数,而不必再单独声明一个构造函数
与Groovy一样,最大的不同是事件监听器。Scala同样允许我们简单的传入一个匿名函数,而不需要使用匿名内部类。
button.addActionListener((e:ActionEvent) => showButtonMessage(e.getActionCommand.toString))
看起来很强大,只不过这儿我做了一个小小的弊。Scala是强类型语言,它不会自动将一个函数类型转换为一个ActionListener。因此上面的代码还不能被编译通过。幸运的是,Scala的隐式转换功能让我们拥有这个能力:强类型加上一个便利的类型系统。所有我们要做的是告诉Scala这个转换是合法的:
// Yes, we can implicit def actionPerformedWrapper(func: (ActionEvent) => Unit) = new ActionListener { def actionPerformed(e:ActionEvent) = func(e) }
将上面的代码放到适当的位置,我们就能够在需要ActionListener的地方传入一个函数。
已经有多个将Swing包装为Scala的项目。使用这些库,你能够书写更加简洁的代码。作为示例,你可以参看ScalaGUI。
JRuby的实现
现在来看看JRuby的情形:
include Java import javax.swing.JFrame import javax.swing.JButton import javax.swing.JOptionPane import java.awt.event.ActionListener button = JButton.new "Click Me" button.add_action_listener do |evt| JOptionPane.showMessageDialog(nil, <<-END) <html>Hello from <b>JRuby</b>. Button '#{evt.getActionCommand()}' clicked. END end frame = JFrame.new "Hello Swing" frame.content_pane.add button frame.default_close_operation = JFrame::EXIT_ON_CLOSE frame.pack frame.visible = true
如果与之前Groovy的代码进行对比,你会发现它们几乎具有相同的特点:
◇ 更少的类型声明
◇ 更少的分号
◇ 更少的括号
◇ 简洁的属性访问(没有getter与setter)
◇ 多行字符串(使用END界定)
◇ 使用${}往字符串里插入it.actionCommand
相比而言,JRuby的ActionListener实现比Groovy稍微简单一点。JRuby能够自动根据block生成ActionListener:
button.add_action_listener { |evt| # do stuff }
在JRuby的例子中,我依照Ruby的命名方式来使用Java方法名:
# Ruby frame.content_pane
Java程序员习惯Camel命名方式。为了便利,JRuby同时支持这两种命名方式:
# Groovy, Scala, or JRuby frame.contentPane
由于Ruby语言的灵活性,鼓励试验不同的语法与Java交互,可以参看JRUBY-903以了解相关历史。如果想了解更符合JRuby习惯用法的Swing使用方式,可以看Profligacy 项目。
结论:在JRuby中,与Java互操作很简单。
Clojure的实现
这儿是Clojure的版本:
; Clojure ; Clojure (import '(javax.swing JFrame JButton JOptionPane)) (import '(java.awt.event ActionListener)) (let [frame (JFrame. "Hello Swing") button (JButton. "Click Me")] (.addActionListener button (proxy [ActionListener] [] (actionPerformed [evt] (JOptionPane/showMessageDialog nil, (str "<html>Hello from <b>Clojure</b>. Button " (.getActionCommand evt) " clicked."))))) (.. frame getContentPane (add button)) (doto frame (setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) pack (setVisible true)))
Clojure是一种Lisp方言,因此其语法与其它几种有着本质上的不同。这一点就得花上几个小时来讨论,但我们现在的焦点是与Java的互操作,所以我将这一点留给这系列以后文章来讨论。现在,让我们把注意力放到与Java互操作上来。
导入Java类是件很容易的事。import之后跟着一串参数,第一项是package,其余的是要导入到当前名字空间的class。注意,这样允许我们在一行中导入多个class。
(import '(javax.swing JFrame JButton JOptionPane))
创建一个Java实例也很简单,使用(class. &args)的形式:
(JFrame. "Hello Swing")
有多种途径来调用Java类中的方法。你可以使用(.methodName obj &args)的方式来调用单个方法。对于静态方法,使用(class/method &args)的方式:
(JOptionPane/showMessageDialog nil "A message")
在Java中,可以通过x.y().z()的方式使用链式调用。在Clojure中你可以使用(.. x (y) (z))的方式:
(.. frame (getContentPane) (add button))
最后的三个方法调用都是在frame对象上。使用Clojure的doto,你能够在一个对象上执行多次操作并避免每次都要重写这个对象:
(doto frame (setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) pack (setVisible true)))
与其它几个例子一样,事件监听器是最有趣的部分。在Clojure中,proxy能够动态创建Java实例,并允许你实现所需的接口与方法。
(proxy [ActionListener] [] (actionPerformed [evt] {do stuff here...}))
同JRuby一样,相对Groovy这个解决方案更具有普适性,同时需要使用更多的语法。同样,你能够构建自己的语法结构。
结论:在Clojure中与Java互操作很简单。
结论
在上面的例子中,我演示了Java.next可以方便的与Java互操作。每一个例子都使用了比Java更少的代码来操作Swing库。更重要的是,Java.next的版本抓住了问题的本质并简化了形式。
与Java的无缝衔接并不是衡量Java.next语言的首要标准,因为它们都做得很好。这里并没有体现出这些语言在复杂情形下的表现,但我认为它们与Java互操作的问题已经得到了根本的解决。
Java.next系列的前两篇文章中,我采用了接近Java语言的风格来展示Java.next语言的特性。有了这些基础,是时候去使用Java.next各自的习惯用法了。在本系列文章接下来的部分,我们将会看到Java.next语言如何支持领域特定语言。
评论
2 楼
hite
2008-11-30
我讨厌,swing是因为每个组件都要j打头,烦不烦!宁愿用swt后者awt写自己使用的小工具
1 楼
Eastsun
2008-09-20
第一部分的翻译见:Java.next:第一部分——共同点
发表评论
-
JavaFX1.2的性能貌似有了很大的提升
2009-06-03 09:36 1981Osvaldo Pinali Doederlein's B ... -
Java.next:第一部分——共同点
2008-09-19 13:31 1541原文地址:Java.next: Common Ground ... -
隐式转换:比动态类型更强大?
2008-09-16 18:37 1672本文内容主要来自Implicit Conversions: ... -
澄清:Java中只有按值传递,没有按引用传递!
2008-07-13 22:23 3982前言:在JAVA面试题解惑系列(五)——传了值还是传了引用 ... -
Ruby,Python不能威胁到Java的13个理由
2008-05-28 22:50 1481最近,danielstoner发表了一篇题为13 reas ... -
Java:进化的尽头
2008-05-28 17:45 1304原文地址:http://blog. ... -
《Effective Java》: Joshua Bloch访谈
2008-05-23 00:52 2613原文地址:Effective ... -
JSR 308:Java语言复杂度在恣意增长?
2008-05-20 13:54 1759原帖地址:http://www ... -
Sun能否让Java重振雄风?
2008-05-13 14:42 0原文地址:Can Sun rejuvenate Java? ... -
Groovy, JRuby, Jython, Scala:谁是胜利者?
2008-05-13 00:04 6557原文地址:Groovy, JRuby, Jython, Sca ... -
JAVA比C++更快?
2008-04-08 15:03 2043首先:我必须承认,我取JA ... -
在J2ME中模拟C语言中的文件操作
2008-02-27 00:09 1616最近在写一个模拟器(OR虚拟机),用于运行文曲星(一种 ... -
使用StAX解析XML:使用定制事件和编写 XML
2007-10-12 23:01 2103除了提供一个低层的基 ... -
使用StAX解析XML: 拉式解析和事件
2007-10-08 20:53 33052007 年 7 月 05 日 Streaming API ... -
[转载]Streaming API for XML (StAX) 简介
2007-10-07 13:35 2307Streaming API for XML (StAX) 是用 ... -
使用CookieHandler管理Cookie数据
2007-05-31 23:22 10886前言 : 因为只学过J2SE部分,对JAVA网络编程也不甚了 ... -
浅谈HTTP的无状态性
2007-05-30 01:26 2033HTTP是Hyper Text Transf ... -
用动态代理进行修饰
2007-04-11 16:26 1847动态代理为实 ... -
一种得到代码所在行号的方法
2007-04-02 20:03 3919RT,今天在论坛上看到有人提出这个问题,马上联想 ... -
网络词汇表
2007-04-01 13:33 1997【协议 】--- protocol,指通信双方通信时遵守的一 ...
相关推荐
2. **Statement 和 PreparedStatement**: 这是JDBC中用于执行SQL语句的两种主要对象。Statement用于执行静态SQL语句,而PreparedStatement可以预编译SQL语句,提高执行效率,同时提供更好的安全性,防止SQL注入。 3...
java.util.LinkedList$ListItr.next(LinkedList.java:886) JMeter.plugins.functional.samplers.websocket.ServiceSocket.getResponseMessage(ServiceSocket.java:125) JMeter.plugins.functional.samplers....
### Java.util.Date与Java.sql.Date互转及字符串转换为日期时间格式 #### 一、Java.util.Date与Java.sql.Date的基本概念 在Java编程语言中,处理日期和时间时经常使用到`java.util.Date`和`java.sql.Date`这两个类...
2. 创建一个单独的`Scanner`对象,并将其作为参数传递给需要读取输入的方法。这种方法允许在所有读取完成后在一个集中的地方关闭`Scanner`。 3. 使用一个静态的`Scanner`对象,直到不再需要读取输入时才关闭它。...
Java.util.ConcurrentModificationException 异常问题详解 ConcurrentModificationException 异常是 Java 中一个常见的异常,它发生在 Iterator 遍历集合时,集合同时被修改引起的异常。在 Java 中,集合类如 ...
java.util.ConcurrentModificationException 解决方法 ... at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) 例如以下程序(转
- **通道(Channel)**:Java NIO 中的通道主要有以下几种实现形式: - **FileChannel**:用于文件的读写操作。 - **DatagramChannel**:用于 UDP 数据报的发送和接收。 - **SocketChannel** 和 **...
Java.util.Date与java.sql.Date的互转及字符串转换为日期时间格式 java.util.Date和java.sql.Date是Java中两个常用的日期时间类,分别属于不同的包。java.util.Date是Java标准库中的日期时间类,而java.sql.Date是...
它的值也是从1970年1月1日开始的毫秒数,不过在创建`java.sql.Date`对象时,会忽略掉时间部分,确保始终表示一天的开始——0点0分0秒。因此,当你通过`new java.sql.Date(new java.util.Date().getTime())`创建`java...
这篇博文主要总结了Java程序中与Oracle数据库交互的一些基本操作。通过`PersonCreditComplainDao.java`这个文件名,我们可以推测这是一个Java Dao(数据访问对象)类,它负责与数据库进行具体的交互。以下是关于Java...
2. `java.io.IOException`:这是所有I/O异常的基类,用于处理输入/输出操作中的错误。 3. `java.util.List`:List接口定义了有序的集合,允许有重复元素,并提供了按索引访问的方法。 4. `java.util.HashMap`:...
2. **使用同步控制:** 如果多线程环境中的并发修改是必须的,你可以通过添加`synchronized`关键字来锁定修改集合的代码块,确保同一时间只有一个线程可以执行修改操作。对于遍历部分,同样需要锁定,但请注意,...
在Java编程中,连接Oracle数据库通常需要使用Java Database Connectivity(JDBC)技术,这是一个Java API,它使得Java程序能够与各种数据库进行交互。Oracle JDBC驱动是Oracle公司提供的用于连接Java应用和Oracle...
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class Greenplum { public static void main(String args[]) throws Exception{ ...
KingbaseV8 JDBC驱动是连接Kingbase数据库管理系统与Java应用程序之间的桥梁,允许Java开发者通过标准的Java Database Connectivity (JDBC) API来访问和操作KingbaseV8数据库。JDBC是Oracle公司提出的用于在Java程序...
2. 使用`CommPortIdentifier`获取可用的串口列表,根据需要选择一个合适的串口。 3. 打开串口,通过`CommPortIdentifier.open()`方法创建一个`SerialPort`实例。 4. 配置串口参数,如波特率、数据位、停止位和校验位...
2. **建立连接**: 使用`java.sql.DriverManager`类的`getConnection()`方法建立连接。例如: ```java String url = "jdbc:oracle:thin:@//hostname:port/service_name"; String username = "your_username"; ...