1. 程式人生 > >類、物件、介面

類、物件、介面

  • 組成Java程式的基本要素
  • 是一類物件的原型
  • 封裝類一類物件的狀態和方法

欄位和方法

  • 欄位(field)是類的屬性,是用變數來表示的。欄位又稱為域、屬性、成員變數
  • 方法(method)是類的功能和操作,是用函式來表示的

構造方法
  • 構造方法是一種特殊的方法
  • 用來初始化(new)該類的一個新的物件
  • 構造方法和類名同名,而且不寫返回值型別

預設構造方法
  • 一般情況下,類都有一個至多個構造方法
  • 如果沒有定義任何構造方法,系統會自動產生一個構造方法,稱為預設構造方法(default constructor)
  • 預設構造方法不帶引數,並且方法體為空

方法過載(overload)
  • 方法的過載(overloading):多個方法有相同的名字,編譯
    時能識別出來
  • 這些方法的簽名不同(signature),或者是引數個數不同,或者是引數型別不同
  • 通過方法的過載可以實現多型(polymorphism)
  • 過載的作用是允許方法的使用者採用不同的引數來呼叫相同名稱的方法
  • 方法型別簽名包括方法名稱和引數型別兩個部分

class MethodOverloadingTest
    {
    public static void main( String[] argv ){
        Person p1 = new Person("Tom", 20);
        Person p2 = new Person("Marry", 18
); p1.sayHello(); p1.sayHello(p2); } } class Person { String name; int age; Person( String name, int age ){ this.name = name; this.age = age; } void sayHello(){ System.out.println("Hello! My name is " + name ); } void
sayHello( Person another ){ System.out.println("Hello, " + another.name + "! My name is " + name ); } }

this的使用
  • 在方法及構造方法中,使用this來訪問欄位及方法
  • 是用this解決區域性變數與域變數同名的問題,區域性變數(方法中的變數)或引數變數與域名變數同名的問題。

Person( int age, String name )
    {
        this.age = age;
        this.name = name;
    }

    this.age表示域變數,而age表示的是引數變數
  • 在構造方法中,用this呼叫裡一個構造方法,在建構函式中呼叫另一個構造方法,則這條語句必須放在第一句
  class Person {
    String name;
    int age;
    Person( String n, int a ){
        name = n;
        age = a;
    }
    Person( String n ){
        name = n;
        age = 0;
    }
    Person( int age, String name )
    {
        this.age = age;
        this.name = name;
    }
    Person(  ){
        this( 0, "" );
    }
    boolean isOlderThan( int anAge ){
        return this.age > anAge;
    }
    void sayHello(){
        System.out.println("Hello! My name is " + name );
    }
    void sayHello( Person another ){
        System.out.println("Hello," + another.name 
            + "! My name is " + name );
    }
    public static void main(String[] args) 
    {
        Person p = new Person("Li Min", 18);
        Person p2 = new Person("Wang Qiang", 20 );
        p.sayHello();
        p.sayHello(p2);
    }
    }

繼承

  • 繼承是面型物件程式設計中最重要的特徵之一
  • 子類(subclass)父類或超類(superclass)
  • 父類包括所有直接或間接被繼承的類
  • Java支援單繼承:一個類只能有一個直接父類

    繼承的好處

    子類繼承父類的狀態和行為

  • 可以修改父類的狀態或過載父類的行為

  • 可以新增新的狀態和行為
  • 所有的類都是直接或間接繼承java.lang.Objectd得到的

    好處

  • 可以提高程式的抽象程度

  • 實現程式碼重用,提高開發效率和可維護性

    欄位

    • 欄位的繼承:子類可以繼承父類的所有欄位
    • 欄位的隱藏:子類重新定義一個與從父類那裡繼承來的與變數完全相同的變數,稱為域的隱藏
    • 欄位的新增:在定義子類的時,加上新的域變數,就可以使子類比父類多一些屬性

    方法

    • 方法的繼承:父類的非私有方法可以被子類自動繼承
    • 方法的覆蓋(Override)(修改) 子類也可以重新定義與父類同名的方法,實現對父類方法的覆蓋(Override)
      JDK 1.5 可以使用Override 來標註

    • 方法的新增:子類可以新增一些新的方法

    • 方法的過載:過載父類的同名方法,過載的方法實際上是新加的方法。

    super的使用

    • 建構函式是不能繼承的,但是子類可以通過super來呼叫父類的構造方法
    • 使用super訪問父類的域和方法
    • 使用super時 super() 必須放在第一句
 public class RoundImageView extends ImageView {
    private int mBorderThickness = 0;  
    private Context mContext;  
    private int defaultColor = 0xFFFFFFFF;  
    private int mBorderOutsideColor = 0;  
    private int mBorderInsideColor = 0;  
    private int defaultWidth = 0;  
    private int defaultHeight = 0;  
      public RoundImageView(Context context) {
        super(context);  
        mContext = context;  
    }  
    public RoundImageView(Context context, AttributeSet attrs) {
        super(context, attrs);  
        mContext = context;  
        setCustomAttributes(attrs);  
    }  
      public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);  
        mContext = context;  
        setCustomAttributes(attrs);  
    }  

父類物件與子類物件的轉換

  • 子類物件可以被視為其父類的一個物件
  • 父類物件不能被當作其某一個子類的物件
  • 如果一個方法的形式引數定義為父類物件,那麼在呼叫這個方法時,可以使用子類物件作為實際引數
  • 如果父類物件引用指向的實際是一個子類物件,那麼這個父類物件的引用可以用強制型別轉換(casting)成子類物件的引用

    • 包的作用:解決名字空間、名字衝突
    • 包的含義:a.名字空間、儲存路徑(資料夾)b.可訪問性(同一包下的各個類預設是可以相互訪問的)
    • 包層次的根目錄是由環境變數CLASSPATH來確定的
    • 簡單情況下,沒有package語句,這時稱為無名包(unnamend package)

    import語句

  • java編譯器自動匯入包java.lang.*

  • 注意:使用 * 只能表示本層的所有類,不包括子層下的類

    CLASSPATH

  • 包層次的根目錄是由環境變數CLASSPATH來確定的。

  • 方法一: 在java 及javac 命令中,用-classpath(或-cp)選項來指明,如: java -classpath d:\code;d:\code\java\classes
  • set classpath= D:\code\Java\learncode\ch04\pk;.

訪問控制符

成員的訪問控制符

同一個類中 同一個包中 不同包中的子類 不同包中的非子類
priavte Yes
預設訪問許可權(包訪問許可權) Yes Yes
protected Yes Yes Yes
public Yes Yes Yes Yes

seter和getter
  • 屬性使用private更好的封裝和隱藏,外部類不能隨意的存取和修改
  • 提供方法來存取物件的屬性,在方法中可以對給定的引數的合法性進行校驗
  • 方法可以用來給出計算後的值
  • 方法可以完成其他必要的工作(如清理資源、設定狀態,等等)
  • 只提供getXX方法,而不提供setXx方法,可以保證屬性是隻讀的

非訪問控制符

基本含義 修飾符 修飾成員 修飾的區域性變數
static 靜態的、非例項的、類的 可以修飾內部類 Yes
預設訪問許可權(包訪問許可權) Yes Yes
final 最終的、不可改變的 Yes Yes Yes
abstract 抽象的、不可例項化的 Yes Yes

static 欄位
  • 靜態欄位最本質的特點是:它是類的欄位,不屬於任何一個物件例項
  • 它不儲存在某個物件例項的記憶體區間中,而是儲存在類的記憶體區域的公共儲存單元
  • 類變數可以通過類名直接訪問,以可以通過例項物件來訪問,兩種方法的結果是相同的
  • static在一定意義上,剋來表示全域性變數

static 方法
  • 用static修飾符修飾的方法僅屬於類的靜態方法,又稱為類方法
  • 於此相對,不用static修飾的方法,則為例項方法
  • 類方法的本質是該方法是屬於整個類,不是屬於某個類的例項的
  • 宣告一個方法為static有以下幾重含義
  • (1)非static的方法是屬於某個物件的方法,在這個物件建立時,物件的方法在記憶體中擁有自己專用的程式碼段。
    而static方法是屬於整個類的,它在記憶體中的程式碼段將隨著類的定義而進行分配和裝載,不被任何一個物件專有
  • (2)由於static方法是屬於整個類的,所以它不能操縱和處理屬於某個物件的的成員變數,而只能處理整個類的
    成員變數,即static方法只能處理本類中的static域或呼叫static方法
  • (3)static方法中,不能訪問例項變數,不能使用this 或super
  • (4)呼叫這個方法時,應該使用類名直接呼叫,也可以用某一個具體的物件名

final類
  • 如果一個類被定義為final修飾和限定,說明這個類不能被繼承,即不可能有子類

final方法
  • final修飾符所修飾的方法,而不能被子類所覆蓋的方法

final欄位及final區域性變數

final欄位、final區域性變數(方法中的變數)
  • 它們的值一旦給定就不能修改
  • 只讀的,它們能切只能被賦值一次,而不能被賦值多次

一個欄位被 static final 兩個修飾符所限定時,它可以表示常量 如:Math.PI

關於賦值
  • 在定義static final 域時,若不給定初始值,則按預設值進行初始化(數值為 0,boolean 為false ,引用型別為null)
  • 在定義final欄位時,若不是static的域,則必須只能賦值一次,不能預設 這種賦值方式有兩種:一種是在定義
    變數時賦值初始化,二是子啊每一個建構函式中進行賦值
  • 在定義為final區域性變數時,必須且只能賦值一次。他的值可能不是常量,但它的取值在變數存在期間不會改變

abstract
  • 凡是用abstract修飾的類被稱為抽象類
  • 抽象類不能例項化

抽象類的意義

為其子類提供一個公共的型別 封裝子類中得重複內容 定義抽象方法,子類雖然有不同的實現 但是定義是一致的

abstract方法
  • 被abstract所修飾的方法叫抽象方法抽象方法的作用在所有的子類定義一個統一的介面。物件方法只需要宣告,而不需要實現,即用分號(;)而不是用{},格式如下:
  • abtract retutrnType abstracmethod([]);
  • 抽象類可以包含抽象方法,也可以不包含抽象方法。但是,一旦某個類中包含類abstract方法,則這個類必須宣告為
    抽象類
  • 抽象方法在子類中必須被實現,否則子類任然是abstract的

介面:某種特徵的約定
  • 所有的方法都自動的是 public abstract
  • 介面的實現 implements 可以實現多繼承,和類的繼承關係無關
  • 通過介面可以實現不相關類的相同行為,而不需考慮這些類之間的層次關係。從而一定意義上實現了多繼承
  • 通過介面可以實現多個類需要實現的方法
  • 通過介面可以瞭解物件的互動介面,而不需要了解物件所對應的類
  • 通常以able或ible結尾,表明介面能完成一定的行為
  • 介面宣告中還可以包括對介面的訪問許可權以及它的父介面列表

[public] interface interfaceName [extends listOfsuperInterface]{
        ...
    }
  • 其中public指明任意類可使用這個介面,預設情況下,只能與該介面點過意在同一個包中的類才可以訪問這個介面
  • extends 子句與類宣告中的 extends子句基本相同,不同的是一個介面可以有多個父介面,用逗號隔開,而一個類只能有一個父類。子接繼承父類中所有的常量和方法
  • 方法定義的格式為:
  • returnType methodName([paramlist])
  • 介面中只進行方法的宣告,而不提供方法的實現,所以,方法定義沒有方法體,且用分號(;)結尾。在介面中宣告的方法具體有public和abstract屬性,所以定義的時候這兩個關鍵詞是可以省略的
  • 如果介面中定義了和父類介面同名的常量或相同的方法,則父介面中的常量被隱藏,方法被過載

介面的實現
  • 在類中可以使用介面中定義的常量

    介面型別

  • 介面可以作為一種引用型別來使用。任何實現該介面的類的例項都可以儲存在該介面型別的變數中,通過這些變數可以訪問類所實現的介面中的方法。Java執行時系統的確定該使用那個類中的方法

  • 把介面作為一種資料型別可以不需要了解隊形所對應的具體類

介面中的常量
  • 介面體中可以包含常量定義
  • 常量定義的格式為: type NAME = value;
  • 其中type可以是任意型別,NAME 是常量名,通常用大寫,value 是常量值
  • 在介面中定義的常量可以被實現該介面的多個類共享
  • 在介面中定義的常量具有 public,static,final的屬性

Java8中的介面
  • Java 8 以上,介面成員還可以是:
  • static 方法
  • 具有實現的方法(default方法) 預設方法的好處:提供一個預設實現,子類在implements 可以不用在重複新寫了

介面的意義

規範、擴充套件、回撥

抽象類介面區別

    引用於:http://www.jackywang.tech/AndroidInterview-Q-A/chinese/java/%E6%8A%BD%E8%B1%A1%E7%B1%BB%E6%8E%A5%E5%8F%A3%E5%8C%BA%E5%88%AB-360.html

    預設的方法實現 抽象類可以有預設的方法實現完全是抽象的。
    介面根本不存在方法的實現(在Java8 此句描述不準確)

    實現 子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有宣告的方法的實現。
    子類使用關鍵字implements來實現介面。它需要提供介面中所有宣告的方法的實現

    構造器
    抽象類可以有構造器
    介面不能有構造器

    與正常Java類的區別
    除了你不能例項化抽象類之外,它和普通Java類沒有任何區 介面是完全不同的型別

    訪問修飾符
    抽象方法可以有public、protected和default這些修飾符 介面方法預設修飾符是public。你不可以使用其它修飾符。

    main方法
    抽象方法可以有main方法並且我們可以執行它
    介面沒有main方法,因此我們不能執行它。

    多繼承
    抽象類在java語言中所表示的是一種繼承關係,一個子類只能存在一個父類,但是可以存在多個介面。

    速度
    它比介面速度要快
    介面是稍微有點慢的,因為它需要時間去尋找在類中實現的方法。

    新增新方法
    如果你往抽象類中新增新的方法,你可以給它提供預設的實現。因此你不需要改變你現在的程式碼。
    如果你往介面中新增方法,那麼你必須改變實現該介面的類。(在Java8 此句描述不準確)