成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《Java編程思想》筆記5.初始化與清理

wangym / 1276人閱讀

摘要:點擊進(jìn)入我的博客初始化和清理是編程安全的兩個問題。延續(xù)了中的構(gòu)造器確保初始化,并引入了垃圾回收器管理和釋放內(nèi)存。用構(gòu)造方法確保初始化構(gòu)造方法和類名相同。用于強(qiáng)制進(jìn)行終結(jié)動作。載入該文件,靜態(tài)數(shù)據(jù)進(jìn)行初始化,執(zhí)行靜態(tài)代碼塊。

點擊進(jìn)入我的博客

初始化和清理是編程安全的兩個問題。Java延續(xù)了C++中的構(gòu)造器確保初始化,并引入了“垃圾回收器”管理和釋放內(nèi)存。

5.1 用構(gòu)造方法確保初始化

構(gòu)造方法和類名相同。原因是盡量減少和成員名稱沖突;并且調(diào)用構(gòu)造方法是編譯器的責(zé)任,名稱相同編譯器才會知道應(yīng)該調(diào)用哪個方法。

由于構(gòu)造方法和類名相同,所以構(gòu)造方法不適應(yīng)于首字母小寫的約定規(guī)范。

構(gòu)造方法有默認(rèn)的無參構(gòu)造方法,也可以帶參數(shù)。

構(gòu)造方法沒有返回值,請注意這跟void不同。

5.2 方法重載

方法重載是指方法名相同,但是參數(shù)的個數(shù)、類型和順序不同。

由于構(gòu)造方法必須和類名相同,即方法名已經(jīng)確定,但想要用多種方式(參數(shù))創(chuàng)建一個對象,就必須引入方法重載

方法重載不僅適用于構(gòu)造方法,還適用于其他方法。

warningfunc(int i, String str)func(String str, int i)參數(shù)順序不同構(gòu)成重載,但請盡量避免這種寫法。

構(gòu)成重載深層次的原因:只要這兩個方法編譯器能區(qū)分開來,在調(diào)用的時候知道要調(diào)用的是哪一個,不會產(chǎn)生混淆,這兩個方法就構(gòu)成重載。

基本類型的重載

對于byte、short、intfloat、double如果找不到對應(yīng)基本類型方法,則會按照向上轉(zhuǎn)化的路線找匹配的方法

如果是char,如果找不到對應(yīng)的基本類型方法,直接從int向上找匹配的方法。

    public static void print(char c) {
        System.out.println("char: " + c);
    }

    public static void print(byte b) {
        System.out.println("byte: " + b);
    }

    public static void print(short s) {
        System.out.println("short: " + s);
    }

    public static void print(int i) {
        System.out.println("int: " + i);
    }

    public static void print(long l) {
        System.out.println("long: " + l);
    }

    public static void print(float f) {
        System.out.println("float: " + f);
    }

    public static void print(double d) {
        System.out.println("double: " + d);
    }
返回值不同無法區(qū)分兩個方法
void f() {};
boolean f() {
    return true;
};
// 只調(diào)用f()無法區(qū)分是哪個方法
5.3 默認(rèn)構(gòu)造器

如果你的類中沒有構(gòu)造器,則編譯器會幫你自動創(chuàng)建一個默認(rèn)構(gòu)造器??梢酝ㄟ^反編譯.class文件來驗證這一點。

如果你自己定義了一個構(gòu)造方法,則編譯器不會幫你創(chuàng)建默認(rèn)構(gòu)造器。

5.4 this關(guān)鍵字

下述代碼中,有兩個對象a1a2,按照面向過程的函數(shù)形式,在執(zhí)行func()函數(shù)的時候,怎么知道是被a1、a2調(diào)用呢?為了能用面向?qū)ο蟮恼Z法來編寫代碼,編譯器做了一些幕后工作。它暗自把“所操作的對象”作為第一個參數(shù)傳遞給func()函數(shù),即func(a1)。這是內(nèi)部的表示形式,我們并不能這樣寫代碼。

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
        a1.func();
        a2.func();
    }
}

class A {
    void func() {}
}

this關(guān)鍵字只能在方法內(nèi)部使用,表示對“調(diào)用方法的那個對象的引用?!?/strong>

有人喜歡將this放到每個方法調(diào)用和字段引用前,千萬不要這么做!

當(dāng)需要返回當(dāng)前對象的引用時,可以通過return this;

5.4.1 在構(gòu)造器中調(diào)用構(gòu)造器

可以通過this(params);來調(diào)用其他的構(gòu)造方法

可以通過this調(diào)用一個其他的構(gòu)造方法,但不能調(diào)用兩個及以上

通過this調(diào)用其他的構(gòu)造方法必須放到該構(gòu)造方法的第一行

構(gòu)造方法不能通過this調(diào)用自己

    public Test(int i) {
        System.out.println("Test " + i);
    }

    public Test(String str) {
        System.out.println("Test " + str);
    }

    // (1)
    public Test() {
        this(1);
        // this("imbug");
        System.out.println("Test");
    }

    public static void main(String[] args) {
        Test test = new Test();
    }
5.4.2 static方法

static方法中不能使用this關(guān)鍵字

static方法中不能調(diào)用非靜態(tài)方法,反之則可以

5.5 清理:終結(jié)處理和垃圾回收

Java的垃圾回收器(GC)負(fù)責(zé)回收無用對象占據(jù)的內(nèi)存資源

假定你的對象(不是通過new)獲得了一塊“特殊”的內(nèi)存區(qū)域,由于GC只知道new分配的內(nèi)存,所以它不知道如何釋放該對象的“特殊”內(nèi)存區(qū)域。為了應(yīng)付這種情況,Java允許在類中定義一個名為finalize()的方法。

5.5.1 finalize()方法

一旦GC準(zhǔn)備釋放對象的存儲空間,首先調(diào)用該方法;并且在下一次垃圾回收動作發(fā)生時,才會真正回收對象占用的內(nèi)存。即調(diào)用該方法但時候,對象還沒有被回收。

finalize()方法不是C++中的析夠方法

在C++中對象一定會被銷毀(代碼無Bug),但是在Java里的對象并非總是被垃圾回收。

垃圾回收只與內(nèi)存相關(guān),也就是說使用GC的唯一原因是為了回收程序不再使用的內(nèi)存。

上述討論了,對象可能會獲得一塊“特殊”的內(nèi)存區(qū)域,這主要發(fā)生在JNI本地方法的情況下,本地方法是在Java中使用非Java代碼的方式。非Java代碼可能會調(diào)用C的malloc()來分配存儲空間,而且除了free()方法否則其存儲空間將得不到釋放,從而造成內(nèi)存泄漏。此時就可以在finalize()中調(diào)用free()方法,清理本地對象。

不建議用finalize方法完成“非內(nèi)存資源”的清理工作,但也可以作為確保某些非內(nèi)存資源(如Socket、文件等)釋放的一個補(bǔ)充。

System.gc()與System.runFinalization()方法增加了finalize方法執(zhí)行的機(jī)會,但不保證一定會執(zhí)行。

用戶可以手動調(diào)用對象的finalize方法,但并不影響GC對finalize的行為,即沒有卵用~

finalize()執(zhí)行流程

5.5.2 你必須實施清理

Java不允許創(chuàng)建局部對象(即堆棧上的對象),必須使用new創(chuàng)建對象。

無論是“垃圾回收”還是“終結(jié)”,都不保證一定會發(fā)生。

5.5.3 終結(jié)條件

如果某個對象的內(nèi)存可以被安全釋放了,例如對象代表了一個打開的文件,那么回收內(nèi)存前必須保證文件關(guān)閉。這個在finalize()中可以檢驗文件的狀態(tài)。

System.gc()用于強(qiáng)制進(jìn)行終結(jié)動作。

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        // if(文件未安全關(guān)閉)
        System.out.println("error");
    }

    public static void main(String[] args) {
        func();
        System.gc();
    }

    public static void func() {
        Test t1 = new Test();
        Test t2 = new Test();
    }
5.5.4 GC如何工作

更詳細(xì)內(nèi)容請看JVM工作原理?。?!

GC會整理堆內(nèi)存空間,因此導(dǎo)致new新建對象時的內(nèi)存分配速度

引用計數(shù)

每個對象都含有一個計數(shù)器,當(dāng)引用連接至對象時+1,引用離開作用域或被置為null時-1。GC遍歷全部對象,發(fā)現(xiàn)計數(shù)器為0的時候就會釋放其內(nèi)存。

優(yōu)點:簡單

缺點:慢、循環(huán)引用問題、對象應(yīng)該被回收但引用計數(shù)不為零

引用計數(shù)只是為了說明GC的工作方式,但實際上似乎沒有任何Java虛擬機(jī)實現(xiàn)過。

根搜索算法

原理:每個“活”的對象,一定能追溯到其存活在堆?;蜢o態(tài)存儲區(qū)之中的引用。

方法:從堆棧和靜態(tài)存儲區(qū)開始,遍歷所有引用;然后追蹤它所引用的對象,然后是這些對象包含的所有對象,反復(fù)進(jìn)行直至“根源于堆棧和靜態(tài)存儲區(qū)的引用”所形成的網(wǎng)絡(luò)被全部訪問完為止

停止-復(fù)制算法

先暫停程序的運(yùn)行,然后將全部活的對象從當(dāng)前堆復(fù)制到另一個堆,沒有復(fù)制的都是垃圾;新堆里的對象在內(nèi)存中時連續(xù)的

不屬于后臺回收模式,因為要暫停程序的運(yùn)行

把對象從一個堆復(fù)制到另一個堆時,所有指向它們的引用都必須要修正。

效率低的原因(1):需要兩個分離的堆,因此需要兩倍的內(nèi)存空間

效率低的原因(2):程序穩(wěn)定后垃圾很少,即需要存活的對象遠(yuǎn)大于垃圾數(shù)量,此時復(fù)制到另一個堆非常浪費(fèi)。

標(biāo)記-清掃算法

用根搜索算法找到所有存活的對象并標(biāo)記(此過程不回收),當(dāng)全部標(biāo)記工作完成的時候,清理所有沒有標(biāo)記的對象

缺點(1):導(dǎo)致內(nèi)存空間不連續(xù)

缺點(2):也會暫停程序

分代算法

JVM中,內(nèi)存以較大的“塊”為單位;如果對象比較大,它會占據(jù)多帶帶的塊;有了塊之后,GC就可以在回收的時候往廢棄的塊中拷貝對象了

每個塊用相應(yīng)的代數(shù)(generation count)來記錄是否存活;如果塊在某處被引用,其代數(shù)會增加;GC會對上次回收動作之后新分配的塊進(jìn)行整理

GC會定期進(jìn)行完整的清理動作,大型對象不會被復(fù)制但是其代數(shù)會增加;小型對象的那些塊則被復(fù)制并整理

自適應(yīng)、分代的、停止復(fù)制、標(biāo)記清掃方式

JVM會進(jìn)行監(jiān)視,如果所有對象都很穩(wěn)定,垃圾回收器的效率降低的話,就切換到標(biāo)記-清掃模式;同樣,JVM會跟蹤標(biāo)記-清掃的效果,要是堆空間出現(xiàn)很多碎片,就會切換回停止-復(fù)制模式。

其他附加技術(shù)

即使編譯器(Just-In-Time JIT):可以把程序全部或部分翻譯成機(jī)器碼來提高運(yùn)行速度。當(dāng)需要裝載某個類時,編譯器會先找到其.class文件,然后將該類的字節(jié)碼裝入內(nèi)存。此時,有兩種方案可供選擇:

讓即時編譯器編譯所有代碼:這種操作散落在整個程序的聲明周期內(nèi),累加起來耗時更長;會增加可執(zhí)行代碼的長度,造成頁面調(diào)度

惰性評估:意思是即時編譯器只在必要的時候才編譯代碼,這樣,從不會被執(zhí)行的代碼也許就壓根不會被JIT所編譯。

5.6 成員初始化

Java盡量保證:所有變量使用前一定會初始化
局部變量:不會自動初始化,而是編譯錯誤
類成員變量:類的每個基本類型數(shù)據(jù)成員都保證會有初始值;引用類型為null

指定初始化

定義類成員變量的時候給它賦值——(1)

通過調(diào)用某個方法來提供初值——(2)

注意:(2)、(3)不能顛倒順序,因為存在向前引用。

缺點:這種方式所有成員有相同的屬性

public class Test {
    // (1)
    int a = 10;
    // (2)
    int i = f();
    // (3)
    int j = g(i);
    int g(int n) {
        return n;
    }
    int f() {
        return 1;
    }

    public static void main(String[] args) {
        Test t = new Test();
    }
}
5.7 構(gòu)造器初始化

無法阻止自動初始化的進(jìn)行,它發(fā)生在構(gòu)造器被調(diào)用之前!

5.7.1 初始化順序

遍歷定義的先后順序決定了初始化的順序。

5.7.2 靜態(tài)數(shù)據(jù)的初始化

靜態(tài)數(shù)據(jù)跟非靜態(tài)數(shù)據(jù)的默認(rèn)初值是一致的。

先初始化靜態(tài)對象,然后初始化非靜態(tài)對象。

靜態(tài)初始化只有在必要的時候執(zhí)行,如創(chuàng)建第一個該類對象或調(diào)用靜態(tài)方法的時候執(zhí)行。

對象創(chuàng)建過程

在調(diào)用該類的靜態(tài)方法或者首次new對象(構(gòu)造器其實也是靜態(tài)方法)的時候,Java解釋器查找類路徑定位到該類的.class文件。

載入該.class文件,靜態(tài)數(shù)據(jù)進(jìn)行初始化,執(zhí)行靜態(tài)代碼塊。

當(dāng)new對象創(chuàng)建對象的時候,首先在堆內(nèi)存中為此對象分配足夠的內(nèi)存空間。

把此存儲空間清零,即所有非靜態(tài)基本數(shù)據(jù)類型置為0,對象類型置為null

執(zhí)行非靜態(tài)數(shù)據(jù)初始化動作。

執(zhí)行構(gòu)造器。

5.7.3 顯式的靜態(tài)初始化

即靜態(tài)代碼塊。

在調(diào)用該類的靜態(tài)方法或者首次new對象的時候執(zhí)行,即和靜態(tài)數(shù)據(jù)初始化相同的條件,但是發(fā)生在靜態(tài)數(shù)據(jù)初始化之后。

5.7.4 非靜態(tài)實例初始化

Java中也有被稱為實例初始化的語法,用來初始化每一個對象的非靜態(tài)變量。

實例初始代碼塊和成員變量的初始化順序是按照遍歷的先后順序執(zhí)行的,但兩者執(zhí)行都在構(gòu)造方法之前。即如果(1)、(2)位置改變,輸出會變成213。

這種語法對于支持“匿名內(nèi)部類”的初始化是必須的

    // (1)
    {
        System.out.println(1);
    }
    // (2)    
    int i = func();
    int func() {
        System.out.println(2);
        return 2;
    }
    // (3)
    Test() {
        System.out.println(3);
    }

    public static void main(String[] args) {
        new Test(); // output 123
    }
5.8 數(shù)組初始化

int[] arr、int arr[]這兩種寫法都可以,但更推薦前者。

為了給數(shù)組創(chuàng)建相應(yīng)的內(nèi)存空間,必須初始化數(shù)組的大?。换蛘叱跏蓟臅r候直接初始化數(shù)組的值(int[] arr = {1, 2, 3}),此時存儲空間的分配由編譯器負(fù)責(zé)。

所有數(shù)組都有一個固定成員length獲知成員數(shù)量,但不可以修改這個值。

數(shù)組坐標(biāo)從0開始。

數(shù)組中的元素會自動初始化為空值。

5.8.1 可變參數(shù)列表

void func(String... args) {}

可變參數(shù)列表可以接受不傳任何參數(shù),即func()是可行的。

可變列表與自動包裝機(jī)制可以和諧相處

數(shù)組的class

基本數(shù)據(jù)類型:class、空格、多個(值為數(shù)組維數(shù))[、對應(yīng)數(shù)據(jù)類型的標(biāo)識

對象類型:class、空格、多個(值為數(shù)組維數(shù))[、大寫L、對應(yīng)數(shù)據(jù)類型的全路徑、;

        System.out.println(new int[0].getClass()); // class [I
        System.out.println(new Integer[0].getClass()); // class [Ljava.lang.Integer;
        System.out.println(new long[0].getClass()); // class [J
        System.out.println(new double[0].getClass()); // class [D
        System.out.println(new int[0][0].getClass()); // class [[I
        System.out.println(new int[0][0][0].getClass()); // class [[[I
        System.out.println(new String[0].getClass()); // class [Ljava.lang.String;
        System.out.println(new String[0][0].getClass()); // class [[Ljava.lang.String;
可變類型引起的重載問題

此段代碼編譯失敗,因為編譯器發(fā)現(xiàn)有多個方法可以調(diào)用。

    public static void main(String[] args) {
        func(1, "a");
        func("a", "b");
    }

    static void func(int i, Character... args) {
        System.out.println("first");
    }

    static void func(Character... args) {
        System.out.println("second");
    }
5.9 枚舉類型

枚舉常量命名規(guī)范:全部大寫字母用下劃線分割

枚舉會自動創(chuàng)建toString()方法

會自動創(chuàng)建ordinal()方法,用來表示枚舉常量的聲明順序

枚舉可以在switch中使用

public class Test {
    public static void main(String[] args) {
        Color green = Color.GREEN;
        Color red = Color.RED;
        System.out.println(green + "   " + green.ordinal());
        System.out.println(red + "   " + red.ordinal());
    }
}

enum Color {
    RED,
    GREEN;
}
反編譯后的Color類

在代碼中Enum禁止繼承

// final class 禁止繼承
final class Color extends Enum
{

    public static Color[] values()
    {
        return (Color[])$VALUES.clone();
    }

    public static Color valueOf(String name)
    {
        return (Color)Enum.valueOf(s2/Color, name);
    }
    // 私有構(gòu)造方法,所以無法用new創(chuàng)建對象
    private Color(String s, int i)
    {
        super(s, i);
    }

    public static final Color RED;
    public static final Color GREEN;
    private static final Color $VALUES[];

    static 
    {
        RED = new Color("RED", 0);
        GREEN = new Color("GREEN", 1);
        $VALUES = (new Color[] {
            RED, GREEN
        });
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72184.html

相關(guān)文章

  • Java編程思想筆記8.多態(tài)

    摘要:多態(tài)的作用是消除類型之間的耦合關(guān)系。編寫構(gòu)造器準(zhǔn)則用盡可能簡單的方法使對象進(jìn)入正常狀態(tài),如果可以的話,避免調(diào)用其他方法。 點擊進(jìn)入我的博客 在面向?qū)ο蟮某绦蛟O(shè)計語言中,多態(tài)是繼數(shù)據(jù)抽象(封裝)和繼承之后的第三種基本特征。多態(tài)通過分離做什么和怎么做,從另一角度將接口和實現(xiàn)分離開來。多態(tài)的作用是消除類型之間的耦合關(guān)系。 8.1 再論向上轉(zhuǎn)型 對象既可以作為它自己的本類使用,也可以作為它的...

    chinafgj 評論0 收藏0
  • Java編程思想筆記7.復(fù)用類

    摘要:在類的構(gòu)造方法中。對基類構(gòu)造器的調(diào)用必須放到子類構(gòu)造器的第一行。約定用大寫字母下劃線命名規(guī)范空白空白指被聲明為但又未給定初值的域,但可以在構(gòu)造方法必須在域的定義處代碼塊或構(gòu)造器中對進(jìn)行賦值。 點擊進(jìn)入我的博客 復(fù)用代碼是Java眾多引人注目的功能之一,但要成為極具革命性的語言,僅僅能夠復(fù)制代碼并對之加以改變是不夠的,它還必須能夠做更多的事情。 7.1 組合 組合語法 就是在當(dāng)前類中產(chǎn)...

    ningwang 評論0 收藏0
  • Java編程思想筆記01------一切都是對象

    摘要:一引用操縱對象在的世界里,一切都被視為對象。特點創(chuàng)建程序時,需要知道存儲在棧內(nèi)所有數(shù)據(jù)的確切生命周期,以便上下移動堆棧指針。因為,指向同一塊內(nèi)存空間除了通過對象引用靜態(tài)變量,我們還可以通過類直接引用靜態(tài)變量 一、引用操縱對象 在Java的世界里,一切都被視為對象。操縱的標(biāo)識符實際上是對象的引用, 例如:遙控器與電視的關(guān)系。 可以在沒有對象關(guān)聯(lián)的情況下,擁有一個引用。沒有電視機(jī),也可以擁...

    yuanxin 評論0 收藏0
  • Java編程思想筆記12.通過異常處理錯誤

    摘要:一旦異常被拋出,就表明錯誤已無法挽回,也不能回來繼續(xù)執(zhí)行。這種在編譯時被強(qiáng)制檢查的異常稱為被檢查的異常。通過獲取原始異常。構(gòu)造器對于在構(gòu)造階段可能會拋出異常,并要求清理的類,最安全的做法是使用嵌套的子句。 點擊進(jìn)入我的博客 Java異常處理的目的在于通過使用少于目前數(shù)量的代碼來簡化大型、可靠的程序的生成,并且通過這種方式可以使你更自信:你的應(yīng)用中沒有未處理的錯誤。 12.1 概念 異...

    Vultr 評論0 收藏0
  • Java編程思想學(xué)習(xí)錄(連載之:始化清理

    摘要:注本文首發(fā)于公眾號,可長按或掃描下面的小心心來訂閱關(guān)于構(gòu)造器與初始化無參構(gòu)造器默認(rèn)構(gòu)造器自己未寫編譯器幫忙自動創(chuàng)建的若自行定義了構(gòu)造器無論參數(shù)有否,編譯器便停止默認(rèn)創(chuàng)建動作類里的對象引用默認(rèn)初始化為,基本類型初始化為構(gòu)造器也是類的靜態(tài)方法四 showImg(https://segmentfault.com/img/remote/1460000015723687); 注: 本文首發(fā)于 ...

    betacat 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<