Java入門(一)——類、抽象類和接口

Java是一門面向對象語言,能夠看出「對象」在Java有着舉足輕重的位置。那麼,「對象」從何而來呢?那必須是丈母孃造出來的,下面咱們就先來講說這個丈母孃——類。html

Java類

  • 對象: 對象具備狀態和行爲。 例如:一隻狗的狀態有:顏色,名稱,品種,它的行爲有:搖尾巴,吠叫,吃東西。 對象是類的實例
  • 類: 類是一個模板,它描述一類具備相同狀態和行爲的對象。好比人類,都具備思考這個行爲,而植物沒有。

類能夠當作是建立Java對象的模板,下面簡單定義一個類:java

public class People{
  String name;  // 成員變量
  int age;
  String weight;
  static final double weeks = 9.5;  // 類變量
  void eat(){
  }
 
  void sleep(){
  }
 
  void play(){
  }
  
  Public People {
    // 這是一個構造方法
    int count = 0; // 局部變量
  }
}

一個類能夠包含如下類型變量:編程

  • 局部變量: 在方法、構造方法或者語句塊中定義的變量被稱爲局部變量。變量聲明和初始化都是在方法中,方法結束後,變量就會自動銷燬
  • 成員變量:成員變量定義在類中,方法體以外的變量。 這種變量在建立對象的時候實例化。成員變量能夠被類中方法、構造方法和特定類的語句塊訪問
  • 類變量:類變量也聲明在類中,方法體以外,但必須聲明爲static類型
  • 類方法:概念同上面的類變量

構造方法

每一個類都有構造方法。若是沒有顯示地爲類定義構造方法,Java編譯器將會爲該類提供一個默認構造方法。yii

在建立一個對象的時候,至少要調用一個構造方法。構造方法的名稱必須與類同名,一個類能夠有多個構造方法函數

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

實例化對象

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

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

下面是一個建立對象的例子:.net

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

編譯並運行上面的程序,會打印出下面的結果:設計

小狗的名字是:tommy

下面的例子展現如何訪問實例變量和調用成員方法:指針

public class Puppy{
   int puppyAge;
   public Puppy(String name){
      // 這個構造器僅有一個參數:name
      System.out.println("小狗的名字是 : " + name ); 
   }
 
   public void setAge( int age ){
       puppyAge = age;  // 當形參`age`也是puppyAge時,須要用this:this.puppyAge = puppyAge
   }
 
   public int getAge( ){
       System.out.println("小狗的年齡爲 : " + puppyAge ); 
       return puppyAge;
   }
 
   public static void main(String[] args){
      /* 建立對象 */
      Puppy myPuppy = new Puppy( "tommy" );
      /* 經過方法來設定age */
      myPuppy.setAge( 2 );
      /* 調用另外一個方法獲取age */
      myPuppy.getAge( );
      /*你也能夠像下面這樣訪問成員變量 */
      System.out.println("變量值 : " + myPuppy.puppyAge ); 
   }
}

編譯並運行上面的程序,產生以下的結果:code

小狗的名字是 : tommy
小狗的年齡爲 : 2
變量值 : 2

Java繼承

Java的繼承是一種機制,表示爲一個對象獲取父對象的全部屬性和行爲

繼承是類與類之間的關係,是一個很簡單很直觀的概念,與現實世界中的繼承(例如兒子繼承父親財產)相似。

Java中的繼承,能夠建立基於現有類構建新的類。 當你從現有類繼承時,就能夠重複使用父類的方法和字段,也能夠在繼承的新類中添加新的方法和字段。

爲何在Java中使用繼承

對於方法覆蓋(所以能夠實現運行時的多態性),提升代碼可重用性。在Java中,子類可繼承父類中的方法,而不須要從新編寫相同的方法。但有時子類並不想原封不動地繼承父類的方法,而是想做必定的修改,這就須要採用方法的重寫(覆蓋)。

Java類繼承的語法示例:

class Super {
}
 
class Sub extends Super {
}

extends關鍵字表示從現有類派生建立的新類。extends的含義是增長功能。在Java的術語中,被繼承的類稱爲父類或超類,新類稱爲子類。

Java繼承示例

java繼承

如上圖所示,Programmer是子類,Employee是超類。 兩個類之間的關係是Programmer IS-A Employee. 它表示 Programmer 是一種 Employee 的類型。

參考下面示例代碼實現:

class Employee {
    float salary = 40000;
}

class Programmer extends Employee {
    int bonus = 10000;

    public static void main(String args[]) {
        Programmer p = new Programmer();
        System.out.println("Programmer salary is:" + p.salary);
        System.out.println("Bonus of Programmer is:" + p.bonus);
    }
}

執行上面代碼獲得如下結果:

Programmer salary is:40000.0 
Bonus of programmer is:10000

在上面的例子中,Programmer對象能夠訪問自身類以及Employee類的字段,即提升了代碼可重用性。

默認的: 不使用任何修飾符聲明的屬性和方法,對同一個包內的類是可見的。接口裏的變量都隱式聲明爲public static final,而接口裏的方法默認狀況下訪問權限爲public

Java繼承類型

在類的基礎上,在Java中能夠有三種類型的繼承:單一,多級和分層繼承。在Java的編程中,僅能經過接口支持多繼承和混合繼承。

java繼承類型

注意:Java中的類不支持多繼承

當一個類擴展多個類,即被稱爲多繼承。例如:

多重繼承

問題:爲何在Java中不支持多繼承?

爲了下降複雜性並簡化語言,Java中不支持多重繼承。想象一個:ABC是三個類。 C類繼承AB類。 若是AB類有相同的方法,而且從子類對象調用它,AB類的調用方法會有歧義。

由於編譯時錯誤比運行時錯誤好,若是繼承2個類,Java會在編譯時報告錯誤。 因此不管子類中是否有相同的方法,都會有報告編譯時錯誤。

注意:構造方法不能被繼承,掌握這一點很重要。 一個類能獲得構造方法,只有兩個辦法:編寫構造方法,或者根本沒有構造方法,類有一個默認的構造方法。

抽象類

在面向對象的概念中,全部的對象都是經過類來描繪的,可是反過來,並非全部的類都是用來描繪對象的,若是一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類

在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。

因爲抽象類不能實例化對象,因此抽象類必須被繼承,才能被使用。也是由於這個緣由,一般在設計階段決定要不要設計抽象類。

抽象類

在Java中使用abstract關鍵字來定義抽象類。以下示例:

//example of abstract class that have method body  
abstract class Bike {
    Bike() {
        System.out.println("bike is created");
    }

    abstract void run();

    void changeGear() {
        System.out.println("gear changed");
    }
}

class Honda extends Bike {
    void run() {
        System.out.println("running safely..");
    }
}

class TestAbstraction2 {
    public static void main(String args[]) {
        Bike obj = new Honda();
        obj.run();
        obj.changeGear();
    }
}

注意到該Bike類沒有什麼不一樣,儘管該類是抽象類,可是它仍然有成員變量,抽象方法,方法體,構造函數甚至main()方法。

執行上面的代碼:

bike is created
running safely..
gear changed

抽象方法

若是你想設計這樣一個類,該類包含一個特別的成員方法,該方法的具體實現由它的子類肯定,那麼你能夠在父類中聲明該方法爲抽象方法。

Abstract 關鍵字一樣能夠用來聲明抽象方法,抽象方法只包含一個方法名,而沒有方法體

抽象方法沒有實現,方法名後面直接跟一個分號,而不是花括號。

public abstract class Employee
{
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();
   
   //其他代碼
}

聲明抽象方法會形成如下兩個結果:

  • 若是一個類包含抽象方法,那麼該類必須是抽象類
  • 任何子類必須重寫父類的抽象方法,或者聲明自身爲抽象類

繼承抽象方法的子類必須重寫該方法。不然,該子類也必須聲明爲抽象類。最終,必須有子類實現該抽象方法,不然,從最初的父類到最終的子類都不能用來實例化對象。

若是Salary類繼承了Employee類,那麼它必須實現computePay()方法:

/* 文件名 : Salary.java */
public class Salary extends Employee
{
   private double salary; // Annual salary
  
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
 
   //其他代碼
}

注意: 抽象類中不能有抽象構造方法或抽象靜態方法

參考:Java抽象類

抽象類和類的區別

抽象類除了不能實例化對象以外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類同樣。

  • 抽象類不能被實例化,若是被實例化,就會報錯,編譯沒法經過。只有抽象類的非抽象子類能夠被實例化

  • 普通類和抽象類均可以被繼承,可是抽象類被繼承後子類必須重寫繼承的方法,除非自類也是抽象類

  • 抽象類中不必定含有抽象方法,可是有抽象方法的類一定時抽象類

  • 抽象類中的抽象方法只是聲明,不包含方法體,即不能給出方法的具體實現

  • 構造方法、類方法(用static修飾的方法)不能聲明爲抽象方法

總之一句話,抽象類只是一種比較特殊的普通類。我以爲這篇文章解釋的不錯,大概意思就是:抽象類嚴格規定了幾個你必須作的事情,好比:不能實例化、子類必須實現父類,除非子類也是抽象類。你不這樣作就會出錯,這種嚴謹的作法比人爲規定的更加有效。

接口

定義:接口在Java中是一個抽象類型,是抽象方法的集合。一個類經過繼承接口的方式,從而繼承接口的抽象方法。

接口一般以interface來聲明,能夠看作是一種特殊的抽象類。一個類經過繼承接口的方式,從而來繼承接口的抽象方法。

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

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

接口的聲明

接口的聲明語法格式以下:

public interface 接口名稱 [extends 其餘的接口名] {
        // 聲明變量
        // 抽象方法
}

接口有如下幾個特徵:

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

注:JDK 1.8 之後,接口裏能夠有靜態方法和方法體

接口的實現

當類實現接口的時候,類要實現接口中的全部的方法。不然,類必須聲明爲抽象類

類使用implements關鍵字實現接口。在類聲明中,Implements關鍵字放在class聲明後面。

實現一個接口的語法,可使用這個公式:

...implements 接口名稱[, 其餘接口名稱, 其餘接口名稱..., ...] ...

下面是一個Java的接口示例:

interface printable {
    void print();
}

class A6 implements printable {
    public void print() {
        System.out.println("Hello, Interface");
    }

    public static void main(String args[]) {
        A6 obj = new A6();
        obj.print();
    }
}

執行上面的代碼,結果以下:

Hello,Interface

接口與類的類似點

  • 一個接口能夠有不少方法
  • 接口文件保存在.java結尾的文件中,文件名使用接口名
  • 接口的字節碼文件保存在.class結尾的文件中
  • 接口相應的字節碼文件必須在與包名稱相匹配的目錄結構中

接口與類的區別

  • 接口不能用於實例化對象
  • 接口沒有構造方法
  • 接口中全部方法必須爲抽象方法
  • 接口不能包含成員變量,除了staticfinal變量
  • 接口不是被類繼承了,而是要被類實現
  • 接口支持多繼承

接口和抽象類的區別

  • 抽象類中的方法能夠不是抽象方法,但接口中的方法必須都是抽象方法
  • 抽象類中的非抽象方法能夠有方法體,就是實現方法的具體功能,避免在子類中重複實現這些方法。但接口中的方法不行(JDK 1.8之後能夠有方法體,做爲默認實現)
  • 抽象類中的成員變量能夠是各類類型的,而接口中的成員變量只能是public static final類型的
  • 抽象類能夠有具體的方法和屬性, 接口只能有抽象方法和不可變常量(final)
  • 一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口
  • 抽象類裏面的抽象方法必須所有被子類實現,若是子類不實現,那麼子類必須也是抽象類。接口裏面的方法也必須所有被子類實現,若是子類不能實現,那麼子類必須是抽象類
  • 抽象類主要用來抽象類別,接口主要用來抽象方法功能。當你關注事物的本質的時候,請用抽象類;當你關注一種操做的時候,用接口
  • 抽離類能夠繼承接口,接口不能繼承抽象類(有待考究)

參考:

抽象類和接口的區別

接口和抽象類有什麼區別?

相關文章
相關標籤/搜索