Java 語言缺乏對空安全(null-safety)的內(nèi)置支持,可能導致 NullPointerException 異常。這是所有Java開發(fā)的必須經(jīng)歷的痛苦。并且需要花大代價進行處理:使用Optional。
1.空指針異常(NullPointException)

Java 語言缺乏對空安全(null-safety)的內(nèi)置支持,可能導致 NullPointerException 異常。這是所有Java開發(fā)的必須經(jīng)歷的痛苦。并且需要花大代價進行處理:使用Optional。
// 使用 ofNullable() 方法創(chuàng)建 Optional 對象
Optional<String> name = Optional.ofNullable(getName());
// 使用 map() 方法轉(zhuǎn)換 Optional 對象的值,使用 orElse() 方法獲取默認值
String message = name.map(n -> "Hello, " + n).orElse("Hello, Guest!");
System.out.println(message);
2.語法冗余
- 必須分號結(jié)束語句。
- 必須明確的訪問修飾符:類、方法和成員變量都需要明確指定訪問修飾符(如 public、private、protected)。
public class MyClass {
private int x;
protected String y;
public MyClass() {
// ...
}
public void myMethod() {
// ...
}
}
- 重復的類型聲明:在 Java 中,變量聲明時需要明確指定類型,這會導致代碼顯得更冗長。Java 10 引入了局部變量類型推斷(var 關鍵字),可以在某些情況下減少冗余。然而,這個特性并不適用于所有場景,例如類成員變量和方法參數(shù)。
List<String> names = new ArrayList<String>();
Map<String, Integer> map = new HashMap<String, Integer>();
- 冗長的異常處理:說真的,看到下面這樣的結(jié)構(gòu)想死的心都有了。
public void readFile(String filePath) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filePath));
String line = null;
while ((line = reader.readLine()) != null) {
// do something with line
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我們實際需要的代碼只有一點點:
public void readFile(String filePath) {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line = null;
while ((line = reader.readLine()) != null) {
// do something with line
}
}
3.缺少屬性(Properties)支持
Java 沒有內(nèi)置的屬性支持,開發(fā)者需要為類的成員變量創(chuàng)建 getter 和 setter 方法。
4.缺少內(nèi)置的函數(shù)式編程支持(Java 8 之前)
Java 8 之前,Java 缺乏對函數(shù)式編程的內(nèi)置支持。雖然 Java 8 引入了 lambda 表達式和 Stream API,但仍然不如一些其他編程語言(如 Scala、Haskell)對函數(shù)式編程的支持更為豐富。
List<String> list = Arrays.asList("apple", "banana", "orange", "pear", "watermelon");
list.stream() // 這里必須.stream()才能用,感覺非常別扭
.filter(s -> s.length() >= 5)
.forEach(System.out::println);
5.類型擦除(Type Erasure)
Java 泛型的實現(xiàn)是基于類型擦除的,在運行時泛型類型信息會丟失,限制了泛型代碼的能力,導致無法創(chuàng)建泛型數(shù)組和泛型實例。
T obj = new T(); // 不支持
T[] array = new T[]; // 不支持
6.基本類型與包裝類型
Java 中的基本類型(如 int、float、boolean)與對應的包裝類型(如 Integer、Float、Boolean)存在差異,它們在使用時可能導致不一致的行為。自動裝箱和拆箱可以在某種程度上解決這個問題,但仍然需要注意。
7.受檢異常(Checked Exceptions)
Java 中有兩種類型的異常:受檢異常(如 IOException)和非受檢異常(如 NullPointerException)。受檢異常必須在方法簽名中聲明或者進行捕獲處理,這會導致異常處理的代碼顯得更加繁瑣。
看到下面的代碼,表示一臉嫌棄。
public void add() throw Exception {
//
}
8.缺少對值類型的支持
Java 語言缺乏對值類型的支持,所有對象都是引用類型,容易導致性能問題。盡管 Java 的開發(fā)團隊已經(jīng)意識到這個問題,正在通過 Project Valhalla 探索解決方案,但目前 Java 語言仍然不支持值類型。
9.單繼承限制
Java 語言只支持單繼承,一個類只能繼承一個父類。雖然可以通過接口實現(xiàn)某種程度的多繼承,但仍然不如多繼承靈活。
10.可變性與不可變性
Java 語言中的類和對象默認是可變的,這可能導致數(shù)據(jù)不一致和線程安全問題。雖然可以通過一些設計模式和實踐來實現(xiàn)不可變性,但 Java 并沒有內(nèi)置支持。