欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java教學(xué)筆記之對象的創(chuàng)建與銷毀

 更新時間:2016年01月30日 11:16:30   投稿:hebedich  
面向?qū)ο蟮木幊陶Z言使程序能夠直觀的反應(yīng)客觀世界的本來面目,并且使軟件開發(fā)人員能夠運用人類認(rèn)識事物所采用的一般思維方法進行軟件開發(fā),是當(dāng)今計算機領(lǐng)域中軟件開發(fā)和應(yīng)用的主流技術(shù)。

本課程的目標(biāo)是幫你更有效的使用Java。其中討論了一些高級主題,包括對象的創(chuàng)建、并發(fā)、序列化、反射以及其他高級特性。本課程將為你的精通Java的旅程提供指導(dǎo)。

1. 引言

在TIOBE 編程語言排名中,Sun 公司于1995年開發(fā)的Java語言是世界上使用最廣泛的編程語言之一。作為一種通用編程語言,因為強大的工具包和運行時環(huán)境、簡單的語法、豐富的平臺支持(一次編寫,到處運行)以及的異?;钴S的社區(qū)支持,Java語言對軟件開發(fā)工程師極具吸引力。

在這一系列的文章中,涵蓋了Java相關(guān)的高級內(nèi)容,因此假設(shè)讀者已具有基本語言知識。這并不是一個完整的參考手冊,而是讓你的技能更上一層樓的詳盡指南。

本課程中包含了大量的代碼片段,在有些對方為了做對比,會同時提供Java 7和Java 8的示例。

2. 實例構(gòu)造

作為一種面向?qū)ο笳Z言,對象的創(chuàng)建也許就是Java語言中最重要的概念之一。構(gòu)造方法是在對象實例初始化過程中具有舉足輕重的地位,并且Java提供了多種方式來定義構(gòu)造方法。

2.1 隱式(產(chǎn)生的)構(gòu)造方法

Java允許在定義類時不聲明任何的構(gòu)造方法,并這并不代表類沒有構(gòu)造方法。我們看下面類的定義:

package com.javacodegeeks.advanced.construction;

public class NoConstructor {
}

這個類未定義構(gòu)造方法,但是Java編譯器會為其隱式生成一個,從而使我們可以使用new關(guān)鍵字來創(chuàng)建新的對象實例。

final NoConstructor noConstructorInstance = new NoConstructor();

2.2 無參構(gòu)造方法

無參構(gòu)造方法是最簡單的通過顯式聲明來替代Java編譯生成構(gòu)造方法的方式。

package com.javacodegeeks.advanced.construction;

public class NoArgConstructor {
  public NoArgConstructor() {
    // Constructor body here
  }
}

在使用new關(guān)鍵字創(chuàng)建新的對象實例時,上面的構(gòu)造方法就會被調(diào)用。

2.3 有參構(gòu)造方法

有參構(gòu)造方法最有意思并且廣泛使用,通過指定參數(shù)來定制新實例的創(chuàng)建。下面的例子中定義了一個有兩個參數(shù)的構(gòu)造方法。

package com.javacodegeeks.advanced.construction;

public class ConstructorWithArguments {
  public ConstructorWithArguments(final String arg1,final String arg2) {
    // Constructor body here
  }
}

這種場景中,當(dāng)使用new關(guān)鍵字來創(chuàng)建實例時,需要同時提供構(gòu)造方法上定義的兩個參數(shù)。

final ConstructorWithArguments constructorWithArguments = 
  new ConstructorWithArguments( "arg1", "arg2" );

有趣的是構(gòu)造方法之間可以通過this關(guān)鍵字互相調(diào)用。在實踐中,推薦通過使用this把多個構(gòu)造方法鏈起來以減少代碼重復(fù),并從基礎(chǔ)上使對象具有單一的初始化入口。作為示例,下面的代碼中定義了只有一個參數(shù)的構(gòu)造方法。

public ConstructorWithArguments(final String arg1) {
  this(arg1, null);
}

2.4 初始化代碼塊

除了構(gòu)造方法,Java還提供了通過初始化代碼塊進行初始化的邏輯。這種用法雖然少見,但多了解一些也沒害處。

package com.javacodegeeks.advanced.construction;

public class InitializationBlock {
  {
    // initialization code here
  }
}

另一方面,初始化代碼塊也可被看作是無參的隱式構(gòu)造方法。在一個具體的類中可以定義多個初始化代碼塊,在執(zhí)行的時候按照他們在代碼中的位置順序被調(diào)用,如下面的代碼所示:

package com.javacodegeeks.advanced.construction;

public class InitializationBlocks {
  {
    // initialization code here
  }

  {
    // initialization code here
  }

}

實始化代碼塊并不是為了取代構(gòu)造方法,相反它們可以同時出現(xiàn)。但是要記住,初始化代碼快會在構(gòu)造方法調(diào)用之前被執(zhí)行。

package com.javacodegeeks.advanced.construction;

public class InitializationBlockAndConstructor {
  {
    // initialization code here
  }
  
  public InitializationBlockAndConstructor() {
  }
}

2.5 保證構(gòu)造默認(rèn)值

Java提供了確定的初始化保證,程序員可以直接使用初始化結(jié)果。未初始化的實例以及類變量(static)會自動初始化為相應(yīng)的默認(rèn)值。

類型 默認(rèn)值
boolean False
byte 0
short 0
int 0
long 0L
char \u0000
float 0.0f
double 0.0d
對象引用 null
表 1

我們通過下面的例子來驗證上表中的默認(rèn)值:

package com.javacodegeeks.advanced.construction;

public class InitializationWithDefaults {
  private boolean booleanMember;
  private byte byteMember;
  private short shortMember;
  private int intMember;
  private long longMember;
  private char charMember;
  private float floatMember;
  private double doubleMember;
  private Object referenceMember;

  public InitializationWithDefaults() {   
    System.out.println( "booleanMember = " + booleanMember );
    System.out.println( "byteMember = " + byteMember );
    System.out.println( "shortMember = " + shortMember );
    System.out.println( "intMember = " + intMember );
    System.out.println( "longMember = " + longMember );
    System.out.println( "charMember = " + 
      Character.codePointAt( new char[] { charMember }, 0 ) );
    System.out.println( "floatMember = " + floatMember );
    System.out.println( "doubleMember = " + doubleMember );
    System.out.println( "referenceMember = " + referenceMember );
  }
}

當(dāng)使用new關(guān)鍵字實例化對象之后:

final InitializationWithDefaults initializationWithDefaults = new InitializationWithDefaults(),
可從控制臺中看到輸出結(jié)果如下:

booleanMember = false
byteMember = 0
shortMember = 0
intMember = 0
longMember = 0
charMember = 0
floatMember = 0.0
doubleMember = 0.0
referenceMember = null

2.6 可見性

構(gòu)造方法遵從Java的可見性規(guī)則,并且可以通過訪問控制修飾符決定在其他類中是否能調(diào)用該構(gòu)造方法。

修飾符 包可見性 子類可見性 公開可見性
public 可見 可見 可見
protected 可見 可見 不可見
<無修飾符> 可見 不可見 不可見
private 不可見 不可見 不可見
表2

2.7 垃圾回收

Java(準(zhǔn)確的說是JVM)擁有自動的垃圾回收機制。簡單來講,當(dāng)有新對象創(chuàng)建時,會自動為其分配內(nèi)在;然后當(dāng)對象不再被引用后,他們會被自動銷毀,相應(yīng)的內(nèi)存也會被回收。

Java垃圾回收采用分代回收的機制,并基于"大多數(shù)對象生命短暫"的假設(shè)(即在對象創(chuàng)建之后很快就不會被再引用,所以可以被安全的銷毀)。大多程序員習(xí)慣性的認(rèn)為Java中對象創(chuàng)建的效率很低所以要盡可能避免新對象的創(chuàng)建。事實上,這種認(rèn)識是不對的。在Java中創(chuàng)建對象的開銷是相當(dāng)?shù)偷?,并且速度很快。真正代來巨大開銷的是不必要的長期存活的對象,因此他們最終會被遷移到老年代,并導(dǎo)致stop-the-world發(fā)生。

2.8 對象終結(jié)器(Finalizers)

前面我們講述的都是構(gòu)造方法和對象初始化相關(guān)的主題,但還未提及他們的反面:對象銷毀。主要是因為Java使用垃圾回收機制來管理對象的生命周期,所以銷毀不必要的對象并釋放所需內(nèi)存就成了垃圾回收的職責(zé)了。

不過,Java還是提供了另外一種類似于析構(gòu)函數(shù)的終結(jié)器(finalizer)的特性,擔(dān)任多種資源清理的責(zé)任。Finalizer一般被看作是危險的事情(因為它會帶來多種副作用和性能問題)。通常并不需要finalizer因此要盡量避免使用它(除了極少見的包含大量本地對象(native objects)的場景)。Java 7中引入的try-with-resources語法和AutoCloseable接口可當(dāng)作finalizer的替代選擇,并可寫出如下簡潔的代碼:

try ( final InputStream in = Files.newInputStream( path ) ) {
  // code here
}

3. 靜態(tài)初始化

上面我們學(xué)習(xí)了類實例的構(gòu)造與初始化,除此之外,Java還支持類級別的初始化構(gòu)造,稱作靜態(tài)初始化。靜態(tài)初始化與上面介紹的初始化代碼塊類似,只是多了額外的static關(guān)鍵字修飾。需要注意的是靜態(tài)初始化只會在類加載時執(zhí)行一次。示例如下:

與初始化代碼塊類似,可以在類中定義多個靜態(tài)初始化塊,它們在類中的位置決定在初始化時執(zhí)行的順序。示例如下;

package com.javacodegeeks.advanced.construction;

public class StaticInitializationBlocks {
  static {
    // static initialization code here
  }

  static {
    // static initialization code here
  }
}

因為靜態(tài)初始化塊可以被多個并行執(zhí)行的線程觸發(fā)(當(dāng)類被初始加載時),JVM運行時保證初始化的代碼以線程安全的方式只被執(zhí)行一次。

4. 構(gòu)造器模式

這些年多種容易理解的構(gòu)造器(創(chuàng)建者)模式被引入到Java社區(qū)。下面我們會學(xué)習(xí)其中比較流行的幾個:單例模式、輔助類模式、工廠模式以及依賴注入(也稱為控制反轉(zhuǎn))。

4.1 單例模式

單例是一種歷史悠久卻在軟件開發(fā)社區(qū)中飽受爭議的模式。單例模式的核心理念是保證在任何時候給定的類只有一個對象被創(chuàng)建。雖然聽起來很簡單,但人們對如何以正確且線程安全的方式創(chuàng)建對象進行了大量的討論。下面的代碼中展示了簡單版本的單例模式實現(xiàn):

package com.javacodegeeks.advanced.construction.patterns;

public class NaiveSingleton {
  private static NaiveSingleton instance;
  
  private NaiveSingleton() {    
  }
  
  public static NaiveSingleton getInstance() {
    if( instance == null ) {
      instance = new NaiveSingleton();
    }
    
    return instance;
  }
}

上面的代碼至少有一個問題:在多線程并發(fā)場景中可能會創(chuàng)建出多個對象。一種合理的實現(xiàn)方式(但不能延遲加載)是使用類的static`final`屬性。如下:

final property of the class.
package com.javacodegeeks.advanced.construction.patterns;

public class EagerSingleton {
  private static final EagerSingleton instance = new EagerSingleton();
  
  private EagerSingleton() {    
  }
  
  public static EagerSingleton getInstance() {
    return instance;
  }
}

如果你不想浪費寶貴的資源,希望單例對象只在真正需要的時候才被創(chuàng)建,那么就要使用顯式的同步方式,不可這種方法可能會降低多線程環(huán)境下的并發(fā)性(更多關(guān)于Java并發(fā)的細(xì)節(jié)將會在Java進階9-并發(fā)最佳實踐中詳細(xì)介紹)。

package com.javacodegeeks.advanced.construction.patterns;

public class LazySingleton {
  private static LazySingleton instance;
  
  private LazySingleton() {    
  }
  
  public static synchronized LazySingleton getInstance() {
    if( instance == null ) {
      instance = new LazySingleton();
    }
    
    return instance;
  }
}

現(xiàn)在,在很多場景下單例模式不再被認(rèn)為是一種好的選擇,因為他們會使代碼不易于測試。另外依賴注入模式的產(chǎn)生也使單例模式變得不再必要。

4.2 工具類/輔助類

工具類/輔助類模式在Java開發(fā)者當(dāng)中相當(dāng)流行。它的核心理念就是使用不可實例化的類(通過聲明private構(gòu)造方法)、可選的final(更多關(guān)于聲明final類的細(xì)節(jié)將會在Java進階3-類和接口的設(shè)計中詳細(xì)介紹)關(guān)鍵字以及靜態(tài)方法。示例如下:

package com.javacodegeeks.advanced.construction.patterns;

public final class HelperClass {
  private HelperClass() {    
  }
  
  public static void helperMethod1() {
    // Method body here
  }
  
  public static void helperMethod2() {
    // Method body here
  }
}

很多經(jīng)驗豐富的開發(fā)者認(rèn)為這種模式會讓工具類成為各種不相關(guān)方法的容器。因為有些方法沒有合適的放置位置卻需要被其他類使用,就會被誤放入工具類中。在大多數(shù)場景中也應(yīng)該避免這種設(shè)計:總會有更好的功能復(fù)用的方式,保持代碼清晰簡潔。

4.3 工廠模式

工廠模式被證明是開發(fā)者的極其強大的利器,在Java中有多種實現(xiàn)方式:工廠方法和抽象工廠。最簡單的例子就是使用static方法返回特定類的實例(工廠方法),如下:

package com.javacodegeeks.advanced.construction.patterns;

public class Book {
  private Book( final String title) {
  }   

  public static Book newBook( final String title ) { 
    return new Book( title );
  }
}

雖然使用這種方法能提高代碼的可讀性,但經(jīng)常爭議的一點是難以給newBook工廠方法賦予更豐富的場景。另外一種實現(xiàn)工廠模式的方法是采用接口或抽象類(抽象工廠)。如下,我們定義一個工廠接口:

public interface BookFactory {
  Book newBook();
}

根據(jù)圖片館的不同,我們可以有多種不同的newBook實現(xiàn):

public class Library implements BookFactory {
  @Override
  public Book newBook() {
    return new PaperBook();
  }
}

public class KindleLibrary implements BookFactory {
  @Override
  public Book newBook() {
    return new KindleBook();
  }
}

現(xiàn)在,BookFactory的不同實現(xiàn)屏蔽掉了具體Book的不同,卻提供了通用的newBook的方法。

4.4 依賴注入

依賴注入(也稱為控制反轉(zhuǎn))被類設(shè)計者認(rèn)為是一種良好的設(shè)計實踐:如果一些類實例依賴其他類的實例,那些被依賴的實例應(yīng)該通過構(gòu)造方法(或者setter方法、策略等方式)提供(注入),而不應(yīng)該是由實例自己去創(chuàng)建。先看一下下面的代碼:

package com.javacodegeeks.advanced.construction.patterns;

import java.text.DateFormat;
import java.util.Date;

public class Dependant {
  private final DateFormat format = DateFormat.getDateInstance();
  
  public String format( final Date date ) {
    return format.format( date );
  }
}

Dependant類需要一個DateFormat類的實例并通過在實例化對象時通過DateFormat.getDateInstance()的方式獲得。更好的方式應(yīng)該通過構(gòu)造方法的參數(shù)來完成同樣的事情:

package com.javacodegeeks.advanced.construction.patterns;

import java.text.DateFormat;
import java.util.Date;

public class Dependant {
  private final DateFormat format;
  
  public Dependant( final DateFormat format ) {
    this.format = format;
  }
  
  public String format( final Date date ) {
    return format.format( date );
  }
}

在上面的例子中,類實例的所有依賴都由外部提供,這樣就很容易調(diào)整DateFormat,并易于編寫測試代碼。

相關(guān)文章

  • java中的JsonSerializer用法,前后端單位轉(zhuǎn)換必備

    java中的JsonSerializer用法,前后端單位轉(zhuǎn)換必備

    這篇文章主要介紹了java中的JsonSerializer用法,前后端單位轉(zhuǎn)換必備!具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 深入探究Java多線程并發(fā)編程的要點

    深入探究Java多線程并發(fā)編程的要點

    這篇文章主要介紹了深入探究Java多線程并發(fā)編程的要點,包括關(guān)鍵字synchronized的使用和wait()與notify()獲取對象鎖的三種方式,需要的朋友可以參考下
    2015-11-11
  • java高并發(fā)下CopyOnWriteArrayList替代ArrayList

    java高并發(fā)下CopyOnWriteArrayList替代ArrayList

    這篇文章主要為大家介紹了java高并發(fā)下CopyOnWriteArrayList替代ArrayList的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • 一文詳解Spring任務(wù)執(zhí)行和調(diào)度(小結(jié))

    一文詳解Spring任務(wù)執(zhí)行和調(diào)度(小結(jié))

    這篇文章主要介紹了一文詳解Spring任務(wù)執(zhí)行和調(diào)度(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java NIO框架Netty簡單使用的示例

    Java NIO框架Netty簡單使用的示例

    本篇文章主要介紹了Java NIO框架Netty簡單使用的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java利用SpEL表達(dá)式實現(xiàn)權(quán)限校驗

    Java利用SpEL表達(dá)式實現(xiàn)權(quán)限校驗

    這篇文章主要為大家詳細(xì)介紹了Java如何利用SpEL表達(dá)式實現(xiàn)權(quán)限校驗功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • Java transient關(guān)鍵字與序列化操作實例詳解

    Java transient關(guān)鍵字與序列化操作實例詳解

    這篇文章主要介紹了Java transient關(guān)鍵字與序列化操作,結(jié)合實例形式詳細(xì)分析了java序列化操作相關(guān)實現(xiàn)方法與操作注意事項,需要的朋友可以參考下
    2019-09-09
  • MybatisPlus多數(shù)據(jù)源及事務(wù)解決思路

    MybatisPlus多數(shù)據(jù)源及事務(wù)解決思路

    這篇文章主要介紹了MybatisPlus多數(shù)據(jù)源及事務(wù)解決思路,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • JDBC連接Mysql的5種方式實例總結(jié)

    JDBC連接Mysql的5種方式實例總結(jié)

    JDBC是Java DataBase Connectivity技術(shù)的簡稱,是一種可用于執(zhí)行 SQL語句的Java API,下面這篇文章主要給大家介紹了關(guān)于JDBC連接Mysql的5種方式,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • java集合中l(wèi)ist的用法代碼示例

    java集合中l(wèi)ist的用法代碼示例

    這篇文章主要介紹了java集合中l(wèi)ist的用法代碼示例,分享了相關(guān)代碼,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11

最新評論