0x01 Java 10簡介
- 自從有了校內的下載網站,不多上Oracle官網下載JDK了,結果前兩天聽鍾神說Java 10都出來了2333。幹IT這行還真是要與時俱進啊,那就來看一下Java 10吧。
- Java 10實際上並未引入太多新特性,不過有一個新特性最引人注目:
JEP 286: Local-Variable Type Inference
- 等了這麼久Java終於支持類型推斷了,那麼今天就來看一看Java 10的類型推斷,和其餘語言相比有哪些異同吧。
0x02 類型推斷概述
- 類型推斷是新型的高級語言提供的一類功能,容許根據編譯上下文來推斷變量的類型,不須要本身手動寫類型,使得代碼更加簡潔。
- 目前我接觸的編程語言中,JavaScript、Swift和Python都支持這種語法。本次Java 10更新也支持了類型推斷,對於Java這種重量級語言來講仍是一件值得高興的事。
0x03 體驗Java 10的類型推斷功能
- 讓咱們寫一段Base64編碼的代碼,體驗一下Java 10的類型推斷功能:
//Java代碼
import java.util.Base64;
class Untitled {
public static void main(String[] args) {
var b64encoder = Base64.getEncoder();
var encodeString = b64encoder.encodeToString("Hello World".getBytes());
System.out.println(encodeString);
}
}
- 初步體驗仍是不錯的,只是個人IDE尚未升級,還不支持自動提示這種語法。甚至Eclipse還不能正常編譯Java 10的代碼,我只能手動經過
javac
來編譯。總體而言Java 10的類型推斷功能是相似於Swift/JavaScript的,須要寫var關鍵字,並不像是Python那樣的使用方式。
0x04 Java 10類型推斷的不足
- 上面的用法看起來很友好,那麼有沒有更自由的寫法呢?很快的我就收到了編譯器錯誤:
//Java代碼
import java.util.Base64;
class Untitled {
public static void main(String[] args) {
var b64encoder = Base64.getEncoder();
var encodeString = b64encoder.encodeToString("Hello World".getBytes());
System.out.println(encodeString);
var a = 1,b = 2;
}
}
錯誤: 'var' 不容許在複合聲明中使用
var a = 1,b = 2;
^
1 個錯誤
- 看來Java 10的類型推斷仍是有諸多限制和不便,不像其餘語言那般好用,對比一下Swift語言:
//Swift代碼
import Foundation
let string = "Hello World"
let data = string.data(using: String.Encoding.utf8)!
let encodeString = data.base64EncodedString()
print(encodeString)
var a = 1, b = 2;
- 好比說Java 10並無
let
關鍵字,也就是說,並不能快速的使用類型推判定義常量。同時也不能一次用var
定義多個變量,當同類型變量較多的時候,我以爲還不如把類型寫出來。
- 同時,根據官方的說明,你也不能將
var
用於成員變量,只能用於局部變量,例以下面的例子會出現編譯錯誤:
//Java代碼
import java.util.Base64;
class Untitled {
class Student {
var name = "";
Student(String name) {
this.name = name;
}
}
public static void main(String[] args) {
var b64encoder = Base64.getEncoder();
var encodeString = b64encoder.encodeToString("Hello World".getBytes());
System.out.println(encodeString);
}
}
錯誤: 此處不容許使用 'var'
var name = "";
^
1 個錯誤
- 而在其餘語言中,你能夠更自由的使用
var
,在任何你想要的地方,只要不引發歧義:
//Swift代碼
import Foundation
class Student {
var name = "";
init(name: String) {
self.name = name;
}
}
var string = "Hello World"
let data = string.data(using: String.Encoding.utf8)!
let encodeString = data.base64EncodedString()
print(encodeString)
- 做爲對比,Swift比Java 10在類型推斷方面更加靈活,同時兩者也有共同點——它們都是強類型語言,任何變量必須具備某種類型,所謂的類型推斷只是一種語法上的精簡。例如你不能像Python同樣在形參列表中也不使用參數類型,或者直接省略返回值類型,這些類型還都是必須的:
#Python代碼
def printNumber(num):
print(num)
return 1
retCode = printNumber(4)
print(retCode)
//Swift代碼
func printNumber(num: Int) -> Int {
print(num)
return 1
}
let retCode = printNumber(num: 2)
print(retCode)
//Java代碼
import java.util.Base64;
class Untitled {
public static int printNumber(int num) {
System.out.println(num);
return 1;
}
public static void main(String[] args) {
var retCode = printNumber(3);
System.out.println(retCode);
}
}
0x05 總結
- 通過簡單的體驗,基本清楚了Java 10的類型推斷功能。之後在局部範圍定義對象,能夠有了更簡略的寫法:
//Before Java 9
MessageDigest md = MessageDigest.getInstance("SHA-512");
//Java 10
var md = MessageDigest.getInstance("SHA-512");
- 顯然這種代碼不兼容早期版本的Java,即便你將Java 10的代碼編譯爲字節碼,也不能在低版本的JVM上運行。這種新語法也不能用於Android開發等用途。好比我使用OpenJDK 1.8來測試咱們前面編碼base64的代碼,就出現了異常:
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
$ java Main
SGVsbG8gV29ybGQ=
# java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (IcedTea 3.2.0) (suse-33.1-x86_64)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)
# java Main
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: Main has been compiled by a more recent version of the Java Runtime (class file version 54.0), this version of the Java Runtime only recognizes class file versions up to 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
- 因此說這種新語法仍是不夠靈活,同時兼容性也堪憂,可是聊勝於無。同時也會必定程度上減小Java代碼的長度,讓編程更加優雅一些。同窗們若是想體驗一下新語法,能夠升級到Java 10,不過好多Java應用都不兼容,因此升級仍是需慎重啊!