1.4 JRuby语言与Java语言实例分析
这一节我们用三个实例来说明JRuby语言和Java语言代码的差异,第一个实例是JRuby语言代码比Java语言代码更为简洁;第二个实例是Java语言的语法太死板,缺乏灵活性;第三个实例是Java语言的面向对象技术不彻底。
1.4.1 实例一:JRuby语言代码的简洁性
本实例展示JRuby语言的简洁特性。
这里有两个实例程序:Java语言程序如代码清单1-6所示,JRuby语言程序如代码清单1-7所示。它们都采用Java语言的类java.util.TreeMap进行代码编程。在这两个程序中,都使用空行将程序分成为三个部分,各部分的含义基本上是相同的。第一部分是定义该程序所需要的类;第二部分是创建基于类java.util.TreeMap的对象map,并且赋予这个对象初始值;第三部分是利用两门语言的不同技术获取对象map的键和值,并且显示它们的和。
代码清单1-6 Java语言程序JavaTreeMap.java
1 import java.util.Iterator;
2 import java.util.Map;
3 import java.util.TreeMap;
4 public class JavaTreeMap {
5 public static void main( String[] args ) {
6 TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
7 map.put( 1, 10 );
8 map.put( 21, 12 );
9
10 int memo = 0;
11 Iterator it = map.entrySet().iterator();
12 while (it.hasNext()) {
13 Map.Entry me = (Map.Entry)it.next();
14 memo = ((Integer)me.getKey()).intValue() + 【空一格继续】
((Integer)me.getValue()).intValue();
15 System.out.println(memo);
16 }
17 }
18 }
代码清单1-7 JRuby语言程序java_tree_map.rb
1 include Java 2 import java.util.TreeMap 3 map = TreeMap.new 4 map[1], map[21] = 10, 12 5 map.inject(nil) do |memo, (key,value)| 6 puts memo = key+value 7 end
现在来分析这两个程序的不同点。
从代码的数量和简易性角度看,两者的差异是显而易见的。
从理解代码的难度看,两门语言都有难点,但是它们的难易程度完全不同。JRuby语言的难点是第三段第5行代码,Java语言程序的难点也是在第三段,但是Java代码需要理解的内容明显多了许多。我们说明一下JRuby语言的第三段代码。这是使用了Ruby语言的代码块技术,它是Ruby语言中一种最常用的技术。这种技术在本书的第8章第4节中将会详细介绍。在JRuby程序中,函数inject的参数(其中的nil)是应用于变量memo的,而对象map的每一个元素是作用于表达式“(key,value)”的。注意:参数值nil仅仅在对象map的第一个元素出现时对变量memo有作用,之后这个变量memo的值就是nil。在这里开始函数inject的参数值就是nil,因此变量memo的值始终是nil。应该说,这一实例已经是Ruby语言的代码块技术中复杂的实例。
从代码记忆的角度看,每一门计算机语言都需要我们去记忆一些代码和技巧。在JRuby程序中,最需要记忆的技巧就是第5行代码。要是能够很好地理解这一行代码,那么对该方法的记忆也就很容易了。而Java语言的第三段代码,首先需要为对象map生成一个迭代器,之后利用这个迭代器来完成对对象map的元素的获取。
在JRuby语言中,可以利用交互工具jirb对每一行代码进行分析,这是一件非常容易的事情。在本书的第2章第4节中详细说明了工具jirb的使用方法。该工具的启动命令如代码清单1-8所示。在Windows系统的DOS窗口下输入这个命令,会出现“ (main):001:0>”,这说明已经进入了jirb的交互环境,可以输入JRuby语言程序代码了。注意:这个命令已经把程序代码清单1-7的第1行代码包括进去了。前面已经提及过,该工具最简单的启动命令也可以是jirb。
代码清单1-8交互工具jirb的启动命令方法
jirb -rjava
接下来就可以在jirb的交互环境下输入代码清单1-7中第2行以后的其他代码,结果如代码清单1-9所示。
代码清单1-9交互工具jirb的启动命令操作输出结果
irb(main):001:0>irb(main):001:0>import java.util.TreeMap => Java::JavaUtil::TreeMap irb(main):002:0>map = TreeMap.new => #<Java::JavaUtil::TreeMap:0x1b9f88b @java_object={}> irb(main):003:0>map[1] = 10 => 10 irb(main):004:0>map[21] = 12 => 12 irb(main):005:0>map.inject(nil) do |memo, (key,value)| irb(main):006:1* p memo = key+value irb(main):007:1>end 11 33 => nil irb(main):008:0>exit
1.4.2 实例二:JRuby语言代码的灵活性
第二个实例是想说明Java语言与JRuby语言在语法方面的差异性。程序的代码分别是代码清单1-10和代码清单1-11。
在代码清单1-10的Java语言程序中,有个关键词switch,而在代码清单1-11的JRuby语言程序中也有类似的关键词case,并且它们的使用方法是类似的,但是它们的功能就大不一样。在Java语言中,switch的判断变量(key)必须是int类型或者enum类型(这种数据类型只有Java版本5.0及其以后版本才能够使用)。在软件开发的实践中,这种限制会带来很多不便,如代码的类型转换等问题。而JRuby语言的关键词case后面的判断变量可以是任何类型的。JRuby语言的关键词case的功能还有更多,这里就不一一细说了。
代码清单1-10包含有关键词switch的Java语言程序
public class JavaSwitch { public static void main(String[] args) { int key = 0; switch (key) { case 1: break; default: break; } } }
代码清单1-11包含有关键词case的JRuby语言程序
1 color = "red" 2 case color 3 when "red" 4 puts color 5 when "yellow" 6 puts color 7 else 8 puts "default color" 9 end
1.4.3 实例三:Java语言面向对象的不彻底性
第三个实例是想要说明一下程序语言的面向对象特点。
尽管Java语言也是号称面向对象的计算机语言,但其实它很多地方并非如此,如Java语言的数据类型int就不是类的对象。但是Java语言也确实存在一个整数类Integer,不过这已是一种不得已的补充。
下面再给出另外一个非面向对象的Java语言代码实例,如代码清单1-12所示。在这个程序中,给出了一个非面向对象的类System和一个面向对象的类Runtime。程序中的两组代码(第一组是第3行,第二组是第4行和第5行)的功能是完全一样的,即都是退出当前运行的程序,返回一个默认值。但是类Runtime的对象能够做更多的事情,正如类Integer和int一样。由此可以看出,Java语言的面向对象的特性是在不断地被完善的。
代码清单1-12包含类System的Java语言程序
1 public class JavaSystem { 2 public static void main(String[] args) { 3 System.exit(0); // 4 Runtime system = Runtime.getRuntime(); // 5 system.exit(0); 6 } 7 }