Java編程思想——那些易被忽視的關鍵點(二)

1.Java中賦值操作,在將一個對象賦值給另一對象時,其實是對引用的賦值

class People{}
public static void main(String[] args)
{
   People p1 = new People();
   People p2 = new People();
   p2=p1;//及將p2的引用給p1,使得倆個引用指向同一個對象 

}

2.比較操作“==”比較的是倆個對象的引用是否相等;equals()比較的是對象的內容是否相等,但是不適用於基本類型。

3.邏輯操作中的短路問題:即一旦可以根據部分邏輯判斷確定整個結果就不需要繼續執行右邊的邏輯判斷了。這也就是爲什麼可以通過將較大概率滿足的邏輯判斷寫在if()中左側來提高代碼運行效率的原因。

4.Java中的直接常量,放在變量的前或後邊,方便編譯器可以一眼認出是什麼類型。

long後綴大小寫L
float後綴大小寫F
double後綴大小寫D
十六進制前綴0X或0x,後續0~9的數字或大小寫a~f
八進制前綴0,後續0~7的數字

5.Java中提供了Integer和Long類的靜態方法toBinaryString(),可將各類型轉換爲二進制輸出

{
  short a=1;
  int b=15;
  System.out.println("a="+Integer.toBinaryString(a));//此時short會自動轉換爲int
  System.out.println("b="+Integer.toBinaryString(b));
}

6.數據的截尾與舍入,當浮點類型轉化爲int類型時不會出現四捨五入,即:

{
  float fa=0.7;
  float fb=0.4;
  int ia=(int)fa;
  int ib=(int)fb;
  System.out.print("ia="+ia+"  ib="+ib);
}
out:ia=0  ib=0
若要四捨五入需要使用java.lang.Math中的round();
{
  float fa=0.7;
  float fb=0.4;
  int ia=(int)fa;
  int ib=(int)fb;
  System.out.print("ia="+Math.round(ia)+"  ib="+Math.round(ib));
}
out:ia=1  ib=1

7.Java中的標籤,標籤一般用在循環結構的前邊,在Java中沒有goto,但利用標籤和continue、break可以做出同樣的效果,continue [Lable]效果爲結束執行後邊的代碼而回到標籤包含的循環的初始繼續執行;break [Lable]效果爲結束標籤包含的循環。需要注意的是標籤在實際開發中比較少用,但是在一些情況使用標籤可以得到比較好的體驗。

public class LableUse{
  public static void main(String[] args)
 {
      int i=0;
      outer://標籤位置
      where(true){
      System.out.println("Outer while loop");
      while(true){
        i++;
        System.out.println("i="+i);
        if(i==1){
         System.out.println("continue"); 
         continue;
       }
       if(i==3){
         System.out.println("continue outer"); 
         continue outer;
       }
       if(i==5){
         System.out.println("break"); 
         break;
       }
       if(i==7){
         System.out.println("break outer"); 
         break outer;
       }
      }
      }
  }
}
out:
Outer while loop
i=1
continue
i=2
i=3
continue outer
Outer while loop
i=4
i=5
break
Outer while loop
i=6
i=7
break outer

8.Java構造器(默認爲靜態方法),主要的目的是對類中的變量進行初始化。構造器有助於減少錯誤,並使代碼易於閱讀。new對象的時候,不但會獲取所需的存儲空間,也同時調用相應的構造器,在Java中“初始化”和“創建”是捆綁在一起不能分離的。注意的是構造器是不返回任何東西的,包括void。Java中有默認的構造器,即爲無參構造器,因爲如果沒有這個構造器將不能new對象。但是如果在類中創建一個構造器就不會有默認構造器了,所以會出現如下問題:

class People{
    People(int i){
    }
}
class Test{
   public static void main(String[] args){
      People p=new People();//報錯,因爲現在只有一個帶有int類型參數的構造器
      int num=9;
      People p2=new People(num);
   }
}

9.Java的傳參:Java方法中的參數如果傳的比預設小則會進行自動提升,若大則進行窄化轉換,也就是向位數較小的格式轉換。

10.this關鍵字,表示的是當前對象的引用。其在a.調用方法時和一般的引用的用法一樣。作爲方法的調用者,this也可以b.作爲參數使用,另外也可以c.調用類的構造器(但是this只能調用一個構造器,且必須放在最起始處,否則就會報錯)d.可以用this調用與參數變量同名的數據變量以區分倆者

class People{
   int i;
   public People(int i){
     this.i=i;//用this區分參數變量與數據成員
   }
}
需要注意的是在static修飾的方法中是不能使用this的。

11.Java垃圾回收,Java中的垃圾回收器只知道釋放那些經由new分配的內存,所以它不知如何釋放那些特殊的內存區域(即不是通過new獲得的內存區域),所以Java提供了finalize()方法(此法主要用在清理通過本地方法獲取的內存塊,即其他語言寫的代碼,不建議過多使用),用以在垃圾回收前做一些重要的清理工作(但不同於C++中的析構函數)。在此需要理解三點:

  • 對象可能不被垃圾回收
  • 垃圾回收並不等於“析構”
  • 垃圾回收只與內存有關

垃圾回收器並不能完全代替析構函數

Java虛擬機沒有采用其他系統的垃圾回收機制--引用計數器(可能出現對象應該被釋放,但由於對象的循環引用導致計數不爲0不能釋放的現象),而是採用了“自適應的垃圾回收技術”。自適應的垃圾回收技術分爲倆個部分:

  • “標記-清除”(通常用於對象穩定,垃圾回收效率低的情況):

      不在後臺運行,需要將運行的程序暫停進行。從堆棧和靜態存儲區開始,遍歷所有引用,進而找出所有的存活對象,並對這些存活的對象進行標記,此過程中不會進行回收,而是在將所有對象進行標記後再執行此動作,在清理中會將所有沒有被標記的對象釋放,過程中不會產生任何的複製操作。

  • “停止-複製”(通常用於堆空間出現大量碎片的情況):

      不在後臺運行,需要將運行的程序暫停進行。內存分配是以較大的“塊”爲單位的(每個塊都由對應的代數進行記錄,若對象被引用,其代數就被增加),如果對象較大會佔用單獨的塊。此操作要求在釋放舊有的對象前,必須將所有存活的對象複製到新堆。大型對象基本不會被複制,而內含許多小的對象的塊會被複制整理。

由於倆個部分各有針對性,所以Java虛擬機會對各個引用和內存區域進行監視,以在合適的情況執行合適的操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章