1. 程式人生 > 實用技巧 >2020年8月3日 過載、命令列引數、可變引數、變數的分類、物件陣列、封裝、繼承、多型、類的三個組成部分;

2020年8月3日 過載、命令列引數、可變引數、變數的分類、物件陣列、封裝、繼承、多型、類的三個組成部分;

/*
方法的過載:
    在同一個類中,出現了兩個或多個的方法名稱相同,形參列表不同,稱為方法的過載。
    形參列表不同:形參的個數、資料型別不同
    方法的過載和返回值型別無關。
    
為什麼要有方法的過載?或者換句話說,為什麼要宣告多個方法名稱相同呢?
(1)方法名代表方法的功能,這幾個方法的功能是一樣的,例如:都是找最大值
(2)為了呼叫者的方便,功能相同的方法取名一樣的話,對於呼叫者來說就減少了學習和記憶的成本
*/
class Test03_Overload{
    public static void main(String[] args){
        System.out.println(max(
1,4)); System.out.println(max(1.0,4.0)); System.out.println(max(1,4,8)); } //寫一個方法,可以找2個整數的最大值 public static int max(int a, int b){ return a>b ? a : b; } //方法過載時,不去看返回值型別是否一致,只看方法名和形參列表 //public static double max(int a,int b){ // return 0.0; //}
//寫一個方法,可以找2給小數的最大值 public static double max(double a, double b){ return a>b ? a : b; } //寫一個方法,可以找3個整數的最大值 public static int max(int a, int b, int c){ int max = a > b ? a : b; max = max > c ? max : c; return max; } }
/*
命令列引數:(瞭解)
    給main方法傳的實參,叫做命令列引數
格式:
    java main所在的類名  實參1  實參2 ...
例如:
    java  Test04_CommandParam  hello java atguigu
*/ class Test04_CommandParam{ /* 因為main也是一個有參無返回值的方法,那麼如何給main傳引數呢? */ public static void main(String[] args){ //args是形參,是String[]型別,是一個一維陣列 for(int i=0; i<args.length; i++){ System.out.println("第" +(i+1) +"個引數的值:" + args[i]); } } }
/*
可變引數:JDK1.5之後引入的
    形參列表中出現了“資料型別... 形參名”形式的形參,就是可變引數。

包含可變引數的方法的呼叫原則:
(1)可變引數的形參部分,可以傳入0~n個對應型別的實參,也可以傳入對應型別的陣列物件
(2)非可變引數的形參部分,原來該怎麼傳,現在還怎麼傳

可變引數的宣告的原則:
(1)一個方法只能包含一個可變引數
(2)可變引數必須是形參列表的最後一個

引數:
(1)形參
(2)實參
(3)命令列引數
(4)可變引數
(5)...
*/
class Test05_VarParam{
    public static void main(String[] args){
        System.out.println(sum(1,2));
        
        int[] arr1 = new int[0];
        System.out.println("0個元素的累加和:" + sum(arr1));//可變引數部分,傳入了對應型別的陣列物件
        
        int[] arr2 = {1,2,3,4,5};
        System.out.println("5個元素的累加和:" + sum(arr2));//可變引數部分,傳入了對應型別的陣列物件
        
        System.out.println("0個元素的累加和:" + sum());//可變引數部分,傳入了0個實參的int值
        System.out.println("5個元素的累加和:" + sum(1,2,3,4,5));//可變引數部分,傳入了5個實參的int值
        System.out.println("3個元素的累加和:" + sum(5,3,1));//可變引數部分,傳入了3個實參的int值
        System.out.println("-------------------------------");
    
        //System.out.println("0個元素的最大值:" + max());//錯誤的,因為max方法有一個非可變引數的形參,必須傳值
        System.out.println("1個元素的最大值:" + max(5));//5賦值給了非可變引數的形參
        System.out.println("5個元素的最大值:" + max(5,1,5,6,8));//第1個5賦值給了非可變引數的形參,剩下的給了可變引數
    }
    
    //宣告一個方法,功能:可以求兩個整數的和
    public static int sum(int a, int b){
        return a + b;
    }
    //宣告一個方法,功能:可以求0~n個整數的累加和
    /*
    //該方法不能與下面的(int... nums)同時存在
    public static int sum(int[] nums){
        int sum = 0; 
        for(int i=0; i<nums.length; i++){
            sum += nums[i];
        }
        return sum;
    }*/
    
    
    public static int sum(int... nums){
        //nums當成陣列用
        int sum = 0; 
        for(int i=0; i<nums.length; i++){
            sum += nums[i];
        }
        return sum;
    }
    
    //宣告一個方法,功能:可以求1~n個整數的最大值
    //int num1就是非可變引數部分
    //int... nums是可變引數
    public static int max(int num1, int... nums){
        int max = num1;
        for(int i=0; i<nums.length; i++){
            if(nums[i] > max){
                max = nums[i];
            }
        }
        return max;
    }
    
}
/*
變數的分類:
1、成員變數:今天討論的都是非靜態的成員變數
2、區域性變數

(1)宣告的位置不同
成員變數:
    類中方法外
    類{
        【修飾符】 資料型別  成員變數;
    }
區域性變數
    方法中:(1)形參,也是區域性變數(2)方法體{}中宣告的變數
    後面可能還要加上程式碼塊中。
    類{
        【修飾符】 返回值型別  方法名(【形參列表】){
            資料型別  區域性變數;
        }
    }
(2)執行時在記憶體中的位置也不相同
成員變數:堆
區域性變數:棧

(3)初始化不同
成員變數:
    如果沒有初始化,有預設值
區域性變數:
    如果沒有初始化,就會報錯,不能用

(4)生命週期
成員變數:
    隨著物件的建立而分配,隨著物件被垃圾回收器回收而結束
區域性變數:
    方法被呼叫,開始分配,方法執行結束就結束

(5)可用的修飾符
成員變數:有很多修飾符,具體哪些後面再講
區域性變數:唯一的一個就是final,具體什麼意思再講
    
*/
class Test07_Variable{
    public static void main(String[] args){//args是區域性變數
        String ming = "張三";//ming區域性變數
        int nian = 23;//nian區域性變數
        
        Student s1 = new Student();//s1區域性變數
        s1.name = ming;//s1.name不是在這裡宣告的,只是使用它
        s1.age = nian;
    }
}
class Student{
    String name;//name是成員變數
    int age;//age是成員變數
    
    void set(String n, int a){//n和a是區域性變數
        name = n;
        age = a;
    }
}
/*
陣列是用來存一組數,這組數可以是基本資料型別,也可以是引用資料型別
例如:
    int[] arr; 存了一組整數
    char[] arr;存了一組單字元
    
    String[] arr; 存了一組字串物件
    Student[] arr; 存了一組學生物件
    Circle[] arr; 存了一組圓物件

當我們陣列中儲存了一組物件時,那麼我們稱為物件陣列。    
*/
class Test08_ObjectArray{
    public static void main(String[] args){
        //要用一個數組,儲存5個圓物件,半徑分別為1-5
        //(1)宣告一個數組
        //陣列的元素的型別是Circle
        Circle[] arr = new Circle[5];//這個new是建立陣列物件
        
        //(2)為陣列的元素賦值
        for(int i=0; i<arr.length; i++){
            //元素:陣列名[下標]
            //arr[i].radius = i+1;//java.lang.NullPointerException
            
            arr[i] = new Circle();//建立圓物件
            arr[i].radius = i+1;
        }
        
        //(3)遍歷陣列,列印每一個圓的資訊
        for(int i=0; i<arr.length; i++){
            //現在的陣列的元素arr[i]就是一個圓物件,既然是圓物件,就可以呼叫圓的屬性和方法
            arr[i].printInfo();
            //System.out.println(arr[i]);
        }
    }
}
class Circle{
    double radius;
    
    double getArea(){
        return 3.14 * radius * radius;
    }
    
    void printInfo(){
        System.out.println("半徑:" + radius + ",面積:" + getArea());
    }
}
/*
面向物件的基本特徵:
(1)封裝
(2)繼承
(3)多型

一、封裝

1、封裝的意義:
(1)隱藏實現細節
(2)安全

2、封裝的型別:
(1)屬性的封裝、方法的封裝等
(2)元件的封裝
(3)系統的封裝

3、封裝的實現,靠許可權修飾符來控制可見的範圍。
許可權修飾符:
(1)可見範圍
                本類    本包    其他包子類        任意位置
private:         √        ×            ×                ×
預設/省略:         √        √            ×                ×
protected:         √        √            √                ×
public             √        √            √                √

(2)哪些可以加許可權修飾符
類、屬性、方法、構造器、內部類

(3)分別可以加什麼許可權修飾符
類:預設或public
    如果類前面有public,那麼必須與原始檔名相同
屬性:四種都可以
方法:四種都可以    

4、屬性的封裝
大多數情況下,屬性都是private
如果屬性私有化了,我們會提供get/set方法
get/set的標準寫法:
    public void set屬性名(資料型別 形參名){
        屬性名 = 形參名;
    }
    public 屬性的資料型別 get屬性名(){
        return 屬性名;
    }

5、方法的封裝
大多數情況下,方法都是public

*/
public class Test10_Encapsulation{
    public static void main(String[] args){
        //1、建立物件
        Circle c1 = new Circle();
        
        //2、為屬性賦值
        //c1.radius = 1.2;//錯誤的
        c1.setRadius(1.2);
        
        System.out.println("半徑:" + c1.getRadius());
    }
}
class Circle{
    private double radius;//僅限與本類中訪問
    
    //radius屬性的set方法,用於在其他類中修改radius的值
    public void setRadius(double r){
        if(r>0){//使得賦值可控
            radius = r;
        }
    }
    //radius屬性的get方法,用於在其他類中獲取radius的值
    public double getRadius(){
        return radius;
    }
    
}
/*
類的第三個組成部分:
    構造器,也稱為構造方法,因為(1)它長的像方法(2)它編譯後是一個例項初始化方法
    
1、構造器的作用
(1)構造物件,建立物件
和new一起使用,每次呼叫它就是在建立新的物件    
(2)可以在建立物件的同時,給屬性賦值

2、構造器的特點
(1)所有類都有構造器
(2)如果一個類沒有顯式宣告構造器,那麼編譯器將會自動生成一個預設的無參構造
(3)如果一個類顯式聲明瞭構造器,那麼編譯器將不會自動生成預設的無參構造了
(4)構造器的名稱必須與類名相同
(5)構造器沒有返回值型別,也不寫void
(6)構造器可以過載

過載:在同一個類中,方法名相同,形參列表不同的兩個和多個方法,和返回值型別無關

3、構造器的語法結構
    【修飾符】 類名(){
        
    }
    【修飾符】 類名(形參列表){
        
    }
    
回憶:
    java.util.Scanner input = new java.util.Scanner(System.in);//呼叫的是有參構造
    int num = input.nextInt();//從鍵盤輸入一個整數
    java.util.Random rand = new java.util.Random();//呼叫的是無參構造
    int num = random.nextInt(10);//產生一個[0,10)的整數
*/
class Test12_Constructor{
    public static void main(String[] args){
        //建立物件
        //類名 物件名 = new  類名();
        //Circle c = new Circle();
        
        Circle c = new Circle(1.2);//1.2給半徑賦值,在建立物件的同時給屬性賦值用的
        c.printInfo();
        
        c.setRadius(2.5);//建立物件之後,修改屬性值用的
        c.printInfo();
        
        Circle c2 = new Circle();//先建立物件,不給半徑賦值
        c2.setRadius(3.6);
        c2.printInfo();
    }
}
class Circle{
    private double radius;
    
    //double r:構造器的形參列表
    public Circle(double r){//有參構造
        radius = r;//給半徑賦值
    }
    
    public Circle(){//無參構造
        
    }
    
    public void printInfo(){
        System.out.println("半徑:" + radius);
    }
    
    public void setRadius(double r){
        radius = r;
    }
    
}