Java小白入門教程(9)——面向對象

提綱:

<code>1、面向對象
2、類和對象
3、方法的重載
4、構造方法
5、this關鍵字
6、匿名對象
7、作業/<code> 


一、面向對象

1.1、生活中什麼是面向對象

<code>洗衣服,吃飯
面向過程:關注點是過程 ————站在一個執行者的角度去考慮事情,做事情
  //step1.找個盆
  //step2.收集要洗的衣服
  //step3.放水,放洗衣粉。。
  //step4:洗一洗
  //step5:曬一曬

面向對象:關注點是對象 ————站在指揮者的角度
  //step1:找個對象
  //step2:讓他洗衣服
  
  
生活中的面向對象:找合適的人,做合適的事兒。。
生活中的面向過程:親力親為,按照流程步驟來,一步一步,吭哧吭哧。。。
​
代碼中:
  Arrays類
    sort();-->排序
    binarySearch();-->搜索
  Scanner類
    sc.nextInt();
    sc.next();
    sc.nextDouble();/<code>



1.2、面向對象和麵向過程

<code>面向對象:(OOP)
  不是一種語言,而是一種編程思想。
  面向對象程序設計:(Object Oriented Programming)
    Object:對象
    Oriented:方向,定向
    Programming:程序
    
面向過程:
  關注點在過程上(步驟)
  step1,step2,step3.。。。。
  總和分析,按照步驟實現即可。
​
面向對象:
  關注點在對象上
    萬事萬物皆對象。
  A:分析當前的問題域中所涉及的對象。
  B:這些對象有什麼樣的特徵和功能。
    外部特徵:靜態屬性
    動作行為:動態屬性
  C:對象和對象之間的關係。
    繼承關係,聚合關係,關聯關係。。。
    
    類的堆砌。/<code> 


二、類和對象

2.1、類和對象

Java小白入門教程(9)——面向對象

<code>
類:其實指的就是類別。對同一類事物的統稱。對這類事物進行描述,--->創建class
 就是一個抽象的概念。
對象:
 類中的一個具體的實例,客觀存在的,能用。個體。
/<code>

如何定義一個類?

  • 要有能夠描述這一類別的外部特徵——我們叫做屬性(靜態屬性)
    變量就可以。(名詞)
  • 要有能夠描述這一類別的行為功能——我們叫做方法(動態屬性)
    方法就可以。(動詞)

2.2、Java中定義類的格式

<code>/*
class ClassName{//類名首字母大寫
  //屬性描述:外部特徵
  //行為描述:能夠幹啥
}
*/
要求:
    1、CLassName要求符合駝峰命名法,首字母大寫,見名知意。
    2、屬性描述:外部特徵,用於描述這個類別的一些特徵,而這些特徵通過一個"詞"來描述清楚,比如姓名,年齡。使用變量來表示。——【成員變量】Field,詞義"字段"
    3、行為描述:能夠幹啥,用於描述這個類別的一些行為功能,而這些行為功能,是一個動作行為,比如吃飯,睡覺。使用方法來表示。——【成員方法】Method,詞義"方法"
      不要加static。/<code> 

方法:就是一段具有獨立功能的代碼。

2.2.1 step1聲明類

<code>public class Person{//類的名字
​
}/<code>


2.2.2 step2聲明類中的【成員變量】

<code>public class Person {
  //step2:成員變量
  String name;//使用String類型的變量name,表示人類中的姓名
  
  int age;//使用int類型的變量age,表示人類中的年齡
  
  char sex;//使用char類型的變量sex,表示人類中的性別
  
  
}/<code>


2.2.3 step3聲明類中的【成員方法】

<code>public class Person {
  //step2:成員變量
  String name;//使用String類型的變量name,表示人類中的姓名
  
  int age;//使用int類型的變量age,表示人類中的年齡
  
  char sex;//使用char類型的變量sex,表示人類中的性別
  
  //step3:成員方法
  public void eat(){
    System.out.println("吃飯啦。。");
  }
  
  public void sleep(){
    System.out.println("睡覺啦。。");
  }
  
  public void daDouDou(){
    System.out.println("打豆豆。。。");
  }
}
​/<code>

2.3、類的對象

2.3.1 創建類的對象

創建對象,也叫做類的實例化。對象,也叫類的實例。

<code>/*
new關鍵字
new,詞義:新的,新建
new 關鍵字,專門用於新建對象。
*/
Scanner sc = new Scanner();//Scanner也是個類,Person也是個類。
int[] arr = new int[5];
​
語法結構:
/*
類名 對象名 = new 類名();
*/
Person p1 = new Person();/<code>

step2:根據類,實例化對象

step1:創建類


2.3.2通過對象訪問屬性

<code>/*
int[] arr = new int[5];
獲取數組的長度:
arr.length
arr的長度
*/
對象訪問屬性的語法:就是一個.
//給對象的屬性,進行賦值
p1.name = "王二狗";//給p1這個對象的name屬性進行賦值
p1.age = 18;
p1.sex = '男';
​
​
//獲取對象的屬性值
System.out.println("姓名:"+p1.name);
System.out.println("年齡:"+p1.age);
System.out.println("性別:"+p1.sex);/<code>


2.3.3通過對象訪問方法

<code>/*
Scanner sc = new Scanner();
sc.nextInt();
*/
Scanner,就是一個class,一個類
sc,是根據Scanner創建出來的一個對象
​
對象調用類中的方法,語法,也是.
對象.方法名();
p1.eat();
p1.sleep();
p1.daDouDou();/<code>


2.3 內存分析

實例代碼:

<code>package com.qf.demo01;
​
public class Test1Person {
​
  public static void main(String[] args) {
    //step1:創建Person類的對象
    //語法:類名 對象名 = new 類名();
    
    Person p1 = new Person();
    System.out.println(p1);//打印p1的值,p1是引用類型,打印都是p1指向的對象的地址。
    
    System.out.println(p1.name);
    System.out.println(p1.age);
    System.out.println(p1.sex);
    
    
    
    
    /*
     * com.qf.demo01.Person@15db9742
     * 包名.類名@編碼值  ---->理解為p1的內存地址。
     * 
     * java中的數據類型:
     *  基本類型:byte,short,char,int,long,bolean,float,double
     *  引用類型:
     *      數組,類類類型
     * 
     */
    //step2:通過對象訪問屬性,語法是.
    //給對象的屬性,進行賦值
    p1.name = "王二狗";//給p1這個對象的name屬性進行賦值
    p1.age = 18;
    p1.sex = '男';
    
    
    //獲取對象的屬性值
    System.out.println("姓名:"+p1.name);
    System.out.println("年齡:"+p1.age);
    System.out.println("性別:"+p1.sex);
    
    
    //step3:通過對象,訪問成員方法--->理解為就是對象調用成員方法
    p1.eat();
    p1.sleep();
    p1.daDouDou();
    
    
  }
​
}
​/<code> 

內存分析圖

Java小白入門教程(9)——面向對象


示例代碼:

<code>package com.qf.demo01;
​
public class Test2Person {
​
  public static void main(String[] args) {
    //1.創建一個Person類的對象
    Person p1 = new Person();
    System.out.println(p1);//p1的內存地址:com.qf.demo01.Person@15db9742
    
    p1.name = "張三狗";
    p1.age = 19;
    p1.sex = '男';
    
    System.out.println(p1.name);//張三狗
    System.out.println(p1.age);//19
    System.out.println(p1.sex);//男
          
    //2.再創建一個Person類的對象
    
    Person p2 = new Person();
    System.out.println(p2);//p2的內存地址,com.qf.demo01.Person@6d06d69c
    
    p2.name = "李小花";
    p2.age = 17;
    p2.sex = '女';
    
    System.out.println(p2.name);//李小花
    System.out.println(p2.age);//17
    System.out.println(p2.sex);//女
      
    //3.
    Person p3 = null;//僅僅聲明瞭Person類型的對象p3,但是實際上,並沒有在堆內存中,創建出真正的對象。
    
    /*
     * NullPointerException,空指針異常
     * 
     * 對象不存在,就是個null,
     *  強行的訪問對象的屬性或調用方法,就會空指針異常。
     */
    //System.out.println("---->"+p3.name);//報錯啦:NullPointerException
    
    p3 = p1;//將p1的值(p1對象的內存地址),賦值給p3,結果-->p1和p3存儲的是同一個對象的內存地址。
    
    p3.name = "李鐵柱";
    System.out.println(p1.name);//李鐵柱
    System.out.println(p2.name);//李小花
    System.out.println(p3.name);//李鐵柱
    
    Person p4 = new Person();
    System.out.println(p4);//?
    
    p4.name = "王二丫";
    p4.age = 18;
    p4.sex = '女';
    System.out.println(p4.name );
    System.out.println(p4.age);
    System.out.println(p4.sex);
    
    p4 = p1;//改變對象的內存地址了,就不再指向原來的內存對象。
    System.out.println(p1.name);
    System.out.println(p3.name);
    System.out.println(p4.name);
  }
​
}
​/<code>

內存分析圖:

Java小白入門教程(9)——面向對象


2.5、方法的重載:overload

<code>概念:一個類中的,一個功能方法的多種體現形式(有不同的方法體)。
舉例:
    1、人類,有吃的功能:eat()
            eat(食物);
            eat(藥);
            eat(口香糖);
        
    2、求和的功能:
            getSum(int i,int j);
            getSum(double d1, double d2);
    3、水:
        常溫:液態
        0度以下:固態
        100度以上:氣態
        
就是同一個功能的方法,因為參數的不同,調用的具體的方法也不同。
如何判定多個方法是否是重載的?衡量標準,要同時滿足以下三條:
    A:必須同一個類中。
    B:方法名稱必須一致。
    C:參數列表必須不同。(順序,個數,類型)
    
        和static,public,返回值,void等等都沒有關係。
優點:
    1、簡化了開發的壓力
    2、簡化了記憶的壓力
    3、調用方法更方便,更簡潔,又滿足了不同的情況
        
基本原理:
    當方法名稱一致時,通過形式參數列表的不同來選擇要執行的方法。/<code>

示例代碼:

<code>package com.qf.demo01.overload;
​
import java.util.Arrays;
​
/*
 * 方法的重載:
 * 同一個功能:
 *  根據參數的不同,執行的具體的方法也不同
 * 
 * 衡量方法是否重載:
 *  1、同一個類中
 *  2、方法名必須一致
 *  3、參數列表必須不同:類型,個數,順序
 */
public class Test1 {
  //求兩個數的和:
  
  //求兩個整數的和
  public static void getSum(int i,int j){
    int sum = i + j;
    System.out.println(i+" + " + j +"的總和是:"+sum);
  }
  
  public static void getSum(double d1, double d2){
    double sum = d1 + d2;
    System.out.println("總和是:"+sum);
  }
  
  
  public static void getSum(int i,double j){
    
  }
  
  public static void getSum(double d1,int i1){
    
  }
​
  public static void main(String[] args) {
    getSum(1, 2);
    
    getSum(3.14, 4.21);
​
    
  }
  
  
}
​/<code>



2.6、構造方法

構造方法:是一個很特殊的方法。

  • 聲明的語法:public 類名(){}
    • 修飾符:只能有訪問權限的修飾符,public。不能加static。
    • 返回值:沒有返回值,也不能寫void。
    • 方法名:必須和類名相同


  • 調用的方式:new 關鍵字調用
    • new關鍵字後面跟著構造方法即可。


  • 作用:專門用於創建對象。

普通方法:一段具有特殊功能的代碼。而且可以被多次調用執行。

  • 聲明的語法:public static void main(String[] args){}
  • 調用的方式:方法名(實參);
  • 作用:1、避免重複的代碼增強程序的可讀性。2、提高程序的可維護性。


<code>1、編寫java的源代碼(給人看):XXX.java
2、將源文件進行編譯(機器執行的就是這個字節碼文件):XXX.class
  javac命令  javac XXX.java
3、JVM執行字節碼文件:XXX.class
  java命令  java XXX
​
Java反編譯工具:我們現在將class文件,進行反編譯,可以看見類似於底層語言
  javap -c -l -private XXX.class
  
  /<code>

2.6.1 Java編譯器提供的默認的構造方法

<code>問題:創建對象的時候,代碼:new Person();調用的這個Person()這個方法,在程序中並沒有寫,哪來的?
​
試著將Person.class文件進行反編譯:/<code>
Java小白入門教程(9)——面向對象


結論:通過反編譯工具,發現了一些和源代碼不相符的內容,這就是javac編譯器,自動給代碼中添加的構造方法。用於創建對象。

java編譯器,發現代碼中沒有任何的構造方法,在編譯時,會自動的幫我們添加一個無參的構造方法。

如果代碼中自己寫了構造方法,那麼編譯器不再幫我們添加無參的構造方法。



2.6.2 自定義的構造方法

<code>記住一條:如果一個類中,沒有寫任何的構造方法,那麼編譯器自動添加一個無參的構造方法。但是如果你寫了構造方法,那麼編譯器不再添加了。
我們寫程序的規則:
  無參構造要寫
  有參構造看實際情況
  一個類中可以有多個構造方法的。也是方法的重載。
  
創建對象的語法:
  new 構造方法(可能有參數);
  
如果添加自己定義的構造方法:
語法規則:
public 類名(){
​
}
public 類名(參數列表){
  將參數的數值,賦值給屬性即可。
}/<code>

如何創建一個對象?就是通過new這個關鍵字,調用一個類的構造方法。就創建了對象。

先聲明,再調用--->普通方法,還適合構造方法。

如果一個類中,沒有手動的寫一個構造方法的話,那麼編譯器會自動的添加一個無參的構造方法。

示例代碼:

<code>class Person{
  String name;
  int age;
    public Person(){//無參的構造方法
        
    }
    public Person(String n,int a){//有參的構造方法
        name = n;
        age = a;
    }
}
class Test{
    public static void main(String[] args){
        Person p1 = new Person();
        p1.name = "李小花";
        p1.age = 18;
        
        Person p2 = new Person("王二狗",18);
    }
}/<code>


注意點:

1、如果代碼中,沒有寫構造方法。編譯器會自動的添加一個無參的構造方法。
2、如果代碼中,寫了構造方法。編譯器都不會再給我們添加無參的構造方法。編碼習慣:寫了有參構造,再寫上無參構造。


對比一下構造方法和普通方法:

Java小白入門教程(9)——面向對象

2.7、this關鍵字

詞義:這個。

2.7.1 就近原則問題

<code>當寫代碼的時候,要給成員變量,參數,局部變量等等,要進行命名。根據見名知意的原則,很容易就命名衝突了。
在程序當中,有個就近原則,一旦名字衝突,就要看離哪個聲明近。
導致名稱中成員變量和局部變量的命名衝突!!!
public Person(String name,int age){//name="李小花"
    name = name; //=兩側的name,都是指參數
    age = age;
}
因為命名規範,見名知意,成員變量和局部變量,命名相同了。
因為就近原則問題:構造方法Person中,name和age,都會看成了這個參數,就是局部變量。
    
希望有一種方式,來告訴編譯器:=左邊的是成員變量,=右邊的才是參數。
  可以藉助於this這個關鍵字解決。/<code>

2.7.2 this的用法一

表示當前對象。

<code>this.屬性,沒有this的就是局部變量。可以解決命名衝突的問題。
public Person(String name,int age){//name="李小花"
    this.name = name; //=左側的是this的name屬性
    this.age = age;
}
使用this關鍵字,明確的告訴編譯器,this後的這個name,就是成員變量。對象的屬性。沒有this的就是參數。
    解決成員變量和局部變量的命名衝突。
      this點的就是成員變量,沒有this的就是局部變量。/<code> 

示例代碼:

<code>package com.qf.demo03;
​
public class Person {
  //成員變量
  String name;//屬性,成員變量,人有姓名
  int age;
  
  public Person(){
    
  }
  
  /*
   * 就近原則:成員變量和局部變量命名衝突了。方法中name默認都是參數。
   */
  public Person(String name,int age){//name="李小花"
    this.name = name; 
    this.age = age;
  }
  
  public void eat(){
    System.out.println(name+",吃東西啦。。");
  }
  
  //this,當前的對象。誰調用誰就是當前的對象
  //當p1調用的時候,this就指代p1
  //當p2調用的時候,shis就指代p2
  
  
  //在類中提供一個功能:成員方法
  public void showInfo(){
    System.out.println("姓名:"+this.name+",年齡:"+age);
  }
}
​/<code>

2.7.3 this的用法二

this()指代當前類的構造方法。

<code>this(參數),就表示的構造方法。
如果一個類中,有多個構造方法,之間存在了調用關係,那麼使用this()來指代這個構造方法。具體指代哪個構造方法,要靠參數來區分。
注意點:當this()指代構造方法,那麼必須放在首行。/<code>

示例代碼:

<code>package com.qf.demo03;
​
public class Student {
  String name;
  int age;
  String sex;
  double score;
  
  public Student(){
    System.out.println("無參的構造方法,Student()...");
  }
  
  
  public Student(String name,int age){//給name和age屬性賦值
    System.out.println("有參構造方法。。2個參數。。");
    this.name = name;
    this.age = age ;
  }
  
  public Student(String name,int age,String sex,double score){
    this(name,age);//this(),指代構造方法。
    System.out.println("有參構造方法。。4個參數。。");
//    this.name = name;
//    this.age = age;
    this.sex = sex;
    this.score = score;
  }
  
  public void showInfo(){
    System.out.println("姓名:"+name+",年齡:"+age+",性別:"+sex+",成績:"+score);
  }
}
​/<code>

2.8、匿名對象

<code>創建對象的語法:
    Person p1 = new Person();
    //=左側在做對象的聲明,開闢的是棧內存
    //=右側,才是真正的創建對象
    //結果:內存中,創建了一個對象,對象的地址,賦值給p1。
匿名對象,就是隻有=右側,沒有=左側。
    new 構造方法(必要的參數);
匿名對象的用途:
    1、使用匿名對象,直接調用類的方法。
    2、匿名對象直接作為一個方法的參數。
    
注意點:
    匿名對象只能使用一次。隨著它的創建而使用一次。(一次性的)
優勢:
    1、使用後即銷燬,就是被GC回收。
    2、代碼書寫方法,提高效率。/<code>

示例代碼:

<code>package com.qf.demo01;
​
public class Test1 {
​
  public static void main(String[] args) {
    //創建正常的對象,有引用,有對象
    Person p1 = new Person();
    
    //通過p1,來指揮對象:可以訪問屬性,賦值,取值,,可以調用方法
    p1.name = "王二狗";
    p1.age = 19;
    System.out.println(p1.name);
    System.out.println(p1.age);
    
    p1.eat();
    p1.eat();
    
    
    
    //創建一個匿名對象,沒有棧的引用,只有堆中的對象。
    //侷限:只能使用一次,創建的時候使用一次。
    new Person().eat();
    new Person("李小花",18).eat();
    
    
    //只有=左側
    Person p2 = null;//只有對象聲明
    p2.eat();
    
  }
​
}
​/<code>



三、作業


<code>1.this關鍵字的用法寫3遍,記下來.
2.創建一個Teacher類。設置屬性和方法。無參構造方法和有參構造方法。並創建對象,打印對象的屬性信息。執行成員方法。
​
3.創建一個Computer類,設置該類的屬性,以及一個方法,用於顯示計算機的屬性信息.並添加構造方法,無參的和有參的.分別創建該類的對象.執行方法.
​
4.創建一個Girl類,設置屬性name,age,無參構造和有參構造.創建該類對象,為屬性賦值.打印屬性值.
5.(選做)設計一個學生類,有姓名,有年齡,有性別,有英語成績,數學成績,語文成績,提供無參構造和有參構造
​
  設計方法,求總分,平均分,以及打印學生的信息。3個對象。/<code> 


分享到:


相關文章: