虽说 Java 的支持泛型以及近期 Lambda 表达式的加入, 在对类型进行推断上已经很强大了, 但在类型声明的时候仍然略显冗余, 最主要的一点是 Java 不能像 Scala 那样在声明变量有赋值的情况下进行类型推断. 我们先来看下 Java 已经为我们所进行的改进:
List<String> strings = new ArrayList<String>(); //刚引入泛型时我们是这样
List<String> strings = new ArrayList<>(); //后来变成这样了, 可以钻石符号推断, Java 7List<String> list = new ArrayList<>();
list.addAll(new ArrayList<>()); //根据 list.addAll() 上下文推断要创建的类型是 new ArrayList<String>(), Java 8interface Foo {
void dodo();
}
Foo foo = () -> System.out.println("Foo:dodo()"); //Java 8 Lambda 可以根据 Lambda 表达式的签名推断出接口类型
foo.dodo();
在 Java 7 的泛型方法其实也是可以通过声明类型与方法参数来推断要返回的具体类型的.
可以我觉得这种类型推断做得还不够, 变量声明时最前面的类型始终需要, 比如能不能像 Scala 一样, 把
List<String> strings = new ArrayList<String>(); 写成 var strings = new ArrayList<String>();
如果对于这个例子来讲, 也许几时有需求要把 strings 赋值为 new LinkedList<String>() 而不能在这里用 var 的话, 那么像 int, double, string 等应该可以写成
1 2 3 4 |
var length = 100; //无需写成 int length = 100; var weight = 63.4; //不用 double weight = 63.4 var name = "Yanbin"; //不用 String name = "Yanbin" var result = foo(); //推断方法的返回类型 |
如果方法返回类型 T 的时候, 也可以直接用 var result = foo()
来接收方法的返回值.
或许要说 Java 的设计是方便于针对接口去编程, 所以声明类型倾向于接口, 但 Java 8 已经在拥抱函数式编程. 我们可以仅在需要多态时使用上层接口或类去引用变量, 多数时候或在局部区域用 var
推断出具体类型即可.
我们无法把 Java 与动态类型语言相比, 和 Scala, C# 类比还是可以的, Scala 在用 var
或 val
在多数时候都不需要指定变量类型, 完全依赖对所赋值类型的推断. 而且 C# 早已在使用 var
关键字了, 代码书写何需如此繁琐. IDE 聪明, 用 var
也知道具体类型, 而我们人一般也是心里有底的.