天天看點

Java學習路線-2:面向對象-類

2、面向對象簡介

Java語言最大特點:面向對象程式設計設計

面向過程:C語言,面對一個問題的解決方案

面向對象:C++/Java,子產品化設計,進行重用配置,考慮标準

1、面向對象三個主要特征:

封裝性:内部操作對外部不可見

繼承性:已有結構的基礎上繼續進行功能擴充

多态性:是在繼承性的基礎上擴充而來的概念,指類型的轉換處理

2、面向對象開發三個步驟:

OOA:面向對象分析

OOD:面向對象設計

OOP:面向對象程式設計

3、類與對象

類:對某一類事物共性的抽象

對象:描述一個具體的産物

類是一個模型,對象是類可以使用的執行個體

先有類再有對象

類的組成:

成員屬性Field 簡稱屬性

操作方法Method 對象的行為

4、類與對象的定義及使用

Java中,類是一個獨立的結構體

屬性就是變量

方法就是可以重複執行的代碼

// 定義類
class Person {
    // 定義屬性
    String name;  // 引用資料類型 預設值 null
    int age;      // 基礎資料類型 預設值 0

    // 定義方法
    public void tell(){
        System.out.println("姓名:" + this.name + " 年齡:" + this.age);
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.name = "張三";
        person.age = 18;
        person.tell();
        // 姓名:張三 年齡:18
    }

}      

生産對象兩種方式:

1、聲明并執行個體化對象

類名稱 對象名稱 = new 類名稱();

2、分步完成

(1)聲明對象:類名稱 對象名稱 = null;

(2)執行個體化對象:對象名稱 = new 類名稱();

執行個體化對象調用操作:

調用屬性:執行個體化對象.成員屬性;

調用方法:執行個體化對象.方法名稱();

5、記憶體對象分析

最常用的2塊記憶體空間

堆記憶體:儲存對象具體資訊 new開辟堆記憶體空間

棧記憶體:儲存一塊堆記憶體位址

/**
棧記憶體              堆記憶體     
位址Ox0001    ->   對象内容
*/


// 方式一
Person person = new Person();


// 方式二
Person person = null;
person = new Person();
      

所有的對象在調用屬性或方法之前,必須執行個體化

6、對象引用分析

同一塊堆記憶體可以被不同的棧記憶體所指向,也可以更換指向

修改person2, person1也會被修改

Person person1 = new Person();
person1.name = "張三";
person1.age = 19;

Person person2 = person1;
person2.tell();
// 姓名:張三 年齡:19      

引用傳遞可以發生在方法調用

public static void main(String[] args) {
    Person person = new Person();
    person.name = "張三";
    person.age = 18;
    
    change(person); // 相當于: Person temp = person;

    person.tell();
    // 姓名:李四 年齡:18
}

public static void change(Person temp){
    temp.name = "李四";
    // 方法結束後斷開引用
}      

7、引用于垃圾産生分析

垃圾空間:沒有任何棧記憶體指向的堆記憶體空間

垃圾會被GC(Garbage Collector)垃圾收集器定期回收

垃圾過多會影響GC性能

一個棧記憶體隻能儲存有一個堆記憶體的位址資料

Person person1 = new Person(); // Ox0001
Person person2 = new Person(); // Ox0002

person2 = person1;   // 此時 person2 指向的 Ox0002 對象成為了垃圾      

8、成員屬性封裝

封裝:對資料進行保護

private關鍵字對外不可見

使用setter、getter設定或擷取屬性

類中的所有屬性都必須使用private封裝,需要提供setter、getter方法

class Person {
    
    // 私有化屬性
    private String name; 

    // 對外提供geter, setter方法
    public void setName(String n){
        name = n;
    }

    public String getName(){
        return name;
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.setName("張三");
        System.out.println(person.getName());
        // 張三
    }
}      

9、構造方法與匿名對象

現有程式使用類,經過了2個步驟:

1、聲明執行個體化對象,隻能使用預設值

2、通過 setter 方法設定屬性

構造方法: 執行個體化對象時進行資料初始化

1、構造方法名與類名必須一緻

2、構造方法無傳回值

3、構造方法在new執行個體化對象時自動調用

class Person {
    
    // 私有化屬性
    private String name; 
    
    // 有參構造方法
    public Person(String n){
        name = n;
    }

    public static void main(String[] args) {
        Person person = new Person("張三");
        System.out.println(person.getName());
        // 張三
    }
}
      

(1)Person 定義對象所屬類型,類型決定可以調用的方法

(2)person 執行個體化對象的名稱

(3)new 開辟新的堆記憶體空間

(4)Person(“張三”) 調用構造函數(有參,無參)

所有的類都會提供有無參構造方法,程式編譯時自動建立,如果明确構造方法則不自動建立

結論:一個類至少存在一個構造方法

問題:構造方法沒有傳回值?不使用void

構造方法與普通方法差別:

構造方法在類對象執行個體化時調用

普通方法在類對象執行個體化之後調用

構造方法重載

隻用考慮方法簽名(參數個數,類型,順序)

按照參數數量順序排列構造方法

class Person {
    
    // 私有化屬性
    private String name; 
    
    // 無參構造方法
    public Person(){
    }

    // 有參構造方法
    public Person(String n){
        name = n;
    }

    public String getName(){
        return name;
    }

    public static void main(String[] args) {
        Person person = new Person("張三");
        System.out.println(person.getName());
        // 張三
    }
}      

匿名對象

new Person("張三").getName());
// 張三      

使用一次後就會被GC回收釋放

方法可以傳遞基本資料類型和引用資料類型

10、this調用本類屬性

三類描述

1、目前類中的屬性 this.屬性

2、目前類中的方法(構造方法:this()、普通方法:this.方法())

3、描述目前對象

通路本類中的屬性一定要加this

public Person(String name, int age){
    this.name = name ;
    this.age = age ;
}      

11、this調用本類方法

1、調用普通方法

setName(name) ;

// 或者

this.setName(name) ;
      

好的代碼:

代碼結構可以重用

沒有重複代碼

2、調用構造方法

this()

必須在執行個體化新對象的時候調用

隻允許放在構造函數首行

互相調用必須有出口

// 無參構造方法
public Person(){
    this("張三");
}

// 有參構造方法
public Person(String name){
    this.name = name;
}      

構造方法調用實作預設參數

class Person {
    
    // 私有化屬性
    private String name; 
    private int age;

    // 無參構造方法
    public Person(){
        this("張三");
    }

    // 一參構造方法
    public Person(String name){
        this(name, 21);
    }

    // 兩參構造方法
    public Person(String name, int age){
        this.name = name;
        this.age = age ;
    }

    public void getInfo(){
        System.out.println("name: " + this.name + " age: " + this.age);
    }

    
    public static void main(String[] args) {
        new Person().getInfo();
        new Person("李四").getInfo();
        new Person("王五", 22).getInfo();
        /*
        name: 張三 age: 21
        name: 李四 age: 21
        name: 王五 age: 22
        */
    }
}      

12、綜合實戰:簡單Java類

簡單Java類:

可以描述某一類資訊的程式類,沒有特别複雜的操作,隻作為一種資訊存儲的媒介

核心結構

1、類名有意義,明确描述某一類事物

2、屬性必須使用private封裝,提供setter、getter

3、可以提供多個構造方法,必須保留無參構造方法

4、不允許有任何輸出,内有擷取必須傳回

非必須:

1、可以提供擷取對象詳細資訊方法,getInfo()

涉及概念

資料類型、類的定義、private封裝、方法定義、對象執行個體化

class Person {
    
    // 私有化屬性
    private String name; 
    private int age;

    // 無參構造方法
    public Person(){
        this("張三", 23);
    }

    // 兩參構造方法
    public Person(String name, int age){
        this.name = name;
        this.age = age ;
    }

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

    public String getName(){
        return this.name ;
    }

    public void setAge(int age){
        this.age = age;
    }

    public int getAge(){
        return this.age ;
    }

    public String getInfo(){
        return "name: " + this.name + " age: " + this.age;
    }

    public static void main(String[] args) {
        System.out.println(new Person("王五", 22).getInfo());
        // name: 王五 age: 22
    }
}      

13、聲明static屬性

static修飾的屬性為公共屬性,一個對象修改,所有對象都會被修改

應該由類來進行通路,而不是對象,可以由類名來調用

static 屬性不受類執行個體化限制,不執行個體化也可以調用

進行類設計時首選非static屬性,涉及公共資訊才使用static

全局資料區        棧記憶體      堆記憶體
static 資料      person1   ->  {name, age}
                person1   ->  {name, age}      
class Person {
    String name; 
    static String country;
    
    public Person(String name){
        this.name = name;
    }

    public static void main(String[] args) {
        Person person1 = new Person("張三");
        Person person2 = new Person("李四");

        Person.country = "中國";
        System.out.println(person1.country);
        System.out.println(person2.country);
        // 中國   中國
    }
}      

14、聲明static方法

static方法隻允許調用static屬性或static方法

static屬性和方法都可以在沒有執行個體化對象的前提下使用

應用場景:

回避執行個體化對象調用并且描述公共屬性的情況

15、static應用案例

實作執行個體化對象個數統計

class Person {
    
    static int count;

    public Person(){
        count ++;
        System.out.println("第 " + count + " 個執行個體");
    }

    public static void main(String[] args) {
        new Person();
        new Person();
        new Person();
        /*
        第 1 個執行個體
        第 2 個執行個體
        第 3 個執行個體
        */
    }
}      

16、普通代碼塊

代碼塊:由"{}"定義的結構

分類:

1、普通代碼塊

2、構造代碼塊

3、靜态代碼塊

4、同步代碼塊(多線程)

普通代碼塊

定義在方法中的代碼塊

// 普通代碼塊
{
    int age = 12;
    System.out.println(age);  // 12
}

int age = 15;
System.out.println(age);  // 15      

17、構造代碼塊

構造塊優先于構造方法執行,每次執行個體化都會調用構造代碼塊

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

    {
        System.out.println("構造代碼塊");
    }

    public static void main(String[] args) {
        new Person();
        new Person();
        /**
        構造代碼塊
        構造方法
        構造代碼塊
        構造方法
        */
    }
}      

18、靜态代碼塊

static關鍵字定義的代碼塊

靜态代碼塊優先于構造函數執行,不管執行個體化多少次隻會執行一次

主要目的是為了靜态屬性初始化

靜态代碼塊優先于主方法先執行

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

    {
        System.out.println("構造代碼塊");
    }

    static {
        System.out.println("靜态代碼塊");
    }

    public static void main(String[] args) {
        System.out.println("主方法代碼塊");
        new Person();
        new Person();
        /**
        靜态代碼塊
        主方法代碼塊
        構造代碼塊
        構造方法
        構造代碼塊
        構造方法
        /
    }
}      

19、案例分析一(Address)

實作一個位址類,包含國家,省份,城市,街道,郵政編碼

實作一個簡單java類

class Address {
    private String country;
    private String province;
    private String city;
    private String street;
    private String zipcode;

    // setter
    public void setCountry(String country){
        this.country = country;
    }

    public void setProvince(String province){
        this.province = province;
    }

    public void setCity(String city){
        this.city = city;
    }

    public void setStreet(String street){
        this.street = street;
    }

    public void setZipcode(String zipcode){
        this.zipcode = zipcode;
    }

    // getter
    public String getCountry(){
        return this.country;
    }

    public String getProvince(){
        return this.province;
    }

    public String getCity(){
        return this.city;
    }

    public String getStreet(){
        return this.street;
    }

    public String getZipcode(){
        return this.zipcode;
    }

    // info
    public String getInfo(){
        return "國家: " + this.country +
               ", 省份: " + this.province + 
               ", 城市: " + this.city + 
               ", 街道: " + this.street + 
               ", 郵政編碼: " + this.zipcode;
    }

    public Address(String country, String province, String city, String street, String zipcode){
        this.country = country;
        this.province = province;
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }


    public static void main(String[] args) {
        Address address = new Address("中國", "北京", "朝陽", "大望路", "10001");
        System.out.println(address.getInfo());
        // 國家: 中國, 省份: 北京, 城市: 朝陽, 街道: 大望路, 郵政編碼: 10001

    }
}      

20、案例分析二(Employee)

實作一個員工類,包含編号,姓名,薪水,稅率,還包括薪水增長計算和增長後的工資

class Employee{
    private long no;
    private String name;
    private double salary;
    private double rate;

    // setter getter ...

    public String getInfo(){
        return "編号:" + this.no + 
                ", 姓名: " + this.name + 
                ", 薪水 " + this.salary + 
                ", 漲幅: " + this.rate; 
    }

    public void increaseSalary(){
        this.salary = this.salary * (1 + this.rate);
    }

    public Employee(long no, String name, double salary, double rate){
        this.no = no;
        this.name = name;
        this.salary = salary;
        this.rate = rate;
    }

    public static void main(String[] args){
        Employee employee = new Employee(1L, "張三", 3000.0, 0.3);
        System.out.println(employee.getInfo());
        // 編号:1, 姓名: 張三, 薪水 3000.0, 漲幅: 0.3

        employee.increaseSalary();
        System.out.println(employee.getInfo());
        // 編号:1, 姓名: 張三, 薪水 3900.0, 漲幅: 0.3
    }

}      

21、案例分析三(Dog)

建立Dog類,有名字,顔色,年齡,定義構造方法初始化屬性

class Dog{
    private String name;
    private String color;
    private int age;

    // getter setter

    public Dog(String name, String color, int age){
        this.name=name;
        this.color=color;
        this.age=age;
    }

    public static void main(String[] args) {
        Dog dog = new Dog("小黑", "黑色", 2);
    }
        
}      

22、案例分析四(Account)

定義銀行賬戶類,包括

1、資料:賬戶名稱,賬戶餘額

2、方法:開戶(設定賬号,餘額),利用構造方法完成

3、查詢餘額

class Account{
    private String name;
    private double balance;

    public Account(String name){
        this(name, 0.0);
    }

    public Account(String name, double balance){
        this.name = name;;
        this.balance = balance;;
    }

    // 查詢餘額
    public double getBalance(){
        return this.balance;
    }

    public static void main(String[] args) {
        Account account = new Account("張三", 2000.0);
        System.out.println(account.getBalance());
        // 2000.0
    }
}      

23、案例分析五(User)

建立使用者類

1、使用者名,記錄使用者個數

2、擷取使用者數

class User{
    private String name;

    private static int count = 0;

    public User(String name){
        this.name = name;
        count++;
    }

    public static int getCount(){
        return count;
    }

    public static void main(String[] args) {
        User user1 = new User("小明");
        User user2 = new User("小紅");
        User user3 = new User("小花");

        System.out.println(User.getCount());
        // 3

    }
}      

24、案例分析六(Book)

建立圖書類

資料:書名,價格,編号(利用靜态資料實作自動編号)

方法:統計總數

class Book{
    private int uid;
    private String name;
    private double price;
    private static int count = 0;

    public Book(String name, Double price){
        count++;
        this.uid = count;
        this.name = name ;
        this.price = price ;
    }

    public String getInfo(){
        return "<"+ this.uid + "> <<" + this.name +">> "+ this.price;
    }

    public static int getCount(){
        return count;
    }

    public static void main(String[] args) {
        Book book1 = new Book("今日頭條", 12.0);
        Book book2 = new Book("百度", 14.0);
        Book book3 = new Book("騰訊", 11.0);

        System.out.println(Book.getCount()); 
        // 3
        
        System.out.println(book3.getInfo());
        // <3> <<騰訊>> 11.0
    }
}