1. 程式人生 > 其它 >Java基礎 — 面向物件

Java基礎 — 面向物件

面向物件程式設計

1 類的呼叫

  • 靜態方式
  //Student.java
  public class Student {
      public static void sayHi(){
          System.out.println("Hello World!");
      }
  }

  //main.java
  public class main {
      public static void main(String[] args) {
          Student.sayHi();
      }
  }
  • 非靜態方式
//Student.java
  public class Student {
      public void sayHi(){
          System.out.println("Hello World!");
      }
  }
  
  //main.java
  public class main {
      public static void main(String[] args) {
          Student student = new Student();
          student.sayHi();
      }
  }
  • 靜態方法和非靜態方法
//可以直接呼叫
  public static void a(){
      b();
  }
  public static void b(){}
  
  //可以直接呼叫
  public void a(){
      b();
  }
  public void b(){}
  
  //不可以呼叫
  //方法 a 由 static 修飾,與類一起載入
  //方法 b 無 static 修飾符,只有例項化之後才會在記憶體中載入,因此此種呼叫方式錯誤
  public static void a(){
      b();
  }
  public void b(){}

2 值傳遞和引用傳遞

  • 值傳遞
public class main {
      public static void main(String[] args) {
          int num = 5;
          System.out.println(num);		//num = 5
          change(num);
          System.out.println(num);		//num = 5
      }
  
      public static void change(int num){
          num = 100;
      }
  }
  • 引用傳遞
public class main {
      public static void main(String[] args) {
          Person person = new Person();
          System.out.println(person.name);	//null
          main.change(person);
          System.out.println(person.name);	//Bob
      }
  
      public static void change(Person person){
          person.name = "Bob";
      }
  }
  
  class Person {
      String name;
  }

3 類的例項化

  • 建構函式
  // new 的本質,就是在呼叫構造器
  public class Person {
      String name;
      
      //無參構造
      public Person(){
          this.name = "Bob";
      }

      //有參構造
      public Person(String name){
          this.name = name;
      }
  }
  • 記憶體分析
 public class main {
      public static void main(String[] args) {
          Pet dog = new Pet();
          dog.name = "旺財";
          dog.age = 3;
          dog.shout();
          Pet cat = new Pet();
      }
  }
  
  public class Pet {
      public String name;
      public int age;
  
      public void shout(){
          System.out.println("Shout!");
      }
  }
  

4 三大特性

封裝

public class Pet {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age < -1 || age > 120){
            this.age = 3;
        }else{
            this.age = age;
        }
    }
}

public class main {
    public static void main(String[] args) {
        Pet dog = new Pet();
        dog.setAge(500);
        System.out.println("age = " + dog.getAge()); //age = 3
    }
}
  • 封裝的作用:
    • 提高程式安全性,保護資料
    • 隱藏程式碼實現細節
    • 統一介面 get / set
    • 系統可維護性增加

繼承:本質是對一批類的抽象,使用關鍵字 extends

public class Pet {
    private String name = "Bob";
    protected int age = 5;
    int money = 100;
    public void shout(){
        System.out.println("Hi");
    }
}

public class Cat extends Pet {}

public class main {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.shout();	//Hi
        System.out.println(cat.name);	//Error
        System.out.println(cat.age);	//5
        System.out.println(cat.money);	//100
    }
}
  • 子類會繼承父類中 public、protected、default 修飾的所有屬性和方法,private 修飾的則不會被繼承
  • Java 中所有的類,都預設繼承 Object
  • Java 中的類都是單繼承,沒有多繼承
  • 私有屬性和方法均無法被繼承
public class Pet {
    public String name = "Pet";

    public void shout(){
        System.out.println("Father");
    }
}

public class Cat extends Pet {
    public String name = "Cat";

    public void print(){
        System.out.println("Son");
        System.out.println(super.name);
        super.shout();
    }
}

public class main {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.print();
        // Son  Pet  Father
    }
}
  • super 注意點

    • super 呼叫父類的構造方法時,必須出現在子類構造方法的第一行
    • super 必須只能出現在子類的方法或者構造方法中
    • superthis 不能同時呼叫構造方法
  • super VS this

    • 代表的物件不同
      • this :本身呼叫者這個物件
      • super :代表父類的引用
    • 適用前提不同
      • this :有無繼承均可使用
      • super :只能在繼承的條件下使用
    • 構造方法
      • this :本類的構造方法
      • super :父類的構造方法
  • 方法重寫

    • 方法名與引數列表必須一致
    • 修飾符的範圍可以擴大,但不能縮小 public > protected > default > private
    • 丟擲的異常,範圍可以擴大不能縮小
    • 子類重寫父類方法,只是方法體不同
//使用 static 關鍵字:方法的呼叫只和左邊的型別有關
public class B {
    public static void test(){
        System.out.println("B ==> test()");
    }
}

public class A extends B{
    public static void test(){
        System.out.println("A ==> test()");
    }
}

public class main {
    public static void main(String[] args) {
        A a = new A();
        a.test();	//A ==> test()
        B b = new A();
        b.test();	//B ==> test()
    }
}


//方法重寫:重寫的定義只針對無 static 修飾的方法
public class B {
    public static void test(){
        System.out.println("B ==> test()");
    }
}

public class A extends B{
    //對父類的 test() 方法進行了重寫
    @Override
    public static void test(){
        System.out.println("A ==> test()");
    }
}

public class main {
    public static void main(String[] args) {
        A a = new A();
        a.test();	//A ==> test()
        B b = new A();
        b.test();	//A ==> test()
    }
}

多型

public class Person {
    public void run(){
        System.out.println("Person ==> run()");
    }
}

public class Student extends Person{
    @Override
    public void run() {
        System.out.println("Student ==> run()");
    }

    public void eat(){
        System.out.println("Student ==> eat()");
    }
}

public class main {
    public static void main(String[] args) {
        Student s1 = new Student();
        Person s2 = new Student();
        Object s3 = new Student();

        s1.run();				//Student ==> run()
        s1.eat();				//Student ==> eat()
        ((Student) s2).eat();			//Student ==> eat()
    }
}
  • 多型注意事項
    • 多型是方法的多型,屬性沒有多型
    • 父類與子類必須有聯絡,否則就會轉換異常 ClassCastException
    • 子類需要對父類方法進行重寫,父類的引用物件指向子類
  • 類的型別轉化
    • 父類的引用指向子類的物件
    • 子類轉為父類,是低轉高,向上轉型,直接轉換
    • 父類轉為子類,是高轉低,向下轉型,要強制轉換,父類可能會丟失一些原有的方法

5 static 關鍵字

public class Person {

    {
        System.out.println("匿名程式碼塊");
    }

    static {
        System.out.println("靜態程式碼塊");
    }

    Person(){
        System.out.println("構造方法");
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("-----------");
        Person person2 = new Person();
    }
}

/*
靜態程式碼塊
匿名程式碼塊
構造方法
---------
匿名程式碼塊
構造方法
*/
  • 靜態程式碼塊和類一起載入,且只加載一次
  • 匿名程式碼塊在構造方法之前載入

6 抽象類

  • 使用關鍵字 abstract 修飾
  • 抽象類與抽象方法的作用是實現約束
  • 子類如果繼承了抽象類,那麼就必須實現父類的抽象方法,除非子類也是抽象類
  • 不能 new 抽象類,只能靠子類去實現
  • 抽象類裡可以寫普通方法,但是普通類裡不能寫抽象方法,抽象方法只能在抽象方法中
public abstract class Person {

    public abstract void doSomething();
}

public class Student extends Person{
    @Override
    public void doSomething() {

    }
}

  • 抽象類也有構造方法
public abstract class Person {
    public abstract void doSomething();
    Person(){
        System.out.println("構造方法");
    }
}

public class Student extends Person{
    @Override
    public void doSomething() {
        System.out.println("doSomeThing()");
    }
}

public class main {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

//構造方法

7 介面

  • 類、抽象類、介面
    • 類:只有具體實現
    • 抽象類:具體實現的規範(抽象方法)都具有
    • 介面:使用關鍵字 interface ,只有規範,自己無法寫方法,實現約束和具體步驟的分離,更加規範
  • 介面中所有的方法,其實都是抽象的,預設使用 public abstract 修飾
public interface UserAction {
    void run();
}
  • 類實現介面使用關鍵字 implements
  • 實現了介面的類,就必須重寫介面中的所有方法,介面可以“多繼承”
public interface UserAction {
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}

public interface UserTime {
    void timer(String name, int age);
}

public class UserActionImpl implements UserAction, UserTime{
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer(String name, int age) {

    }
}

8 內部類

  • 一般內部類(可以訪問外部類的私有屬性)
public class Outer {
    private final int id = 10;

    public void printOut(){
        System.out.println("外部類的方法");
    }

    class Inter {
        public void printIn(){
            System.out.println("內部類方法");
        }

        public void getOutId(){
            System.out.println(id);
        }
    }
}

public class main {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inter inter = outer.new Inter();
        inter.getOutId();		//10
    }
}
  • 區域性內部類
public class Outer {

    public void method(){
        class test{
        }
    }
}
  • 匿名內部類
public class main {
    public static void main(String[] args) {
        new Apple().eat();
    }
}

class Apple{
    public void eat(){
    }
}