
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名、虚拟主机、营销软件、网站建设、杏花岭网站维护、网站推广。
本文转载自微信公众号「小二十七」,作者肖斌2 。转载本文请联系小二十七公众号。
前言
这篇文章示例代码比较多, Java 程序员可以看到一些 Ruby 相关语法和使用,Ruby 程序员可以看看 Java 的基本语法和使用方法,本文比较长,将近万字左右,预计需要十几分钟,如果有耐心读完文章的话,你将获得和了解:
网上单独介绍 Ruby ,Java 的文章应该很多,但是对比两种编程语言的基本语法使用的文章应该不多见,写这篇文章的目的主要是对自己近期几个月学习 Ruby 做总结和回顾,我之前最熟悉的编程语言是 Java,我个人认为合格的程序员应该掌握多门语言,多学一门语言没有坏处,在解决问题的时候可以多些思路,在经历最近几个月的横向对比和使用感受,先抛我个人结论,在个人项目或者小型团队,技术能力较强的团队我推荐使用 Ruby, 在团队需要快速扩展和大型项目规划的情况下我推荐 Java,因为得益于 Java 语法的严谨性和安全性,很大程度上可以保证团队水平的下限,Java 较强的工程化规约和代码类型检查,可以保证新手不至于写出破坏性很强的代码,如果把两种语言作为一个简单的比如,最直观的感受就是可以把 Ruby 和 Java 比做金庸小说里的两把武器:
在很多人的印象中 Ruby 主要是在初创公司会比较流行,例如早期的 Airbnb,GitLab 都是使用 Ruby 作为开发语言,Ruby 是一门很灵活也很优雅的动态语言,解释运行,有兴趣了解的同学可以点开 链接 查看维基百科的词条,Ruby 语法精炼,做相同的事情代码行数通常会比 Java 要短的多,使用 Ruby 写程序的的过程是非常舒服的,因为不必拘泥于那些刻板强制的语法规范,可以让开发者随心所欲的表达自己的想法,不必强制分号结尾,不强制中括号,不强制方法参数长度等语法规范所限制,这种灵活的表达方式设计体现在语言使用的方方面面,并且如果你是用 Mac OS 则系统天生支持 Ruby 开发环境,在 Mac 终端 输入以下命令就可以看到 Ruby 版本号:
- ruby -v
 - # ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
 
然后只要在终端里面键入 irb 就可以进入调式模式,不像要运行 Java 程序首先安装 JDK 然后再配置环境变量 JAVA_HOME 和 CLASS_PATH 经过繁琐的配置才勉强可以执行 java 命令执行 class 程序,在 irb 模式下,对于简单的逻辑程序可以先在调式模式将代码写出来验证想法的可行后再加入到代码库中去,使用起来非常的方便,示例如下:
- >irb
 - >2.6.5 :001 > p "hello world"
 - # => "hello world"
 
下面简单的写一个 Hello World 程序进行对比,两种编程语言在打印 HelloWorld 程序上的写法,示例代码如下:
- // java print
 - public class Main {
 - public static void main(String[] args) {
 - System.out.println("hello world!"); // 注意分号结尾
 - }
 - }
 
- # ruby print
 - p "hello world!"
 
通过一个简单的 Hello World 程序你就可以发现两者的明显区别:
经过以上讲解,大家可能会对开始产生一些兴趣,不过这仅仅只是开始,后面主要简单介绍一下 Ruby 常用的对象,条件,循环,方法,运算符,数值,数组,字符串,散列等使用方法,本文不算严格意义的文章,因为示例代码量占了文章的 50% ,而且本文的特点就是会在语法将 Ruby 和 Java 进行对比,不过还是会讲解 Ruby 基本语法为主,本文偏入门级水平,介绍的内容都是平时使用比较的多的场景,暂时不会涉及到例如 Ruby 的 metaprogramming 和 Java 的 反射等较为深入的知识点,可能后续会有单独的文章进行分析,看完文章应该可以用写一些简单的程序用于跑一些简单的脚本应该是够用了,实际上脚本处理程序也正是 Ruby 很擅长的领域
补充:文章对比 Java,Ruby 两种语言在语法上的区别,并不是争论哪种编程语言的好坏优劣,我个人观点是:编程语言本身没有好坏之分,只有在不同场景下做出合适的选择,而且熟悉 Java 的同学也应该明白 Java 的优势从来都不在语言和语法层面,而是在生态,并发编程,虚拟机和稳定这些特性才是 Java 的核心竞争力,在生态上 Spring Framework为代表的高质量轮子覆盖 Java 应用的方方面面,可以说在轮子的多样性上面,暂时没有哪种语言可以跟 Java 抗衡,所以如果简单的用语法概括语言的好坏就非常以偏概全的看法,话不多说,我们进入正题,先列一下文章大纲,入门篇只会简单说一些基本语法:
多重赋值
每个变量单独赋值的场景大多相同,就不做介绍,在程序开发中,我们经常会把多个变量同时赋值,这样效率会高很多,每种语言对多重赋值的支持都不同,我们先通过一段代码对比 Java,Ruby 语言对于多重赋值的不同写法:
- // Java 多重赋值
 - int a, b, c = 1, 2, 3; // compile error
 - int a, long b, short c = 1, 2L, 3; // complier error
 - int a = 1, b = 2, c =3; // compile pass
 
- # Ruby 中多重赋值非常轻松
 - a, b, c = 1, 2, 3
 - # => [1, 2, 3]
 - # 兼容不同类型
 - a, s, c = 1, "2", 3
 - # => [1, "2", 3]
 - # 兼容不同长度
 - a, b, c = 1, 2
 - # => [1, 2, nil]
 - a, b, c, = 1, 2, 3, 4
 - # => [1, 2, 3] 自动裁掉超出的长度
 
结合以上案例感觉 Java 对多重赋值不是很友好,很多不合规范的语法在编译期就会被拦截并且报错,简单对比后总结:
条件判断
Ruby 的条件判断主要有以下三种:
先看实例和对比代码:
- a, b = 10, 20
 - p "a 比 b 大" if a > b
 - p "a 比 b 小" if a < b
 - # => a 比 b 小
 - # unless 条件就不多做介绍,用法刚好与 if 语句相反,类似java中的 != 运算符,实例代码:
 - a, b = 10, 20
 - p "a 和 b 不相等" unless a == b
 - # => a 和 b 不相等
 
- int a = 10, b = 20;
 - if (a > b) System.out.println("a 比 b 大"); // 在合作项目中还是推荐使用中括号 {}
 - if (a < b) System.out.println("a 比 b 小");
 - //=> a 比 b 小
 - int a = 10, b = 20;
 - if (a != b) System.out.println("a 和 b 不相等");
 - //=> a 比 b 小
 
还有 case 语句主要用于多条件进行判断,语句用法是 case~when~end 进行组合条件判断,功能跟 Java 中的 switch 相同,还有逻辑运算符 ==, !=, ||, && 都是通用的基本知识,所以就不写详细说明和写示例代码了,不然会显得很啰嗦
总结:条件判断语句用法非常简单,两种编程语言基本类似语言类似,不过还是有以下区别:
循环
Ruby 的循环结构语句比较丰富,相比 Java 只有 for,while 两种循环方式来说,Ruby 中的可用的循环方法有:time,while,each,for,until,loop,不过大多都异曲同工,就不一一介绍了,本章节主要围绕平时常用的几个需求来做一个简单的讲解,对比两种语言的使用区别,具体如下:
执行固定次数的循环是 time循环 方法的拿手好戏,用于和语句也很简单,如果不需要下标值,|i| 参数也是可以移除的,示例代码如下
- 3.time do |i| # i 也可以省略
 - p "第#{i}次打印"
 - end
 - # => 第0次打印
 - # => 第1次打印
 - # => 第2次打印
 
在 Java 中想要执行固定长度的循环,不能通过 forEach只能通过古老的 for..i 来实现,具体代码如下:
- for (int i = 0; i < 3; i++) {
 - System.out.println("第" + i + "次打印");
 - }
 - // 第0次打印
 - // 第1次打印
 - // 第2次打印
 
如何遍历一个数组?
在 Ruby 中通常会推荐使用 **each ** 不仅语法简单,而且可以轻松拿到元素值,示例代码如下:
- ["abc","efg","hmn"].each do |e|
 - p "#{e}!"
 - end
 - #=> abc! dfg! hmn!
 
Java 在 JDK 8 经过 Stream 和 Lambda 语法增强后,遍历数组也没有想象中那么古板,示例代码:
- Arrays.asList("abc", "dfg","hmn").forEach(e ->
 - System.out.println(e + "!")
 - );
 - // abc! dfg! hmn!
 
不过在平时遍历数组的时候经常会遇到一种需求,不仅想要拿到数组的元素,还需要拿到当前循环的索引值,Ruby 中提供一个特别的 each 方式实现,就是 each_with_index 方法,它会把 [元素, 索引] 传入到 do 代码块的后,具体示例代码:
- ["abc","def","ghi"].each_with_index do |e, i|
 - p "当前元素 #{e} , 以及第 #{i} 次循环"
 - end
 - #=> "当前元素 abc , 以及第 0 次循环"
 - #=> ...
 
Java 想要实现相同循环效果就不能用基于迭代器的 ForEach 实现了,只能用 for..i 实现,示例代码如下:
- List
 list = Arrays.asList("abc", "deg", "ghi"); - for (int i = 0; i < list.size(); i++) {
 - String e = list.get(i);
 - System.out.println("当前元素" + e + ",以及第 " + i + "次循环");
 - }
 - // 当前元素abc,以及第 0次循环
 - // ..
 
如何遍历一个 Hash ?
Hash 是 Ruby 的常用的对象,因此循环遍历获取 K,V 也是相当方便的,示例代码:
- hash = {name: "apple", age: 15, phone: "15815801580"}
 - hash.each do |k, v|
 - p "key: #{k}, value: #{v}"
 - end
 - #=> key: name, value: apple
 - #=> ...
 
Java 中最常用的 K-V 结构的 Hash 实现是基于 Map 接口的 HashMap,它是一种非线程安全的哈希表实现,之所以常用是因为它兼顾的效率和时间的平衡,内部是通过数组实现,采用使用链表法处理哈希冲突,JDK 8 后又引入 红黑树 解决哈希冲突过多导致链表过长的问题,这块就先不展开讲了,不然可以讲很久,示例代码展示 Java 如何遍历 Hash:
- Map
 hashMap = new HashMap<>(); - hashMap.put("name", "apple");
 - hashMap.put("age", "15");
 - hashMap.put("phone", "15815801580");
 - for (Map.Entry
 entry : hashMap.entrySet()) { - System.out.println("key :" + entry.getKey() + ", value : " + entry.getValue());
 - }
 - // key :name, value : apple
 - // ....
 
Java 遍历 Hash 的方式还有很多种,我们这里只展示最常用的用法,通过 ForEach 遍历 entrySet() 返回的集合即可。
最后再说一个有意思的循环方法,不过使用场景应该很少,一个没有终止的循环 loop方法,因为没有终止条件,所以必须依赖 break 关键字跳出循环,Java 也可以很轻松实现这种循环效果,只是语法上不同而已,我们可以看看以下实例对比:
- // java 使用 while(true) 或者 for(;;) 实现无限循环
 - while (true) System.out.println("i use java");
 
- # ruby 无限循环
 - loop do
 - p "i use ruby"
 - end
 
如果程序进入无限循环就只能通过 CTRL + C 来终止程序运行了 总结:循环上两种语言区别不大,Ruby 虽然循环方式多,但是平时常用的也就 each, for 会比较多,在循环上的区别,大多只是两种语言在语法上的区别
方法
分类
Ruby 中的方法大致可分为 3 类:
实例方法:Ruby 中的实例方法 Instance method 和 Java 中的普通方法类似,顾名思义就是调用方必须是一个类的实例(对象),需要调用实例方法就必须先通过类构造一个实例对象才能进行调用,具体请看示例代码:
- # ruby 中的实例方法
 - [1, 2, 3] .clear # 清理数组 => []
 - 100.to_s # int 转 string => "100"
 - "100".to_i # string 转 int => 100
 - ["a", "b", "c"].index("b") # 查找下标 => result: 1
 
- // java 中的实例方法
 - StringBuilder stringBuilder = new StringBuilder();
 - stringBuilder.append("abc"); // 实例方法 append
 - stringBuilder.append("efg");
 - List
 strList = new ArrayList<>(); - strList.add("abc"); // 实例方法 add
 - strList.add("efg");
 
类方法:Ruby 的类方法 class method 可以理解为 Java 的静态方法,就是需要类对象作为接收方的方法,指无需构建类的对象即可以直接通过类调用其自身的方法,大多常见于工具类当中,请看示例代码:
- // java 中的静态方法
 - Arrays.asList(T...a) // 数组转集合
 - Executors.newCachedThreadPool() // 创建线程池
 
- # ruby 中的类方法
 - Hash.new # 创建散列对象
 - Time.new # 创建时间对象
 
函数方法是指没有接收者的方法,这种类型方法在Java中倒是不存在,参考示例代码,例如上文中函数方法 p
- p "hello"
 - puts "print words"
 
定义实例方法
Ruby 定义方法非常简单,没有 Java 那么多的格式规范:修饰符:静态声明:返回值:方法名:(参数...),在方法声明的形式上要简单许多,主要通过 def 关键字定义,具体参考示例代码:
- // java define method
 - public static int add(int x, int y) {
 - return x * y
 - }
 - add(2, 5)
 - // 10
 
- # ruby define method
 - def add(x, y)
 - x * y
 - end
 - add(2, 5)
 - #=> 10
 - # 带默认值的方法
 - def add(x=2, y=6)
 - x * y
 - end
 - # 省略参数使用默认值调用方法
 - add
 - #=> 12
 - # 指定参数的方法
 - add(2, 5)
 - #=> 10
 
在方法的命名规则,两种语言还有如下区别:
返回值return:上面的 ruby 方法并没有声明 return 语句也可以拿到返回值,并不代表 ruby 没有 return 关键字,ruby 有一个特点就是如果没有声明 return 语句那么方法最后一个表达式会成为方法的返回值遵循这个约定所以上述的方法就可以省略 return 关键字,所以在日常开发中会较少的使用 return 关键字
定义类方法
前面讲过 Ruby 的类方法实际上就等于 Java 的静态方法,Ruby 中定义类方法的示例代码:
- # ruby 定义类方法
 - class Hello
 - # class << self 定义类方法的一种方式
 - class << self
 - def say_morning
 - p "hello good morning"
 - end
 - #... class << self 块后面还可以定义多个类方法
 - end
 - end
 - Hello.say_morning # 类方法
 - #=> "hello good morning"
 - h = Hello.new
 - h.say_morning # 如果用实例对象类方法就会报错!undefined method 'say_morning'
 
在 Java 中定义静态方法的示例:
- public class Hello {
 - public static void sayMorning() {
 - System.out.println("hello good morning");
 - }
 - public static void main(String[] args) {
 - Hello.sayMorning();
 - }
 - }
 - #=> "hello good morning"
 
定义方法也都是很简单的知识点,通过以上程序,我们可以得出:
Ruby 的特点是特定的功能都可以有N种不同的方式实现,所以定义类方法不但只有 class << self ~ end 还可以使用 def class_name.method_name ~ end 这种形式定义 class_name 是类名,method_name 为方法名,如果是在当前 class 上下文中可以像示例代码用同样的形式 def self.method_name ~ end 定义类方法
方法参数
默认参数 Rudy 的方法默认参数是我个人比较喜欢的特性,Java 程序里方法参数是强类型检查的,就是必须按照参数定义的类型进行传参,JDK 1.5 后 Java 也出了可变参的特性,不过因为实现效果不是很理性,目前在主流 Java 开发规范中还是不被推荐使用的,我们先看一段 Java 定义参数和使用参数的示例代码:
- // 方法要求类型,顺序,并且必传
 - public void show(String name, int age, String address) {
 - System.out.println(name + ", " + age + ", " + address);
 - }
 - // new Person().show("胖大海"); // 编译出错,参数不符合要求
 - // new Person().show("胖大海", 19); // 编译出错,参数不符合要求
 - new Person().show("胖大海", 19, "北京朝阳区"); // 编译通过输出:胖大海, 19, 北京朝阳区
 
Ruby 则会灵活一些,具体请看示例代码:
- # 无需声明类型,带默认值的参数可不传
 - def show(name, age=18, address="北京市")
 - p "#{name}, #{age}, #{address}"
 - end
 - Person.new.show("胖胖") #=> 输出:胖胖, 18, 北京市
 
不过对于可变参数两种语言的实现几乎相同,形式上都是对参数进行特殊标记,Java 是通过在参数前面加...标识,ruby 则在参数前面使用 * 号标识,解释器会对这种语法用数组进行转换,两者代码量也差不多,没有什么差别,简单看下示例代码:
- public void names(String ...names) {
 - System.out.println("params :" + Arrays.toString(names));
 - }
 - new Person().names("java", "ruby", "go", "c++");
 - // 输出结果 :params :[java, ruby, go, c++]
 
- def names(*names)
 - p "params: #{names}"
 - end
 - Person.new.names("java", "ruby", "go", "c++")
 - # 输出结果:params: [\"java\", \"ruby\", \"go\", \"c++\"]
 
简单通过 2 段代码的对比,我们可以对两种语言的方法参数得出以下结论:
方法的基本使用大概就讲到这里,函数方法定义平时使用不多就暂时先不聊,继续了解还可以看看:定义带块的方法,关键字参数等都是一些语法糖,就不详细讲解了,接下来聊聊类和模块
类和模块
类
Ruby 也是通过 class 关键字定义类,简单的用法参考以下代码:
- class Hello
 - end
 - h = Hello.new
 
Java 也是通过 class 定义类,不同的是最外层的类 Java 必须使用 public 进行修饰,具体请看示例代码:
- public class Hello {
 - public static void main(String[] args) {
 - Hello h = new Hello();
 - }
 - }
 
那么 Ruby 和 Java 在定义类方面有什么区别?
两种编程语言在构造函数上对比的示例代码:
- # 带构造函数的 Ruby 类
 - class Hello
 - def initialize(name="Ruby") # 默认参数
 - @name = name
 - end
 - def say_hello # 实例方法
 - p "hello #{@name} ! how are you?"
 - end
 - end
 - h = Hello.new("james")
 - h.say_hello
 - #=> "hello james ! how are you?"
 - // 带构造函数的 java 类
 - public class Hello {
 - private String name;
 - // 有参构造函数
 - public Hello(String youName) {
 - this.name = youName;
 - }
 - public void sayHello() {
 - System.out.println("hello! " +name+ " how are you ?");
 - }
 - public static void main(String[] args) {
 - Hello h = new Hello("jack");
 - h.sayHello();
 - }
 - }
 - #=> "hello! jack how are you ?"
 
方法聊到这里,下来聊聊方法里的常量
常量对比
如果在 Java 和 Ruby 中定义常量,参考示例代码:
- // Java 中定义常量
 - public class Hello {
 - // 常量必须是 static final 修饰,代表不可变
 - public static final String VERSION = "1.0";
 - public static void main(String[] args) {
 - // Hello.VERSION = "1.5"; // 尝试修改则会在编译期报错
 - System.out.println(Hello.VERSION);
 - }
 - }
 - #=>"1.0"
 - # Ruby 中定义常量
 - class PhoneNumber
 - BeiJing = "020"
 - GuangZhou = "021"
 - end
 - p PhoneNumber::BeiJing #=> "020"
 - p PhoneNumber::GuangZhou #=> "021"
 - Phonenumber::BeijING = "303" #=> Ruby 可以修改常量,不会报错,但会提示警告
 - p PhoneNumber.Beijing #=> ERROR undefined method !
 
在定义常量上的区别:
访问级别
Ruby 和 Java 在方法访问级别上没有什么很大不同,只是 Ruby 没有包(Package)的概念,所有自然也就没有 Java 里面的包访问权限,细节上但是还有些许区别,Ruby 的三种访问级别的定义方法,具体用法直接看示例代码:
- # 定义方法时声明访问权限
 - private def call_v1
 - p "call_v1 is private"
 - end
 - # 定义方法后,再设定访问权限
 - def call_v2
 - p "call_v2 is private"
 - end
 - private :call_v2 # 设定 call_v2 为 private
 - # 对代码块设定, 以下的方法定义为 private
 - private
 - def call_v3
 - p "call_v3 is private"
 - end
 - def call_v3
 - p "call_v4 is private"
 - end
 
Java 设定方法访问级别的方式则比较单一,只能在定义时声明:
- private String priv() {
 - return "priv is private";
 - }
 
综上所述,两种语言在访问级别的差异和总结:
Java 方法默认修饰符是 包访问权限
Ruby 方法默认访问级别是 public(initialize 例外)
Java 方法只能在定义的时候使用关键字设定访问级别
Ruby 常用的则有三种方式可以设定方法的访问级别,非常灵活
继承
Ruby 和 Java 的所有类都是基于 Object 的子类,Ruby 则还有更加轻量级的 BasicObject原始类,这里先不详细描述,继承这个概念也不多说,面向对象的基础知识,直接先看两种语言实现继承的方式
Ruby 通过 < 父类名 实现继承,示例代码:
- class Car
 - def drive
 - p "car start.."
 - end
 - end
 - class SuperCar < Car
 - def speed_up
 - p "speed to 200km ..."
 - end
 - end
 - s = SuperCar.new
 - s.drive
 - s.speed_up
 - #=> "car start.."
 - #=> "speed to 200km ..."
 
Java 通过 extends实现继承的,示例代码:
- class Car {
 - void drive(){
 - System.out.println("Car Start ...");
 - }
 - }
 - public class SuperCar extends Car {
 - void speedUp() {
 - System.out.println("speed to 200km...");
 - }
 - public static void main(String[] args) {
 - SuperCar c = new SuperCar();
 - c.drive();
 - c.speedUp();
 - }
 - }
 - // Car Start ...
 - // speed to 200km...
 
关于类的继承方面我们可以得出以下总结:
关于继承还有一些经验分享的就是,继承的特性更多用于重写父类和多态,如果是想要复用公共的功能,但是类之类没有明显的继承关系的话,就应该遵循组合优先大于继承的原则,不过在 Ruby 中很好的通过 Mix-in 扩展解决的继承这个问题
模块和Mix-in
模块使用 module 关键字创建,命名规则和类一样,首字母必须大写,我们先来看看如何创建模块
- module Display
 - def open
 - p "open display..."
 - end
 - end
 - Display.open # private method `open' called for Display:Module (NoMethodError)
 
模块是 Ruby 的特色功能,定位也很明确,有以下几个特点:
Ruby 中的模块提供的命名空间 namespace 概念就跟 Java 的包(Package)类似,都是用于区分相同的类,常量,Mix-in 结合 include 也就类似 Java 里面的静态导入,在 Java 中 import static 可以无需声明包路径直接调用导入类的变量和方法,所谓的 Mix-in 就是利用模块的抽象能力把非继承关系的类之间的共性进行抽象和复用,有些类似 AOP 的概念,可以使代码既强大又灵活
当我们用 OOP 思想对现实进行抽象的时候,会发现很多非继承关系又存在共同功能的事物,例如智能手机,手表继承自不同的父类,但是他们又都有看时间 watch_time的能力,我们用代码展现这种继承关系,请看示例代码:
- class Phone
 - def call
 - p "phone call.."
 - end
 - end
 - class IPhone < Phone
 - # iPhone 继承自 Phone 类,但是不仅可以打电话,还可以看时间
 - def watch_time
 - p "watch_time 12:00:000"
 - end
 - end
 - class Watch
 - # 手表都可以看时间
 - def watch_time
 - p "watch_time 12:00:000"
 - end
 - end
 - class AppleWatch < Watch
 - # AppleWatch 不仅看时间,还有运动的功能
 - def run
 - p "start run"
 - end
 - end
 
结合上面的代码,我们可以看到 watch_time 代码重复,对于不同继承体系但是相同功能的时候,就可以用 Mix-in 解决这个问题,思路如下:
使用 Mix-in 后我们可以看下代码变化,示例代码:
- module WatchTime
 - # 抽出通用的方法
 - def watch_time
 - p "watch_time 12:00:000"
 - end
 - end
 - class Phone
 - def call
 - p "phone call.."
 - end
 - end
 - class IPhone < Phone
 - include WatchTime
 - end
 - class Watch
 - include WatchTime
 - end
 - class Apple_watch < Watch
 - # apple_watch 不仅看时间,还可以运动
 - def run
 - p "start run"
 - end
 - end
 
使用 Mix-in 这种灵活的语法实现了鱼和熊掌兼得,即没有破坏继承结构关系又实现共性方法的代码复用问题,因为 Java 没有 Mix-in 的概念所以就不展示示例代码了,不过 Java 也有自己的解决方案,而且在 Java 的解决代码复用问题通常都应该遵循 组合大于继承 的原则,因为 Java 的语言设计让继承更多用于多态而非复用
运算符
简单说一下运算符,虽然大多编程语言的运算符非常的简单,赋值运算,逻辑运算,条件运算符所有语言的使用方式都几乎差不多,好像没什么好讲的,但 Ruby 灵活的语法是有不少语法糖,还是可以 Java 程序员羡慕的一下的,假设一张我们在业务代码中经常遇到的情况,根据表达式取值,当表达式为 true 时改变变量的值,这种简单逻辑赋值在 Java 只能这样写,请看示例代码
- String value = "abc";
 - if (condition != null) {
 - value = condition;
 - }
 - // 看上去很啰嗦
 
这种情况在 Ruby 中一行代码可以实现相同语义:
- # 当 condition 表达式为 true 执行 value = condition , 否则执行 value = "abc"
 - value = condition || "abc"
 
只所以可以实现是因为 Ruby 有一个不同 Java 的特定, Ruby 对象都可以用于进行布尔表达式判断,判断逻辑为**对象本身不为 nil 或者 false 表达式则为 true,否则为 false **
还有一种逻辑则是取相反的情况,例如我们经常遇到一种情况是,判断数组不为空的时候取数组的某一个下标,在 Java 中只能这样写,示例代码
- List
 list = Arrays.asList("a", "b", "c"); - String item = null;
 - if (list != null) {
 - item = list.get(0);
 - }
 - // "a"
 
这种情况可以用逻辑运算符 &&, 它刚好与上面 || 相反,也是一行代码可以实现相同功能
- str_list = ["a", "b", "c"]
 - item = str_list && str_list[0]
 - #=> "a"
 
我个人非常喜欢这种简洁的写法,不过建议在多人项目中不要用太多语法糖,不然可能会造成项目代码可读性混乱
异常处理
很多程序员大部分时间都花在查错上,所以迅速定位异常很关键,先看看 Ruby 的异常格式 文件名:行号:in 方法名:错误信息(异常类名) 简单的用法就不写示例代码了,不然占用太多篇幅,两种语言处理异常方法大同小异,具体处理方式有如下区别:
不过 Ruby 的 Retry 倒是 Java 没有的特性,它适合对一些容易出错的程序(例如调用外部 API )可以进行快速重试,具体可以请看示例代码
- class HandleException
 - def zero
 - x, y = 100, 0
 - begin
 - x = x / y
 - rescue
 - p '执行异常逻辑'
 - y = 2
 - retry
 - end
 - x
 - end
 网页题目:Ruby和Java的基础语法比较 
文章URL:http://www.wtcwzsj.com/article/dhdiiji.html
Copyright © 2009-2022 www.wtcwzsj.com 青羊区广皓图文设计工作室(个体工商户) 版权所有 蜀ICP备19037934号