面向對象(Object Oriented)java
Java支持面向對象三大特性:封裝、繼承、多態。(抽象)
一、封裝(Encapsulation)
封裝:隱藏對象內部的複雜性,只對外公開簡單的接口。便於外界調用,從而提升系統的可擴展性、可維護性。一般有兩種訪問方式:set 設置,get 獲取。
程序設計要追求「高內聚,低耦合」
• 高內聚 :就是類的內部數據操做細節本身完成,不容許外部干涉;
• 低耦合 :僅暴露少許的方法給外部使用
封裝的具體優勢:
1. 提升代碼的安全性。
2. 提升代碼的複用性。
3. 「高內聚」:封裝細節,便於修改內部代碼,提升可維護性。
4. 「低耦合」:簡化外部調用,便於調用者使用,便於擴展和協做。
Java是使用「訪問控制符」來控制哪些細節須要封裝,Java中4種「訪問控制符」分別爲 private、default、protected、public,它們說明了面向對象的封裝性,使用修飾符儘量的讓訪問權限降到最低,從而提升安全性。
1. private 表示私有,只有本身類能訪問
2. default表示沒有修飾符修飾,只有同一個包的類能訪問
3. protected表示能夠被同一個包的類以及其餘包中的子類訪問
4. public表示能夠被該項目的全部包中的全部類訪問
編程
1 package com.test; 2 3 /** 4 * 封裝的應用 5 * 6 * @author Administrator 7 * 8 */ 9 public class EncapsulationTest { 10 public static void main(String[] args) { 11 Student student = new Student("小明", "男", 18, 60); 12 student.showInformation(); 13 14 Student student2 = new Student(); 15 student.setName("小紅"); 16 student.setGender("男"); 17 student.setAge(18); 18 student.setScore(60); 19 student.showInformation(); 20 21 } 22 23 } 24 25 // 建立學生類對象 26 class Student { 27 // 屬性設置私有性,對外提供getter.setter方法 28 private String name; 29 private String gender; 30 private int age; 31 private int score; 32 33 // 無參構造函數 34 public Student() { 35 } 36 37 // 有參構造函數 38 public Student(String name, String gender, int age, int score) { 39 super(); 40 this.name = name; 41 this.gender = gender; 42 this.age = age; 43 this.score = score; 44 } 45 46 // getter.setter方法 47 public String getName() { 48 return name; 49 } 50 51 public void setName(String name) { 52 this.name = name; 53 } 54 55 public String getGender() { 56 return gender; 57 } 58 59 public void setGender(String gender) { 60 this.gender = gender; 61 } 62 63 public int getAge() { 64 return age; 65 } 66 67 public void setAge(int age) { 68 this.age = age; 69 } 70 71 public int getScore() { 72 return score; 73 } 74 75 public void setScore(int score) { 76 this.score = score; 77 } 78 79 public void showInformation() { 80 System.out.println("Student [name=" + name + ", gender=" + gender + ", age=" + age + ", score=" + score + "]"); 81 } 82 83 }
關於類成員的權限的使用的基本原則:
1:類中的成員變量要求所有私有。若是其餘的類有訪問私有成員變量的需求,那麼統一的提供訪問器和修改器來提供訪問的功能。getter 和 setter
2:全部的類中的成員的訪問權限,要儘可能的小。越小越好。
3:若是某個類不想被實例化,那麼構造方法私有化。
類的訪問權限:在class 關鍵字 前面 添加的 類的被訪問的權限。
類的訪問權限 就 2個
1:public:工程級別的訪問權限,全部的本工程的類,均可以訪問使用public 修飾的類。
2:默認的:本包其餘的類。
二、構造器
用於建立對象並初始化對象屬性的方法,叫「構造方法」,也叫「構造器」;構造器在類中定義。
1)構造器的名稱必須與類名同名,包括大小寫。
2)構造器沒有返回值,但也不能寫 void,也不能寫 return。
3)構造器的參數:通常是初始化對象的前提條件。
4)用 new 調用!且對象一創建,構造器就運行且僅運行一次。通常方法可被調用屢次。
5)若是類沒有聲明(定義)任何的構造器,Java 編譯器會自動插入默認構造器!
6)默認構造是無參數,方法體是空的構造器,且默認構造器的訪問權限隨着所屬類的訪問權限變化而變化。如,若類被 public 修飾,則默認構造器也帶 public 修飾符。
7)默認構造器是看不到的,一旦自定義構造器則默認構造器就沒有了,本身寫的叫自定義構造器,即使本身寫的是空參數的構造器,也是自定義構造器,而不是默認構造器。
8)若是類聲明瞭構造器,Java 編譯器將再也不提供默認構造器。若沒手動寫出無參構造器,但卻調用了無參構造器,將會報錯!
9)構造器是能夠重載的,重載的目的是爲了使用方便,重載規則與方法重載規則相同。
10)構造器是不能繼承的!雖然說是叫構造方法,但實際上它不是常說的通常方法。
11)子類繼承父類,那麼子類型構造器默認調用父類型的無參數構造器。
12)子類構造器必定要調用父類構造器,若是父類沒有無參數構造器,則必須使用super(有參數的),來調用父類有參的構造器。
爲何子類必定要訪問父類的構造器?
由於父類中的數據子類能夠直接獲取。因此子類對象在創建時,須要先查看父類是如何對這些數據進行初始化的,因此子類在對象初始化時,要先訪問一下父類中的構造器。總之,子類中至少會有一個構造器會訪問父類中的構造器,且子類中每個構造函數內的第一行都有一句隱式 super()。
三、super()、super.和 this()、this.
1)this:在運行期間,哪一個對象在調用 this 所在的方法,this 就表明哪一個對象,隱含綁定到當前「這個對象」。
2)super():調用父類無參構造器,必定在子類構造器第一行使用!若是沒有則是默認存在 super()!這是 Java 默認添加的 super()。
3)super.是訪問父類對象,父類對象的引用,與 this.用法一致
4)this():調用本類的其餘構造器,按照參數調用構造器,必須在構造器中使用,必須在第一行使用,this() 與 super() 互斥,不能同時存在
5)this.是訪問當前對象,本類對象的引用,在能區別實例變量和局部變量時,this 可省略,不然必定不能省!
6)若是子父類中出現非私有的同名成員變量時,子類要訪問本類中的變量用 this. ;子類要訪問父類中的同名變量用 super.安全
1 package com.boom.test; 2 public class SuperTest { 3 public static void main(String[] args) { 4 ChildrenClass childrenClas = new ChildrenClass(); 5 childrenClas.show(); 6 } 7 8 } 9 //定義個父類 10 class FatherClass{ 11 public int value; 12 public void show(){ 13 value = 100; 14 System.out.println("FatherClass = " + value);//FatherClass = 100 15 } 16 } 17 //子類繼承父類 18 class ChildrenClass extends FatherClass{ 19 private int value; 20 21 @Override 22 public void show() { 23 super.show();// 調用父類的show方法 24 value = 200; 25 System.out.println("ChildrenClass = " + value);//ChildrenClass = 200 26 System.out.println("value = " + value);//value = 200 27 System.out.println("value = " + super.value);// 訪問父類value = 100 28 } 29 }
四、重載和重寫
1)重載:方法名同樣,參數列表不一樣的方法構成重載的方法(多態的一種形式)
①調用方法:根據參數列表和方法名調用不一樣方法。
②與返回值類型無關。
③重載遵循所謂「編譯期綁定」,即在編譯時根據 參數變量的類型判斷應調用哪一個方法。
2)重寫:經過類的繼承關係,因爲父類中的方法不能知足新的要求,所以須要在子類中修改從父類中繼承的方法叫重寫(覆蓋)。
①方法名、參數列表、返回值類型與父類的如出一轍,但方法的實現不一樣。若方法名、參數列表相同,但返回值類型不一樣會有變異錯誤!若方法名、返回值類型相同,參數列表不一樣,則不叫重寫了。
②子類若繼承了抽象類或實現了接口,則必須重寫所有的抽象方法。若沒有所有實現抽象方法,則子類還是一個抽象類!
③子類重寫抽象類中的抽象方法或接口的方法時,訪問權限修飾符必定要 >= 被重寫的抽象方法的訪問權限修飾符!
如何重寫?
一、訪問權限: 子類重寫的方法的訪問權限必須 >= 父類被重寫的方法的權限
二、方法的返回類型:
1) 返回類型是void ,那麼必須都是 void。
2) 返回類型 是基本數據類型的話,那麼子類和父類的重寫的方法必需要一致。
3) 返回類型 是引用數據類型的話,子類重寫的方法的返回類型 能夠是父類返回類型的 子類型。
三、方法名字必須一致。
四、參數列表:必須一致,若是不一致,那就是重載了。
五、方法的拋出的異常類型:子類重寫方法拋出的異常的類型能夠是 父類中被重寫方法拋出的異常的類型的子類型jvm
1 package com.boom.test; 2 /** 3 * 方法的重寫 Override 4 * @author Administrator 5 * 6 */ 7 public class OverrideTest { 8 9 public static void main(String[] args) { 10 Cat cat = new Cat(); 11 cat.sound(); 12 } 13 14 } 15 class Animal{ 16 void sound(){ 17 System.out.println("動物發出聲音"); 18 } 19 } 20 class Cat extends Animal{ 21 @Override 22 void sound() { 23 System.out.println("咱們一塊兒學貓叫,一塊兒 ~~喵喵喵~~"); 24 } 25 }
靜態方法是否能夠重寫??
不能夠,靜態方法能夠被子類繼承,不能被子類重寫。
對象的比較 == 和 equals
== :比較兩基本類型變量的值是否相等,比較兩個引用類型的值即內存地址是否相等,便是否指向同一對象。
equals():兩對象的內容是否一致
由於equals 源碼也是使用 == 進行判斷,通常都須要重寫equals方法
ide
重載重載的總結:
五、繼承(Extends)
函數
繼承:子類對象中包含了全部的父類實例成員屬性,而且子類擁有父類的成員並能夠在子類中直接訪問父類中的成員的過程
語法:
class 繼承類名 extends 被繼承的類名{
//類體
}
被繼承的類名:父類、基類、超類
繼承類名:子類、衍生類、派生類
extends:java 關鍵字。擴展、繼承。
兩層意思:繼承、擴展
繼承:子類擁有父類的功能。
擴展:子類中定義了新的功能和屬性、子類中重寫了父類的方法。
繼承優缺點:1, 提升代碼複用性;
2, 讓類與類之間產生關係,給多態提供前提。
缺:爲了讓子類繼承父類的某些成員,那麼會在必定程度上打破封裝
Java中支持單繼承[單繼承:一個子類之只能有一個直接父類],不直接支持多繼承,但對C++中的多繼承機制進行改良。
多個類能夠繼承一個父類:
class A{ }
class B extends A{ }
class C extends A{ }
多重( 多層 )繼承:一個類只能有一個直接的父類,可是能夠有多個間接的父類
class A{ }
class B extends A{ }
class C extends B{ }
多繼承:一個子類能夠有多個直接父類(Java中不容許,進行改良)在Java中經過「多實現」方式體現
class A{ }
class B{ }
class C extends A,B{ }
多繼承存在問題:不直接支持,多個父類中有相同的成員,會產生調用的不肯定性。
繼承體系:java 的整個類的體系結構,是一個單根的系統。根就是 Object 類
在java 體系中,任何一個類(jdk提供的 + 自定義的),都直接的或者間接的繼承了 Object 類。 除了Object 類自身。若是一個類沒有顯式的直接繼承任何一個類,那麼該類默認繼承 Object(隱式繼承)。
繼承的疑問?
一、是先有子類,仍是先有父類?
答:先有子類的。先定義了子類,而後將子類中公有的部分抽取出來造成的父類。
二、哪一個類型更大?表示的對象的範圍更大?
答:父類類型描述的對象的範圍更大、子類描述的類型更加的具體,功能更強大。子類中的功能和屬性每每更多一些
三、子類繼承父類的成員變量和成員方法,但不繼承父類的構造方法,但不見得能夠直接訪問(好比,父類私有的屬性和方法)
六、static關鍵字
靜態的,只能在類內部使用,能夠修飾:屬性,方法,內部類。在類加載期間初始化,存在方法區中。
1)靜態成員隨着類的加載而加載,加載於方法區中,且優先於對象存在。
2)靜態修飾的成員:屬於類級別的成員,是全體類實例(全部對象)所共享。
3)靜態屬性:只有一份(而實例變量是每一個對象有一份),全體實例共享,相似於全局變量
4)使用類名訪問靜態變量,以及類名直接調用方法,不須要建立對象。
5)靜態方法只能訪問靜態成員(靜態屬性和靜態方法),非靜態方法既可訪問靜態,也可訪問非靜態。
6)靜態方法中沒有隱含參數 this,所以不能訪問當前對象資源。也不能定義 this 和 super關鍵字,由於靜態優於對象先存在。
7)非靜態方法省略的是 this,靜態方法省略的是類名(在同一類中),即直接使用屬性和方法。
靜態代碼塊與代碼塊
靜態代碼塊:在類加載的時候,執行,而且僅執行一次。且優先於主函數,用於給類初始化。對類的靜態成員變量初始化,並執行靜態代碼塊。
做用:若是某些代碼但願僅執行一次,能夠在這裏面進行,還有對靜態成員變量初始化。
代碼塊(構造代碼塊):給全部對象進行統一初始化,且優先於構造器執行;而構造器是給對應的對象進行初始化。
oop
static關鍵字使用注意點:
1, 靜態方法只能訪問靜態成員;
2, 靜態方法中不可使用this或者super關鍵字(this和super是賴於某個對象的);
3, 主函數是靜態的 (由jvm 負責調用執行。不須要建立所在類的對象就能夠直接運行)
七、final關鍵字(最終的,能夠修飾:類、方法、變量(成員變量和局部變量)
1)final 修飾的類:不能再繼承。
2)final 修飾的方法:不能再重寫。
3)final 的方法和類,阻止了動態代理模式!動態代理模式普遍的應用在: Spring 、Hibernate 、Struts2
4)企業編程規範:不容許使用 final 的方法和類!
5)final 的變量:final 變量只能初始化一次(賦值一次,且方法中不能有給 final 變量賦值的語句!由於方法可被調用屢次!),不能再修改!也可在方法參數列表添加 final。
6)static final 共同修飾的叫常量,常量:public static final double PI = 3.14; PI 是直接數的代名詞,是名字。字面量(==直接量):直接寫出數值 3.1415926535897 宏觀說:字 面量和常量都稱爲常量!
八、多態(polymorphism)
1)多態指的是同一個方法調用,因爲對象不一樣可能會有不一樣的行爲。
2)多態的存在要有3個必要條件:繼承,方法重寫,父類引用指向子類對象。
3)父類引用指向子類對象後,用該父類引用調用子類重寫的方法,此時多態就出現了。
多態的優缺點:優勢:提升程序可擴展性和後期可維護性
缺點:經過父類引用操做子類對象時,只能使用父類中已有的方法,不能操做子類特有方法
多態的應用:1:父類類型做爲參數,傳遞的是子類對象。
2:父類類型做爲方法的返回類型,返回的是子類對象。ui
1 package boom.oop02; 2 3 public class PolymTest { 4 5 public static void main(String[] args) { 6 // 建立動物類對象 7 Animal animal = new Animal(); 8 AnimalSonud(animal);//調用動物本身 9 10 Dog dog = new Dog(); 11 AnimalSonud(dog); 12 AnimalSonud(new Cat()); 13 14 AnimalSonud(new Trigger()); 15 16 } 17 // 定義動物發出聲音的方法,把動物類傳參進來 18 static void AnimalSonud(Animal animal){ 19 animal.sound(); 20 } 21 } 22 // 建立動物類 父類 23 class Animal{ 24 public void sound(){ 25 System.out.println("動物發出了聲音……"); 26 } 27 } 28 29 // 貓繼承了動物類 30 class Cat extends Animal{ 31 public void sound() { 32 System.out.println("貓發出了喵喵喵……"); 33 } 34 } 35 36 class Dog extends Animal{ 37 public void sound() { 38 System.out.println("旺財發出了旺旺……"); 39 } 40 } 41 42 class Trigger extends Animal{ 43 public void sound() { 44 System.out.println("虎嘯震山谷……"); 45 } 46 }
1 package com.test; 2 /** 3 * 多態的綜合應用:人去演奏樂器,不一樣的樂器發出不一樣的聲響 4 * 大鼓Drum,吉他Guitar,鋼琴Piano,小號Trumpet 5 * @author Administrator 6 * 7 */ 8 public class Code { 9 10 public static void main(String[] args) { 11 12 Person person = new Person(); 13 14 Drum drum = new Drum(1000, "戰鼓"); 15 person.play(drum); 16 Piano piano = new Piano(2000, "鋼琴"); 17 person.play(piano); 18 Guitar guitar = new Guitar(2000, "吉他"); 19 person.play(guitar); 20 Trumpet trumpet = new Trumpet(2000, "軍號"); 21 person.play(trumpet); 22 23 24 // Instrument instrument = new Drum(12000, "fas"); 25 // instrument.sound(); 26 // 27 28 29 } 30 // void paly(Instrument instrument){ 31 // instrument.sound(); 32 // } 33 // 34 } 35 36 // 定義person類 37 class Person{ 38 // 定義人具備演奏樂器的方法 39 void play(Instrument instrument){ 40 instrument.sound(); 41 } 42 } 43 44 45 // 定義樂器類 46 class Instrument{ 47 // 樂器的屬性:單價 樂器名 48 private int price; 49 private String name; 50 // 定義無參有參的構造方法,進行樂器的初始化 51 public Instrument() { 52 } 53 public Instrument(int price, String name) { 54 super(); 55 this.price = price; 56 this.name = name; 57 } 58 59 // getter setter方法 60 public int getPrice() { 61 return price; 62 } 63 public void setPrice(int price) { 64 this.price = price; 65 } 66 public String getName() { 67 return name; 68 } 69 public void setName(String name) { 70 this.name = name; 71 } 72 // 定義樂器類發出聲音的方法 73 void sound(){ 74 // 空實現 75 } 76 } 77 78 class Drum extends Instrument{ 79 80 public Drum(int price, String name) { 81 super(price, name); 82 } 83 84 @Override 85 void sound() { 86 System.out.println(getName() + "\t被用力的敲擊了幾下,發出了 ~~~~咚咚咚~~~的聲音!"); 87 } 88 89 } 90 91 class Piano extends Instrument{ 92 public Piano(int price, String name) { 93 super(price, name); 94 } 95 96 @Override 97 void sound() { 98 System.out.println(getName() + "\t被手指撥弄了幾下,發出了 ~~~叮噹叮叮的~~~的聲音!"); 99 } 100 } 101 102 class Trumpet extends Instrument{ 103 104 public Trumpet(int price, String name) { 105 super(price, name); 106 } 107 108 @Override 109 void sound() { 110 System.out.println(getName() + "\t被吹了幾下,發出了 ~~~~嘟嘟嘟~~~的聲音!"); 111 } 112 } 113 114 class Guitar extends Instrument{ 115 public Guitar(int price, String name) { 116 super(price, name); 117 } 118 119 @Override 120 void sound() { 121 System.out.println(getName() + "\t被彈奏了幾下,發出了 ~~~~噹噹噹~~~的聲音!"); 122 } 123 }
多態的轉型:自動轉型 強制轉型
自動向上類型轉換:子類對象當父類類型來使用。自動的必定是安全的。父類有的功能,子類必定有。
當咱們須要使用子類中特有的方法的時候,須要強制向下
強制向下類型轉換。這種轉換是強制的,不是安全的。這種轉換隻有被轉換的對象的確是須要轉換的類型才能夠轉換成功
注意:只有對象的實際類型是你強制轉換的類型的時候,才能夠轉換成功。否則運行期會拋出錯誤
this
instanceof:關鍵字、運算符。左邊操做數的對象的類型 和 右邊操做數的類型 必須存在繼承關係纔可使用 instanceof 進行判斷
二元運算符:做用:用來判斷 一個對象 是不是某種類型的實例的。
用法:操做數1 instanceof 操做數2
操做數1:必須是一個對象
操做數2:必須是一種類型
返回 boolean
若是 操做數1 對象 是 操做數2 類型的實例 返回 true 不然返回 false。
spa