Java核心技術初階04:面向對象思想、類和對象

1.面向對象思想

1.1

  • 現實世界是由對象和對象之間相互作用共同組成的
  • 每個對象有自己的特有屬性,也有自己專有的方法。外部對象想要調用這些方法,可以向它請求並傳入參數,等方法執行結束後,返回結果。
  • 對象=屬性+方法
  • 對象的規範=屬性定義+方法定義

對象調用過程:
1.輸入參數;
2.等待目標方法執行結束;
3.返回結果

1.2

Java中,引入對象和類的概念

  • 對象是一個變量(具體的東西)
  • 類就是類型(是規範、是定義),從萬千對象中抽取共性
  • 類規定了對象應該有的屬性內容和方法
  • 對象是類的距體表現,是活生生的
  • 例如:土豆絲菜譜是類,一盤土豆絲是對象

1.3

  • 從程序發展的角度來理解,OO(Oriented Object:面向對象)是對OP(Oriented Procedure:面向過程)的一種改進
  • OP的典型代表是C和Pascal。更強調方法動作,所有的變量是被動參與進來,沒有自主決定權
  • OO的方法輸語每個對象的。能否實現是由每個對象說了算的,有主人翁精神

1.4

  • OP的例子
public class OPExample {
    public static void main(String[] args) {
        int a, b, c;
        a = 1;
        b = 2;
        c = add(a, b);
        System.out.println("c is " + c);
    }

    // 函數定義
    public static int add(int m, int n) {
        return m + n;
    }
}

方法是主體,所有的參數是類似於賓語.

  • OO的例子
public class OOExample {
    private int a;

    public void setA(int a) {
        this.a = a;
    }

    public int add(int b) {
        return this.a + b;
    }

    public static void main(String[] args) {
        int b = 5;
        OOExample obj = new OOExample();
        obj.setA(10);
        System.out.println(obj.add(b));
    }

}

方法從屬於一個對象,而這個對象可以執行自身的某個方法.
obj.add(b):主語obj,謂語add,賓語b

1.4.1

  • 計算機的發展和社會發展也是相似之處
    • 更強調方法的執行主體
    • 增加類型的重用部分(內容和行爲)

1.5

  • 變量定義的變遷:更加功能強大
  • 基本類型(一種變量)=>>結構體(多種變量捆綁)=>>類(多種變量+方法)
  • 類可以繼承;子類可以繼承父類所有內容(不能直接訪問private成員)
    • 基本類型無法做到
    • 結構體只能做到全包含,不能控制包含粒度

short和int都是整數類型,但是沒有繼承關係,只是表示的整數範圍不同而已。

1.6

  • 基本變量例子:int a; float b;
  • 結構體變量例子
// c語言結構體不能包含函數
struct Simple{
	int a;
	double b;
};//成員默認均爲public

struct Complex{
	char c;
	struct Simple foo;
	//Complex必須包含Simple所有內容
};

Complex包含:int a,float b,char c

  • 類/對象例子:
public class Father {
    private int money=100;//私有
    long mobile=1399999999L;

    public void hello(){
        System.out.println("hello");
    }
}

//--------------------------------------------

public class Son extends Father {
    public void hi(){
        //子類可以擴展自己的成員方法
        System.out.println("hi !!!!!");
    }

    public static void main(String[] args){
        Son s=new Son();
        System.out.println(s.mobile);//Son沒有定義mobile,而是通過父類繼承的
        //  System.out.println(s.money);//error 父類的money是私有的,子類無法直接訪問

        s.hello();// Son沒有定義f1,而是通過父類繼承的
        s.hi();//Son可以自定義自己的成員方法
    }
}

子類必須通過父類的方法才能訪問父類的私有變量。

1.7

  • OO最早的始於Simula 67,成形於20實際70年代Smalltalk
  • 當前最主要的代表是C++和Java
  • 面嚮對象語言主要特點:
    • 識認性:辨識/認定爲一種對象
    • 類別性:好幾種對象可以歸爲一類
    • 多態性:是指在這個類別裏面,這些對象有一定的共同性,也有一定的不同性
    • 繼承性:每個子類都會繼承父類的所有東西,然後可以使用它們

1.8總結

  • OO總結
    • 現實世界是由對象和對象之間相互作用共同組成的
    • 對象不僅包含成員變量,還有成員方法
    • 對象的內容可以繼承

2.Java類和對象

2.1

  • 最簡單的類class A{}//沒有任何屬性和行爲
  • 對象 A obj = new A();
  • 類是定義,是規範,是“死‘的東西
  • 對象是實例,是類的一個實現,是一個具體的東西
  • 例如:
    • 類等價於一個土豆絲菜譜
    • 對象是根據類製作出的對象,等價於一盤土豆絲
      2.1.1

2.2

  • A obj1 = new A(); A obj2 = new A();
  • 以上有 2個對象,它們的類型都是 A,但是這是兩個不同的對象,在內存中有不同的放地址。因此,沒有兩個對象是完全一樣的。
    2.1.2

2.3

  • A obj = new A();
  • obj 可以看作是內存中一個對象 (包括若干個數據)的句柄
  • 在C/C++中, obj稱爲指針,在 Java 中稱爲 Reference(參考)
  • 對象賦值是Reference 賦值,而基本類型是直接值拷貝
  • 參看例子ReferenceTest.java 和ArgumentPassingTest.java ,來查看基本類型賦值和普通對象賦值的不同
    2.3.5
// MyNumber
class MyNumber
{
	int num = 5; 
}

// ReferenceTest 
public class ReferenceTest {

	public static void main(String[] args) {
		
		int num1 = 5;
		int num2 = num1;
		System.out.println("num1: " + num1 + ", num2: " + num2);
		num2 = 10;
		System.out.println("num1: " + num1 + ", num2: " + num2);
		
		
		MyNumber obj1 = new MyNumber();
		MyNumber obj2 = new MyNumber();
		System.out.println(obj1.num);
		System.out.println(obj2.num);
				System.out.println("======接下來輸出新值ֵ=====");

		obj2 = obj1;
		obj2.num = 10;
		
		System.out.println(obj1.num);
		System.out.println(obj2.num);

	}
}

2.3.12.3.22.3.3

// ArgumentPassingTest 
public class ArgumentPassingTest {

	public static void main(String[] args) {
		int a = 1, b = 2;
		swap(a,b);
		System.out.println("a is " + a + ", b is " + b);  //a=1, b=2
		
		MyNumber obj1 = new MyNumber();
		MyNumber obj2 = new MyNumber();
		obj2.num = 10;
		swap(obj1, obj2);
		System.out.println("obj1 is " + obj1.num + ", obj2 is " + obj2.num);  //  obj1  10,   obj2  5

	}
	// int型是直接賦值的
	public static void swap(int m, int n)
	{
		int s = m;
		m = n;
		n = s;
	}
	public static void swap(MyNumber obj3, MyNumber obj4)
	{
		int s = obj3.num;
		obj3.num = obj4.num;
		obj4.num = s;
	}

}

2.3.4
調用swap(a,b);在內存裏出現a和b,以及m和n,都是單獨的數字,m和n的交換不影響a和b

2.4

  • 產生一個對象, A obj = new A();
    • 99% 的情況是用new關鍵字,還有 1% 是用克隆和反射生成
  • new出對象後,內部屬性值默認是? 例子Initialization.java
    • short 0 int long 0L
    • boolean false
    • char ‘\u0000‘(’\u0000‘相當於一個空格)
    • byte 0
    • float 0.0f
    • double 0.0d

public class Initialization {
	
	boolean v1;
	byte v2;
	char v3;
	double v4;
	float v5;
	int  v6;
	long v7;
	short v8; 
	
	
	public static void main(String[] args) {
		Initialization obj = new Initialization();
		System.out.println("The initial value of boolean variable is " + obj.v1);
		System.out.println("The initial value of byte variable is " + obj.v2);
		System.out.println("The initial value of char variable is " + obj.v3);  //\u0000 space
		System.out.println("The initial value of double variable is " + obj.v4);
		System.out.println("The initial value of float variable is " + obj.v5);
		System.out.println("The initial value of int variable is " + obj.v6);
		System.out.println("The initial value of long variable is " + obj.v7);
		System.out.println("The initial value of short variable is " + obj.v8);
		
		int a;
		// System.out.println(a);  //error, a 沒有初始化

	}

}

2.4.1

2.5 總結

  • 類是規範,對象根據產生出的實例
  • 基本型別賦值是 拷貝賦值,對象賦值是reference賦值
  • 類成員變量有初值,函數臨時變量必須初始化

3.構造函數

3.1

  • 如何在對象產生時就給成員變量賦值呢
  • 答案就在構造函數裏,constructor function
public class A {
	int id;
	
	public A(int id2) {
		id = id2;
	}
}
  • A obj = new A(10);會調用構造函數

構造函數沒有返回值
public void A(int id2)不是構造函數,而實普通函數

3.2

  • Java構造函數的名稱必須和類名一樣,且沒有返回值
  • Java有構造函數,但是沒有析構函數
    • 構造函數是製造對象的過程,析構函數是清除對象的過程
  • 每個變量都是有生命週期的,它只能存儲在離它最近的一
    對{}中
    • 參看LifeCycleTest.java
public class LifeCycleTest {

	public static void main(String[] args) {
		int a=0;  // a 在main函數中都是active
		
		//i只能活在for循環中
		for(int i=0; i<5; i++) {
			int k = 0;
			k++;
		}
		
		if(a>0) {
			Object obj1 = new Object();  //obj1 只能在if分支中
			System.out.println("a is positive");
		} else {
			Object obj2 = new Object();  //obj2 只能else分支中
			System.out.println("a is non-positive");
		}
	}
}

每一個變量,都只能存活於離它最近的一對大括號當中

  • 當變量被創建時,變量將佔據內存;當變量消亡時,系統
    將回收內存

3.3

  • Java具有內存自動回收機制的,當變量退出其生命週期後,
    JVM會自動回收所分配的對象的內存。所以不需要析構函 數來釋放內存
  • 對象回收效率依賴於垃圾回收器GC(Garbage Collector),
    其回收算法關係到性能好壞,是JVM的研究熱點。

3.4

  • 每個Java類都必須有構造函數。
  • 如果沒有顯式定義構造函數,Java編譯器自動爲該
    類產生一個空的無形參構造函數。如果已經有了顯
    式的有參構造函數,編譯器就不會越俎代庖了。
    3.4.1在這裏插入圖片描述
  • 每個子類的構造函數的第一句話,都默認調用父類
    的無參數構造函數super(),除非子類的構造函數第
    一句話是super,而且super語句必須放在第一條,
    不會出現連續兩條super語句。(本條規則在後續繼
    承時會再提到)

3.5

  • 一個類可以有多個構造函數,只要形參列表不相同
    即可。

函數重載(overload),函數名相同,形參不同

  • 在new對象的時候,根據實參的不同,自動挑選相應
    的構造函數。如果實參形參匹配不上,將會報錯。
  • 查看例子ConstructorTest.java
class MyPairNumber
{
	int m;
	int n;
	public MyPairNumber()
	{
		m = 0;
		n = 0;
	}
	public MyPairNumber(int a)
	{
		m = a;
		n = 0;
	}
	public MyPairNumber(int a, int b)
	{
		m = a;
		n = b;
	}	
}
public class ConstructorTest {

	public static void main(String[] args) {
		MyPairNumber obj1 = new MyPairNumber();
		MyPairNumber obj2 = new MyPairNumber(5);
		MyPairNumber obj3 = new MyPairNumber(10,20);
		System.out.println("obj1 has " + obj1.m + "," + obj1.n);
		System.out.println("obj2 has " + obj2.m + "," + obj2.n);
		System.out.println("obj3 has " + obj3.m + "," + obj3.n);

		// A a = new A();  //error, A類中沒有無參數的構造函數
	}
}

多個class可以寫在一個.java文件中,但是最多隻能由一個類時public class,並且public class類的名字必須和.java的文件名相同
如果類由構造函數,編譯器不會自動增加無參的空的構造函數

3.6 總結

  • 構造函數是一個對象初始化的過程。
  • 一個類必須有構造函數,可以有多個構造函數。在new的
    時候根據實參和形參進行匹配。
  • Java只有構造函數,沒有析構函數。

4 信息隱藏和this

4.1 信息隱藏原則1

  • 面向對象有一個法則:信息隱藏
    • 類的成員屬性,是私有的private;
    • 類的方法是公有public的,通過方法修改成員屬性的值。
  • 打個比方:朋友再熟悉,也不會到他抽屜直接拿東西,而
    是通過他的公開接口來訪問、修改東西。
// InfoHiding 
class InfoHiding {
	private int id;

	public InfoHiding(int id2) {
		id = id2;
	}
	public int getId() {
		return id;
	}
	public void setId(int id2) {
		id = id2;
	}
}
// InfoHidingTest 
public class InfoHidingTest {
	public static void main(String[] args) {
		InfoHiding obj = new InfoHiding(100);
		obj.setId(200);
		System.out.println(obj.getId());
	}
}

信息隱藏:通過類的方法來間接訪問類的屬性,而不是直接訪問類的屬性

4.2 信息隱藏原則2

  • 類成員是私有private的
  • get和set方法是公有public的,統稱爲getter和setter
  • 外界對類成員的操作只能通過get和set方法
  • 可以用Java IDE快速生成
public class Person {
	private int height;
	private int weight;
	private int age;
	private String name;
	
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

4.3 this(1)

  • this負責指向本類中的成員變量
// InfoHiding
class InfoHiding {
	private int id;

	public InfoHiding(int id2) {
		id = id2;
	}
	public int getId() {
		return id;
	}
	public void setId(int id2) {
		id = id2;
	}
}

// InfoHiding2 
public class InfoHiding2 {
	private int id;
	
	public InfoHiding2(int id)
	{
		this.id = id;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
}

在這裏插入圖片描述在InfoHiding2 的構造函數裏,形參的優先級更高

4.4 this(2)

  • this負責指向本類中的成員方法
    • this.add(5,3); //調用本類的add方法, this可忽略
      在不影響歧義的情況下,this可以省略
  • this可以代替本類的構造函數
    • this(5); //調用本類的一個形參的構造函數
  • 參看ThisTest.java
// ThisTest 
public class ThisTest {

	public static void main(String[] args) {
		MyPairNumber obj = new MyPairNumber(5);
				
		System.out.println(obj.sum());
	}
}

// MyPairNumber 
public class MyPairNumber {
	private int m;
	private int n;
	public int getM() {
		return m;
	}
	public void setM(int m) {
		this.m = m;
	}
	public int getN() {
		return n;
	}
	public void setN(int n) {
		this.n = n;
	}	
	public MyPairNumber()	{
		this(0, 0);
	}	
	public MyPairNumber(int m)	{
		this(m, 0);
	}	
	public MyPairNumber(int m, int n)	{
		this.m = m;
		this.n= n;
	}	
	public int sum() {
		return this.add(m,n);  //return add(m,n);  also ok
	}
	public int add(int a, int b){
		return a+b;
	}	
}


this:指向本類中的成員變量;指向本類中的成員方法;可以當作構造函數使用

4.5 總結

  • 信息隱藏原則
    • 保護屬性信息
    • 公開行爲信息
  • this負責指向本類中的成員
  • this可以代替本類的構造函數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章