1. 程式人生 > >我們都說java是面向物件的程式語言,那什麼是面向物件呢?什麼是類呢?什麼是方法呢?

我們都說java是面向物件的程式語言,那什麼是面向物件呢?什麼是類呢?什麼是方法呢?

類、物件、方法

  類是物件的抽象定義,物件是類的具體例項。

  :指的是一類東西,比如汽車,人類,書等這些都指的是一類東西或物品。

  物件:指類的具體的實體,比如一輛汽車,一本書等,我們要記住一切皆物件(東西)。

  同時物件具有狀態(屬性)和行為(方法)

 我以人為例:
  人屬性有:臉,手,腳,鼻子,耳朵,身高,性別,鼻子,耳朵等屬性
  人的行為(方法):吃,喝,跑,睡覺等。

 這幾個大家都能理解吧,而java中是如何建立類和物件的呢

 先建立一個學生類(這些都是學生的屬性和方法)

public class Student {
    String name;      //姓名
int age; //年齡 String classNo; //班級 String hobby; //愛好 public void chi(){ System.out.println(name+"吃飯了") } //輸出資訊方法 public void show(){ System.out.println(name + "\n年齡:" + age + "\n就讀於:" +classNo + "\n愛好:" + hobby); } }

  這樣就建立好一個類了,那如何建立一個物件呢。

  首先舉一個例子:小李設計了一張汽車設計圖,然後交給生產車間來生產汽車,有黑色的、紅色的、白色的... 這裡,汽車設計圖就是我們說的類(class),生產車間就是new構造器(大部分物件都是new出來的),生產出來的汽車就是我們要說的物件。可以說java程式設計實質就是構建類的過程。

public class InitialStudent {
    public static void main(String args[]){
        Student student = new Student();    //建立物件
        student.name = "小明";            //給物件賦值
student.age = 10; student.classNo = "S1班";       student.hobby = "籃球"; student.chi(); student.show();            //呼叫方法 } }

  到現在我都是以自己的組織的語言給大家講解,為的是讓大家能夠理解,那麼java程式設計的規範有哪些,它的具體的細節又有哪些下面我就具體講一下

類的定義

  類必須先定義才能使用。類是建立物件的模板,建立物件也叫類的例項化。(類是物件的抽象定義,物件是類的具體例項)類實質上是一個數據型別。

例子:

public class Dog
{
   String name;
   int age;

   void bark()//汪汪叫
   {
       System.out.println("汪汪,不要過來");
   }
   void hungry()
   {
       System.out.println("主人,我餓了");
   }
}

對示例的說明:

  • public 是類的修飾符,表明該類是公共類,可以被其他類訪問。
  • 一個類儲存到一個檔案中,並且檔名要與類名相同。(一個檔案中可以執行多個類宣告,只能有一個類是public,檔名必須和該類類名一致)

  • class 是定義類的關鍵字。

  • Dog是類的名稱。

  • name,age是類的成員變數,也叫屬性;bark(),hungry()是類中的函式,也叫方法。
  • 物件例項化: 類名 物件名 = new 類名(); //未例項化的物件不能訪問其屬性和方法

  • 訪問屬性:物件名.屬性名

  • 訪問方法:物件名.方法名(引數列表)

作用域修飾詞

  1、public:public表明該資料成員、成員函式是對所有使用者開放的,所有使用者都可以直接進行呼叫

  2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有財產神聖不可侵犯嘛,即便是子女,朋友,都不可以使用。

  3、protected:protected對於子女、朋友來說,就是public的,可以自由使用,沒有任何限制,而對於其他的外部class,protected就變成private。

作用域 當前類 同一package 子孫類 其他package
public
protected ×
friendly(預設) × ×
private × × ×

一個類可以包含以下型別變數:

  • 區域性變數:在方法或者語句塊中定義的變數被稱為區域性變數。變數宣告和初始化都是在方法中,方法結束後,變數就會自動銷燬。

  • 成員變數:成員變數是定義在類中,方法體之外的變數。這種變數在建立物件的時候例項化(分配記憶體)。成員變數可以被類中的方法和特定類的語句訪問。

  • 類變數:類變數也宣告在類中,方法體之外,但必須宣告為static型別。static也是修飾符的一種。

  同時類也可以被final修飾,下面將會講解finnal關鍵字和static關鍵字
  

比較 成員變數 區域性變數
作用域 整個類中起作用(包括方法中) 只在方法中起作用
初始值 byte,short,int,long型是0
float,double型是0.0
char型是’\0’
boolean型是false
沒有初始值,無法使用

  注:當局部變數與成員變數重名時,在方法中優先使用區域性變數,方法中使用成員變數使用this,this代表當前類的當前物件。

static(靜態)

  類的靜態成員不依賴類的某一例項,可使用類名直接訪問

1.靜態變數(類變數)

當類第一次被載入(任何一個物件的宣告,首先要載入類),該類的靜態變數就分配獨立記憶體,直到程式結束被回收。靜態成員是公共的。(區域性變數不能用static修飾)

比較 靜態變數 成員變數
作用域 當前類 當前類
生命週期 類載入到程式結束 從物件產生到物件回收
使用方法 類名.靜態變數名 物件名.成員變數名

  靜態變數即類變數 成員變數即例項變數,物件例項化後才能使用

靜態方法

  • 訪問靜態方法:類名.方法名(引數列表)

  靜態方法在同一個類中被呼叫時,類名可以省略。普通成員方法必須在物件例項化後才可以呼叫

比較 靜態方法 成員方法
呼叫 類名.方法名(引數) 物件名.方法名(引數)
呼叫普通方法 不能直接呼叫 同一個類中可以呼叫
呼叫靜態方法 類名.方法名(引數) 類名.方法名(引數)
訪問靜態變數 類名.靜態變數名 類名.靜態變數名
訪問成員變數 不能直接訪問 同一類中可以直接訪問
this關鍵字 不能使用 可以使用

static程式碼塊

  static關鍵字還有一個比較關鍵的作用就是 用來形成靜態程式碼塊以優化程式效能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被載入的時候,會按照static塊的順序來執行每個static塊,並且只會在類載入的時候執行一次

  一般用來載入靜態資源比如載入圖片,視訊,音訊等。

final

Java關鍵字final有“這是無法改變的”或者“終態的”含義,它可以修飾非抽象類、非抽象類成員方法和變數。

1.修飾類

  當用final修飾一個類時,表明這個類不能被繼承。也就是說,如果一個類你永遠不會讓他被繼承,就可以用final進行修飾。final類中的成員變數可以根據需要設為final,但是要注意final類中的所有成員方法都會被隱式地指定為final方法

  注:在使用final修飾類的時候,要注意謹慎選擇,除非這個類真的在以後不會用來繼承或者出於安全的考慮,儘量不要將類設計為final類。

修飾方法

  使用final方法的原因有兩個。
   第一個原因是把方法鎖定,以防任何繼承類修改它的含義;
   第二個原因是效率。在早期的Java實現版本中,會將final方法轉為內嵌呼叫。但是如果方法過於龐大,可能看不到內嵌呼叫帶來的任何效能提升。在最近的Java版本中,不需要使用final方法進行這些優化了。

  注:類的private方法會隱式地被指定為final方法。

修飾變數

  修飾變數是final用得最多的地方,也是重點闡述的內容

  對於一個final變數,

    如果是基本資料型別的變數,則其數值一旦在初始化之後便不能更改;

    如果是引用型別的變數,則在對其初始化之後便不能再讓其指向另一個物件。

  • 類的final變數和普通變數有什麼區別
  • 當用final作用於類的成員變數時,成員變數(注意是類的成員變數,區域性變數只需要保證在使用之前被初始化賦值即可)必須在定義時或者構造器中進行初始化賦值,而且final變數一旦被初始化賦值之後,就不能再被賦值了。
public class Test {
    public static void main(String[] args)  {
        String a = "hello2"; 
        final String b = "hello";
        String d = "hello";
        String c = b + 2; 
        String e = d + 2;
        System.out.println((a == c));//true
        System.out.println((a == e));//false
    }
}

分析
  為什麼第一個比較結果為true,而第二個比較結果為fasle。這裡面就是final變數和普通變數的區別了,當final變數是基本資料型別以及String型別時,如果在編譯期間能知道它的確切值,則編譯器會把它當做編譯期常量使用。也就是說在用到該final變數的地方,相當於直接訪問的這個常量,不需要在執行時確定。這種和C語言中的巨集替換有點像。因此在上面的一段程式碼中,由於變數b被final修飾,因此會被當做編譯器常量,所以在使用到b的地方會直接將變數b 替換為它的 值。而對於變數d的訪問卻需要在執行時通過連結來進行。想必其中的區別大家應該明白了,不過要注意,只有在編譯期間能確切知道final變數值的情況下,編譯器才會進行這樣的優化,比如下面的這段程式碼就不會進行優化:

public class Test {
    public static void main(String[] args)  {
        String a = "hello2"; 
        final String b = getHello();
        String c = b + 2; 
        System.out.println((a == c));//這段程式碼的輸出結果為false。
 
    }
 
    public static String getHello() {
        return "hello";
    }
}
  • 被final修飾的引用變數指向的物件內容可變嗎
  • 引用變數被final修飾之後,雖然不能再指向其他物件,但是它指向的物件的內容是可變的。
public class Test {
    public static void main(String[] args)  {
        final MyClass myClass = new MyClass();
        System.out.println(++myClass.i);//結果為1
    }
}
 
class MyClass {
    public int i = 0;
}
  • final引數的問題
  • 無論引數是基本資料型別的變數還是引用型別的變數,使用final宣告都不會防止你無意的修改而影響到呼叫方法外的變數
public class Test {
    public static void main(String[] args)  {
        MyClass myClass = new MyClass();
        StringBuffer buffer = new StringBuffer("hello");
        myClass.changeValue(buffer);
        System.out.println(buffer.toString());
    }
}
 
class MyClass {
 
    void changeValue(final StringBuffer buffer) {
        buffer.append("world");
    }
}

  執行這段程式碼就會發現輸出結果為 helloworld。很顯然,用final進行修飾並沒有阻止在changeValue中改變buffer指向的物件的內容。有人說假如把final去掉了,萬一在changeValue中讓buffer指向了其他物件怎麼辦。有這種想法的朋友可以自己動手寫程式碼試一下這樣的結果是什麼,如果把final去掉了,然後在changeValue中讓buffer指向了其他物件,也不會影響到main方法中的buffer,原因在於java採用的是值傳遞,對於引用變數,傳遞的是引用的值,也就是說讓實參和形參同時指向了同一個物件,因此讓形參重新指向另一個物件對實參並沒有任何影響。

static final

  •   static作用於成員變數用來表示只儲存一份副本,而final的作用是用來保證變數不可變。

  •   static final修飾的屬性表示一旦給值,就不可修改,並且可以通過類名訪問。

  •   static final也可以修飾方法,表示該方法不能重寫,可以在不new物件的情況下呼叫。
      

    方法

  • 為什麼要有方法
    • 提高程式碼的複用性
  • 什麼是方法
    • 完成特定功能的程式碼塊。
  • 方法的格式

修飾符 返回值型別 方法名(引數型別 引數名1,引數型別 引數名2...) {
            方法體語句;
            return 返回值; 
        } 
  • 方法的格式說明
    • 修飾符:一般就用 public,static,final。
    • 返回值型別:就是功能結果的資料型別。
    • 方法名:符合命名規則即可。方便我們的呼叫。
    • 引數:
      • 實際引數:就是實際參與運算的。
      • 形式引數;就是方法定義上的,用於接收實際引數的。
    • 引數型別:就是引數的資料型別
    • 引數名:就是變數名
    • 方法體語句:就是完成功能的程式碼。
    • return:結束方法的。
    • 返回值:就是功能的結果,由return帶給呼叫者。

構造方法(特殊的方法)

  在類例項化的過程中自動執行的方法叫做構造方法,它不需要你手動呼叫。構造方法可以在類例項化的過程中做一些初始化的工作。

  構造方法的名稱必須與類的名稱相同,並且沒有返回值。

  每個類都有構造方法。如果沒有顯式地為類定義構造方法,Java編譯器將會為該類提供一個預設的構造方法。

public class Dog
{
  String name;
  int age;

  //構造方法,沒有返回值
  Dog(String name1,int age1)
  {
     name = name1;
     age = age1;
     System.out.println("感謝主人領養了我");
  }

  //普通方法,必須有返回值
  void bark()
  {
     System.out.println("汪汪,不要過來");
  }

  void hungry()
  {
      System.out.println("主人,我餓了");
  }

  public static void main(String[] args)
  {
      //建立物件時傳遞的引數要與構造方法引數列表對應
      Dog myDog = new Dog("花花",3);
  }
}

執行結果:

感謝主人領養了我

package day23;
/*構造方法
 - 作用是用於初始化引數
 - 所有的數字變數全部設定為0
 - 所有的boolean型別全部設定為false
 - 所有的物件變數全部設定為null
 */
/*
 - 設計自己的構造方法
 -   方法名稱必須和類的名稱相同
 -   沒有返回值
 */
/*
 - 如果自己寫了有參的構造方法,那麼編譯器不會再提供
 - 預設的構造方法了
 - 如果我們還想用無參的構造方法,
 - 那麼需要手動實現
 */
public class People 
{
    String name;
    String sex;
    int age;

    //無參的構造方法(可以不寫編譯器自動加上,前提是沒有任何其他構造方法)
    People()//構造方法(可刪掉,編譯器預設加上)
    {
//      name = null;
//      sex = null;
//      age = 0;
    }

    //有參的構造方法
    People(String name,String sex,int age)
    {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    //部分初始化
    People(String name)
    {
        this.name = name;
    }

    People(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
    public static void main(String[] args)
    {
        People p = new People();
        System.out.println(p.name);
        System.out.println(p.sex);
        System.out.println(p.age);

        People p1 = new People("張三","男",30);
        System.out.println(p1.name+","+p1.sex+","+p1.age);

        People p2 = new People("老王");
        System.out.println(p2.name);

        People p3 = new People("小老虎",3);
        System.out.println(p3.name+","+p2.age);
    }
}

說明:

  • 構造方法不能被顯式呼叫。

  • 構造方法不能有返回值,因為沒有變數來接收返回值

建立物件

  物件是類的一個例項,建立物件的過程也叫類的例項化。物件是以類為模板來建立的。
  在Java中,使用new關鍵字來建立物件,一般有以下三個步驟:

  • 宣告:宣告一個物件,包括物件名稱和物件型別

  • 例項化:使用關鍵字new來建立一個物件。

  • 初始化:使用new建立物件時,會呼叫構造方法初始化物件。
    例如:

Dog myDog;//宣告一個物件
myDog = new Dog("花花",3);//例項化

也可以在宣告的同時進行初始化:

Dog myDog = new Dog("花花",3);

訪問成員變數和方法

通過已建立的物件來訪問成員變數和成員方法,例如:

//例項化
Dog myDog = new Dog("花花",3);
//通過點號訪問成員變數
myDog.name;
//通過點號訪問成員方法
myDog.bark();

  下面的例子演示瞭如何訪問成員變數和方法:

public class Dog
{
  String name;
  int age;

  Dog(String name1,int age1)
  {
     name = name1;
     age = age1;
     System.out.println("感謝主人領養了我");
  }

  void bark()
  {
    System.out.println("汪汪,不要過來");
  }

  void hungry()
  {
    System.out.println("主人,我餓了");
  }

  public static void main(String[] args)
  {
    Dog myDog = new Dog("花花",3);
    //訪問成員變數
    String name = myDog.name;
    int age = myDog.age;
    System.out.println("我是一隻小狗,我名字叫" + name + ",我" + age + "歲了");
    //訪問方法
    myDog.bark();
    myDog.hungry();
  }
}

 執行結果: 
   感謝主人領養了我
   我是一隻小狗,我名字叫花花,我3歲了
   汪汪,不要過來
   主人,我餓了