1. 程式人生 > >Java基礎(2):Java面向物件

Java基礎(2):Java面向物件

Java面向物件

1 Java類與物件

1.1 類

  • 屬性:類的成員變數,作用範圍是整個類,有預設值。
  • 功能:類的成員方法
    一般成員變數設為private, 成員方法為public.
    修飾符 class 類名{
         //成員變數定義
       修飾符 資料型別 變數名[
    =] ; //成員方法定義 修飾符 返回值型別 方法名(引數列表){ ... //方法內容 } }
  • 構造方法
    修飾符 構造方法名(引數列表){
        ...  //構造方法實體
    }
    
    • 構造方法注意事項
      • 構造方法沒有返回值型別和返回值。
      • 構造方法名和類名相同
      • 構造方法在建立物件的時候執行一次,未自己定義構造方法時編譯器會建立一個預設構造方法,自己定義了則編譯器不會建立預設構造方法。
      • 構造方法可以過載
  • static關鍵字
    • static修飾類中的成員,該成員屬於該類,不屬於該類的某個物件。(物件的共享資料)
    • 成員呼叫:類名.成員,也可以使用物件.成員
    • static注意事項:
      • 靜態不能呼叫非靜態。原因:靜態內容先於物件存在記憶體中,只能訪問靜態,不能用this/super。
        但是可以建立物件來呼叫非靜態方法。
        public class Fu {
            public static int a = 1;
        
            public static void show() {
                System.out.println("This is superclass!!");
                ceshi();  //編譯錯誤,靜態不能呼叫非靜態,而且這裡不能使用 this.ceshi();
        //但是可以建立一個物件來呼叫非靜態方法 Fu f = new Fu(); f.ceshi(); } public void ceshi() { System.out.println("xixix"); } }
      • 技巧:方法中未用到非靜態成員,推薦使用static修飾該方法。

1.2 物件

物件是類的例項。

  • 建立物件:
       類名 物件名 = new 構造方法(引數列表);
    
  • 匿名物件:沒有引用變數,只能使用一次。
    new 構造方法(引數列表)
    

1.3 內部類

  • 類寫在其他類內部,作為成員內部類區域性內部類
    public class Outer{
        //成員內部類
        public class Inner{
           public void show(){
               System.out.println("This is an inner class!!");
           }
        }
    }
    
  • 非靜態內部類不能有靜態成員。
    原因:JVM載入順序:類 \rightarrow 靜態成員 \rightarrow 類物件,要求靜態變數在物件建立之前完成,
  • 建立內部類引用物件:外部類名.內部類名 變數 = 外部類物件.new 內部類構造方法(引數列表).
    Outer.Inner in = new Outer().new Inner();
    in.show();  //呼叫內部類方法
    
  • 在內部類中對內部類與外部類同名成員呼叫:
    • 內部類成員:this.成員
    • 外部類成員:外部類名.this.成員
    package org.ywq.innerclass;
    
    public class Outer {
        private int a=1;
        //成員內部類
        public class Inner{
    	private int a=2;
    	public void inner() {
    	    int a=3;
    	    System.out.println(a);		//output 3
    	    System.out.println(this.a);		//output 2
    	    System.out.println(Outer.this.a);  //output 1
    	}
        }
    }
    
    

2 面向物件三大特徵

2.1 封裝

  • 隱藏實現細節,對外提供可以訪問的方式。
  • 方法、類、包都是封裝。
  • 封裝要求將成員變數設為private, 所以要新增set變數名(), get變數名()成員方法對成員變數進行間接訪問。(private成員只能在本類中使用)
    public class Person{
    	private String name;
    	private int age;
    	//set方法
    	public void setName(String name){
    	    this.name=name;
    	}
    	public void setAge(int age){
    	    this.age=age;
    	}
    	//get方法
    	public String getName(){
    	    return name;
    	}
    	public int getAge(){
    	    return age;
    	}
    }
    
  • this關鍵字
    • this表示本類物件的引用呼叫方法的物件,在類中可以省略不寫(強烈不建議)
    • 通過this可區分類中成員變數和區域性變數同名。
    • this()用法:呼叫本類的構造方法。(該語句必須是構造方法中第一個statement
      class Person{
          protected String name;
          protected int age;
          //default constructor
          public Person(){
              this("Lili",1);  //呼叫過載的構造方法Person(String name, int age)
          }
          //Overload constructor
          public Person(String name, int age){
              this.name=name;
              this.age=age;
          }
      }
      

2.2 繼承

子類擁有父類所有可繼承的變數和方法。

  • 格式(extends關鍵字)

    class 子類 extends 父類{
        ....
    }
    
  • 繼承的注意事項

    • Java不允許多繼承:一個類只能繼承一個父類。
      class A extends B,C{}	//錯誤,不被允許
      
      原因:可能有安全隱患,如兩個類中有相同的方法。
    • Java支援多重繼承:B類繼承A類,C類繼承B類。
      class A{}
      class B extends A{}
      class C extends B{}
      
  • 方法重寫(Override

    • 子類中對父類的方法進行重寫(方法名和引數列表保持一致)。

    • 主要目的是保持父類功能,並新增子類的新功能。

      class Son extends Father{
          @Override
          public void showTelephone(){
              super.showTelephone();	//父類的功能
              System.out.println("New Function!!");	//新增子類的新功能
      }
      

      [特殊重寫方式1]——通過匿名物件重寫方法(僅臨時有效)

      public class Test{
          public static void main(String[] args) {
              //Way 1:
              Son son = new son(){
                  //Override
                  public void showTelephone(){
                      ...  //新增重寫方法體,僅臨時有效
                  }
              };
              son.showTelephone();
              //Way 2:
              new son(){
                  //Override
                  public void showTelephone(){
                      ...  //新增重寫方法體,僅臨時有效
                  }
              }.showTelephone();
          }
      }
      

      [特殊重寫方式2]——Lamba表示式(Java8新特性)

      • Lambda表示式相當於一個匿名方法,主要用來代替匿名物件方法重寫的繁瑣語法(也是建立一個物件例項)。
      • Lambda表示式組成:
        • 形參列表;(允許省略形參型別)
        • 箭頭(->)
        • 程式碼塊。
      • Java中Lambda表示式的目標型別必須是函式式介面——只有一個抽象方法的介面,但可以多個非抽象方法。
        package org.ywq.lambda;
        
        interface Eatable {
            void taste();
        }
        
        interface Flyable {
            void fly(String weather);
        }
        
        interface Addable {
            int add(int a, int b);
        }
        
        public class Test {
            public void eat(Eatable e) {
                System.out.println(e);
        	e.taste();
            }
        
            public void drive(Flyable f) {
                System.out.println("我正在駕駛: " + f);
        	f.fly("[大晴天]");
            }
        
            public void addTest(Addable add) {
                System.out.println("5和3的和為: " + add.add(5, 3));
            }
        
            public static void main(String[] args) {
                Test la = new Test();
            //建立了Eatable介面例項,重寫taste()方法,程式碼塊只有1條語句,可省略花括號和分號
        	la.eat(() -> System.out.println("真香!!")); 
        	// 建立了Flyable介面例項,重寫fly(String weather)方法,引數列表只有一個形參可以省略圓括號
        	la.drive(weather -> {
        	    System.out.println("今天天氣是:" + weather);
        	    System.out.println("飛機飛行正常!!!");
        	}
        	);
        	// 建立了Addable介面例項,重寫add(int a, int b)方法,程式碼塊只有1條語句,省略花括號,也可省略return
        	la.addTest((a, b) -> a + b);
            }
        }
        
    • 注意:重寫時子類方法許可權要大於等於父類方法許可權

      class father{
          public void show(){
          }
      }
      class son extends father{
          void show(){	//default許可權 < public許可權,編譯失敗
          }
      }
      

      四大許可權public > protected > default > private.
      技巧:所有方法許可權都設定為public.
      java中4種訪問許可權:

許可權 public protected default private
本類 Class Y Y Y Y
本包 Package Y Y Y
子類 Subclass Y Y
外部包 World Y
  • super關鍵字
    • 父類英文為superclass
    • super指父類的儲存空間,可以理解為父類的引用物件。
    • super()用法:呼叫父類的構造方法,完成父類成員的初始化操作。
      • 子類的構造方法第一行都有預設的隱式super();語句,除非是第一行使用this(引數列表);語句。
      • super();可以替換成手動寫的super(引數列表);呼叫父類的相應構造方法。

2.3 多型

  • 表現:父類引用變數可以指向子類物件。(介面與實現類也滿足)

  • 自動型別轉化

    父類 引用變數名 = new 子類();
    
  • 多型規則

    • 成員變數
      編譯、執行全看父類。
    • 成員方法
      編譯看父類,非靜態成員方法執行先看子類(重寫方法),子類未重寫再看父類。
      靜態成員方法執行也看父類。(多型針對物件,而靜態成員與物件無關)
      注:如果是子類特有方法,需要強制型別轉換才能呼叫。
  • 多型作用
    在方法的引數列表中,可以使用父類資料型別,引用變數呼叫方法時引數可以是各個子類物件。
    如:

    /******************介面 USB.java****************************/
    /*
    *如果對介面不熟悉,可以參見本文 第4部分介面 內容
    */
    package org.ywq.duotai;
    
    public interface USB {
        public abstract void open();
        public abstract void close();
    }
    
    /******************滑鼠 Mouse.java****************************/
    package org.ywq.duotai;
    
    public class Mouse implements USB{
        @Override
        public void open() {
    	System.out.println("開啟滑鼠");
        }
    
        @Override
        public void close() {
    	System.out.println("關閉滑鼠");
        }
    }
    
    /******************鍵盤 Keyboard.java****************************/
    package org.ywq.duotai;
    
    public class Keyboard implements USB{
    
        @Override
        public void open() {
    	System.out.println("開啟鍵盤");
        }
    
        @Override
        public void close() {
    	System.out.println("關閉鍵盤");
        }
    }
    
    /******************電腦 Computer.java****************************/
    package org.ywq.duotai;
    
    public class Computer {
        public static void open() {
    	System.out.println("開啟電腦");
        }
        public static void close() {
    	System.out.println("關閉電腦");
        }
        //使用USB裝置
        public void useUSB(USB usb) {  //成員方法引數型別為USB介面型別,可以用Mouse和Keyboard引用變數
    	usb.open();
    	usb.close();
        }
    }
    
    /******************測試 Test.java****************************/
    package org.ywq.duotai;
    
    public class Test {
        public static void main(String[] args) {
    	Computer computer=new Computer();
    	computer.useUSB(new Mouse());
    	computer.useUSB(new Keyboard());
        }
    }
    
  • instanceof關鍵字

    • 用於判斷物件是否屬於某種資料型別。
      物件 instanceof 資料型別	//返回 true 或 false
      

    注意:資料型別為類時,物件 instanceof 父類true.
    如任意建立的類都是Object類的子類,所以物件 instanceof Object始終是true.

3 抽象類

  • 使用abstract關鍵字。

  • 定義抽象類

    public abstract class Develop {
        public abstract void work();
    }
    
  • 抽象類作用:定義沒有方法體的方法,子類繼承抽象類並強制重寫抽象方法。

    public class JavaEE extends Develop {
        @Override
        public void work() {
    	System.out.println("JavaEE工程師在工作!");
        }
    }
    
  • 注意

    • 抽象類不能例項化物件。
    • 如果子類繼承抽象類並只重寫了一部分抽象方法,則該子類還是抽象類。
    • 抽象類中可以沒有抽象方法。
  • final關鍵字

    • final意思是最終,不可變的。
    • final可以修飾類、類的成員和區域性變數。
      • final修飾的類不能被繼承,但可以繼承其他類。
        public final class Zi extends Fu{
        }
        
      • final修飾的方法不能被重寫(Override)
      • final修飾的基本資料型別變數稱為常量,只能被賦值一次。
        final int a = 1;
        
      • final修飾的引用變數,保持記憶體地址不變。
        final Fu fu = new Zi();
        fu = new Zi();   //編譯錯誤,final引用變數地址不能改變。
        

4 介面

  • 介面是功能的集合,是比抽象類更抽象的類,使用interface關鍵字。
  • 介面只描述應該具備的方法,沒有具體實現。(介面內方法全是抽象方法
  • 介面中成員變數必須為常量。
  • 介面定義
    MyInterfaceDemo.class檔案:
    public interface MyInterfaceDemo{
        //定義常量
        public static final 資料型別 變數名 =;
        //定義抽象方法
        public abstract 返回值型別 方法名(引數列表);
    }
    
  • 介面實現implements關鍵字)——介面和實現類
    public classimplements 介面{
        重寫介面中的抽象方法;
    }
    
  • 介面注意事項
    • 介面允許多實現:實現多個介面。
      public class C implements A,B{}
      
      原因:介面中都是抽象方法,沒有安全隱患。
    • 類可以繼承superclass同時實現介面
      public class D extends C implements A,B{}
      
    • 介面可以繼承介面,且支援多繼承。
      public interface C extends A,B{}
      
  • 介面和抽象類的區別
    • 抽象類是事物都具備的內容(共性),繼承體系是is..a關係
    • 介面是事物額外內容(特性),繼承體系是like..a關係

5 包Package

  • 包就是資料夾,存放類檔案,一般將相同功能的類放到一個包中。
  • 類中包的宣告格式(在class檔案最開頭):package 包名.包名.包名...;
  • 匯入包:import 包名.包名...包名.類名;