1. 程式人生 > 實用技巧 >《 高淇Java300集視訊》:【3】面向物件基礎

《 高淇Java300集視訊》:【3】面向物件基礎

面向過程(Procedure Oriented)和麵向物件(Object Oriented,OO)都是對軟體分析、設計和開發的一種思想,它指導著人們以不同的方式去分析、設計和開發軟體。

面向物件程式設計,是一種通過物件的方式,把現實世界對映到計算機模型的一種程式設計方法。

一、類與物件

類(Class):是對一類事物的描述 ,是抽象的 、概念上的定義。由屬性(Field)、方法(Method)和構造方法(Constructor )組成。

物件(Object):是實際存在的該類事物的每個個體,因而也稱為例項(instance)。

如:“書”是一種抽象的概念,所以它是類,而《Java核心技術》、《Java程式設計思想》是物件。

1.1、定義類

語法:

修飾符 class 類名 {
    //屬性宣告
    //方法宣告   
}

 1 /**
 2  * 測試定義類
 3  * @author 4  *
 5  */
 6 public class TestStudent {
 7     String name;    //屬性宣告
 8     int age;
 9     
10     void study() {    //方法宣告
11         System.out.println("學習中");
12     }
13 }

1.2、建立物件

語法:

修飾符 資料型別 屬性名 = 初始化值 ;

// 測試建立物件
TestStudent s=new TestStudent();

1.3、屬性

資料型別初始化預設值
整型 0
浮點型 0.0
字元型 '\u0000'
布林型 false
所有引用型別 null

Java 語言中除基本型別之外的變數型別都稱之為引用型別。

1.4、修飾符

同一個類同一個包子類所有類
private × × ×
default(預設) × ×
protected ×
public

1.5、記憶體分析

堆( Heap):儲存物件例項

棧( Stack)

: 儲存區域性變數

方法區(Method Area) :儲存類資訊、 常量、 靜態變數、 靜態方法、程式碼

二、方法

語法:

修飾符 方法返回型別 方法名(方法引數列表) {
        若干方法語句;
        return 方法返回值;
}

2.1、引數

方法可以包含0個或任意個引數。方法引數用於接收傳遞給方法的變數值。呼叫方法時,必須嚴格按照引數的定義一一傳遞。

可變引數用型別...定義,可變引數相當於陣列型別。

1 class Group {
2     String[] names;
3  
4     public void setNames(String... names) {
5         this.names = names;
6     }
7 }

// 測試可變引數
Group g=new Group();
g.setNames();               //傳0個引數
g.setNames("林一");         //傳1個引數
g.setNames("林一","林二");    //傳2個引數

【1】基本型別引數傳遞,傳遞的是數值。

 1 // 測試基本型別引數傳遞
 2 public class Main {
 3     public static void main(String[] args) {
 4         Person p = new Person();
 5         int n = 15;
 6         p.setAge(n);     //setAge()方法獲得的引數,複製了n的值給p.age,後面n改變不影響p.age
 7         System.out.println(p.getAge()); // 列印15
 8         n = 20;
 9         System.out.println(p.getAge()); // 列印15
10     }
11 }
12 
13 class Person {
14     private int age;
15  
16     public int getAge() {
17         return this.age;
18     }
19  
20     public void setAge(int age) {
21         this.age = age;
22     }
23 }

【2】引用型別引數的傳遞,傳遞的是物件地址。

 1 // 測試引用型別引數的傳遞
 2 public class TestMethod {
 3     public static void main(String[] args) {
 4         Person p=new Person();
 5         String[] f=new String[] {"林一","林二"};
 6         p.setName(f);  //陣列是一個物件,傳入陣列只是傳引用地址
 7         System.out.println(p.getName());
 8         f[1]="林三";  //修改陣列元素
 9         System.out.println(p.getName());  //引用地址沒變,陣列元素改變,結果也改變
10     }
11 }
12  
13 class Person{
14     private String[] name;
15     
16     public String getName() {
17         return this.name[0]+" "+this.name[1];
18     }
19     
20     public void setName(String[] name) {
21         this.name=name;
22     }
23 }

2.2、方法過載(Overload)

方法名相同,但各自的引數不同,稱為方法過載。

注意:方法過載的返回值型別通常都是相同的。

方法過載的目的是,功能類似的方法使用同一名字,更容易記住,因此,呼叫起來更簡單。

2.3、構造方法

構造方法(constructor),是一個建立物件時被自動呼叫的特殊方法,目的是物件的初始化。

【構造方法要點】:

  1. 通過new關鍵字呼叫。

  2. 構造方法有返回值,但不能定義返回值型別,不能在構造器裡使用return返回某個值。

  3. 如沒有定義構造方法,則編譯器會自動定義一個無參的構造方法。如已定義則編譯器不會自動新增。

  4. 構造器的方法名必須和類名一致。

 1 package com.test;
 2 /**
 3  * 測試定義構造方法
 4  * @author 5  *
 6  */
 7 public class TestStu {
 8     public static void main(String[] args) {
 9         Stu s=new Stu("林一",17);        // 建立物件會自動呼叫構造方法
10         System.out.println(s.getName());
11     }
12 }
13  
14 class Stu{
15     private String name;
16     private int age;
17     
18     public Stu(String name,int age) {    //定義構造方法
19         this.name=name;
20         this.age=age;
21     }
22     
23     public String getName() {
24         return this.name;
25     }
26     
27     public int getAge() {
28         return this.age;
29     }
30 }

【1】預設構造方法

如一個類沒有定義構造方法,編譯器會自動為我們生成一個預設構造方法,它沒有引數,也沒有執行語句。

如自定義了一個構造方法,那麼,編譯器就不再自動建立預設構造方法。

【2】構造方法過載(Overload)

構造方法過載,根據不同引數區別不同得構造方法。

 1 /* 測試構造方法過載 */
 2 class Person {
 3     private String name;
 4     private int age;
 5  
 6     public Person(String name, int age) {
 7         this.name = name;
 8         this.age = age;
 9     }
10  
11     public Person(String name) {
12         this.name = name;
13         this.age = 12;
14     }
15  
16     public Person() {
17     }
18 }

2.4、equals與==方法

Object 的 equals 方法預設就是比較兩個物件的hashcode,是同一個物件的引用時返回 true 否則返回 false。

==代表比較雙方是否相同。如果是基本型別則表示值相等,如果是引用型別則表示地址相等即是同一個物件。

【eclipse把游標放String類,按ctrl鍵+點選滑鼠左鍵看類原始碼】

 1 package com.test;
 2  
 3 /**
 4  * 測試equals與==方法
 5  * @author 6  *
 7  */
 8  
 9 public class TestEquals {
10     public static void main(String[] args) {
11         Person p1=new Person();
12         Person p2=new Person();
13         System.out.println(p1==p2);    //false
14         System.out.println(p1.equals(p2));    //false
15         
16         String s1=new String();
17         String s2=new String();
18         System.out.println(s1==s2);    //false
19         System.out.println(s1.equals(s2));    //true,equals重構過
20     }
21 }
22  
23 class Person{
24     int id;
25     String name;
26     public void showName() {
27         System.out.println(id+" "+name);
28     }
29 }

2.5、toString方法

Object類中定義有public String toString()方法,其返回值是 String 型別。

Object類中toString方法的原始碼為:

1 public String toString() {
2     return getClass().getName() + "@" + Integer.toHexString(hashCode());
3 }

 1 package com.test;
 2 /**
 3  * 測試toString預設輸出值
 4  * @author 5  *
 6  */
 7 public class TestToString {
 8     public static void main(String[] args) {
 9         Per p=new Per();
10         System.out.println(p);        
11     }
12 }
13  
14 class Per{
15     String name;
16     int age;
17 }
執行結果:
com.test.Per@15db9742

 1 package com.test;
 2 /**
 3  * 測試重寫toString方法
 4  * @author 5  *
 6  */
 7 public class TestToString {
 8     public static void main(String[] args) {
 9         Per p=new Per();
10         p.name="林一";
11         p.age=18;
12         System.out.println(p);        
13     }
14 }
15  
16 class Per{
17     String name;
18     int age;
19     @Override
20     public String toString() {    //重寫toString方法
21         return name+" "+age;
22     }
23 }

三、關鍵字

3.1、this關鍵字

在方法內部,可以使用一個隱含的變數this,它始終指向當前物件。因此,通過this.field就可以訪問當前物件的欄位。

如果沒有命名衝突,可以省略this

1 class Person {
2     private String name;
3     public String getName() {
4         return name; // 相當於this.name
5     }
6 }

如果有區域性變數和欄位重名,那麼區域性變數優先順序更高,就必須加上this

1 class Person {
2     private String name; 
3     public void setName(String name) {
4         this.name = name; // this不可少,this.name為成員變數
5     }
6 }

3.2、super關鍵字

super關鍵字表示父類(超類)。子類引用父類的欄位時,可以用super.fieldName

1 class Student extends Person {
2     public String hello() {
3         return "Hello, " + super.name;    //呼叫父類屬性
4     }
5 }
1 class Student extends Person {
2     protected int score;
3     public Student(String name, int age, int score) {
4         super(name, age); // 呼叫父類的構造方法Person(String, int)
5         this.score = score;
6     }
7 }

3.3、static關鍵字

static宣告的成員變數為靜態屬性。

static宣告的方法為靜態方法

  • 靜態屬性被該類的所有例項共享,在類被載入時被顯式初始化。

  • 靜態屬性使用 “類名.類屬性” 呼叫。

  • 靜態方法不需要物件, 就可以呼叫(如:類名.方法名)。

  • 呼叫靜態方法時, 不會將物件的引用傳遞給它, 所以在static方法中不可訪問非static的成員。

  • 靜態方法不能以任何方式引用this和super關鍵字。

 1 /**
 2  * 測試static關鍵字
 3  * @author 4  *
 5  */
 6 public class TestStatic {
 7     int a;
 8     static int width;    //靜態成員變數、類屬性
 9     
10     static void gg() {    //靜態方法
11         System.out.println("gg");
12     }
13     
14     void tt() {    //普通方法
15         System.out.println("tt");
16     }
17     
18     public static void main(String[] args) {    //java程式執行入口
19         TestStatic hi=new TestStatic();
20         TestStatic.width=2;        //呼叫靜態成員變數
21         TestStatic.gg();   //呼叫靜態方法
22     }    
23 }

【1】靜態初始化塊

  • 如果希望載入後, 對整個類進行某些初始化操作, 可以使用static初始化塊。

  • 類第一次被載入時先執行static程式碼塊; 類多次載入時, static程式碼塊只執行一次; Static經常用來進行static變數的初始化。

  • 經常用來進行static變數的初始化。

  • 靜態初始化塊中不能訪問非static成員。

 1 /**
 2  * 測試靜態初始化塊
 3  * @author 4  *
 5  */
 6 public class TestStaticBlock {
 7     static { //靜態初始化塊,類載入時載入
 8         System.out.println("靜態初始化塊");
 9     }
10     
11     public static void main(String[] args) {
12         System.out.println("main方法");
13     }
14 }

3.4、final關鍵字

final作用:

  1. 修飾變數: 被他修飾的變數不可改變。一旦賦了初值,就不能被重新賦值。

  2. 修飾方法:該方法不可被子類重寫。但是可以被過載。

  3. 修飾類: 修飾的類不能被繼承。比如:Math、String等。

四、垃圾回收機制

五、包

包機制是Java中管理類的重要手段,通過包我們很容易對解決類重名的問題,也可以實現對類的有效管理。

【二個要點】:

  • 通常是類的第一句非註釋性語句。

  • 包名:域名倒著寫即可,再加上模組名,便於內部管理類。

1 package com.test;
2  
3 public class TestPerson {
4  
5 }

5.1、常用包

Java常用包說明
java.lang 包含一些Java語言的核心類,如String、Math、Integer、System和Thread,提供常用功能。
java.awt 包含了構成抽象視窗工具集(abstract window toolkits)的多個類,這些類被用來構建和管理應用程式的圖形使用者介面(GUI)。
java.net 包含執行與網路相關的操作的類。
java.io 包含能提供多種輸入/輸出功能的類。
java.util 包含一些實用工具類,如定義系統特性、使用與日期日曆相關的函式。

5.2、匯入類

【要點】:

  • Java會預設匯入java.lang包下所有的類,因此這些類我們可以直接使用。

  • 如果匯入兩個同名的類,只能用包名+類名來顯示呼叫相關類。

 1 package com.test;
 2 /**
 3  * 測試匯入同名類的處理
 4  * @author 5  *
 6  */
 7  
 8 import java.sql.Date;
 9 import java.util.*;
10  
11 public class Test {
12     public static void main(String[] args) {
13         Date now;
14         java.util.Date now2=new java.util.Date();    //java.util.Date和java.sql.Date類同名,需要完整路徑
15         System.out.println(now2);
16         Scanner input=new Scanner(System.in);
17     }
18 }

5.3、靜態匯入

靜態匯入:其作用是用於匯入指定類的靜態屬性,這樣可以直接使用靜態屬性。

 1 package com.test;
 2  
 3 /**
 4  * 測試靜態屬性匯入的使用
 5  * @author 6  *
 7  */
 8  
 9 import static java.lang.Math.*;        //匯入Math類的所有靜態屬性
10 import static java.lang.Math.PI;
11  
12 public class Test {
13     public static void main(String[] args) {
14         System.out.println(PI);
15         System.out.println(random());
16     }
17 }