學了Java 你未必知道這些


    作為一個正奔跑向編程完美天堂的朝聖者,本人覺得在平常的編程中,應該要做到以下幾點:

    一:汝應注釋,這樣做既方便別人,也方便自己去讀懂代碼的邏輯

    二:注重細節,為自己寫的每行代碼負責,比如,在並發編程的過程中,應該給那些可變的共享單元加“同步鎖”或把可變的共享變量的粒度降到每個線程的級別

    三:注重效率,由於本人的學校比較重視算法這一塊,於是不知不覺中就對程序執行效率這一塊比較執着,假如你和你的同事們都寫了一個相同功能的程序,然后老板給你們                  各100萬條數據,你的同事的程序很快就把這100萬條數據執行完了,然后去喝了杯咖啡,回來時如果你的代碼還在跑,這不是......(后面的話你們都懂的)

    四:注重代碼的整潔性和盡力讓代碼的冗余降到最低,這在代碼的重構上是要注意的地方。

  后續本人會寫一些本人讀到的比較好的算法例子,讀這些例子有利於我們思維活躍開來,當然,相信你也會像本人一樣為這些算法解法的巧妙性而嘖嘖稱奇,以致使自己在以后的編程中更加注重這一塊,這些例子大家以后可以查看這個網址 http://www.cnblogs.com/wanggangjia/來看看(后續會補上這些算法序列)
  好吧!前菜已了,正餐現在來了

      1.請你完善下列函數來實現這個功能:交換下面例子中A、B的值 

1 public class TestAdd {
2     public static void main(String[] args) {
3            int A = 100;
4            int B = 10;
5            .....   //在這里寫下你的代碼,使A,B的值交換
6            System.out.println("A:" + A + "\t" + "B:" + B);  //輸出  A:10   B:100
7 }  
8 
9 }

    (1)大多數的我們都會定義一個臨時變量temp,然后就如下面代碼一樣

int temp = A;
A = B;
B = temp;

    (2)又有人會說,定義一個變量多奢侈啊!看我的

A = A + B;
B = A - B;
A = A - B;

    (3)這確實比(1)解法好了一點,但我們知道系統處理數據最快的是位操作,我們能不能從這方面下手使我們的程序更快呢?而且,把A+B賦值給A可能會產生越界,這不是不安全嗎?那怎么辦才能兼顧安全、快速、簡潔呢?看碼如下(采用“異或”操作符):

A = A ^ B;
B = A ^ B;
A = A ^ B;

說明:異或運算是按照二進制位進行異或運算的,這個運算是最低級的CPU位運算,運行速度快,而且不會產生進位。

拓展:位操作符由於它們具有運行速度快的特點(思考一下它們快的原因),所以經常被使用,特別是“>>”或“<<”位運算符,這點讀者可以看看jdk中有關hashcode這一塊的源碼

拓展例子:編程實現2 * 8,直接給碼如下:

2<<3;  //假設每個變量的存儲是8位,則2的二進制是0000 0010,向左偏移3位后,可得0001 0000,轉換成十進制為16,不就是2 * 8,數3是因為2的3次方為8

  2.這條語句:float i = 3.3;能編譯通過嗎?

float i = 3.3;不能通過編譯,因為常數 3.3 Java默認是double類型,而float類型的范圍是比double小的,把3.3賦值給i 是向下轉型,會損失精度,如果真的需要賦值給i,需強制轉型float i = (float)3.3;

拓展:short i = 1,i = i + 1;這也是不能通過編譯的,因為Java默認常數1位int類型,理由同上,但是short i = 1,i += 1;卻是可以的,這是因為jdk在編譯的時候,會隱式的將類型強制轉換成i = (short)(i + 1);

  3.Java中int類型和Integer類型有什么區別?

 首先,int類型是Java的基本數據類型,而Integer是一個對象,是一個引用,它們在內存邏輯就不同,關於內存邏輯,可以看看本人所寫的“一個大三學生的學習之悟”這篇文章,下面給出這兩個類型的內存結構,既然Integer是一個對象,那么它相對於int這基本類型來說就有很多額外的方法,具體可自查Java的API,要特別說明的是:在jdk1.5引入了“自動拆箱和裝箱”,使得基本數據類型和其對應的封裝對象能夠隱式的轉換。

綜合例子:涵蓋的知識點包括自動裝箱和拆箱、內存結構分析、自動裝箱和拆箱背后的類似“對象池”的思想

 1 public class BoxingTest {
 2     public static void main(String[] args) {
 3           Integer i = new Integer(300);
 4           Integer j = 300;  //自動裝箱,內部機制是調用Integer的valueOf(int)方法
 5           int z = 300;
 6           System.out.println(i == j);  //false  因為它們的內存地址不同
 7           System.out.println(z == j); //true  因為j自動拆箱,內部機制是調用Integer的intValue()方法,它們比較的都是數值300
 8     }
 9 
10 }

讀到這里,如果你沒有一種去讀Integer的valueOf(int)方法的源碼的沖動,那么你將失去挺多東西的,因為它里面包含着Java在性能優化的一些蛛絲馬跡,算了,我還是講講吧!如果你沒有去看這個方法的源碼,相信把下面這道題完全做對的應該不太可能,先炫代碼:

 1 public class ValueOfTest {   //使用駝峰形式命名
 2 
 3       public static void main(String[] args) {
 4              Integer i = 50;
 5              Integer j = 50;
 6              Integer x = 200;
 7              Integer y = 200;
 8            
 9              System.out.println(i == j);  //true
10              System.out.println(x == y); //false
11        }
12 
13 }

分析如下:

1  public static Integer valueOf(int i) {   //注意這里是靜態方法,隸屬於類,所以可以直接使用 “Integer.方法名” 來調用該方法
2  
3          if (i >= IntegerCache.low && i <= IntegerCache.high)  //這里的IntegerCache.low默認值為-128   IntegerCache.high默認值為127
4              return IntegerCache.cache[i + (-IntegerCache.low)];  //這些Integer對象,默認范圍在[-128~127],已經被創建,被放在常量池里
5  
6          return new Integer(i);
7 
8     }

 

由於Java的操作不外乎是創建對象---使用對象----銷毀(回收)對象,因為創建對象比較耗時間,損失了系統的性能,所以我們一般都會在程序開始時對一些比較耗時但在我們的程序又經常使用的對象先會初始化一些實例,對象池的對象是如此,線程池的線程是如此,數據庫連接池的Connection對象也是如此,供我們在程序中調用,以達到對象的重用及快速引用,這是優化程序功能的一個方法。好吧!回歸本題,范圍在[-128~127]的Integer對象已經被初始化在常量池里了,所以在這區間的Integer對象創建時都會指向常量池中相對應的對象,這也是上面代碼中為什么第一個輸出為true的原因,在這個范圍之外的,它會自己創建一個Integer對象,所以根據內存邏輯可知它們並不相等,所以為false

  其實,有空讀讀Java源代碼也是有好處的,在這里,本人只是希望編程者們在平常的代碼編輯中,要時刻注重自己程序的安全性、代碼運行的效率性及項目的性能的優化等等

 


免責聲明!

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



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