利用抽象數據類型將數據和基於數據的操做封裝在一塊兒,使其構成一個不可分割的獨立實體。 數據被保護在抽象數據類型的內部,儘量地隱藏內部的細節, 只保留一些對外接口使之與外部發生聯繫。用戶無需知道對象內部的細節, 但能夠經過對象對外提供的接口來訪問該對象。程序員
注意:局部變量名能夠和成員變量名同樣,在方法中使用的時候,採用就近原則。併發
以Student類爲例:分佈式
public class Student { private String name; private int age; public Student() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } Student s=new Student();
具體步驟:ide
封裝:一個標準的手機類的代碼及測試
手機類
public class SmartPhone { private String brand; private double price; private String color; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void call(String name){ System.out.println("打電話給"+name); } public void sendMessage(String name){ System.out.println("給"+name+"發短信"); } public void playGame(){ System.out.println("玩遊戲"); } }
手機測試類1
public class SmartPhoneDemo { public static void main(String[] args) { SmartPhone sp=new SmartPhone(); sp.setBrand("IPhone"); sp.setPrice(6666); sp.setColor("白色"); System.out.println("使用"+sp.getBrand()+"牌、售價爲"+sp.getPrice()+"元的" +sp.getColor()+"的手機"); sp.call("Jobs"); sp.sendMessage("Kuke"); sp.playGame(); } }
一個手機對象的內存簡圖:函數
手機測試類2
public class SmartPhoneDemo2 { public static void main(String[] args) { SmartPhone sp=new SmartPhone(); sp.setBrand("IPhone"); sp.setPrice(6666); sp.setColor("白色"); System.out.println("使用"+sp.getBrand()+"牌、售價爲"+sp.getPrice()+"元的" +sp.getColor()+"的手機"); sp.call("Jobs"); sp.sendMessage("Kuke"); sp.playGame(); SmartPhone sp2=new SmartPhone(); sp2.setBrand("小米"); sp2.setPrice(1000); sp2.setColor("黑色"); SmartPhone sp3=sp; sp.setPrice(3555); System.out.println("使用"+sp.getBrand()+"牌、售價爲"+sp.getPrice()+"元的" +sp.getColor()+"的手機"); } }
多個手機對象的內存簡圖:高併發
執行順序:性能
靜態代碼塊---構造代碼塊---構造方法測試
public class CodeBlock { //構造方法 CodeBlock(){ int a=10; System.out.println(a); } //構造代碼塊 { int a=100; System.out.println(a); } //靜態代碼塊 static { int a=1000; System.out.println(a); } public static void main(String[] args) { CodeBlock codeBlock=new CodeBlock(); } }
輸出結果:優化
1000 100 10
繼承實現了 IS-A 關係,例如 Cat 和 Animal 就是一種 IS-A 關係,所以 Cat 能夠繼承自 Animal,從而得到 Animal 非 private 的屬性和方法。this
繼承應該遵循里氏替換原則,子類對象必須可以替換掉全部父類對象。
Cat 能夠當作 Animal 來使用,也就是說可使用 Animal 引用 Cat 對象。父類引用指向子類對象稱爲 向上轉型 。
Animal animal = new Cat();
在子類方法中的查找順序:
在子類方法的局部範圍找,有就使用
在子類的成員範圍找,有就使用
在父類的成員範圍找,有就使用
若是還找不到,就報錯
緣由:由於子類會繼承父類中的數據,可能還會使用父類的數據。因此,子類初始化以前, 必定要完成父類數據的初始化。
方式一:子類經過super去顯示調用父類其餘的帶參的構造方法
方式二:子類經過this去調用本類的其餘構造方法 (子類必定要有一個去訪問父類的構造方法,不然父類數據就沒有初始化)
/** * 1. 子類中全部的構造方法默認會都會訪問父類中空參數的構造方法 * 2. 每個子類的構造方法第一條語句默認是:super() */ class Father{ public Father() { System.out.println("Father的無參構造函數"); } } class Son extends Father{ public Son() { //super(); System.out.println("Son的無參構造函數"); } public Son(String name) { //super(); System.out.println("Son的帶參構造函數"); } } public class InheritanceDemo { public static void main(String[] args) { //使用無參構造函數初始化 Son son=new Son(); System.out.println("==========="); //使用帶參構造函數初始化 Son son2=new Son("林青霞"); } }
輸出結果:
Father的無參構造函數 Son的無參構造函數 =========== Father的無參構造函數 Son的帶參構造函數 /** * 3. 若是父類中沒有無參構造方法,該怎麼辦呢? 方式一:子類經過super去顯示調用父類其餘的帶參的構造方法 方式二:子類經過this去調用本類的其餘構造方法 (子類必定要有一個去訪問父類的構造方法,不然父類數據就沒有初始化) */ class Parent{ public Parent(String name){ System.out.println("Parent的帶參構造函數"); } } class Child extends Parent{ public Child() { //子類經過super去顯示調用父類其餘的帶參的構造方法 super("林青霞"); System.out.println("Child的無參構造函數"); } public Child(String name) { //方式一:子類經過super去顯示調用父類其餘的帶參的構造方法 //super(name); //方式二:子類經過this去調用本類的其餘構造方法 this();//嗲用Child()的無參構造函數 System.out.println("Child的帶參構造函數"); } } public class InheritanceDemo2 { public static void main(String[] args) { Child c = new Child(); System.out.println("=============="); Child c2 = new Child("林青霞"); } }
輸出結果:
Parent的帶參構造函數
Child的無參構造函數
==============
Parent的帶參構造函數
Child的無參構造函數
Child的帶參構造函數
一個類的成員變量的初始化:
子類的初始化(分層初始化)
class X{ Y b=new Y(); //顯式初始化 X(){ System.out.println("X"); } } class Y{ Y(){ System.out.println("Y"); } } public class Z extends X{ Y y=new Y(); public Z() { super();//子類的初始化(分層初始化):先進行父類的初始化,而後再進行子類的初始化。 System.out.println("Z"); } public static void main(String[] args) { new Z(); } }
輸出結果:
Y
X
Y
Z
重寫(Override):子類和父類中出現瞭如出一轍的方法聲明
注意:
final關鍵字是最終的意思,能夠修飾類,修飾變量,修飾成員方法
注意:
在方法內部,該變量不能夠被改變
在方法聲明上,分爲基本類型和引用類型的狀況
(1)基本類型:是值不能變
(2)引用類型:是地址不能變,可是該對象的堆內存中的值是能夠改變的
在對象構造完畢前便可(非靜態常量),被final修飾的變量只能賦值一次。
繼承:一個標準的動物類、貓類、狗類的代碼及測試
動物類
class Animal{ private String name; private int age; private String color; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void eat(){ System.out.print("吃什麼東西?"); } }
貓類
class Cat extends Animal{ @Override public void eat() { super.eat(); System.out.println("貓糧"); } public void play(){ System.out.println("小貓在玩耍"); } }
狗類
class Dog extends Animal{ @Override public void eat() { super.eat(); System.out.println("狗糧"); } public void bark(){ System.out.println("小狗汪汪叫"); } }
測試
public class AnimalDemo { public static void main(String[] args) { Dog dog=new Dog(); dog.setName("旺財"); dog.setAge(12); dog.setColor("黃色"); System.out.println(dog.getName()+"\t"+dog.getAge()+"\t"+dog.getColor()); dog.eat(); dog.bark(); Cat cat=new Cat(); cat.setName("湯姆"); cat.setAge(12); cat.setColor("藍色"); System.out.println(cat.getName()+"\t"+cat.getAge()+"\t"+cat.getColor()); cat.eat(); cat.play(); } }
某一個事物,在不一樣時刻表現出來的不一樣狀態。 具體來說,就是調用同一方法,會執行不一樣的功能。
實際生活:水在不一樣時刻的狀態。
多態分爲編譯時多態和運行時多態:
好處
提升了代碼的維護性(由繼承保證)
提升了程序的擴展性(由多態保證)
弊端
不能訪問子類特有功能(特有方法)
如何訪問子類中的特有功能?
/** * 對象間的轉型問題: 向上轉型: Parent f = new Child(); 向下轉型: Child z = (Child)f; //要求該f必須是可以轉換爲Zi的。(父到子) */ class Parent { public void show() { System.out.println("show fu"); } } class Child extends Parent { public void show() { System.out.println("show zi"); } public void method() { System.out.println("method zi"); } } public class PolymorphismDemo { public static void main(String[] args) { Parent fu=new Child(); fu.show(); //fu.method();//不能訪問子類特有功能(特有方法) Child zi=(Child)fu; //向下轉型 zi.show(); zi.method(); } }
輸出結果:
show zi show zi method zi class Animal { public void eat(){} } class Dog extends Animal { public void eat() {} public void lookDoor() { } } class Cat extends Animal { public void eat() { } public void playGame() { } } public class PolymorphismDemo3 { public static void main(String[] args) { //內存中的是狗 Animal a = new Dog(); Dog d = (Dog)a; //內存中是貓 a = new Cat(); Cat c = (Cat)a; //內存中是貓 Dog dd = (Dog)a; //ClassCastException } }
多態中對象內存圖
/** * 多態中的成員訪問特色: A:成員變量 編譯看左邊,運行看左邊。 B:構造方法 建立子類對象的時候,訪問父類的構造方法,對父類的數據進行初始化。 C:成員方法 編譯看左邊,運行看右邊。( 因爲成員方法存在方法重寫,因此它運行看右邊。) D:靜態方法 編譯看左邊,運行看左邊。(靜態和類相關,算不上重寫,因此,訪問仍是左邊的) */ class Fu{ public int num=100; public void show(){ System.out.println("show function"); } public static void function(){ System.out.println("function Fu"); } } class Zi extends Fu { public int num = 1000; public int num2 = 200; @Override public void show() { System.out.println("show Zi"); } public void method() { System.out.println("method zi"); } public static void function() { System.out.println("function Zi"); } } public class PolymorphismDemo2 { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num); //System.out.println(f.num2); f.show(); //找不到符號 //f.method(); f.function(); } }
輸出結果:
100 show Zi function Fu
免費Java高級資料須要本身領取,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分佈式等教程,一共30G。
傳送門:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q