Java_2 面向對象

目錄

  • 對象
  • 構造方法
  • 引用與對象實例
  • static
  • final
  • 封裝
  • 繼承
  • 方法重載與重寫
  • 多態
  • 抽象類
  • 接口
  • 內部類


Java是面向對象的高級語言,類和對象是Java程序的核心。

類和對象

當我們買一部手機時,需要的是內存大一點、運行速度快一點、像素高一點等等,它是對象麼?
不是,它是一個類。
當我們買了一部華爲時,它就是一個對象。對象是具體的、確定的物體。
這部手機的顏色、尺寸、編號等是它的屬性;我們使用手機來打電話、發短信的行爲是它的“方法”。

  • 創建類
    類,是具有相同屬性和方法的對象的集合。

    public class 類名{
    // 屬性(成員變量)
    屬性類型1 屬性命1;
    ...
    
    // 方法
    方法1;
    ...
    

    一個類可以包含以下類型變量:
    局部變量:在方法、構造方法或者語句塊中定義的變量被稱爲局部變量。變量聲明和初始化都是在方法中,方法結束後,變量就會自動銷燬。
    成員變量:成員變量是定義在類中,方法體之外的變量。這種變量在創建對象的時候實例化。成員變量可以被類中方法、構造方法和特定類的語句塊訪問。
    類變量:也叫靜態變量,類變量也聲明在類中,方法體之外,但必須聲明爲 static 類型。

  • 創建對象
    創建類時,不會開闢內存進行存儲。當創建對象時,纔開闢內存存儲屬性和方法。

    類名 對象名 = new 類名();
    
    // Test.java
    public class Test{
    	// 屬性(成員變量)
        double height;
        int age;
        int sex;  // 性別,0爲男;非0爲女
    	// 方法
        void laugh(){
            System.out.println("我有笑");
        }
        void printBaseMes(){
            System.out.println("我的身高是:" + height);
            System.out.println("年齡:" + age);
            if (this.sex == 0){
                System.out.println("男");
            }
            else{
                System.out.println("女");
            }
        }
    }
    // NewObj.java
    public class NewObj{
        public static void main(String[] args){
            Test test = new Test();
    
            test.height = 170;
            test.age = 20;
            test.sex = 0;
    
            test.printBaseMes();
        }
    }
    

    關於對象中各變量的作用域:
    1.局部變量的作用域僅限於定義它的方法內。而成員變量的作用域在整個類內部都是可見的。
    2.同時在相同的方法中,不能有同名的局部變量;在不同的方法中,可以有同名的局部變量。
    3.成員變量和局部變量同名時,局部變量具有更高的優先級。

構造方法

  • 每個類至少會生成一個構造方法
    1.構造方法名稱與類名相同,沒有返回值。
    2.如定義類時如未定義構造方法,系統自動生成無參構造方法;如定義,則不再自動生成。

    // Test1.java
    public class Test1{
        double height;
        int age;
    
        public Test1(double h, int a){
            height = h;
            age = a;
        }
    
        void print(){
            System.out.println("我的身高:" + height);
            System.out.println("我的年齡:" + age);
        }
    }
    
    // NewObj.java
    public class NewObj{	
        public static void main(String[] args){
            Test1 t1 = new Test1(170, 22);
            t1.print();
        }
    }
    

    3.構造方法的重載:可以定義多個構造方法,使用時系統據給定的不同參數自動選擇相應的構造方法。

    // Test1.java
    public class Test1{
        double height;
        int age;
        int sex;  // 性別,0爲男,非0爲女
    
        public Test1(double h, int a){
            height = h;
            age = a;
        }
        public Test1(int s){
            sex = s;
        }
    
    
        void print(){
            System.out.println("我的身高:" + height);
            System.out.println("我的年齡:" + age);
        }
        void printSex(){
            if (sex == 0){
                System.out.println("男");
            }
            else{
                System.out.println("女");
            }
        }
    }
    
    // NewObj.java
    public class NewObj{
        public static void main(String[] args){
            Test1 t1 = new Test1(170, 22);
            t1.print();
            Test1 t2 = new Test1(0);
            t2.printSex();
        }
    }
    

引用與對象實例

當Java新建一個對象時,只是創建了一種引用,類似於c語言中的指針,指向內存中存儲數據的地址。

static

  • 靜態成員(或類成員)
    // Static.java
    public class Static{
        public static String str = "shiyan";
        public String str1 = "test";
        public static void main(String[] args){
        	// 靜態成員,不需要實例化可以直接通過類名訪問
            System.out.println(Static.str);
    		// 非靜態成員,必須實例化後纔可訪問
            Static str2= new Static();
            System.out.println(str2.str1);
        }
    }
    
  • 靜態方法
    不需要實例化即可調用。
    不能使用關鍵字this,不能訪問非靜態成員和非靜態方法。

final

final 修飾類,則該類不允許被繼承,爲最終類
final 修飾方法,則該方法不允許被覆蓋(重寫)
final 修飾屬性,則該類的屬性不會進行隱式的初始化(類的初始化屬性必須有值)或在構造方法中賦值(但只能選其一)
final 修飾變量,則該變量的值只能賦一次值,即常量

public final static String Test = "test";

封裝

隱藏對象的屬性和實現細節,僅對外公開接口,並控制對象屬性的讀和修改的權限。

  • 權限修飾符
訪問修飾符 本類 同包 子類 其它
private 1
默認 1 1
protected 1 1 1
public 1 1 1 1
  • getter/setter
    對外提供的每個屬性讀寫的公共訪問方法。並在getter/setter中加入判斷語句,否定非法輸入。
// Test1.java
public class Test1{
    private double height;
    public double getHeight(){
        return height;
    }
    public void setHeight(double newHeight){
        height = newHeight;
    }
}

// NewObj.java
public class NewObj{
    public static void main(String[] args){
        Test1 t1 = new Test1();
        t1.setHeight(177);
        System.out.println(t1.getHeight());
    }
}
  • this
    代表當前對象。
    當成員變量與局部變量相同時,局部變量優先級更高。如需訪問成員變量,使用this.屬性。方法亦同。

繼承

解決代碼複用的問題。

class 子類 extends 父類

子類擁有父類除private以外的所有屬性和方法;
子類可以有自己的屬性和方法;
子類可以重寫父類的方法;
Java中的繼承是單繼承,一個類只有一個你類。
補:Java實現多繼承的方法implements接口。

// Animal.java
public class Animal{
    public int legNum;

    public void bark(){
        System.out.println("叫");
    }
}

// Dog.java
public class Dog extends Animal{
}

// Test.java
public class Test{
    public static void main(String[] args){
        Dog dog = new Dog();
        dog.legNum = 4;
        dog.bark();
    }
}
  • super
    在子類內部使用,代表父類對象。
    1.父類屬性:super.屬性
    2.父類方法:super.bark()
    3.子類構造方法需要調用父類的構造方法時,在子類構造方法體最前面加上:super()

方法重載與重寫

  • 方法重載
    一個類中可以定義多個同名的方法,但每個方法的參數類型或參數個數都不一樣。

方法中的參數列表必須不同。比如:參數個數不同或者參數類型不同。
重載的方法中允許拋出不同的異常
可以有不同的返回值類型,但是參數列表必須不同
可以有不同的訪問修飾符

public class Test{
    void f(int i){
        System.out.println(i);
    }
    void f(double d){
        System.out.println(d);
    }
    void f(String s1, String s2){
        System.out.println(s1 + s2);
    }
    void f(String s, int i){
        System.out.println(s + ", " + i);
    }

    public static void main(String[] args){
        Test t = new Test();
        t.f(0);
        t.f(1.0);
        t.f("I", "love u");
        t.f("I", 4);
    }
}
  • 方法重寫
    子類繼承父類的方法後,可以方法進行重寫。
// Animal.java
public class Animal{
    void bark(){
        System.out.println("叫");
    }
}

// Dog.java
public class Dog extends Animal{
	// 重寫
    void bark(){
        System.out.println("汪");
    }
}

// Test.java
public class Test{
    public static void main(String[] args){
        Animal ani = new Animal();
        Dog dog = new Dog();
        ani.bark();
        dog.bark();
    }
}

多態

又稱動態綁定。
同一消息,發送給不同的對象,產生不同的行爲。

  • 向上轉型
    子類可以自動向上轉型爲父類。反之,不行。
public class Test{

    public static void main(String[] args){
    	// Dog -> Animal
    	// 遺忘子類中與父類不同的方法,重寫與父類相同的方法
        Animal ad = new Dog();
        ad.bark();
    }
}
  • 多態的實現條件:繼承、重寫、向上轉型
  • 多態的實現方式
    1.繼承父類進行方法重寫
    2.抽象類和抽象方法
    3.接口實現

抽象類

抽象類的實現規則:
用 abstract 修飾符定義抽象類
用 abstract 修飾符定義抽象方法,只用聲明,不需要實現
包含抽象方法的類就是抽象類
抽象類中可以包含普通的方法,也可以沒有抽象方法
抽象類的對象不能直接創建,通常是定義引用變量指向子類對象。

使用抽象類:
1.自上而下的設計時,只需知道父類需要實現哪些功能,不需關心子類具體的實現方式;
2.從多個類中抽象出子類模版。

// TelePhone.java
public abstract class TelePhone{
    public abstract void call();
    public abstract void message();
}

// CellPhone.java
public class CellPhone extends TelePhone{

    @Override
    public void call(){
        System.out.println("打電話");
    }
    @Override
    public void message(){
        System.out.println("發短信");
    }

    public static void main(String[] args){
        CellPhone c = new CellPhone();
        c.call();
        c.message();
    }
}

接口

用於描述類所具有的功能,而不提供實現的方式。

修飾符 interface 接口名稱 [extends 其它接口名]{
	// 聲明變量
	// 抽象方法
}

// 多繼承實現方式
修飾符 interface A extends 接口1,接口2{
}

修飾符 class A implements 接口1, 接口2{
}
// Animal.java
interface Animal{
    int y = 7;
    public void eat();
    public void run();
}

// Dog.java
public class Dog implements Animal{

    public void eat(){
        System.out.println("Dog eat");
    }
    public void run(){
        System.out.println("Dog run");
    }
    public static void main(String[] args){
        Dog d = new Dog();
        System.out.println(d.y);
        d.eat();
        d.run();
    }
}

內部類

將一個類定義到另一個類的內部。與之對應的類爲外部類。作用:
1.更好的封裝;
2.內部類可以訪問外部類的所有變量;
3.有些功能使用內部類可以更好的實現;
4.內部類允許繼承多個非接口類型。

內部類是一個編譯時的概念,一旦編譯成功,就會成爲完全不同的兩類。對於一個名爲 outer 的外部類和其內部定義的名爲 inner 的內部類。編譯完成後出現 outer.class 和 outer$inner.class 兩類。所以內部類的成員變量/方法名可以和外部類的相同。

  • 成員內部類
// Animal.java
public class Animal{
    private int ID = 0;
    // 內部類 Dog
    public class Dog{
        String name = "dog";
        public void bark(){
            System.out.println("汪");
        }
    }

    public static void main(String[] args){
        Animal ani = new Animal();
        Dog dog = ani.new Dog();
        dog.bark();
    }
}

1.Dog相當於Animal的一個成員變量;
2.Dog的方法可以訪問Animal的所有屬性和方法;
3.成員內部類的實例化:內部類 對象名 = 外部類.new 內部類();
4.如內部類與外部類有相同屬性或方法,內部類默認優先訪問內部類的屬性或方法。如需訪問外部類的屬性或方法,使用this關鍵字;
5.成員內部類不能含有 static 的變量和方法,因爲成員內部類需要先創建了外部類,才能創建它自己。

  • 靜態內部類
    嵌入類。
// Animal.java
public class Animal{

    private int legNum = 4;
    static String ID = "20200001";
    static int age = 3;

    public static class Dog{
        String ID = "20200002";
        public void printInfo(){
            System.out.println("Dog ID:" + ID);
            System.out.println("Animal age:" + age);
            System.out.println("Animal ID:" + Animal.ID);
            System.out.println("Animal legNum:" + new Animal().legNum);
        }
    }

    public static void main(String[] args){
        Dog dog = new Dog();
        dog.printInfo();
    }
}

1.靜態內部類成員名與外部靜態成員名相同時,靜態內部類優先訪問自身的成員:成員
2.外部類的靜態成員名與靜態內部類不同名時,靜態內部類可直接訪問:成員
3.靜態內部類訪問外部類的靜態成員:外部類名.靜態成員
4.靜態內部類訪問外部類的非靜態成員:new 外部類().成員
5.靜態內部類可以直接實例化:靜態內部類 對象 = new 靜態內部類().

  • 局部內部類
    內部類定義在方法和作用域內。
// Animal.java
public class Animal{

    // 定義在方法內
    public void printInfo(){
        final String NAME = "Animal";
        class Dog{
            String ID = "20200002";
            public void print(){
                System.out.println("Dog ID:" + ID);
                System.out.println("printInfo() NAME:" + NAME);
            }
        }
        Dog dog = new Dog();
        dog.print();
    }
    // 定義在作用域內
    public void printInfo2(boolean b){
        if (b){
            final String NAME = "Animal_";
            class Dog{
                String ID = "20200002_";
                public void print(){
                    System.out.println("Dog ID:" + ID);
                    System.out.println("printInfo2() NAME:" + NAME);
                }
            }
            Dog dog = new Dog();
            dog.print();
        }
    }
    // test
    public static void main(String[] args){
        Animal ani = new Animal();
        // 方法內
        ani.printInfo();
        // 作用域內
        ani.printInfo2(true);
    }
}

如何理解定義在作用域內?

  • 匿名內部類
    沒有名字的內部類,只能使用一次,通常用來簡化代碼。
    使用前提:必須繼承一個父類,或實現一個接口
// Outer.java
public class Outer{

    public Inner getInner(final String name, String city){
        return new Inner(){
            private String nameStr = name;
            public String getName(){
                return nameStr;
            }
        };
    }

    public static void main(String[] args){
        Outer outer = new Outer();
        Inner inner = outer.getInner("Inner", "NewYork");
        System.out.println(inner.getName());
    }
}
interface Inner{
    String getName();
}

1.匿名類不能加訪問修飾符;
2.new 匿名類(),要先定義,否則會報錯;
3.當所匿名類所在方法的形參需要在匿名類內部使用時,必需使用final

// 因匿名內部類無名字,默認無參構造函數
// 帶參構造函數的實現
    public Inner getInner(final String name, string city){
        return new Inner(name, city){
            private String nameStr = name;
            public String getName(){
                return nameStr;
            }
        };
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章