利用抽象數據類型將數據和基於數據的操做封裝在一塊兒,使其構成一個不可分割的獨立實體。 數據被保護在抽象數據類型的內部,儘量地隱藏內部的細節, 只保留一些對外接口使之與外部發生聯繫。用戶無需知道對象內部的細節, 但能夠經過對象對外提供的接口來訪問該對象。程序員
注意:局部變量名能夠和成員變量名同樣,在方法中使用的時候,採用就近原則。bash
以Student類爲例:ide
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();複製代碼
具體步驟:函數
封裝:一個標準的手機類的代碼及測試
手機類
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()+"的手機");
}
}複製代碼
多個手機對象的內存簡圖:測試
執行順序:優化
靜態代碼塊---構造代碼塊---構造方法ui
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();
}
}複製代碼
輸出結果:this
1000
100
10複製代碼
繼承實現了 IS-A 關係,例如 Cat 和 Animal 就是一種 IS-A 關係,所以 Cat 能夠繼承自 Animal,從而得到 Animal 非 private 的屬性和方法。spa
繼承應該遵循里氏替換原則,子類對象必須可以替換掉全部父類對象。
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複製代碼