Java 语言的几个缺陷之四: 过时的 JavaBean

曾几何时在业务分层结构中的 VO 或 DTO 层充斥着无数的标准 JavaBean 类, 那些碍手脚的 getter/setter 方法简值不忍直视. 或许 JavaBean 设定规范的用意是当某些属性为只读时不提供 setter 方法, 而实际使用时, 因 getter/setter 都同时具备, 那么 JavaBean 的所有私有属性又何异于公有属性呢. 

更别说对于某些形式的属性名, 若属性名为 xCoordinate  时, 它所对应的 getter 方法分别是 getxCoordinate(),一般的 IDE 都会为它自动生成 getXCoordinate() 方法, 这是错误的.  实际上 getXCoordinate() 对应的属性名是 XCoordinate

所以 Play Framework 1 以及 Play Framework 2.4.6 之前的版本采用了字节码增强的技术, 实现了像 Objective-C 的 @property 的特性, 即只要声明公有属性, 编译器为该属性生成默认的 getter/setter 方法, 您也可以手工去覆盖个别默认的 getter/setter 方法.

因此在 Play Framework 中书写的的  model 类就只需要属性了, 像

就这么简单, 想像一下如果我们为一个众多属性的 model 类补全所有的 getter/setter 方法读起来有多恐怖. 阅读全文 >>

Java 语言的几个缺陷之三: 不支持 var 类型推断

虽说 Java 的支持泛型以及近期 Lambda  表达式的加入, 在对类型进行推断上已经很强大了, 但在类型声明的时候仍然略显冗余, 最主要的一点是 Java 不能像 Scala 那样在声明变量有赋值的情况下进行类型推断. 我们先来看下 Java  已经为我们所进行的改进:

List<String> strings = new ArrayList<String>();  //刚引入泛型时我们是这样
List<String> strings = new ArrayList<>();             //后来变成这样了, 可以钻石符号推断, Java 7

List<String> list = new ArrayList<>();
list.addAll(new ArrayList<>()); //根据 list.addAll() 上下文推断要创建的类型是 new ArrayList<String>(), Java 8

interface Foo {
  void dodo();
}
Foo foo = () -> System.out.println("Foo:dodo()");   //Java 8 Lambda 可以根据 Lambda 表达式的签名推断出接口类型
foo.dodo();

在 Java 7 的泛型方法其实也是可以通过声明类型与方法参数来推断要返回的具体类型的. 阅读全文 >>

Java 语言的几个缺陷之二: equals() 比较字符串

对于面向对象的语言不知道除了 Java 还有没别的语言会拿怎么比较两个字符串相等频频作为面试题来考. 原本是在编程语言中两个字符串内容是否相等时用 == 比较时却可能是不对的. 在 Java 中

"ab" == "ab"                                                                                   //true
"ab" == "new String("ab")                                                          //false
"ab" == String.value("ab")                                                         //true
new String("ab").equals(new String("ab"))                            //true
new String("ab").intern() == new String("ab").intern()      //true

在 Java 中明明看到两个字符串内容一样用 == 进行比较多数时候不是你想要的结果, 只有用 equals() 方法才是王道.  使用 Java 的字符串必须了解它内部是怎么存储的. 比于上面的结果我不作细说, 主要涉及到字符串常量池及内部状态, == 比较引用, equals() 比较内容.

Java 还常常对 equals 比较字符串津津乐道, 而我仍然认为它是语言设计上的一个缺陷, 所以 JVM 上的其他编程语言如 Groovy, Scala 纷纷倒勾, 无一不是用== 来比较字符串的内容, 它们也提供字符串引用的比较, 但多少人实际关心两个字符串的引用是否相同呢, 反正字符串设计的是 Immutable 的.

若说是因为 Java 不支持操作符的重载, 但可以像 Scala, Groovy 那样在编译器上下功夫的. 最终我想依然是受累于 100% 源代码与二进制的兼容性, 改进的话会造成早先代码的行为错乱. 阅读全文 >>