1. 程式人生 > >面向物件程式設計基礎(java)

面向物件程式設計基礎(java)

面向物件程式設計基礎

1.1 面向物件概述

在程式開發初期,大家使用的是結構化開發語言,也就是面向過程(opp),但隨著市場需求劇增,軟體的規模也越來越大,結構化語言的弊端也暴露出來。

開發週期無休止的拖延,軟體質量也越來越差。

為了更好的適應市場,有人就開始以另一種開發思想引入程式中,也就是面向物件的開發思想(oop)。

面向物件思想是人類最自然的一種思考方式,他將所有預處理的問題抽象為物件,同時瞭解這些物件具有哪一些對應的屬性以及行為,以解決這些物件面臨的一些實際問題,面向物件設計實質上就是對現實世界的物件進行建模操作。或者說把現實世界的操作虛擬到程式中去

1.2 物件

物件,是一個抽象概念,英文稱為“Object”,表示存在的事物。通俗的來說就是世間萬物皆物件!現實世界中肉眼可見的一種事物都是物件,物件是事物存在的實體,例如:人、手機、電腦。為了大家能簡單的理解,只要現實世界中看得到的實物都是一個物件。

1.2.1 物件的組成

一個實體(物件)可以劃分兩個部分,一個是描述外觀和功能。那麼在程式裡關於實體(物件)描述外觀的稱為“屬性”;實體(物件)的功能稱之為“行為”或“方法”,也就是實體(物件)執行的動作。例如:人的性別是描述這個實體(物件)的,人能行走也能吃飯和學習是執行的動作。

實體(物件)由屬性和行為組成,也就是實體(物件)的外觀和功能。

1.3 類

類是封裝物件的屬性和行為的載體,反過來說具有相同屬性和行為的一類實體被稱之為類(簡單的理解也可以是分類)。例如:大雁群就可以看做是大雁類,因為每一隻大雁都有相同的嘴、翅膀和爪等外貌特性;同時每一隻大雁也會睡覺、飛行、覓食等行為。所以就可以進行分類用程式角度來說的話這一群大雁就是一個大雁類。而大雁群中的每一隻大雁都是大雁類的一個物件。

 從上面兩張流程圖我們知道大雁群中的每一隻大雁都具備一樣的外觀描述和行為(功能),那麼我們就可以把這個實體(物件)稱之為這個分類下的物件或者實體。

總結:類可以理解為分類,是抽象的。而物件就是實體,可以看得到摸得著的。

 1.3.1 OPP程式設計特點簡單介紹

面向物件程式設計具有以下三個通用特點:

封裝性

√繼承性

√多型性

a).封裝

封裝是面向物件程式設計的核心思想。也就是將物件的特徵和行為封裝起來,其載體就是類,類通常會隱藏其實現細節,這就是封裝的思想。也就是說現實生活中的物品或商品你只要負責使用就ok,其他的你可以不管。例如:使用手機打電話,只要你打通電話就行,具體內部怎麼實現無需知道。

總結:程式中採用封裝的思想主要是保證了類內部資料結構的完整性和安全性,使用該類的使用者不能輕易的直接操作次資料結構,只能操作類允許公開的資料。這樣一來就避免了外部操作對內部資料的影響,提高了程式的可維護性。

b) 繼承

繼承是每一門計算機語言不可少的機制,主要作用就是利用繼承機制使新建的類可以建立在原有類的基礎之上。在使用或者重寫原有類的行為或者功能(程式裡叫成員方法)以及訪問原有類的特徵(也就是類的成員變數)。我們可以稱新類為子類,原有類為父類。舉個例子:如果類A是類B的父類,而類B是類C的父類,那麼也可稱類C是類A的子類,類C是從類A基礎而來。同時在java中,關於類的繼承是單一繼承的,也就是說,一個子類只能擁有一個父類,一個父類可以有多個子類。總而言之,繼承是在程式碼中實現重複利用的重要手段,子類通過繼承,複用父類特徵和行為的同時又添加了子類特有的特徵和行為。

c) 多型

將父類物件應用於子類的特徵就是多型。多型通俗理解就是多種形態,但每一個實體(物件)還是具備了父類的特徵和行為。

 

 

2.類與物件

上面我們認識類的時候就已經講過,類是我們封裝實體(物件)的外觀特徵(屬性)和行為的載體,也就是說這個實體(物件)有哪一些外觀描述和功能都可以在類裡面進行封裝描述

2.1 類的宣告

語法:

public class 類名稱
{
    //類的主體...  
}

 

注意:

  1. 如果類檔案中只有一個類時,檔名必須與類名保持一致;
  2. 一個java檔案中只能有一個public類;
  3. 如果類檔案中不止一個類,檔名必須與public類名一致;
  4. 如果檔案中不止一個類,而且沒有public類,檔案可與任意類名一致;

java類名的命名規則: 

  1. 類名應該以下劃線(_)或者字母開頭,最好以字母開頭;
  2. 第一個字母最好大寫,如果類名由多個單片語成,則每個單詞的首字母最好都大寫;
  3. 類名不能為java中的關鍵字,例如:String、this、double、int等;
  4. 類名不能包括任何嵌入的空格或點號,以及除了下劃線(_)和美元符號($)字元之外的特殊符號。

2.2   a 成員變數

java中實體(物件)的特徵(屬性)也稱之為成員變數,成員變數的定義和普通變數定義是一樣的。

資料型別 變數名稱 [ = 值 ];

 注意:程式碼中的[ = 值]表示可選內容,也就是說定義變數時可以為其賦值也可以不賦值。

我們來舉一個例子,例如鳥類==》Bird類,成員變數對應於類物件屬性,鳥都有翅膀、爪子、嘴巴、羽毛...而這一些都是描述鳥的外觀也就是物件的屬性,所以Bird應該有四個成員變數:wing、claw、beak、feather。

//定義一個Bird鳥類
public class Bird{
    String wing;      //翅膀
    String claw;      //爪子
    String beak;     //嘴巴
    String feather;  //羽毛
}

 

分析:上面 程式碼使用關鍵字class定義類,類名是Bird,同時在Bird類中定義了4個成員變數,成員變數的型別可以設定java中合法的資料型別,說到底成員變數和普通變數是一樣的,成員變數也可以設定初始值,也可以不設定初始值。不設定初始值就會有一個預設值。

資料型別 預設值   詳細說明  
float、double      0.0 浮點零
char '' 空格字元
boolean false 邏輯符
引用型別,如:String     null 空值
int、byte、short、long  0 0值

上面是我們在定義類時使用的一些資料型別以及對應的預設值

2.2 b 成員方法

2.2.1 成員方法的定義

成員方法對應類物件(實體)的行為或者功能,主要是用來定義類可執行的操作,行為或者功能就是一系列語句組成的程式碼塊。

語法:

 

[許可權修飾符] [返回值型別] 方法名 ([引數型別 引數名]){
    //方法體--> 一系列程式碼
    return 返回值;  
}

 

 分析:

  1. 許可權修飾符可以是private、public、protected中的任意一個,也可以不寫,主要來控制方法(行為)的訪問許可權。
  2. 返回值型別用來指定方法(行為)返回資料的型別,可以是任何型別,如果方法不需要返回值則可以使用void關鍵字。
  3. 一個成員方法(行為)可以有引數也可以沒有引數,同時引數是物件也可以是基本資料型別。
class Person{
    String name = "張三";//成員變數也稱之為類物件屬性
//定義一個方法,作用是做一個自我介紹 //不需要返回 public void showInfo(){ System.out.println(name); } }
public class Per{
    public static void main(String[] args){
        Person p = new Person();
        p.showInfo();//輸出張三
    }
}

 

 注意:

方法的定義必須是在某個類的裡面 ,也就是在類中;同時定義方法如果沒有給定許可權訪問修飾符,該方法的預設許可權也缺少,也就是隻能在本類以及同一個包中的類進行訪問。

如果定義的方法有設定了返回值,則方法裡必須使用return關鍵字返回一個指定型別的資料,並且返回型別要與方法返回值的型別一致。

2.2.2 成員方法的引數

在呼叫方法時可以給該方法傳遞一個或者多個值,傳遞給方法的值叫做實參,在方法內部,接受實參的變數叫作形參,形參的宣告語法和變數的宣告語法是一樣的。在java中方法的引數主要有以下三種:

  1. 值引數
  2. 引用引數
  3. 不定長引數

【值引數:】

值引數是實參與形參之間按值傳遞,當使用值引數方法被呼叫時,編譯器為形參分配儲存空間,然後將對應的實參的值複製到形參中,由於是值型別的傳遞方式,所以在方法中對值型別的形參和修改不會影響實參。

例:書架上有30本書,箱子裡有40本書,現吧書架上的書全部放入箱子後,使用帶引數的成員方法統計箱子裡書的總數。

public class Book{
    public static void mian(String []){
        Book b = new Book();
        int num1 = 30;
        int num2 = 40;
        int box = b.add(num1,num2);
        System.out.println("箱子書總數為:"+ box);
    }

    //統計箱子中所有書本
    public int add(int num1, int num2){
        int box = 0;
        box = num1+num2;
        return box;
    }
}

 

【引用引數:】

在給方法傳遞引數時,引數的型別陣列或者其它引用型別,那麼,在方法中對引數的修改會反映到原有的陣列或者其他的引用型別上,這種型別的方法引數就叫做引用引數。

現將1、10、100美元存入double陣列中,使用引用引數將陣列的美元轉化成RMB,例1:6.903

public class Rate{
  public static void main(String[] args){
    double[] arr = {1, 10, 100};
    
    //輸出陣列中的美鈔
    for(int i = 0; i < arr.length; i++){
      System.out.println(arr[i] + "美元");
    }
    
    //呼叫方法change
    change(arr);
    
    //再次輸出陣列中資料
    for(int i = 0; i < arr.length; i++){
      System.out.println(arr[i] + "元");
    }
  }
  
  //定義一個方法,引數為一維陣列(形參)
  public void change(double[] arr){
    for(int i = 0; i < arr.length; i++){
      arr[i] *= 6.903; //換算成RMB
    }
  }
}

【不定長引數:】

在宣告方法的時候,如有若干個相同型別的引數,則可以定義不定長引數的成員方法。

public class Scal{
  public static void main(String[] args){
   int num1=20,num2=42,num3=32,num4=329,num5=329;
    Scal s = new Scal();
    int sum1 = s.add(num1, num2); //只計算二個數值的和
    int sum2 = s.adds(num1,num2,num3,num4,num5);
    
    System.out.println("sum1=" + sum1);
    System.out.println("sum2=" + sum2);
  }
  
  //計算二個數之和
  public int add(int num1, int num2){
    return num1 + num2;
  }
  
  //計算一系列整數之和
  public int adds(int... num){
    int sum = 0;
    for(int i = 0; i < x.length; i++){
      sum += x[i];
    }
    //返回和
    return sum;
  }
}

 

 2.3 區域性變數

區域性變數從字面意思來理解就是在一定範圍有效。

定義:成員方法內部定義的變數,那麼這個變數就是區域性變數。

分析:區域性變數在方法執行時被建立在方法執行結束後就會被銷燬。同時區域性變數在使用時必須進行賦值操作或者初始化,否則會出現編譯錯誤。

public class Demo{
  public static void main(String[] args){
    Demo d = new Demo();
    d.sayHello();
  }
  
  //說hello
  public void sayHello(){
    String name = "Java"; //是在方法sayHello體內宣告的所以是區域性變數
    System.out.println(name);
  }
  
}

 

2.4 構造方法

2.4.1 無參構造方法定義

在類中除了有成員方法之外還有一個特殊型別的方法,那就是構造方法。構造方法是一個類與類同名的方法,我們實體就是通過構造方法來建立的。也就是說每當類例項化一個物件時,類都會自動呼叫構造方法。

  • 構造方法沒有返回值型別,也不能定義void
  • 構造方法的名稱要與本類的名稱相同
  • 構造方法主要作用是完成初始化工作,也能把定義物件的引數傳給物件成員

分析:

在定義一個類的構造方法時,構造方法是沒有返回值(一定要記住),同時也要知道構造方法與普通方法沒有返回值的方式不同,普通方法返回值的方法用public void 方法名()形式定義,但構造方法並不需要void關鍵字進行修飾。

public class 類名 {
  //構造方法
  public 類名() {
    
  }
}

注意:

  1. public 修飾符關鍵字不能少
  2. 類名一定要保持一致

2.4.2 定義有參構造方法

在對構造方法中可以為成員變數進行賦值,這樣當例項化一個本類的物件時,相應的成員變數也會被初始化。類中沒有定義構造方法時,編譯器會自動建立一個不帶引數的構造方法作為預設。

public class Book {
  //書名
  String name;
  //定義一個有引數的構造方法
  public Book(String str){
    name = str;
  }
}

 

注意:

  1. public修飾符關鍵字不能少
  2. 類名一定要保持一致
  3. 構造方法的引數可以是一個或多個

分析:

如果在類中定義的構造方法是有參構造方法,編譯器就不會為類自動生成一個預設無參構造方法,此時當呼叫無參構造方法例項化一個物件時,編譯器就會報錯。因此要記住,只有在類中沒有定義構造方法時,編譯器才會去自動生成一個不帶引數的構造方法。

public class Per{
  public static void main(String[] args){
    Per p = new Per();
    p.sayHello("張三", "男");
  }
  //無參構造方法
  public Per(){
  }
  //介紹自己
  public void sayHello(String name, String sex){
    System.out.println("我的名字"+ name + ",性別是" + sex);
  }
}
public class Per{
  String username; //成員變數
  String agender;  //成員變數
  public static void main(String[] args){
      
  }
  //有參構造方法
  public Per(String name, String sex){
    username = name;
    agender = sex;
  }
  public void sayHello(){
    System.out.println("我的名字是:" + username + ",性別為:" + agender);
  }                             
}

 

2.5 this關鍵字

this關鍵字在方法體內表示當前類的物件。類是物件的載體,把通過類可以創建出很多的物件,那麼當建立的物件去呼叫方法時,被呼叫的方法體內有this關鍵字,那麼這個方法體內的this就是當前物件自己本身。

關於this的三種用法:

1.區分成員變數和區域性變數

public class Demo{
  public static void main(String[] args){
     Demo2 d = new Demo2("張三", 32);
     d.sayHello();
  }
}
​
class Demo2{
  String name; //名字
  int age; //年齡
  public Demo2(String name, int age){
    name = name;
    age = age;
  }
  
  //說出自己個人資訊
  public void sayHello(){
    System.out.println("我的名字是" + name + ",年齡為" + age);
  }
}

 

輸出結果為:我的名字是null,年齡為0

在我們構造方法中如果沒有使用this來作為變數區分,那麼name = name 和 age = age 都是區域性變數在操作。也就是區域性變數name = 區域性變數name,所以成員變數name就一直沒有操作。

public class Demo{
  public static void main(String[] args){
     Demo2 d = new Demo2("張三", 32);
     d.sayHello();
  }
}
​
class Demo2{
  String name; //名字
  int age; //年齡
  public Demo2(String name, int age){
    this.name = name;
    this.age = age;
  }
  
  //說出自己個人資訊
  public void sayHello(){
    System.out.println("我的名字是" + name + ",年齡為" + age);
  }
}

 

輸出結果為:我的名字是張三,年齡為32

總結:this在構造方法中,如果引數名稱和成員變數一樣,則可以使用this來進行區分。

2.構造方法中的使用

public class People{
  String name; //姓名
  int age; //年齡
  String agender; //性別
​
  public static void main(String[] args){
    People p = new People("張三");
    p.sayHello();
  }
​
  public People(String name, String agender, int age){
    this.name = name;
    this.agender = agender;
    this.age = age;
    System.out.println("這是類的第一個構造方法");
  }
​
  public People(String name, String agender){
    this.name = name;
    this.agender = agender;
    System.out.println("這是類的第二個構造方法");
  }
​
  public People(String name){
    this.name = name;
    System.out.println("這是類的第三個構造方法");
  }
​
  public void sayHello(){
    System.out.println("name=" + name + ",agender=" + agender + ",age=" +age);
  }
}

輸出結果為:

這是類的第三個構造方法

name=張三,agender=null,age=0

 如果在類構造方法中使用this關鍵字後:

public class People{
  String name; //姓名
  int age; //年齡
  String agender; //性別
​
  public static void main(String[] args){
    People p = new People("張三");
    p.sayHello();
  }
​
  public People(String name, String agender, int age){
    this.name = name;
    this.agender = agender;
    this.age = age;
    System.out.println("這是類的第一個構造方法");
  }
​
  public People(String name, String agender){
    this(name, agender, 32);
    this.name = name;
    this.agender = agender;
    System.out.println("這是類的第二個構造方法");
  }
​
  public People(String name){
    this(name, "男");
    this.name = name;
    System.out.println("這是類的第三個構造方法");
  }
​
  public void sayHello(){
    System.out.println("name=" + name + ",agender=" + agender + ",age=" +age);
  }
}

 

 輸出結果為:

這是類的第一個構造方法

這是類的第二個構造方法

這是類的第三個構造方法

name=張三,agender=男,age=32

3.表示當前物件

public class Demo{
  String name;
  int age;
  public static void main(String[] args){
    Demo d = new Demo("張三", 32);
    System.out.println(d.name + d.age);
  }
  
  public Demo(String name, int age){
    this.name = name;
    this.age = age;
  }
}

 

分析:

this表示當前呼叫物件也就是物件“d”,那麼構造方法中的this.name就完全等價於d.name = “張三”。

3 static關鍵字

在程式碼中使用static關鍵字修飾的變數、方法、常量都被稱為靜態變數、方法、常量,也可以稱之為類的靜態成員。

靜態成員的使用不需要例項化物件就可以使用,使用的方法也很簡單就是【類名.家庭成員】

3.1 靜態成員

public class StaticStu
{
  public static String name = "";
​
  public static void main(String[] args){
    name = "張三"; //等價於StaticStu.name = "張三"
    System.out.println(name);
  }
}
​
//輸出的結果為:張三

 

注意:

在類中使用靜態成員可以直接使用,也是不需要例項化。

3.2靜態方法

public class StaticStu
{
  public static void main(String[] args){
    StaticStu.SayHello();
  }
  
  public static void SayHello(){
    System.out.println("深夜了"); 
  }
}
//輸出結果為:深夜了

注意:

定義和使用跟變數一樣,都是static進行修飾,也不需要例項化就可直接使用

3.3 靜態程式碼塊

類有類的成員,那麼類也有著自己的行為,那就是類的程式碼塊,也稱之為靜態程式碼塊。主要作用和構造方法雷同,是用來為為類做一些初始化工作。

public class StaticStu
{
  static {
    System.out.println("我是類的程式碼塊,我初始化了");
  }
  public static void main(String[] args){
  }
}
​
//輸出結果為:我是類的程式碼塊,我初始化了

 

注意:

類有程式碼塊那麼物件也有程式碼塊,直接是以{}即可。

 

 

&n