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

Java基礎---面向物件

面向物件

面向物件程式設計的本質:以類的方式組織程式碼,以物件的組織(封裝)資料

四大特徵:封裝、繼承、多型、抽象(具有相同特徵和行為的物件抽象

方法的深入

  1. 方法的定義

    • 修飾符

    • 返回型別

    • break和return的區別

      break用於switch或迴圈中跳出整個迴圈體

      return表示方法結束,返回一個結果,必須與返回值型別相同;

    • 方法名

    • 引數列表(引數型別,引數名)

    • 異常丟擲 ???(以後講)

  2. 方法的呼叫

    • 靜態方法--可以直接通過類名.方法名呼叫

    ​ --兩個靜態方法可互相呼叫;兩個非靜態方法也可以互相呼叫

    • 非靜態方法--不可直接呼叫,

      ---需要例項化(new一個物件),物件型別 物件名 = 物件值(new 物件型別)通過物件名.方法名來呼叫

      public class student {  //新建一個學生類
        //非靜態方法
        public void say(){
            System.out.println("學生說話了");
        }
      }
      
      student zxy = new student();  //例項化
      zxy.say();   //物件名.方法
      

    • 形參和實參

    • 值傳遞和引用傳遞

    • this關鍵字

物件的建立和分析

類和物件的關係

--類是一種抽象的資料型別,對一類事物整體的描述,不能代表某一具體事務

--物件是抽象概念的具體例項

--建立物件:new關鍵字--本質是呼叫構造器

使用new時,除了分配空間外,還會給物件預設初始化以及對類中構造方法的呼叫;

student zxy = new student();   //呼叫了構造器
public student(){   }         //預設無參構造器
student wzh = new student(wangzihe); //呼叫構造器,有參構造
public student(String name){
        this.name = name;   //this.name指的是當前類中定義的name;第二個name是引數傳進來的
    }
//如果定義了有參構造,那麼無參構造必須顯示寫出來

--構造方法(構造器):與類名相同;沒有返回值型別,也不能寫void;完成資料初始化操作;

--記憶體分析:物件通過引用來操作:棧---->堆

封裝

  • 資料的隱藏,應禁止直接訪問一個物件的資料的實際表示,通過操作介面來訪問
  • 屬性私有(private)---get/set
  • 提供一些操作這些屬性的方法:get(獲取這個資料) set(給資料賦值)

繼承

  • 本質:對某一批類的抽象,是類和類之間的關係,子類和父類之間

  • 關鍵字:extends(擴充套件)---子類是父類的擴充套件

  • Java中類只有單繼承,沒有多繼承;----一個兒子只能有一個爸爸,一個爸爸有多個兒子

  • 私有的東西無法繼承

  • 在Java中,所有類都預設直接或間接繼承Object類

  • 在執行時,子類會預設呼叫父類的無參構造;

  • 被final修飾的類不能被繼承;--final之後斷子絕孫。。。

  • public class person    //父類
    public class student extends person  //子類/派生類--學生 is 人
    public class teacher extends person  //子類/派生類--老師 is 人
    

    super

    //主函式所在--測試類
    public class test {
        public static void main(String[] args) {
            student zxy = new student();
            zxy.test("hhhzxy");
        }}
    
    父類
    public class person {
        protected String name = "張二白";
    }
    
    子類
    public class student extends person {
        private String name = "zhangxiaoyang";
    
        public void test(String name){
            System.out.println(name);    //輸出的是(hhhzxy)主函式中傳的引數
            System.out.println(this.name); //輸出的是(zhangxiaoyang)當前類中的name值
            System.out.println(super.name);//輸出的是(張二白)父類的name值
        }
    }
    

    注意點:

    1)super呼叫父類的構造方法,必須在構造方法的第一個

    2)super必須只能出現在子類的方法中或構造方法中

    3)super和this不能同時呼叫構造方法

與this的區別:

​ 1)代表物件不同:

​ this:本身呼叫這個物件

​ super:代表父類物件的應用

​ 2)前提:

​ this:沒有繼承也可以用

​ super:只能在繼承條件下可用

​ 3)構造方法

​ this():本類的構造

​ super():父類的構造

方法重寫

需要有繼承關係,子類重寫父類的方法;子類和父類的方法必須一致,只是內容不同(方法體不同)

  1. 方法名必須相同
  2. 引數列表必須相同
  3. 修飾符:範圍可以擴大 public>protected>default>private
  4. 丟擲的異常:範圍可以被縮小,但不能擴大--(父親欠了50萬,你還了10萬,還剩40萬,你不能再欠了。。。)

-為什麼要重寫???---父類的功能,子類不一定需要或不一定滿足;子類重寫了父類的方法,執行時執行子類的

-什麼方法不能重寫:

1)static方法,屬於類,不屬於例項

2)被final(常量)修飾的方法

3)private方法

多型

什麼是多型---同一個方法根據傳送物件的不同而採用多種不同的行為方式

一個物件的實際型別是確定的---new student(); new person();

但可以指向物件的引用型別就不確定了,父類的引用指向子類

student s1 = new student();  //s1能呼叫的方法是自己的或繼承父類的
person s2 = new student();   //person可以指向子類,但不能呼叫子類獨有的方法
Object s3 = new student();  
 //物件能執行哪些方法,主要看物件左邊的型別
 s1.run(); 
 s2.run(); //子類重寫了父類的方法,執行子類的方法
 s2.eat(); //s2是person型別,無法呼叫student類裡獨有的方法
 ((student)s2).eat(); //把s2強制轉化成student型別,可以呼叫student裡獨有的方法

注意事項:

  1. 多型是方法的多型

  2. 父類和子類,有聯絡,型別轉換可能發生異常-- ClassCastException!

  3. 存在條件:繼承關係,方法需要重寫,父類引用指向子類物件-father f1 = new son()

    instanceof (型別轉換)

     Object >person >teacher
     Object >person >student
     System.out.println(X instanceof Y);//能不能編譯通過,看X與Y是否有父子關係
     System.out.println(Object instanceof student);  //true
     System.out.println(student instanceof Object);  //true
     System.out.println(student instanceof teacher); //false
    

    子類轉成父類,向上轉型,自動;--可能丟失自己本來的一些方法

    父類轉成子類,向下轉型,強制轉換;

    型別轉換方便方法的呼叫,減少重複程式碼

    static詳解

    1. 靜態屬性

      private static int age; //靜態屬性
      private double score; //非靜態
      public static void main(String[] args) {
              student s1 = new student();
              System.out.println(student.age); //靜態屬性可直接用類名呼叫
              System.out.println(student.score); //非靜態不能用類名直接呼叫
              System.out.println(s1.age);
              System.out.println(s1.score);
      
    2. 靜態方法

      public void run() {
              go(); }  //靜態方法和類一起載入,非靜態方法裡可以呼叫靜態方法
      public static void go() {   
          }
       student.run(); //報錯--非靜態方法不能用類.方法名呼叫
       s1.run();
       student.go();  //靜態方法可直接用類呼叫
      

      !!!是類的載入機制的問題,非靜態都還沒載入進來,自然不能直接用類呼叫,但靜態和類一起載入,故可以呼叫

    3.靜態程式碼塊--最先執行(先於匿名程式碼塊和構造方法),只執行一次

    4.匿名程式碼塊和物件同時產生,在構造方法之前,可以賦一些初始值

    5.靜態匯入包-

    import static java.lang.Math.random;  //把Java.lang包中的Math的random()方法匯入
    System.out.println(Math.random());//不匯入的寫法
    System.out.println(random());  //可以直接呼叫Math中的random()方法
    

抽象類和介面

抽象類(abstract class)

  • 對於抽象類的所有方法,繼承了抽象類的子類,都必須要實現他的方法,除非子類也是抽象類,那就由下一代來實現。。。

  • 不能new這個抽象類,即不能建立例項;只能靠子類去實現它;

  • 抽象類裡可以寫普通方法,但抽象方法必須寫在抽象類裡;

  • 抽象類不能new,那存在構造器嗎? ----存在,編譯器新增預設的無參建構函式,只是不能直接建立抽象類的例項物件

  • 抽象類存在的意義?

  • //抽象類
    public abstract class Action {
        public abstract void dosomething(); //抽象方法--沒有方法體,即具體的實現
    }
    

介面(interface)

  • 普通類:只有具體實現

  • 抽象類:具體實現和規範(抽象方法)都有!

  • 介面:只有規範!自己無法寫方法~專業的約束!約束和實現分離:面向介面程式設計

  • 介面就是規範,定義一組規則---定義一些方法,讓不同的人實現;

  • 介面不能被例項化~,介面沒有構造方法(他連類都不是。。。)

  • 介面的本質是契約,像法律一樣,制定好後大家遵守

  • 其實設計模式所研究的實際上就是如何合理的去抽象,所以設計模式都只針對具備抽象能力的語言(c++,java,c#等)

  • //通過interface定義一個介面,只宣告方法,不實現(型別 方法名)
    public interface timeService {  
        void timer();
    }
    public interface UserService{
      void add(String nam);
      void delete(String nam);
      void update(String nam);
      void query(String nam);
    }
    
    //類 通過關鍵字implements實現介面,實現了介面的類必須重寫介面中的方法(可以通過idea自動生成)
    public class UserServiceImpl implements UserService{  }
    //多繼承---利用介面來實現
    public class UserServiceImpl implements UserService,timeService{}
    

內部類

  1. 成員內部類

    public class Outer {
        private int id = 10;
        public void out(){
            System.out.println("這是外部類的方法");}
        class  Inner{
            public void in(){
                System.out.println("這是內部類的方法");
            }
            //內部類可以獲得外部類的私有屬性
            public void getId(){
                System.out.println(id);
    
            }
        }
    }
    
    
    //在測試類中
    public class test {
        public static void main(String[] args) {
            Outer outer = new Outer();  //外部類new一個物件
            Outer.Inner inner = outer.new Inner();  //通過外部類來例項化內部類。。。
            inner.in();
            inner.getId();
        }
    }
    

  2. 靜態內部類

    public static class  Inner{
            public void in(){
                System.out.println("這是內部類的方法");
            }
            //內部類可以獲得外部類的私有屬性
            public void getId(){
                System.out.println(id);  //若類變成靜態內部類,就無法獲得私有屬性了。。。還是類的載入機制
    
            }
        }
    
  3. 區域性內部類

    public class Outer {
        //區域性內部類---在一個方法裡面定義的類
        public void method(){
            class Inner{ }
        }
    
  4. 匿名內部類

    class Apple {
        public void eat() {
            System.out.println("1");
        }
    }
    
    public class test {
        public static void main(String[] args) {
          new Apple().eat();    //沒有名字初始化類,不用把例項存在變數裡
          //正常情況下:Apple apple = new Apple(); apple.eat();
       }
    
  • 一個java類中可以有多個class類,但是隻能有一個public class類