Java 對象和類

Java 對象和類

類(class)是構造對象的模板或藍圖。前端

對象

對象表示一個能夠明確標識的實體。每一個對象都有本身獨特的標識、狀態和行爲。
對象的狀態(特徵或屬性,即實例變量),由該對象的數據域來表示。
對象的行爲(對象執行的動做,即功能),由方法來定義。java

構造方法

每一個類都有構造方法。若是沒有顯式地爲類定義構造方法,Java編譯器將會爲該類提供一個默認構造方法。
在建立一個對象的時候,至少要調用一個構造方法。構造方法的名稱必須與類同名,一個類能夠有多個構造方法。
下面是一個構造方法示例:編程

public class Puppy{ 

    public Puppy(){ } 

    public Puppy(String name){ // 這個構造器僅有一個參數:name 
    } 
}

建立對象

對象是根據類建立的。在Java中,使用關鍵字new來建立一個新的對象。建立對象須要如下三步:安全

  • 聲明:聲明一個對象,包括對象名稱和對象類型。
  • 實例化:使用關鍵字new來建立一個對象。
  • 初始化:使用new建立對象時,會調用構造方法初始化對象。

下面是一個建立對象的例子:編程語言

public class Puppy{ 
    public Puppy(String name){ //這個構造器僅有一個參name     
        System.out.println("小狗的名字是 : " + name );
    } 
    public static void main(String[] args){ // 下面的語句將建立一個Puppy對象 

        Puppy myPuppy = new Puppy( "tommy" ); 
    } 
}

訪問實例變量和方法

經過已建立的對象來訪問成員變量和成員方法,以下所示:ide

/* 實例化對象 */ 

Object referenceVariable = new Constructor(); 

/* 訪問類中的變量 */ 

referenceVariable.variableName; 

/* 訪問類中的方法 */ 

referenceVariable.methodName();

Java 修飾符

Java語言提供了不少修飾符,主要分爲如下兩類:函數

  • 訪問修飾符
  • 非訪問修飾符

修飾符用來定義類、方法或者變量,一般放在語句的最前端。線程

訪問控制修飾符

Java中,可使用訪問控制符來保護對類、變量、方法和構造方法的訪問。Java 支持 4 種不一樣的訪問權限。設計

  • default (即缺省,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用對象:類、接口、變量、方法。
  • private : 在同一類內可見。使用對象:變量、方法。 注意:不能修飾類(外部類)
  • public : 對全部類可見。使用對象:類、接口、變量、方法
  • protected : 對同一包內的類和全部子類可見。使用對象:變量、方法。注意:不能修飾類(外部類)。

咱們能夠經過如下表來講明訪問權限:指針

修飾符 當前類 同一包內 子孫類(同一包) 子孫類(不一樣包) 其餘包
public Y Y Y Y Y
protected Y Y Y Y/N N
default Y Y Y N N
private Y N N N N

非訪問修飾符

爲了實現一些其餘的功能,Java 也提供了許多非訪問修飾符。

  • static 修飾符,用來修飾類方法和類變量。
  • final 修飾符,用來修飾類、方法和變量,final 修飾的類不可以被繼承,修飾的方法不能被繼承類從新定義,修飾的變量爲常量,是不可修改的。
  • abstract 修飾符,用來建立抽象類和抽象方法。
  • synchronized 和 volatile 修飾符,主要用於線程的編程。

    static 修飾符

    靜態變量:
    static 關鍵字用來聲明獨立於對象的靜態變量,不管一個類實例化多少對象,它的靜態變量只有一份拷貝。 靜態變量也被稱爲類變量。局部變量不能被聲明爲 static 變量。

靜態方法:
static 關鍵字用來聲明獨立於對象的靜態方法。靜態方法不能使用類的非靜態變量。靜態方法從參數列表獲得數據,而後計算這些數據。
對類變量和方法的訪問能夠直接使用 classname.variablename 和 classname.methodname 的方式訪問。

final 修飾符

final 變量:
final 表示"最後的、最終的"含義,變量一旦賦值後,不能被從新賦值。被 final 修飾的實例變量必須顯式指定初始值。
final 修飾符一般和 static 修飾符一塊兒使用來建立類常量。

final 方法
類中的 final 方法能夠被子類繼承,可是不能被子類修改。
聲明 final 方法的主要目的是防止該方法的內容被修改。

final 類
final 類不能被繼承,沒有類可以繼承 final 類的任何特性。

Java 面向對象編程三大特性: 封裝 繼承 多態

Java 封裝

在面向對象程式設計方法中,封裝(英語:Encapsulation)是指一種將抽象性函式接口的實現細節部份包裝、隱藏起來的方法。

封裝能夠被認爲是一個保護屏障,防止該類的代碼和數據被外部類定義的代碼隨機訪問。

要訪問該類的代碼和數據,必須經過嚴格的接口控制。

封裝最主要的功能在於咱們能修改本身的實現代碼,而不用修改那些調用咱們代碼的程序片斷。

適當的封裝可讓程式碼更容易理解與維護,也增強了程式碼的安全性。
封裝的優勢

  1. 良好的封裝可以減小耦合。
  2. 類內部的結構能夠自由修改。
  3. 能夠對成員變量進行更精確的控制。
  4. 隱藏信息,實現細節。

Java 繼承

繼承的概念

繼承是java面向對象編程技術的一塊基石,由於它容許建立分等級層次的類。

繼承就是子類繼承父類的特徵和行爲,使得子類對象(實例)具備父類的實例域和方法,或子類從父類繼承方法,使得子類具備父類相同的行爲。

Java 多態

多態是同一個行爲具備多個不一樣表現形式或形態的能力。

多態就是同一個接口,使用不一樣的實例而執行不一樣操做
多態性是對象多種表現形式的體現。

多態存在的三個必要條件

  • 繼承
  • 重寫
  • 父類引用指向子類對象

多態的實現方式
方式一:重寫:Java 重寫(Override)與重載(Overload)。

方式二:接口

方式三:抽象類和抽象方法

  • 重載: 發生在同一個類中,方法名必須相同,參數類型不一樣、個數不一樣、順序不一樣,方法返回值和訪問修飾符能夠不一樣,發生在編譯時。

  • 重寫: 發生在父子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;若是父類方法訪問修飾符爲 private 則子類就不能重寫該方法。

重寫與重載之間的區別

區別點 重載方法 重寫方法
參數列表 必須修改 必定不能修改
返回類型 能夠修改 必定不能修改
異常 能夠修改 能夠減小或刪除,必定不能拋出新的或者更廣的異常
訪問 能夠修改 必定不能作更嚴格的限制(能夠下降限制)

接口和抽象類的區別

  1. 接口的方法默認是 public,全部方法在接口中不能有實現(Java 8 開始接口方法能夠有默認實現),而抽象類能夠有非抽象的方法。
  2. 接口中除了static、final變量,不能有其餘變量,而抽象類中則不必定。
  3. 一個類能夠實現多個接口,但只能實現一個抽象類。接口本身自己能夠經過extends關鍵字擴展多個接口。
  4. 接口方法默認修飾符是public,抽象方法能夠有public、protected和default這些修飾符(抽象方法就是爲了被重寫因此不能使用private關鍵字修飾!)。
  5. 從設計層面來講,抽象是對類的抽象,是一種模板設計,而接口是對行爲的抽象,是一種行爲的規範。

== 與 equals(重要)

== : 它的做用是判斷兩個對象的地址是否是相等。即,判斷兩個對象是否是同一個對象(基本數據類型==比較的是值,引用數據類型==比較的是內存地址)。

equals() : 它的做用也是判斷兩個對象是否相等。但它通常有兩種使用狀況:

  • 狀況1:類沒有覆蓋 equals() 方法。則經過 equals() 比較該類的兩個對象時,等價於經過「==」比較這兩個對象。
  • 狀況2:類覆蓋了 equals() 方法。通常,咱們都覆蓋 equals() 方法來比較兩個對象的內容是否相等;若它們的內容相等,則返回 true (即,認爲這兩個對象相等)。

舉個例子:

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a 爲一個引用
        String b = new String("ab"); // b爲另外一個引用,對象的內容同樣
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 從常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一對象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

說明:

  • String 中的 equals 方法是被重寫過的,由於 object 的 equals 方法是比較的對象的內存地址,而 String 的 equals 方法比較的是對象的值。
  • 當建立 String 類型的對象時,虛擬機會在常量池中查找有沒有已經存在的值和要建立的值相同的對象,若是有就把它賦給當前引用。若是沒有就在常量池中從新建立一個 String 對象。

hashCode 與 equals (重要)

hashCode()介紹

hashCode() 的做用是獲取哈希碼,也稱爲散列碼;它其實是返回一個int整數。這個哈希碼的做用是肯定該對象在哈希表中的索引位置。

hashCode() 定義在JDK的Object.java中,這就意味着Java中的任何類都包含有hashCode() 函數。

散列表存儲的是鍵值對(key-value),它的特色是:能根據「鍵」快速的檢索出對應的「值」。這其中就利用到了散列碼!(能夠快速找到所須要的對象)

爲何要有 hashCode

咱們先以「HashSet 如何檢查重複」爲例子來講明爲何要有 hashCode: 當你把對象加入 HashSet 時,HashSet 會先計算對象的 hashcode 值來判斷對象加入的位置,同時也會與其餘已經加入的對象的 hashcode 值做比較,若是沒有相符的hashcode,HashSet會假設對象沒有重複出現。可是若是發現有相同 hashcode 值的對象,這時會調用 equals()方法來檢查 hashcode 相等的對象是否真的相同。若是二者相同,HashSet 就不會讓其加入操做成功。若是不一樣的話,就會從新散列到其餘位置。(摘自《Head first java》第二版)。這樣咱們就大大減小了 equals 的次數,相應就大大提升了執行速度。

經過咱們能夠看出:hashCode() 的做用就是獲取哈希碼,也稱爲散列碼;它其實是返回一個int整數。這個哈希碼的做用是肯定該對象在哈希表中的索引位置。hashCode() 在散列表中才有用,在其它狀況下沒用。在散列表中hashCode() 的做用是獲取對象的散列碼,進而肯定該對象在散列表中的位置。

hashCode()與equals()的相關規定

  1. 若是兩個對象相等,則hashcode必定也是相同的
  2. 兩個對象相等,對兩個對象分別調用equals方法都返回true
  3. 兩個對象有相同的hashcode值,它們也不必定是相等的
  4. 所以,equals 方法被覆蓋過,則 hashCode 方法也必須被覆蓋
  5. hashCode() 的默認行爲是對堆上的對象產生獨特值。若是沒有重寫 hashCode(),則該 class 的兩個對象不管如何都不會相等(即便這兩個對象指向相同的數據)

Java 接口

接口(英文:Interface),在JAVA編程語言中是一個抽象類型,是抽象方法的集合,接口一般以interface來聲明。一個類經過繼承接口的方式,從而來繼承接口的抽象方法。

接口並非類,編寫接口的方式和類很類似,可是它們屬於不一樣的概念。類描述對象的屬性和方法。接口則包含類要實現的方法。

除非實現接口的類是抽象類,不然該類要定義接口中的全部方法。

接口沒法被實例化,可是能夠被實現。一個實現接口的類,必須實現接口內所描述的全部方法,不然就必須聲明爲抽象類。另外,在 Java 中,接口類型可用來聲明一個變量,他們能夠成爲一個空指針,或是被綁定在一個以此接口實現的對象。

接口特性

  • 接口中每個方法也是隱式抽象的,接口中的方法會被隱式的指定爲 public abstract(只能是 public abstract,其餘修飾符都會報錯)。
  • 接口中能夠含有變量,可是接口中的變量會被隱式的指定爲 public static final 變量(而且只能是 public,用 private 修飾會報編譯錯誤)。
  • 接口中的方法是不能在接口中實現的,只能由實現接口的類來實現接口中的方法。

抽象類和接口的區別

  1. 抽象類中的方法能夠有方法體,就是能實現方法的具體功能,可是接口中的方法不行。
  2. 抽象類中的成員變量能夠是各類類型的,而接口中的成員變量只能是 public static final 類型的。
  3. 接口中不能含有靜態代碼塊以及靜態方法(用 static 修飾的方法),而抽象類是能夠有靜態代碼塊和靜態方法。
  4. 一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。

反射定義

JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。

用途:

在平常的第三方應用開發過程當中,常常會遇到某個類的某個成員變量、方法或是屬性是私有的或是隻對系統應用開放,這時候就能夠利用Java的反射機制經過反射來獲取所需的私有成員或是方法。固然,也不是全部的都適合反射,以前就遇到一個案例,經過反射獲得的結果與預期不符。閱讀源碼發現,通過層層調用後在最終返回結果的地方對應用的權限進行了校驗,對於沒有權限的應用返回值是沒有意義的缺省值,不然返回實際值起到保護用戶的隱私目的。

反射機制的相關類

與Java反射相關的類以下:

類名 用途
Class類 表明類的實體,在運行的Java應用程序中表示類和接口
Field類 表明類的成員變量(成員變量也稱爲類的屬性)
Method類 表明類的方法
Constructor類 表明類的構造方法
相關文章
相關標籤/搜索