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

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

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

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

1. 引言

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

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

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

2. 實(shí)例構(gòu)造

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

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

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

package com.javacodegeeks.advanced.construction;

public class NoConstructor {
}

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

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)建新的對(duì)象實(shí)例時(shí),上面的構(gòu)造方法就會(huì)被調(diào)用。

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

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

package com.javacodegeeks.advanced.construction;

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

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

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

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

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

2.4 初始化代碼塊

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

package com.javacodegeeks.advanced.construction;

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

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

package com.javacodegeeks.advanced.construction;

public class InitializationBlocks {
  {
    // initialization code here
  }

  {
    // initialization code here
  }

}

實(shí)始化代碼塊并不是為了取代構(gòu)造方法,相反它們可以同時(shí)出現(xiàn)。但是要記住,初始化代碼快會(huì)在構(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é)果。未初始化的實(shí)例以及類變量(static)會(huì)自動(dòng)初始化為相應(yīng)的默認(rèn)值。

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

我們通過下面的例子來驗(yàn)證上表中的默認(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)鍵字實(shí)例化對(duì)象之后:

final InitializationWithDefaults initializationWithDefaults = new InitializationWithDefaults(),
可從控制臺(tái)中看到輸出結(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)的垃圾回收機(jī)制。簡單來講,當(dāng)有新對(duì)象創(chuàng)建時(shí),會(huì)自動(dòng)為其分配內(nèi)在;然后當(dāng)對(duì)象不再被引用后,他們會(huì)被自動(dòng)銷毀,相應(yīng)的內(nèi)存也會(huì)被回收。

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

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

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

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

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

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

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

與初始化代碼塊類似,可以在類中定義多個(gè)靜態(tài)初始化塊,它們?cè)陬愔械奈恢脹Q定在初始化時(shí)執(zhí)行的順序。示例如下;

package com.javacodegeeks.advanced.construction;

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

  static {
    // static initialization code here
  }
}

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

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

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

4.1 單例模式

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

上面的代碼至少有一個(gè)問題:在多線程并發(fā)場(chǎng)景中可能會(huì)創(chuàng)建出多個(gè)對(duì)象。一種合理的實(shí)現(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;
  }
}

如果你不想浪費(fèi)寶貴的資源,希望單例對(duì)象只在真正需要的時(shí)候才被創(chuàng)建,那么就要使用顯式的同步方式,不可這種方法可能會(huì)降低多線程環(huán)境下的并發(fā)性(更多關(guān)于Java并發(fā)的細(xì)節(jié)將會(huì)在Java進(jìn)階9-并發(fā)最佳實(shí)踐中詳細(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)在,在很多場(chǎng)景下單例模式不再被認(rèn)為是一種好的選擇,因?yàn)樗麄儠?huì)使代碼不易于測(cè)試。另外依賴注入模式的產(chǎn)生也使單例模式變得不再必要。

4.2 工具類/輔助類

工具類/輔助類模式在Java開發(fā)者當(dāng)中相當(dāng)流行。它的核心理念就是使用不可實(shí)例化的類(通過聲明private構(gòu)造方法)、可選的final(更多關(guān)于聲明final類的細(xì)節(jié)將會(huì)在Java進(jìn)階3-類和接口的設(shè)計(jì)中詳細(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)驗(yàn)豐富的開發(fā)者認(rèn)為這種模式會(huì)讓工具類成為各種不相關(guān)方法的容器。因?yàn)橛行┓椒]有合適的放置位置卻需要被其他類使用,就會(huì)被誤放入工具類中。在大多數(shù)場(chǎng)景中也應(yīng)該避免這種設(shè)計(jì):總會(huì)有更好的功能復(fù)用的方式,保持代碼清晰簡潔。

4.3 工廠模式

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

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)常爭議的一點(diǎn)是難以給newBook工廠方法賦予更豐富的場(chǎng)景。另外一種實(shí)現(xiàn)工廠模式的方法是采用接口或抽象類(抽象工廠)。如下,我們定義一個(gè)工廠接口:

public interface BookFactory {
  Book newBook();
}

根據(jù)圖片館的不同,我們可以有多種不同的newBook實(shí)現(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的不同實(shí)現(xiàn)屏蔽掉了具體Book的不同,卻提供了通用的newBook的方法。

4.4 依賴注入

依賴注入(也稱為控制反轉(zhuǎn))被類設(shè)計(jì)者認(rèn)為是一種良好的設(shè)計(jì)實(shí)踐:如果一些類實(shí)例依賴其他類的實(shí)例,那些被依賴的實(shí)例應(yīng)該通過構(gòu)造方法(或者setter方法、策略等方式)提供(注入),而不應(yīng)該是由實(shí)例自己去創(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類需要一個(gè)DateFormat類的實(shí)例并通過在實(shí)例化對(duì)象時(shí)通過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 );
  }
}

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評(píng)論