返回信息流http://www.importnew.com/16805.html(懒得改代码格式直接复制url过来了)
这是一条镜像帖。来源:北邮人论坛 / java / #45253同步于 2015/11/5
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
偏执却管用的10条Java编程技巧
zhbzhbzhbz
2015/11/5镜像同步27 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
用Scala吧。
1. 把字符串常量放在前面
// 可怜的Java
foo.equals("hello") // 如果foo==null就NullPointerException
"hello".equals(foo) // 总能工作,但太丑陋
// 如果用apache commons-lang
import extended by org.apache.commons.lang.StringUtils
StringUtils.equals(foo, "Hello") // 总能工作。
// 优雅的Scala
foo == "hello" // 比较内容。即使foo==null也能工作,但Scala不习惯用null。
// 注:Java里的foo=="hello"对应scala里的foo eq "hello"。
2. null返回值
// 可怜的java
File[] files = file.list()
if (files == null) { ... // files有可能是null,但函数签名不告诉你这个
// 新API
for (Path path : Files.newDirectoryStream(...)) { // 如果不是目录就抛异常,是正确的做法
// Scala没有标准的IO API,但是可以用Option对象解决null的问题
Option(file.list()) match {
case None => throw new Exception("Not a directory")
case Some(files) => files.foreach { f => ... }
}
// 如果用scala-io
Path("...").children.foreach { f => ... } // 若非目录,抛NotDirectoryException
3. 用特殊值表示特殊情况。这里Scala的String就是java.lang.String,没办法了。
4. 意外赋值
// 本来就很优雅的Java
if (a = 42) { // 编译器会报错:a和42都是int,但if需要boolean值
if (42 == a) { // 多此一举,Java本来就不怕a = 42这样的错误。C/C++才需要担心
// 同样优雅的Scala
val a = 30 // 默认是常量,不用担心被修改
if (a = 42) // 同样报错
a match {
case 42 => // 这种语法不会和赋值混淆
case 30 => ...
}
5. 检查null和长度
// 丑陋的Java
int[] a = ...;
if (a.length == 42) { ... // a有可能是null
if (a == null && a.length == 42) { ... // 麻烦
// 新API
Optional<int[]> b = ... // Optional类型表示“有可能存在有可能不存在”的值,等同于Scala的Option。
int len;
if (b.isPresent()) {
len = b.get().length
} else {
len = 0;
}
// 优雅的Scala
val a: Array[Int] = ...
if (a.length == 42) { ... // 正常的Scala程序不用null表示特殊值。
// 如果某个值有可能不存在,Scala会用Option[T]类型
val b: Option[Array[Int]] = ...
val bl1 = b match { // 用match case匹配
case None => 0
case Some(ary) => ary.length
}
val bl2 = b.map(_.length).getOrElse(0) // 意思一样,简写
val bl3 = b.getOrElse(Array[Int]()).length // 用“空数组”做默认值。
6. 所有的方法都用 final 声明,但我不赞同这个观点。不要这样做,这样做了,用户早晚要用CGLib和ASM来强制重写那些final方法,你也拦不住。Scala也不这样。
7. 所有的变量和参数都用 final 声明
// 严谨的Java程序员的程序
public int squareDiff(final int a, final int b) {
final int s = a + b;
final int d = a - b;
final int result = s * d;
return result;
}
// Scala程序员的第一课就是用val而不是var
def squareDiff(a: Int, b: Int): Int = { // a,b本来就不能变
val s = a + b // val就是final的意思。
val d = a - b
s * d
}
8. 不要试图混淆单个和多个。这对Java和Scala都适用。如果一个函数可以接受多个参数,请用List或者Seq。不要为“单个”开特例。
public int max(int[] manyNumbers) { /* body */ }
public static void main(String[] args) {
int m = max(new int[]{1});
int n = max(new int[]{1,2,3,4,5,6,7});
}
// 不要提供下面这个特例。如果能接受多个输入,就让用户提供多个输入;把“封装成数组”这件事推给用户。
public int badMax(int onlyOneNumber) { return max(new int[]{onlyOneNumber}); }
// 用vararg函数可以减轻语法上的负担
public int max(int... manyNumbers) { /* body */ }
public static void main(String[] args) {
int m = max(1);
int n = max(1,2,3,4,5,6,7);
}
def max(nums: Seq[Int]): Int = /* body */
val m = max(Seq(1))
val n = max(Seq(1,2,3,4,5,6,7))
def max(nums: Int*): Int = /* body */
val m = max(1)
val n = max(1,2,3,4,5,6,7)
9. 难用的switch和优雅的case match
// 可怜的Java
int a = ...;
switch(a) {
case 1:
doSomething();
// 警告:这里会自动进入下一个case!!
case 2:
doSomethingElse();
break; // 这个很重要
default:
handleOtherCases();
// 如果没有这个,就安静地什么都不做。
}
// 优雅的Scala
val a = ...
a match {
case 1 => doSomething() // 不会跳到下一个
case 2 => doSomethingElse()
} // 如果没有匹配,抛MatchError异常。
10. 用大括号隔开 switch 的每一个 case 块。Scala也可以用。
暖洋洋大神你是在读的研究生么,怎么会这么多语言,,
【 在 nuanyangyang 的大作中提到: 】
: 用Scala吧。
: 1. 把字符串常量放在前面
: [code=java]
: ...................
【 在 zhbzhbzhbz 的大作中提到: 】
: 暖洋洋大神你是在读的研究生么,怎么会这么多语言,,
在读,但我只懂c,java,scala和python。
暖神改推scala了 不推python了
【 在 nuanyangyang (暖羊羊) 的大作中提到: 】
: 用Scala吧。
: 1. 把字符串常量放在前面
: [code=java]
: ...................
python和java很不一样,没有可比性。比如python里变量没有类型,指向什么对象都行,包括None;if里面不能赋值;没有switch;没有final;创建数组非常简单。
scala还算和java一样,都是静态语言。
【 在 maoxian 的大作中提到: 】
: 暖神改推scala了 不推python了
第6点貌似也是一个很好的习惯,我的一位大神师兄(真的非常的大神...)代码里就有不少这种写法...
要么为了继承而设计,要么阻止继承。
【 在 nuanyangyang 的大作中提到: 】
: 用Scala吧。
: 1. 把字符串常量放在前面
: [code=java]
: ...................