JAVA基礎之初始化與清理
阿新 • • 發佈:2019-01-30
用構造器確保初始化
構造器與類名稱相同;是一種特殊型別的方法,因為它沒有返回值。
在建立物件時,會為物件分配儲存空間,並呼叫相應的構造器。
不包含任何引數的構造器叫做預設構造器
方法過載
class Person {
public Person() {}
public Person(String name){}
public Person(String name,int age){}
}
- 區分過載
每個方法都有獨一無二的引數型別列表
- 方法過載
1.如果傳入的資料型別小於方法中宣告的形式引數型別,實際資料型別就會被提升; char略有不同,如果無法找到恰好接受char引數的方法,就會把char直接提升至int型
2.如果傳入的實際引數大於過載方法宣告的形式引數,就需要進行強制轉換,否則編譯器就會報錯。 eg: void test(byte b) {} int i = 5; test(i);//編譯器會報錯
預設構造器
預設構造器又名“無參”構造器,是沒有形式引數的。
如果類中沒有構造器,編譯器會自動幫你建立一個預設構造器。
- 作用
用於建立一個“預設物件”
this關鍵字
this關鍵字只能在方法內部使用,表示對“對呼叫方法的那個物件”的引用
如果在方法內部呼叫同一個類的另一個方法,就不必使用this,直接呼叫即可
class Test { private Test(){} public Test newInstance() { return this; } }
- 在構造器中呼叫構造器
class Test {
String s;
public Test(){this("test");}
public Test(String s){this.s = s;}
}
構造器中只能用this呼叫一個構造器,並且必須置於初始處
除構造器外,編譯器禁止其他方法呼叫構造器
- static的含義
可以通過類本身來呼叫static方法,也可以通過物件來呼叫
static方法就是沒有this的方法
在static方法內部不能呼叫非靜態方法,反過來是可以的。
清理:終結處理和垃圾回收
java垃圾回收器負責回收無用物件佔據的記憶體資源
垃圾回收器只知道釋放那些經由new分配的記憶體
- finalize()的用途何在
一旦垃圾回收器準備好釋放物件佔用的儲存空間,將首先呼叫其finalize(),並且在下一次垃圾回收動作傳送時,才會真正回收物件佔用的記憶體
無論是“垃圾回收”還是“終結”,都不保證一定會發生。 如果java虛擬機器(JVM)並未面臨記憶體耗盡的情形,它是不會浪費時間去執行垃圾回收以恢復記憶體的。
System.gc()用於強制進行終結動作
Java虛擬機器採用一種自適應的垃圾回收技術。
- 自適應技術
標記-清掃: 從堆疊和靜態儲存區出發,遍歷所有的引用,進而找出所有存活的物件。 每當它找到一個存活的物件,就會給物件設一個標記,這個過程中不會回收任何物件。 只有全部標記工作完成的時候,清理動作才會開始。 在清理過程中,沒有標記的物件將被釋放,不會發生任何複製動作。 停止-複製: 先暫停程式的執行,然後將所有的存活的物件從當前堆複製到另一個堆,沒有被複制的全部都是垃圾。 “標記-清掃”與“停止-複製”都是在程式暫停的情況下才能進行。 Java虛擬機器會進行監視,如果所有物件都很穩定,垃圾回收器的效率降低的話,就切換到“標記-清掃”方式; 同樣,Java虛擬機器會跟蹤“標記-清掃”效果,要是堆空間出現很多碎片,就會切換回“停止-複製”方式
- 注意
1.物件可能不被垃圾回收 2.垃圾回收並不等於“析構” 3.垃圾回收只與內容有關
成員初始化
方法的區域性變數沒有初始化就會編譯出錯
- 預設初始化
類的資料成員沒有初始化就會被賦予預設初始值 boolean:false char:0(空白) byte,short,int,long:0 float,double:0.0 物件:null
- 指定初始化(自動初始化)
在定義類成員變數的地方為其賦值
class Test {
int i = 10; //方式1
int j = getNum(i); //方式2
private int getNum(int i) {
return i * 10;
}
}
構造器初始化
在執行時刻,可以呼叫方法或執行某些動作來確定初值
無法阻止自動初始化的進行,它將在構造器被呼叫之前發生
- 靜態資料的初始化
static關鍵字不能應用於區域性變數,無論建立多少個物件,靜態資料都只佔一份儲存區域 靜態初始化只有在必要時刻才會進行,靜態初始化只在Class物件首次載入的時候進行一次
- 物件的建立過程
假設有個類為Dog
1.首次建立Dog物件(或Dog的靜態方法/靜態域首次被訪問)時,編譯器首先會找到Dog.class檔案 2.載入Dog.class,執行所有有關靜態初始化的動作 3.使用new Dog()建立物件時,首先在堆上為Dog物件分配足夠的儲存空間 4.這塊儲存空間會被清零,將Dog物件中所有基本型別資料設定成預設值(預設初始化),設定引用為null 5.執行所有出現與欄位定義處的初始化動作(指定初始化) 6.執行構造器
- 初始化順序
變數定義的先後順序決定了初始化的順序,即使變數定義散佈於方法定義之間,它們仍舊會在任何方法(包括構造器)被呼叫之前得到初始化。
//當new Hello()時,物件建立順序依次為t1,t2,t3,t4,t5,t6
//靜態物件 - 靜態程式碼塊初始化 - 顯示初始化 - 構造程式碼塊初始化 - 建構函式初始化
class Test {
public Test(int marker) {
System.out.println("Test(" + marker + ")");
}
}
class Hello {
static Test t1 = new Test(1);
Test t3 = new Test(3);
Test t4;
Test t5;
static {
//靜態程式碼塊,只執行1次
Test t2 = new Test(2);
}
{
//構造程式碼塊,先於構造器初始化,無論呼叫哪個建構函式,都會執行該初始化
t4 = new Test(4);
}
public Hello() {
t5 = new Test(5);
Test t6 = new Test(6);
}
}
陣列初始化
- 定義陣列
型別後加[],如int[] i;或int i[];
- 陣列初始化
int[] i = {1,2,3};
Integer[] a = new Integer[]{new Integer(1),2,new Integer(3)};
int[] j = new int[10];
Random rand = new Random();
int[] a = new int[rand.nextInt(20)];
Object[] obj = new Object[]{new Integer(1),new Float(2.0),new Double(3.0)};
Object[] objects = new Integer[]{1,2,3};
- 可變引數列表
class Test {
public static void main(String[] args) {
Test test = new Test();
test.printArray(1, new String("Hello"), new Float(2.0));
test.printArray(2, (Object[])new String[] {"Hello","World"});
test.printArray(0);
}
public void printArray(int num, Object... objects) {
System.out.print(num + " ");
for (Object object : objects) {
System.out.print(object + " ");
}
System.out.println();
}
}
列舉型別
由於列舉型別的例項是常量,按照命名慣例都用大寫字母表示
列舉型別可以在switch語句內使用
class Test {
public enum Animal {
PIG, DOG, SHEEP, DUCK, WOLF
}
public static void main(String[] args) {
for (Animal animal : Animal.values()) {
System.out.println(animal.ordinal() + " : " + animal);
}
Animal animal = Animal.PIG;
System.out.print(animal);
}
}