Java基礎(07)— 面向對象

面向對象

初識面向對象

面向過程&面向對象

  • 面向過程
    • 線性思惟,步驟清晰簡單,第一步作什麼,第二步作什麼
    • 面對過程適合處理一些較爲簡單的問題
  • 面向對象
    • 物以類聚,分類的思想模式,思考問題首先會解決問題須要哪些分類,而後對這些分類進行單獨思考。最後纔對某個分類下的細節進行面向過程的思索
    • 面向對象適合處理複雜的問題,適合處理須要多人協做的問題
  • 對於描述負責的事物,爲了從宏觀上把握,從總體上合理分析,咱們須要使用面向對象的思路來分析整個系統。可是具體到微觀操做,仍須要面向過程的思路去處理

什麼是面向對象?

  • 面向對象編程(Object-Oriented Programming, 00P)
  • 面向對象編程的本質就是:以類的方式組織代碼,以對象的組織(封裝)數據
  • 抽象:編程思想
  • 三大特性
    • 封裝
    • 繼承
    • 多態
  • 從認識論角度考慮是先有對象後有類。對象,是具體的事物。類,是抽象的,是對對象的抽象
  • 從代碼運行角度考慮是先有類後有對象。類是對象的模板

方法回顧和加深

方法的定義

  • 修飾符java

  • 返回類型c++

    /*
        修飾符 返回值類型 方法名(...){
        	方法體
        	return 返回值
        }
    */
    public String sayHello(){
    	return "hello,world!";
    }
    
    public int max(int a, int b){
    	return a > b ? a : b; //三元運算符
    }
  • break 和 return 的區別編程

    • break:跳出switch,結束循環
    • return:結束方法,返回結果
  • 方法名:注意命名規範就OK,見明知意c#

  • 參數列表:(參數類型 參數名)...設計模式

  • 異常拋出:疑問後面講解安全

    public void readFile(String file) throws IOException{ }

方法的調用

  • 靜態方法多線程

  • 非靜態方法dom

    //學生類
    public class Student {
        //靜態方法
        public static void say(){
            System.out.println("學生在說話....");
        }
        //非靜態方法
        public void eat(){
            System.out.println("學生在吃飯....");
        }
    }
    public static void main(String[] args) {
        //靜態方法調用
        Student.say();
        /*
            非靜態方法調用
            實例化這個類  new
            對象類型 對象名 = 對象值;
         */
        Student stu = new Student();
        stu.eat();
    }

  • 形參和實參ide

    public static void main(String[] args) {
        //形參和實參類型要對映
        //int add = new Demo03().add(2,3);
        int add = add(2,3);
        System.out.println(add);
    }
    public static int add(int a,int b){
        return a+b;
    }
  • 值傳遞和引用傳遞oop

    //值傳遞
    public static void change(int a){
        a = 10;
    }
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a); //1
        change(1);
        System.out.println(a);
    }
    
    //引用傳遞:對象,本質仍是值傳遞
    //對象,內存!
    //定義一個Person類,有個屬性是name
    class Person{
        String name;
    }
    public static void change(Person person){
        //person是一個對象,指向的Person person = new Person();這是具體的人,能夠改變屬性。
        person.name = "葉凡";
    }
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);//null
        change(person);
        System.out.println(person.name);//???
    }
  • this 關鍵字(繼承和多態的時候學)

對象的建立分析

類與對象的關係

  • 類是一種抽象的數據類型,它是對某一類事物總體描述定義,可是並不能表明某一個具體的事物

    • 動物、植物、手機、電腦....
    • Person類、Pet類、 Car類等,這些類都是用來描述/定義某類具體的事物應該具有的特色和行爲
  • 對象是抽象概念的具體實例

    • 張三就是人的一個具體實例,張三家裏的旺財就是狗的一個具體實例
    • 可以體現出特色,展示出功能的是具體的實例,而不是一個抽象的概念
  • 構造器必需要掌握

建立與初始化

  • 使用new關鍵字建立對象的時候,除了分配內存空間以外,還會給建立好的對象進行默認的初始化以及對類中構造器的調用

    //學生類
    public class Student {
        //屬性/字段
        String name;
        int age;
        //方法
        public void study(){
            System.out.println(this.name + "在學習");
        }
    }
    //一個項目應該只存在一個main方法
    public class Application {
        public static void main(String[] args) {
            /*
            類:抽象的,實例化
            類實例化後會返回一個本身的對象
            jack/tom 對象就是Student類的具體實例
             */
            Student jack = new Student();
            Student tom = new Student();
    
            jack.name = "jack";
            jack.age = 3;
            System.out.println(jack.name);
            System.out.println(jack.age);
    
            tom.name = "tom";
            tom.age = 3;
            System.out.println(tom.name);
            System.out.println(tom.age);
        }
    }

構造器詳解

  • 類中的構造器也稱爲構造方法,是在進行建立對象的時候必需要調用的,而且構造器有如下倆個特色

    • 必須和類的名字相同
    • 必須沒有返回類型,也不能寫void
  • IDEA生成構造器快捷鍵:Alt+Insert

    public class Person {
        /*
        一個類即便什麼都不寫,也會存在一個方法(空參構造)
            public Person() {}
         */
        String name;
        //實例化初始值
        /*
        1.使用new關鍵字,本質是再調用構造器
         */
        public Person(){
        }
        /*
        2.有參構造,一旦定義了有參構造,無參必須顯示定義
         */
        public Person(String name){
            this.name = name;
        }
    }
    public static void main(String[] args) {
        //實例化一個對象
        Person person = new Person("葉凡");
        System.out.println(person.name);
    
    }

建立對象內存分析

  • 代碼

    public class Pet {
        public String name;
        public int age;
        public void shout(){
            System.out.println("叫了一聲!");
        }
    }
    public class Application {
        public static void main(String[] args) {
            Pet dog = new Pet();
            dog.name = "旺財";
            dog.age = 3;
            dog.shout();
            Pet cat = new Pet();
            cat.name = "湯姆";
            cat.age = 2;
            cat.shout();
        }
    }
  • 示意圖

  • 小結:

    • 類與對象

      • 類是一個模板,抽象
      • 對象是一個具體的實例
    • 方法

      • 定義,調用!
    • 對象的引用

      • 引用類型:基本類型(8)以外的,對象是經過引用來操做的:棧 ---> 堆
    • 屬性:字段Field/成員變量

      • 默認初始化(char-u0000/boolean-false/引用-null)
      • 修飾符 : 屬性類型 屬性名 = 屬性值、
    • 對象的建立和使用

      • 必須使用new關鍵字創造對象,構造器 Person Jack = new Person();
      • 對象的屬性 jack.name/jack.age
      • 對象的方法 jack.sleep();
      • 靜態的屬性
      • 動態的行爲

面向對象三大特性

封裝

  • 該露的露,該藏得藏

    • 咱們程序設計要追求 "高內聚,低耦合"。高內聚就是類的內部數據操做細節本身完成,不容許外部干涉;低耦合:僅暴露少許的方法給外部使用。
  • 封裝(數據的隱藏)

    • 一般,應禁止直接訪問一個對象中數據的實際表示,而應經過操做接口來訪問,這稱爲信息隱藏。
    • 記住一句話:屬性私有,set/get (快捷鍵 Alt+Insert)
    public class Student {
        /*
        private 屬性私有
         */
        private String name;//名字
        private int id;     //學號
        private char sex;   //性別
        private int age;    //年齡
    
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            //能夠加一些校驗
            if(age > 120 || age < 0){
                age = 3;
            }
            this.age = age;
        }
        /*
        提供一些能夠操做這個屬性得方法
        提供一個public的get/set方法
         */
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setName("葉凡");
        System.out.println(stu.getName());
        stu.setAge(999);
        System.out.println(stu.getAge());
    
    }
  • 好處

    • 提升程序的安全性,保護數據
    • 隱藏代碼的實現細節
    • 統一接口,造成規範
    • .系統可維護性增長了

繼承

  • 繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模

  • extends的意思是「擴展」,子類是父類的擴展

  • JAVA中類只有單繼承,沒有多繼承

  • final修飾的類不能被繼承

  • 繼承是類和類之間的一種關係。除此以外,類和類之間的關係還有依賴、組合、聚合等

    • 繼承關係的兩個類,一個爲子類(派生類),一個爲父類(基類),子類繼承父類,使用關鍵字extends來表示
    • 子類和父類之間,從意義上講應該具備"is a"的關係
    /*
    Person 人  父類/基類
    java中,全部類都直接或間接繼承Object類
    */
    public class Person {
        /*
        四個級別:
            public
            protected
            default
            private
         */
        private int money = 10_0000_0000;
        public void say(){
            System.out.println("說了一句話....");
        }
        public int getMoney() {
            return money;
        }
        public void setMoney(int money) {
            this.money = money;
        }
    }
    public static void main(String[] args) {
        Student stu = new Student();
        stu.say();
        System.out.println(stu.getMoney());
    }
  • super注意點

    • super調用父類的構造方法,必須在構造方法的第一行
    • super 必須只能出如今子類的方法或者構造方法中
    • super 和 this 不能同時調用構造方法(由於都要在第一行)
  • VS this

    • 表明對象不一樣

      this:表明調用者這個對象

      suoer:表明父類對象的應用

    • 前提

      this:沒有繼承也能夠用

      super:只能在繼承條件纔可使用

    • 構造方法

      this:本類的構造

      super:父類的構造

  • Ctrl + H:顯示繼承關係

    //父
    public class Person {
       protected String name = "葉凡";
       public void print(){
           System.out.println("Person");
       }
       public Person(){
           System.out.println("Person無參構造執行了");
       }
    }
    //子
    public class Student extends Person {
        private String name = "葉依水";
        public void print(){
            System.out.println("Student");
        }
        public Student(){
            //隱藏代碼super():調用了父類的無參構造
            System.out.println("Student無參構造執行了");
        }
        public void test1(String name){
            System.out.println(name); //石昊
            System.out.println(this.name); //葉依水
            System.out.println(super.name);//葉凡
        }
        public void test2(){
            print();
            this.print();
            super.print();
        }
    }
    //效果
    public static void main(String[] args) {
        Student stu = new Student();
        stu.test1("石昊");
        stu.test2();
    }
  • 方法重寫

    • 前提:須要有繼承關係,子類重寫父類的方法!

      • 方法名必須相同
      • 參數列表必須相同
      • 修飾符:範圍能夠擴大,但不能縮小 (public > protected > default > private)
      • 拋出異常:範圍,能夠被縮小,不能擴大 ClassNotFoundException --> Exception
    • 子類的方法和父類的方法必需要一致,只方法體不一樣

    • 爲何須要重寫?

      • 父類的功能子類不須要或者不知足!
      • Alt + Insert ---> override
      //重寫都是方法的重寫,與屬性無關
      public class A{
          public void test(){
              System.out.println("A-->test()");
          }
      }
      public class B extends A{
          @Override //重寫,註解:有功能的註釋
          public void test() {
              super.test();
          }
      }
      //運行
      public class Application {
          /*
          靜態方法和非靜態方法區別很大:
              靜:方法調用只和左邊類型有關
              非靜:才能夠重寫,子類重寫了父類的方法
           */
          public static void main(String[] args) {
              B b = new B();
              b.test();
              //父類指向子類
              A a = new B();
              a.test();
          }
      }

多態

  • 同一方法能夠根據發送對象的不一樣而採用多種不一樣的行爲方式

  • 一個對象的實際類型是肯定的,但能夠指向對象的引用的類型有不少

  • 多態存在的條件

    • 有繼承關係
    • 子類重寫父類方法
    • 父類引用指向子類對象
  • 注意事項

    • 多態是方法的多態,屬性沒有多態性
    • 父類和子類,有聯繫,類型轉換異常! ClassCastException !
    • 存在的條件:繼承關係,方法須要重寫,父類指向子類對象!Fathor f = new Son();
    public static void main(String[] args) {
        //一個對象的實際類型是肯定的
        Student student = new Student();
        Person person = new Person();
            /*
            能夠指向引用類型就不肯定了:
                父類的引用指向子類,這就是多態
                不能調用子類的獨有方法
             */
            Person stu = new Student();
        Object os = new Student();
        stu.run();
    }
  • instanceof (類型轉換)引用類型,判斷要給對象是什麼類型

    public static void main(String[] args) {
          //Object > Person > Student
          Object obj = new Student();
          System.out.println(obj instanceof Student); //true
          System.out.println(obj instanceof Person);  //true
          System.out.println(obj instanceof Object);  //true
          System.out.println(obj instanceof Teacher); //false
          System.out.println(obj instanceof String);  //false
    
          System.out.println("==========");
    
          Person per = new Student();
          System.out.println(per instanceof Student); //true
          System.out.println(per instanceof Person);  //true
          System.out.println(per instanceof Object);  //true
          System.out.println(per instanceof Teacher); //false
          //System.out.println(per instanceof String);  //編譯都報錯了!
    
          System.out.println("==========");
    
          Student stu = new Student();
          System.out.println(stu instanceof Student); //true
          System.out.println(stu instanceof Person);  //true
          System.out.println(stu instanceof Object);  //true
          //System.out.println(stu instanceof Teacher); //編譯報錯!
          //System.out.println(per instanceof String);  //編譯都報錯了!
    
      }
  • 類型轉換

    • 父類引用指向子類的對象
    • 把子類轉爲父類,向上轉型
    • 把父類轉爲子類,向下轉型,強制轉換
    • 方便方法的調用,減小重複的代碼!
    //父轉子
    public static void main(String[] args) {
        //類型之間轉換:父   子
        //高                低
        Person per = new Student();
        per.run();
        //per.go();不可以使用
        //將這個對象轉換成Student類型,就能夠用student類的方法了
        Student stu = (Student) per;
        stu.go();
    }
    //子轉父,會丟失子類的方法
    public static void main(String[] args) {
        Student stu = new Student();
        stu.go();
        Person per = stu;
        //per.go();//不可以使用
    }
  • static

    public class Student{
        private static int age; //靜態變量 多線程會多用!
        private double score;   //非靜態變量
        public void run(){
            System.out.println("run...");
        }
        public static void go(){
            System.out.println("go...");
        }
        public static void main(String[] args) {
            Student stu = new Student();
            System.out.println(stu.score);
            System.out.println(stu.age);
            //System.out.println(Student.score);//不可以使用
            System.out.println(Student.age);
    
            //run()://不可調用
            new Student().run();
            go();//能夠用
        }
    }
    public class Person {
        {
            /*
            代碼塊(匿名代碼塊)建立對象時候建立
            附初始值
             */
            System.out.println("匿名代碼塊");
        }
        static{
            /*
            靜態代碼塊(加載初始化內容)
            類加載就執行了,永久執行一次~
             */
            System.out.println("靜態代碼塊");
        }
        public Person(){
            System.out.println("構造器");
        }
        public static void main(String[] args) {
            Person person = new Person();
            /*
            執行順序
                1.靜態代碼塊
                2.匿名代碼塊
                3.構造器
             */
        }
    }
    /*
    靜態導入包
     */
    import static java.lang.Math.random;
    import static java.lang.Math.PI;
    public class Test {
        public static void main(String[] args) {
            //System.out.println(Math.random());
            System.out.println(random());
            System.out.println(PI);
        }
    }
    /*
    被final修飾的類就斷子絕孫了...
    被final修飾的基本變量必須有初始值,且不可更改
    被final修飾的引用變量不能在指向其餘對象
    */

抽象類和接口

抽象類

  • abstract修飾符能夠用來修飾方法也能夠修飾類,若是修飾方法,那麼該方法就是抽象方;若是修飾類,那麼該類就是抽象類

    //abstract 抽象類: 類,extends 單繼承~  接口能夠多實現
    public abstract class Action {
        /*
        abstract 抽象方法,只有方法名,沒有方法的實現!
        約束,幫咱們實現
         */
        public abstract void doSomething();
        /*
        1.不能new抽象類,只能開子類去實現:約束!
            new的話編譯報錯:'Action' 是抽象的;沒法實例化
        2.抽象類中能夠寫普通方法
        3.抽象方法必須在抽象類中
        
        抽象的抽象:約束
        思考題? 存在構造器嗎?
        存在的意義 抽象出來~ 提升開發效率
         */
    }
    /*
    抽象類的全部方法,除非子類也是抽象類,不然繼承了他的子類都要實現他的方法~
     */
    public class A extends Action{
        @Override
        public void doSomething() {
    
        }
    }

接口

  • 比較

    • 普通類,只有具體實現
    • 抽象類,具體實現和規範(抽象方法)都有!
    • 接口,只有規範!本身沒法寫方法~專業的約束!約束和實現分離:面對接口編程
  • 接口就是規範,定義的是一組規則,體現了現實世界中 "若是你...則必須能...的思想"

    • 若是你是天使,則必須能飛。若是你是汽車,則必須能跑。若是你好人,則必須幹掉壞人;若是你是壞人,則必須欺負好人
  • 接口的本質是契約,就像咱們人間的法律同樣。制定好後你們都遵照

  • oop的精髓,是對對象的抽象,最能體現這一點的就是接口。爲何咱們討論設計模式都只針對具有了抽象能力的語言(好比c++、java、 c# 等),就是由於設計模式所研究的,實際上就是如何合理的去抽象

    //抽象的思惟~ Java
    //關鍵字 interface
    public interface UserService {
        //常量~ public static final
        int AGE = 99;
        //接口中的全部定義的方法都是抽象的 public abstract
        void add(Long id);
        void delete(Long id);
        void update(Long id);
        void query(Long id);
    }
    public interface TimeService {
        void timer();
    }
    /*
    類能夠實現接口 implements 接口
    實現了接口的類,就須要重寫接口中的方法~
    多實現~利用接口實現多繼承
     */
    public class UserServiceImpl implements UserService,TimeService{
        @Override
        public void add(Long id) { }
        @Override
        public void delete(Long id) { }
        @Override
        public void update(Long id) { }
        @Override
        public void query(Long id) { }
        @Override
        public void timer() { }
    }
  • 做用

    • 約束
    • 定義一些方法,讓不一樣的人實現
    • 接口都是public abstract
    • 常量都是public static final
    • 接口不能被實例化,接口中沒有構造方法
    • 接口可implements多個,必須重寫接口中全部的方法

內部類及OOP實戰

  • 內部類就是在一個類的內部在定義一個類。好比A類中定義一個B類,那麼B類相對A類來講就稱爲內部類,而A類相對B類來講就是外部類了

    public class Outer {
        private int age = 10;
        public void out(){
            System.out.println("這是外部類方法");
        }
    
        public class Inner{
            public void in(){
                System.out.println("這是內部類方法");
            }
            public void getAge(){
                System.out.println(age);
            }
        }
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        //經過這個外部類來實例化內部類~
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getAge();//10
    }
    
    //若是內部類加修飾詞static成爲靜態內部類
    public static class Inner{
        public void getAge(){
            //System.out.println(age);編譯都出錯了,static實例化在age以前因此拿不到age了。除非age也成爲靜態變量
        }
    }
    
    /*
    一個java類中能夠有多個class類,可是隻能由一個 public 修飾的 class
     */
    public class Outer {
    }
    class A{
    }
    
    //寫在外部類方法中的類就是局部內部類
    public class Outer {
        public void method(){
            class Inner{
                public void in(){
                    System.out.println("局部內部類");
                }
            }
        }
    }
    
    /*
    匿名內部類的更多實現
     */
    public class Test {
        public static void main(String[] args) {
            //沒有名字初始化類,不用將實例保存到變量中
            new Apple().eat();
    
            //匿名內部類實現接口
            UserService userService = new UserService() {
                @Override
                public void hello() {
                }
            };
        }
    }
    class Apple{
        public void eat(){
            System.out.println("1");
        }
    }
    interface UserService{
        void hello();
    }
  • 思想很重要!!!

相關文章
相關標籤/搜索