在面向對象的思想中,一切事物均可以認爲是對象——萬物皆對象,把對象定義成包含狀態和行爲的一個實體,存在於現實世界中而且能夠與其餘實體區分開來的。對象具備狀態和行爲;好比:想一想你心儀的小姐姐,能夠把這個小姐姐看做是一個對象,那麼該對象有兩方面的定義:狀態和行爲;狀態,如身高,年齡,三圍,頭髮(長髮或者短髮)等;行爲,如調戲你、跳舞,玩手機等。java
經過多個相同類型的對象的狀態和行爲分析,能夠把對象抽象成類(class);咱們把具備相同特性(狀態)和行爲(功能)的對象的抽象定義類,對象的抽象是類,類實例化後即是對象,類的實例是對象,類其實就是對象的數據類型,但其和基本數據類型的差別在於類是程序員爲了解決某些問題而自定義的,基本數據類型是計算機中的數據存儲單元。程序員
在Java中,對象的狀態,用成員變量來描述;對象的行爲,用方法來描述;故Java中類能夠這樣定義,語法以下:設計模式
類定義示例代碼:數組
定義Java 類時有一些必要的規範須要遵照:jvm
先考慮下面的代碼:函數
上述示例代碼運行結果爲:工具
爲何會出現這樣的結果呢?都是一樣的值,爲何會有不一樣的比較結果?那是由於==和!=這兩個比較運算符在比較基本數據類型和對象對象類型時是由區別的:性能
那麼哪些數據類型時基本數據類型,哪些是引用數據類型呢?spa
因此,若是要對對象的值作比較,就必需要是用對象的equals()方法了;這裏須要注意,equals()方法並不適用於基本數據類型,對於基本數據類型的變量來講,使用== 和 !=足夠了。下面用一個例子來實踐,代碼以下:操作系統
上述案例輸出結果爲:
由此可看出,使用對象的equals()方法是能正確比較對象的值的,由於Integer已經自定義了equals方法了,下面是源碼:
不難發現,Integer的equals()方法的底層是使用基本數據類型的值作==比較的。若是是咱們自定義的類,並且沒有從新定義equals()方法呢,結果又會是怎樣的,一塊兒來看看:
輸出結果爲:false。
由於在Java中,有一個全部引用類型都直接或者間接繼承的父類,Object;所以,也能夠說在java中,全部類都是Object的子類,那麼,若是咱們沒從新實現equals()方法,會默認調用Object的equals()方法,Object的equals()方法比較的是對象的引用,因此結果輸出爲false。
因此想要使用自定義對象的equals方法比較對象的值,那麼就必須從新實現equals方法。
默認狀況下,Java對象打印的效果是:類的名稱@十六進制的hashCode,好比:
輸出爲:com.strlite.admin.demo.Value@79b4d0f,com.strlite.admin.demo.Value是類的名稱,79b4d0f是一個十六進制的數,是對象在堆中的內存地址。
重寫toString() 方法
能夠經過重寫toString() 方法來改變對象的打印效果:
輸出爲:
對象的開始:每次使用new關鍵字建立對象,就會在內存中開闢新的空間存儲對象信息,此時對象開始存在。
對象的結束:當堆中的對象,沒有被任何變量所引用,此時該對象就成了垃圾,等待垃圾回收器(GC)來回收;當對象被回收後,對象被銷燬,對象佔用的內存空間被釋放,對象的生命週期結束。
對象建立以後沒有將其賦給某一個變量。匿名對象只是在堆中開闢一塊新的內存空間,可是沒有把該空間地址賦給任何變量。由於沒有變量引用指向,因此匿名對象僅僅只能使用一次,通常會把匿名對象做爲方法的參數傳遞。
在建立對象時使用的特殊方法,出現new 關鍵字以後的方法,稱之爲構造方法、構造器、構造函數(Constructor)。
構造器的做用:
構造器的特色:
若是類中沒有構造器,編譯器會自動建立一個默認的無參構造器。
咱們將上述代碼通過編譯,獲得字節碼文件,再將字節碼文件反編譯,反編譯的結果以下:
經過反編譯後的結果,不難發現,即使咱們沒有建立構造器,編譯器也會爲咱們建立一個默認的,編譯器建立的默認構造器有如下的特色:
若是類中沒有構造器,編譯器會自動建立一個默認的無參構造器。可是,若是咱們顯式地定義了一個構造器,則編譯器再也不建立默認構造器。案例以下所示:
經過上述對比,不難發現,當類中存在一個構造器時,編譯器便不會建立默認的構造器,而是使用咱們定義的構造器,由此可得出:在一個類中,至少存在一個構造器。
假如每一個人都有name和age兩個狀態,可是不一樣人的name和age是不同的;也就說name和age是屬於對象的。可是在生活中有些東西並非單單屬於某一個對象的,而是屬於整個類的,好比:每一個人都會老去、都會死。
因此,狀態和行爲的所屬也應該有對象和類之分。 有的狀態和行爲應該屬於對象,不一樣的對象,狀態和行爲能夠不同;而有的狀態和行爲應該屬於類,不屬於對象。爲了區別與對象的狀態和行爲,引入static修飾符來修飾類的狀態和行爲。
static修飾符表示靜態的,可修飾字段、方法、內部類,其修飾的成員屬於類,static修飾的資源屬於類級別,區別於對象級別。static的真正做用是用來區別字段、方法、內部類、初始化代碼塊是屬於對象仍是屬於類自己。
static修飾符的特色:
下面咱們經過一個案例來實踐static關鍵字的使用:
static修改的變量稱爲常量,會長時間存在於JVM內存中,因此JVM也會爲它分配必定的存儲空間,如下即是static常量在jvm 中的內存模型:
JVM會將靜態變量存儲在方法區中,以便於及時調用;並保證其可以長時間存儲於JVM中。
類中的成員:字段,方法,內部類。
通常狀況下,類成員只能訪問類成員,實例成員只能訪問實例成員;但深究發現,對象其實能夠訪問類成員,可是底層依然使用類名訪問的。
在static方法中,只能調用static成員;非static方法,能夠訪問靜態成員,也能夠訪問實例成員;
那何時定義成static的字段和方法:
若是不使用static修飾,則這些方法屬於該類的對象,咱們得先建立對象才能調用方法,在開發中工具對象只須要一份便可,可能建立N個對象,此時能夠考慮使用單例設計模式。
好處:對對象的共享數據進行單獨空間的存儲,節省空間,沒有必要每個對象中都存儲一份,能夠直接被類名調用。
弊端:生命週期過長。
局部變量定義後,必須顯式初始化後才能使用,由於JVM不會爲局部變量執行初始化操做。這就意味着,定義局部變量後,JVM並未爲這個變量分配內存空間。直到程序爲這個變量賦值時,系統纔會爲局部變量分配內存,並將初始值保存到該內存中。
局部變量不屬於任何類或實例,所以它是保存在其所在方法的棧幀內存中。
棧幀內存中的變量隨方法或代碼塊的運行結束而銷燬,無須JVM回收。
完結。老夫雖不正經,但老夫一身的才華