Java的三大特性--封裝、繼承、多型
Java的三大特性
一、封裝
public :公共的。 public修飾的成員變數或者方法任何人都可以直接訪問。
private : 私有的。private修飾的成員變數或者方法只能在本類中進行直接訪問。
1.封裝的步驟
①使用private修飾需要被封裝的屬性。
②提供一個公共的方法設定或者獲取該私有的成員屬性。
命名規範:
set屬性名();
get屬性名();
注意:封裝不一定要提供get和set方法,具體是要根據需求而定的。
2.規範
在現實開發中一般實體類的所有成員屬性(成員變數)都要封裝起來。
實體類:實體類就是用於描述一類 事物的就稱作為實體類。
class Member{ publicString name; //名字 private String sex; //性別 publicint salary; //薪水 //定義一個公共的方法設定sex屬性 public void setSex(String s){ if (s.equals("男")||s.equals("女")){ //注意: 如果比較兩個字串的內容是否一致,不要使用==比較, 使用equals方法。 sex = s; }else{ //預設是男 sex = "男"; } } //定義一個公共的方法獲取sex屬性 public String getSex(){ return sex; } //聊天 public void talk(){ System.out.println(name+"聊得非常開心"); } } class Demo{ public static void main(String[] args) { Member m = new Member(); m.name="小紅"; m.setSex("女"); m.salary= 5000; System.out.println("姓名:"+ m.name+" 性別:"+ m.getSex()+" 薪水:"+ m.salary); } }
例項:描述一個計算器類,計算器具備運算元1,運算元2 、操作符三個公共的屬性
,還具備計算的功能行為。 不能直接對運算元1,運算元2,運算子這些屬性進行直接 的賦值,要封裝起來。
//計算器類 class Calculator{ private int num1; //運算元1 private int num2;//運算元2 private char option ; //運算子 //提供公共的方法設定屬性值.... public void initCalculator(int n1 , int n2 , char o){ num1 = n1; num2 = n2; if(o=='+'||o=='-'||o=='*'||o=='/'){ option = o; }else{ option = '+'; } } //計算的功能 public void calculate(){ switch(option){ case '+': System.out.println("做加法運算,結果是:"+(num1+num2)); break; case '-': System.out.println("做減法運算,結果是:"+(num1-num2)); break; case '*': System.out.println("做乘法運算,結果是:"+(num1*num2)); break; case '/': System.out.println("做除法運算,結果是:"+(num1/num2)); break; } } }
3.封裝的好處
- 提高資料的安全性。
- 操作簡單。
- 隱藏了實現。
二、繼承
在現實生活中事物與事物之間存在的兩種關係:
- 動物和貓 整體與部分的關係has a
- 程式員和人 繼承的關係 is a
繼承:使用關鍵字extends。
語法格式:
class 類名1 extends 類名2{ }
繼承要注意的事項:
- 千萬不要為了減少重複程式碼而去繼承,只有真正存在著繼承關係的時候才去繼承。
- 父類私有的成員不能被繼承。
- 父類的建構函式不能被繼承。
- 建立子類物件時預設會先呼叫父類無參的建構函式。
//人類 class Person{ String name; private int age; publicPerson(String name){ this.name = name; } public Person(){ System.out.println("Person類的構造方法被呼叫了...."); } public void eat(){ System.out.println(name+"在吃飯..."); } } //學生類 class Student extends Person {// Student 就稱作為Person類的子類, Person類就稱作為Student的父類(超類、基類) int num; //學號 public Student(){ System.out.println("Student類的構造方法被呼叫了...."); } public void study(){ System.out.println(name+"good good study , day day up"); } } class Demo7 { public static void main(String[] args) { Student s = new Student(); /* s.name = "小紅"; System.out.println("名字:"+ s.name); s.eat(); */ } }
建立子類物件時預設會先呼叫父類無參的建構函式的原因:
呼叫父類的構造方法是可以初始化從父類繼承下去的屬性的。
class Parent{ int x = 10; String name; public Parent(String name){ this.name = name; System.out.println("父類帶參的構造方法"); } public Parent(){ System.out.println("父類無參的構造方法"); } } class Child extends Parent{ int x = 20; public Child(String name){ super(name); //指定呼叫父類一個引數的建構函式。 } public void print(){ System.out.println("x1 = "+ x); } } class Demo { public static void main(String[] args) { Child c = new Child("大頭兒子"); System.out.println("name= "+c.name); } }
super關鍵字
super關鍵字代表了父類空間的引用。
1.super關鍵字的作用:
- 子父類存在著同名的成員時,在子類中預設是訪問子類的成員,可以通過super關鍵字指定訪問父類的成員。
- 建立子類物件時,預設會先呼叫父類無參的構造方法,可以通過super關鍵字指定呼叫父類的構造方法。
2.super關鍵字呼叫父類構造方法要注意的事項:
- 如果在子類的構造方法上沒有指定呼叫父類的構造方法,那麼java編譯器會在子類的構造方法上面加上super()語句。
- super關鍵字呼叫父類的建構函式時,該語句必須要是子類建構函式中的第一個語句。
- super與this關鍵字不能同時出現在同一個建構函式中呼叫其他的建構函式。因為兩個語句都需要第一個語句。
3.super關鍵字與this關鍵字的區別:
①代表的事物不一致。
- super關鍵字代表的是父類空間的引用。
- this關鍵字代表的是所屬函式的呼叫者物件。
②使用前提不一致。
- super關鍵字必須要有繼承關係才能使用。
- this關鍵字不需要存在繼承關係也可使用。
③呼叫建構函式的區別:
- super關鍵字是呼叫父類的建構函式。
- this關鍵字是呼叫本類的建構函式。
demo:
class Parent{ int x = 10; String name; public Parent(){ System.out.println("父類無參的構造方法.."); } public Parent(String name){ this.name = name; System.out.println("父類帶參的構造方法.."); } public void eat(){ System.out.println("爸爸做飯"); } } class Child extends Parent{ int x = 20; int num; public Child(String name,int num){ super(name); //指定呼叫了父類帶參的構造方法... this(); // 呼叫本類無參構造方法.. //super(); //指定呼叫了父類無參構造方法。。。 System.out.println("子類帶參的構造方法"); } public Child(){ System.out.println("子類無參的構造方法"); } public void print(){ System.out.println("x = " +super.x); } public void eat(){ System.out.println("兒子吃飯"); } } class Demo9 { public static void main(String[] args) { Child c = new Child("小紅"); } }
方法的重寫
方法重寫的前提:必須要存在繼承的關係。
方法的重寫:子父類出了同名的函式,這個我們就稱作為方法的重寫。
適用場景:父類的功能無法滿足子類的需求時。
注意事項:
1.方法重寫時,方法名與形參列表必須一致。
2.方法重寫時,子類的許可權修飾符必須要大於或者等於父類的許可權修飾符。
3.方法重寫時,子類的返回值型別必須要小於或者 等於父類的返回值型別。
4.方法重寫時,子類丟擲的異常型別要小於或者等於父類丟擲的異常型別。
class Animal{//大的資料型別 } class Fish extends Animal{//Fish 小的資料型別。 } class Parent{ String name; public Parent(String name){ this.name = name; } public Animal eat() throws RuntimeException { System.out.println(name+"做飯"); return new Animal(); } } class Child extends Parent{ String num; public Child(String name){ super(name);//指定呼叫父類帶參的構造方法 } //重寫父類的eat方法 public Animal eat() throws Exception{ System.out.println("喝湯"); System.out.println("吃肉"); System.out.println("吃青菜"); return new Animal(); } } class Demo{ public static void main(String[] args) { Child c = new Child("大頭兒子"); c.eat(); } }
方法的過載
方法的過載:在一個類中 存在兩個或者兩個 以上的同名函式,稱作為方法過載。
方法過載的要求:
- 函式名要一致。
- 形參列表不一致(形參的個數或形參 的型別不一致)
- 與返回值型別無關。
instanceof關鍵字
instanceof關鍵字的使用前提:判斷的物件與指定的類別必須要存在繼承或者實現的關係。
instanceof關鍵字的使用格式:
物件instanceof 類別
instanceof關鍵字的作用:判斷一個物件是否屬於指定的類別。
一般我們做強制型別轉換之前都會使用該關鍵字先判斷一把,然後再進行轉換的。
class Animal{ String name; String color; public Animal(String name, String color){ this.name = name; this.color = color; } } //狗是屬於動物中一種 class Dog extends Animal { public Dog(String name,String color){ super(name,color); //指定呼叫父類兩個 引數的建構函式。 } public void bite(){ System.out.println(name+"咬人!!"); } } //貓也是屬於動物中一種 class Cat extendsAnimal{ public Cat(String name,String color){ super(name,color); } public void eat(){ System.out.println(name+"吃魚.."); } } class Demo{ public static void main(String[] args) { Dog d = new Dog("哈士奇","白色"); System.out.println("狗是狗類嗎?"+ (d instanceof Dog)); System.out.println("狗是動物類嗎?"+ (d instanceof Animal)); //System.out.println("狗是貓類嗎?"+ (d instanceof Cat));// false true Animal a = new Animal("小紅","黃色"); //小紅是人 System.out.println("動物都是狗嗎?"+ (a instanceof Dog)); } }
final關鍵字
用法:
- final關鍵字修飾一個基本型別的變數時,該變數不能重新賦值,第一次的值為最終的。
- fianl關鍵字修飾一個引用型別變數時,該變數不能重新指向新的物件。
- final關鍵字修飾一個函式的時候,該函式不能被重寫。
- final關鍵字修飾一個類的時候,該類不能被繼承。
//圓形 class Circle{ double r; //半徑 public static final double pi = 3.14; //固定不變的 public Circle(double r){ this.r = r; } //計算面積 public final void getArea(){ System.out.println("圓形的面積是:"+r*r*pi); } } class Demo extends Circle { public Demo(double r){ super(r); } public static void main(String[] args) { /* final Circle c = new Circle(4.0); test(c); */ Demo c = new Demo(4.0); c.getArea(); } public static void test(Circle c){ c = new Circle(5.0);//c變數又重新指向了新的物件。 c.getArea(); } }
三、多型
1.概念
多型:一個物件具備多種形態。
①父類的引用型別變數指向了子類的物件
②介面的引用型別變數指向了介面實現類的物件
多型的前提:必須存在繼承或者實現關係。
動物 a= new 狗();
2.多型要注意的細節:
- 多型情況下,子父類存在同名的成員變數時,訪問的是父類的成員變數。
- 多型情況下,子父類存在同名的非靜態的成員函式時,訪問的是子類的成員函式。
- 多型情況下,子父類存在同名的靜態的成員函式時,訪問的是父類的成員函式。
- 多型情況下,不能訪問子類特有的成員。
總結:多型情況下,子父類存在同名的成員時,訪問的都是父類的成員,除了在同名非靜態函式時才是訪問子類的。
注意:java編譯器在編譯的時候,會檢查引用型別變數所屬的類是否具備指定的成員,如果不具備馬上編譯報錯。(編譯看左邊)
//動物類 abstract class Animal{ String name; Stringcolor = "動物色"; public Animal(String name){ this.name = name; } public abstract void run(); public static void eat(){ System.out.println("動物在吃.."); } } //老鼠 classMouse extends Animal{ String color = "黑色"; public Mouse(String name){ super(name); } publicvoid run(){ System.out.println(name+"在大街上竄"); } public static void eat(){ System.out.println("老鼠在偷吃.."); } //老鼠特有方法---打洞 public void dig(){ System.out.println("老鼠在打洞.."); } } class Fish extends Animal { public Fish(String name){ super(name); } publicvoid run(){ System.out.println(name+"慢慢的遊"); } } class Demo { public static void main(String[] args) { /* Mouse m = new Mouse("老鼠"); System.out.println(m.color); //多型: 父類的引用型別變數指向子類的物件 */ Animal a = new Mouse("老鼠"); a.dig(); //a.eat(); } }
4.多型的應用:
- 多型用於形參型別的時候,可以接收更多型別的資料。
- 多型用於返回值型別的時候,可以返回更多型別的資料。
多型的好處: 提高了程式碼的拓展性。
定義一個函式可以接收任意型別的圖形物件,並且列印圖形面積與周長。
//圖形類 abstract class MyShape{ public abstract void getArea(); public abstract void getLength(); } class Circle extends MyShape{ public static final double PI = 3.14; double r; public Circle(double r){ this.r =r ; } publicvoid getArea(){ System.out.println("圓形的面積:"+ PI*r*r); } publicvoid getLength(){ System.out.println("圓形的周長:"+ 2*PI*r); } } class Rectextends MyShape{ int width; int height; public Rect(int width , int height){ this.width = width; this.height = height; } publicvoid getArea(){ System.out.println("矩形的面積:"+ width*height); } publicvoid getLength(){ System.out.println("矩形的周長:"+ 2*(width+height)); } } class Demo{ public static void main(String[] args) { /* //System.out.println("Hello World!"); Circle c = new Circle(4.0); print(c); Rect r = new Rect(3,4); print(r); */ MyShape m = getShape(0); //呼叫了使用多型的方法,定義的變數型別要與返回值型別一致。 m.getArea(); m.getLength(); } //需求1: 定義一個函式可以接收任意型別的圖形物件,並且列印圖形面積與周長。 public static void print(MyShape s){ // MyShpe s = new Circle(4.0); s.getArea(); s.getLength(); } // 需求2: 定義一個函式可以返回任意型別的圖形物件。 public static MyShapegetShape(int i){ if (i==0){ return new Circle(4.0); }else{ return new Rect(3,4); } } }
5.資料型別轉換
目前多型情況下不能訪問子類特有的成員。
如果需要訪問子類特有的成員,那麼需要進行型別強制轉換.
①基本資料型別的轉換
- 自動型別轉換:小資料型別--->大資料型別
- 強制型別轉換:大資料型別--->小資料型別 小資料型別 變數名 = (小資料型別)大資料型別;
②引用資料型別的轉換
- 自動型別轉換:小資料型別--->大資料型別
- 強制型別轉換:大資料型別--->小資料型別
//動物類 abstract class Animal{ String name; public Animal(String name){ this.name = name; } public abstract void run(); } //老鼠 classMouse extends Animal{ public Mouse(String name){ super(name); } publicvoid run(){ System.out.println(name+"在大街上竄!"); } //老鼠特有方法---打洞 public void dig(){ System.out.println("老鼠在打洞.."); } } //魚 class Fish extends Animal{ public Fish(String name){ super(name); } publicvoid run(){ System.out.println(name+"在水裡慢慢的遊!"); } //吹泡泡 public void bubble(){ System.out.println(name+"吹泡泡...!"); } } class Demo2 { public static void main(String[] args) { /* Animal a = new Mouse("老鼠");//多型 //呼叫子類特有的方法 Mouse m= (Mouse)a;//強制型別轉換 m.dig(); */ Mouse m = new Mouse("米老鼠"); Fish f = new Fish("草魚"); print(f); } //需求: 定義一個函式可以接收任意型別的動物物件,在函式內部要呼叫到動物特有的方法。 public static void print(Animal a){ // Animal a= new Mouse("米老鼠"); if(a instanceof Fish){ Fish f = (Fish)a; f.bubble(); }else if(a instanceof Mouse){ Mouse m = (Mouse)a; m.dig(); } } }
多型: 父類的引用型別變數指向了子類的物件或者是介面型別的引用型別變數指向了介面實現類的物件。
實現關係下的多型:
介面變數= new介面實現類的物件。
Demo:
interface Dao{//介面的方法全部都是非靜態的方法。 public void add(); public void delete(); } //介面的實現類 class UserDao implements Dao{ public void add(){ System.out.println("新增員工成功!!"); } public void delete(){ System.out.println("刪除員工成功!!"); } } class Demo { public static void main(String[] args) { //實現關係下的多型 Dao d = new UserDao(); //介面的引用型別變數指向了介面實現類的物件。 d.add(); } }