深入Java類、對象 與 Static
深入Java類、對象與Static
今日閑來無事,室外都快成烤箱了。。。So,沒事做就仔細研究了一下Java的類、對象和Static的關系。剛開始學習Java的時候,對著Core Java看,看了好久也沒明白什么是類,什么是對象,還有這個頭疼的Static。隨著工作了一段時間,類和對象這些概念有了一些理解,但一直沒有仔細深入的分析。期間也在網上、各大論壇求解過像Static做用什么的,但一直不得要旨。今天就來仔細總結一下。隨著發掘的深入,我發現Java的類、對象和Static這三個概念是密切相關的,他們不能分開。
在面向對象中,有兩個重要概念:類和對象。對象也被稱作“實例(instance)”那么究竟什么是類?類是某一批對象的抽象。對象是一個具體存在的實體。我這么說,你看懂了嗎?我覺得可能大部分人還是看不懂,因為這個定義太特么抽象了。你是不是再說:“U TM Say What 呢?” Well~ Keep Easy~ 一會兒我用“人”類來給你做個解釋。
重定義你的觀念 -> 接口:在Java和C#中,接口這個概念可不是你想的那么簡單。在很多書和論壇中大家對接口的一般定義為:比抽象類更加徹底的抽象類-interface。接口里不能包含普通方法,只能是抽象方法云云。但是這里我要告訴你的是:接口,他代表了一個類型!就是說:你這個類,只要實現了我的接口,你便擁有了我的類型特征。Java中提倡單一繼承,多重實現。你可以implements多個接口,也就是說你定義的類將擁有多重類型特征。比如在代碼程序中我們定義了一個接口:Person,他的實現類是YellowPerson。你在編程的時候可能會用到類型匹配的邏輯,比如:如果你的類是Person類,那么執行代碼邏輯。YellowPerson yp = new YellowPerson(); if(yp.IsPartTypeOf (Person)) ……當然這里的IsPartTypeOf方法是你要自己寫的。接口作為順帶介紹,與本文關聯并不大。你要知道他還有類型的意義就夠了。下面用代碼說明類、對象和Static。
public interface Person
{
void say();
void head();
void body();
void armsAndlegs();//四肢
public static final int eyes =2;
public static final int mouth = 1;
}
public class YellowPerson implements Person
{
private static int ears = 2;
private static int nose = 1;
private String sex ;
private String skin ;
public void head()
{
System.out.println("我繼承了人類,我有:" + this.eyes
+ "個 眼睛和 :" + this.mouth + " 張嘴");
}
public void body()
{
System.out.println("我還有:
" + ears + "個 耳朵;: " +
nose + " 個鼻子");
}
public void armsAndlegs()
{
String a = getSex();
String b = getSkin();
System.out.println("人的性別和膚色是不固定的,我是 " + a +
b+ "皮膚");
}
public void say()
{
this.head();
this.body();
}
//########################################
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getSkin() {
return skin;
}
public void setSkin(String skin) {
this.skin = skin;
}
}
public class Test
{
public static void main(String[] args)
{
YellowPerson yp = new YellowPerson();
yp.say();
yp.setSex("男人");
yp.setSkin("黃色");
yp.armsAndlegs();
System.out.println("眼睛數量:"+yp.eyes);
}
}
打印結果:
我繼承了人類,我有:2個 眼睛和 :1 張嘴
我還有: 2個 耳朵;: 1 個鼻子
人的性別和膚色是不固定的,我是 男人黃色皮膚
眼睛數量:2
靜態變量代表是這個類的固有屬性。比如正常人肯定有2個眼睛、一張嘴、2個耳朵,一個鼻子等等。但是這個人的名字、性別、膚色、身高、體重都是不確定的,所以這些不是靜態屬性。我們在Test.java中調用YellowPerson的時候產生一個對象:yp。yp對象中就已經包含了所有 “靜態屬性” 值:鼻子、眼睛、嘴等等。你用yp直接可以調用該對象包含的static變量,比如:“眼睛數量:2”。但是非靜態的普通屬性你則需要設定。
也就是說:作為“類”來講,他定義了很多內容,其中有固定的,有的不是固定的,固定的都是static的;“類”更像是一個模板,而對象則是從這個模板中復制出來的東西。凡是模板都有固定的東西,比如做月餅的模子,他有固定的花紋,但月餅餡不同;“人”這個模板則固定有頭、身體、四肢、五官、器官等等static屬性,而姓名、性別、身高等等每個人不同,則是普通屬性。從這個角度講:我們日常說的人其實都是“人”這個類的實例(對象),而不是人類。就是說:當你在其他地方調用一個類的時候,他的靜態屬性已隨著對象的初始化復制而出,你直接可以使用,但是普通屬性你需要設定,或者更改。比如上述代碼中的性別和膚色等。注意:靜態屬性也可以不通過去創建對象來調用,直接用類名+屬性或方法就可以,如:YelloPerson.eyes
那么對象如何初始化?
通過構造器,也就是常說的構造函數。每一個類都有一個默認的構造函數。構造函數是用于構造一個類實例的根本途徑,即:對象初始化。(順便提一句方法用于定義類或類實例的行為特征與功能實現。構造函數與方法的區別是沒有修飾詞。) 你要時刻記得:對象即實例。對象的創建和使用如下,很簡單但很容易被忽略:
YellowPerson
yp ; //定義一個YelloPerson類型的變量
yp = new YellowPerson(); //通過new 關鍵字調用YelloPerson類的構造函數,返回一個類實例
//將實例付給yp變量
因為調用的是類的構造函數,所以YelloPerson后面會有括號。new YellowPerson()即為實例(對象)。
總結一句:你不是人這個類我也不是人這個類,所有活著的人都是“人”的實例(對象)。
不得不修改一下,我在寫這篇博客的時候,對類、對象、實例和Static的理解存在不足的地方,現在給予糾正。
首先是對象。在《Think In Java》和《Java核心技術中》給予對象的定義是這樣的:“萬物皆對象。” 這樣放到現實中來講,包括類以及由類產生的實例都屬于對象的范疇。類、對象和類實例之間的關系應該是這樣來描述:【類】是一個被定義的模板(包括各種具體屬性,如字段、方法);【類實例】是從這個模板中復制出的一個對象;而【對象】應該包括【類】和【類實例】。所以說:“對象即實例”,這句話本身存在缺陷,是錯誤的。應該這樣描述更加確切:【new 一個類的構造函數產生的是一個類實例】,如果你硬說產生的是一個對象,這樣也沒錯,只不過這樣顯得空乏,因為對象是一個全集的概念。如下舉例:
yp = new YellowPerson(); //通過new 關鍵字調用YelloPerson類的構造函數,返回一個類實例
在上面這段代碼中【通過new 關鍵字調用YelloPerson類的構造函數,返回一個類實例】這樣描述要比【通過new 關鍵字調用YelloPerson類的構造函數,返回一個“對象”】這個描述更加準確。
其次是“static”。上文中描述【靜態變量代表是這個類的固有屬性】,這也是不確切的,是狹隘的理解,當然就是錯的。舉例如下:定義一個Person類,類中定義一個靜態屬性方法:
public static int nose();
然后分別創建了10個Person類實例,但事實上這10個類實例只有一個nose()方法,并不是每一個類實例都包括了一個自己的nose()方法,即:他們公用一個nose()方法;如果這個比方在現實中發生,那么他們這10個人其實是連體嬰兒,因為他們公用一個鼻子。如果在Person類中nose()方法變成非static,而定義一些這樣的static方法:air()、water()、sunshine() ,那么會顯得更合理一些,也更說的通;因為這些方法是人類共同需要的、無法脫離的。
在從內存中解釋,【static類型屬性和方法】在內存中只有一個地址,不是你有多少個類實例就會有多少個地址,你只是引用了這個地址。如果從這個角度講,那么當你設計一個程序的時候,事實上絕大多數的類是可以不包括【static類型屬性和方法】,而單獨的設計一個類專門去做這件事。這樣在程序的可讀性和可維護性上也會好很多。