Java中常見的坑


概述

Java是門極簡風格的語言,比其它語言相比,它故意保持較少的特性,不僅在有些不常見的情況下會出些奇奇怪怪的錯誤,即使很一般的情況下也有可能讓人栽根頭。如果你習慣了別的語言,你讀Java 的代碼很容易搞錯一些概念。

變量要么是引用 ,要么是基礎類型

這是對的,變量不是對象。也就是說在下面這個例子里,s不是個對象,也不是字符串,它只是一個字符串的引用。

String s = "Hello";

這個能解釋很多的問題,比如: 問題:如果說字符 串是不可變的,為什么我能修改它? s+=“!” 回答:在Java里是不可變的,你改變的只是引用而已。

==比較的是引用,不是內容

讓人更混亂的是,有時候用==是能比較內容的。如果你有兩個一樣的不可變值,JVM會嘗試引用 同一個對象 。

String s1 = "Hi", s2 = "Hi"; Integer a = 12, b = 12;

這兩個例子中用到了對象池,所以最后引用 的是同樣的對象。s1==s2和a==b都是返回true,JVM已經把兩個引用 都指向了同一個對象。然而,如果稍微改下代碼,JVM沒有把對象放到池里的話,==就會返回false,可能會讓你意想不到。這個時候你得用equals了。

String s3 = new String(s1); Integer c = -222, d = -222; s1 == s2 // is true s1 == s3 // is false s1.equals(s3) // is true a == b // is true c == d // is false (different objects were created) c.equals(d) // is true

對於整型來說,對象池緩存的范圍是-128到127(還有可能更高)。

Java通過傳值進行引用傳遞

所有的變量都是傳值,包括引用。這就是說如果你有個變量,它是一個對象的引用,這個引用會被拷貝后再傳參,而不是傳遞的對應的那個對象。

public static void addAWord(StringBuilder sb) { sb.append(" word"); sb = null; } StringBuilder sb = new StringBuilder("first "); addWord(sb); addWord(sb); System.out.println(sb); // prints "first word word"

引用的對象可以改變,不過如果修改拷貝的這個引用,對調用方是沒有影響的。

在大多數JVM實現里,Object.hashCode和內存地址無關

hashCode必須是保持不變的。不然的話HashSet或者ConcurrentHashMap就沒法玩了。然而對象可以在內存的任何地方,並且它的位置還可能不斷變化,而這個對你的程序來說是透明的。使用內存地址來當做hashCode是不可行的(除非你自己有一個JVM,對象是固定不動的)。 對於 OpenJDK和Hotspot JVM來說,hashCode是按需生成的,並存儲在對象的頭部。使用Unsafe API你看到hashCode是否已經生成了,甚至還可以修改它。

Object.toString那些不為人知的事情

toString的默認行為是打印類的的內部名稱還有對象的hashCode。 上面已經提到,hashCode並不是內存地址,盡管它是用16進制打印的。同樣的,類名,尤其是數組的類名,更容易讓人頭暈。比如說String[]的名稱是[Ljava.lang.String; 這個[表明它是個數組,L說明它是Java語言(Language)創建的類,並不是基礎類型比如byte這些,順便提一下byte內部名稱是B。;號標識類的結束。比如你有個這樣的數組:

String[] words = { Hello, World}; System.out.println(words);

輸出會是這樣:

[Ljava.lang.String;@45ee12a7

很不幸你只知道這是個對象數組。如果你只有一個Object實例words,這樣是不夠的,你得調用下Arrays.toString(words)。這極其惡劣地破壞了封裝的原則,在StackOverflow上面這也是最常見的一類問題。

我問過Oracle的好些個工程師,從他們的反饋感覺,這個問題目前很難解決。

原創文章轉載請注明出處:http://it.deepinmind.com/java/2014/03/07/Java-common-problems.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM