一些java中常見的基礎問題的總結

        經常在論壇碰到大家重複在問的問題,然後每次的答案都是越來越有新意,有時只能讚歎,唉.經常糾纏於那些無聊的概念,感覺自己很無聊,以後不去看這些無聊的問題了.把自己遇到過的一些總結一下,不斷更新.
1.&和&&的區別.
      java中的邏輯運算符:
   & 邏輯與(AND)
   |   邏輯或(OR)
   ^ 邏輯抑或(XOR)
   ! 邏輯非
   && 條件與(AND)
   ||      條件或(OR) 
  注意&&和||會進行短路計算,第一個條件可以判斷表達式的結果時,不對後面的條件進行判斷了.
 位操作運算符:
  & 按位與(AND)
  |   按位或(OR)
  ^  按位抑或(XOR)
  ~ 按位取反
  所以,問&和&&的區別時,千萬別僅僅説一個是位操作符,一個是邏輯運算符.
2. short s=0;
        s+=1;
  正確,而
  s=s+1;
  不正確,為什麼?
  java中byte ,short,char之類的運算都是提升為int類型進行的,所以運算完之後要進行強制類型轉換,複合賦值操作符編譯器會自動添加強制轉換操作.建議:儘量不要對byte,short,char這樣的類型使用複合賦值運算符.

3.String str=new String("abc");
這句話創建了幾個對象?
  如果有人這麼問問題,直接不要理會了,這個問題太難回答.不精通jvm的話還難精確的説會創建很多對象.自己目前能想到的,比如String類型對應的Class對象,這個Class內部的對象就好多個,可以去看Class類的源代碼.
  如果問創建了多少個String對象,那起碼還好説點,首先對於"abc",如果常量池中已經有了的話,那就不用創建了,如果沒有肯定要解析常量池,並創建String對象,進行intern()操作.所以這裏肯定會存在一個常量池裏的對象.new String("abc");當然會導致在堆中創建一個對象.這裏自己也不知道答案該如何歸納,1個或2個?等深入的學習一下再總結.

  String str="a"+"b"+"c"+"d";
  這句話會創建幾個對象?
  用SUN的jdk處理,經過javac編譯之後,常量運算已經直接處理掉了,所以生成的class文件裏的常量池表中有"abcd"這個串.
所以執行這句話的時候,只會有一個對象.對於連編譯和運行都分不清的人就不用多解釋了.
  這個問題有人用組合的方法得出很多結論,後來看到有人説,Thinking in Java上介紹的,內部原理是用的StringBuilder來連接的,這裏有2個問題,第一,如果這個例子會用StringBuilder來連接的話,那麼String對象還是隻有1個,第二,如果問一共有幾個對象,再考慮StringBuilder來連接的問題的話,那這裏面起碼又帶來了StringBuilder類對應的Class對象及其內部對象,這個數量就很大了.一個值得思考的問題是,既然能看到Thinking In Java中的結論,為什麼不能看看TIJ中分析問題的思路呢.
順便寫點測試代碼:
  1. public class Main{
  2.   public static void main(String arg[]){
  3.       String str="a"+"b"+"c"+"d";
  4.   }
  5. }
按照TIJ上的方法,也是我喜歡的方法:
javap -c Main
  1. Compiled from "Main.java"
  2. public class Main extends java.lang.Object{
  3. public Main();
  4.   Code:
  5.    0:   aload_0
  6.    1:   invokespecial   #1//Method java/lang/Object."<init>":()V
  7.    4:   return
  8. public static void main(java.lang.String[]);
  9.   Code:
  10.    0:   ldc #2//String abcd
  11.    2:   astore_1
  12.    3:   return
  13. }

      可以看到,裏面只有一個String abcd.
      "a"+"b"+"c"+"d"都是常量的緣故,編譯的時候就直接處理掉了,所以不會在運行的時候再通過StringBuilder來連接了.
  改變代碼,換個例子:
  1. public class Main{
  2.   public static void main(String arg[]){
  3.       String s="c";
  4.       String str="a"+"b"+s+"d";
  5.   }
  6. }
  這個會出現幾個String?
        javap -c Main
  1. Compiled from "Main.java"
  2. public class Main extends java.lang.Object{
  3. public Main();
  4.   Code:
  5.    0:   aload_0
  6.    1:   invokespecial   #1//Method java/lang/Object."<init>":()V
  7.    4:   return
  8. public static void main(java.lang.String[]);
  9.   Code:
  10.    0:   ldc #2//String c
  11.    2:   astore_1
  12.    3:   new #3//class java/lang/StringBuilder
  13.    6:   dup
  14.    7:   invokespecial   #4//Method java/lang/StringBuilder."<init>":()V
  15.    10:  ldc #5//String ab
  16.    12:  invokevirtual   #6//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  17.    15:  aload_1
  18.    16:  invokevirtual   #6//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  19.    19:  ldc #7//String d
  20.    21:  invokevirtual   #6//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  21.    24:  invokevirtual   #8//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  22.    27:  astore_2
  23.    28:  return
  24. }

  可以發現這個例子中的String 有,"c","ab"(編譯時對可確定的常量進行處理了),"d",以及最後通過StringBuilder.toString生成的String "abcd".
       看書的意義是什麼?起碼不是背結論.
4.<java堆與棧>,一個垃圾帖子卻被到處推薦來推薦去,很詭異的現象,很多人也喜歡給別人講問題的時候引用,自己批評過一些,慢慢的感覺到沒有必要了.原貼只是一個習作,貌似是作者初學的時候的一個總結,已經是若干年前的事情了,如果現在把原作者找出來讓他自己看,估計也會出汗了.
有位老師總結了一下,感覺很好:  http://topic.csdn.net/u/20081127/23/bd9ca56e-44d3-4f94-80f7-88f469f6dd79.html

5.類的初始化順序,這個實在沒有必要討論,自己運行一下就知道了,最笨的方法就是自己調試,單步跟蹤,但也是收穫最大的.

6.以前總有人説,private 的方法默認是final的,後來又有人説static 方法默認也是final.第一個創造這個説法的人可能是為了讓自己理解一些東西方便一些,但是慢慢就認為是真理了。

7.多態與重載什麼關係?
  可以説沒有關係.但是很多面試別人的人自己都不理解,這個實在沒招,但是你可以清晰的給他介紹重載和覆蓋的適用範圍.
  多態性是面向對象的基本特性,重載在本質上是和麪向對象沒有關係的.(當然重載也可以發生在子類和父類的名字相同,簽名不同的方法之間) 多態是和override密切相關的.
以前自己也犯過錯誤,認為重載是靜態綁定的,在C++裏這麼説是沒有問題的,但在java中不能這麼説,因為對於重載而言,雖然編譯的時候可以根據簽名確定方法,但具體調用那個方法(跟java對覆蓋的支持方式有關),還是要運行時來確定的.

8.java的方法調用中,參數傳遞機制為pass by value.
   很多人喜歡生造一個傳引用的説法,但根本不知道傳引用是什麼意思.這點在<The Java Programming Language>上有詳細和權威的説明,也説明了java為什麼沒有pass by reference ,<Core Java>中有內存圖的説明,龍書<編譯原理:技術與工具>第二版裏面也有説明.其實真正把引用和對象兩個概念理解了,也就不會有亂七八糟的説法了.如果不理解,記住!

(待續)