1. 程式人生 > >day7 面向對象(二)

day7 面向對象(二)

ner 括號 特點 eth 私有 函數 png odi 做的

  匿名類對象

  創建的類的對象是匿名的。當我們只需要一次調用類的對象時,我們就可以考慮使用匿名的方式創建類的對象。特點是創建的匿名類的對象只能夠調用一次!

技術分享圖片
package day007;

//圓的面積
class circle {
    double radius;
    public double getArea() {
        // TODO Auto-generated method stub
        return Math.PI * radius * radius;
    }
    
    public void setRadius(double r){
        radius 
= r; } public double getRadius(){ return radius; } public void show(){ System.out.println("我是一個圓"); } } public class lambda{ public void printArea(circle c, int time){ System.out.println("radius"+"\t"+"area"); for(int i =1;i<= time;i++){ c.setRadius(i); System.out.println(c.getRadius()
+ "\t" + c.getArea()); } } public static void main(String[] args){ lambda p = new lambda(); circle c = new circle();//新的圓半徑為0 p.printArea(c, 5); new circle().show();//這個對象就是匿名對象,只使用一次後就無法再次調用 } }
對象作為參數傳遞

  在上面這個例子裏,我們使用new circle()直接調用circle的方法。這個對象就是匿名類對象,這個對象產生時,在內存堆中開辟內存存儲了數據,但是在棧中並沒有相應的變量名指向這塊內存地址,那麽我們無法再第二次調用這個匿名類,即我們不可以使用此類再次調用circle類的屬性與方法。

  在java虛擬機中,這個匿名類對象很快就被垃圾回收機制收走了,切記,當我們某個類對象只需要使用一次的情況,我們才會考慮使用匿名類對象。

  可變個數的行參的方法:

  格式:對於方法的形參: 數據類型 ... 形參名;

  可變個數的形參的方法與同名的方法之間構成重載;

  可變個數的形參在調用時,個數從0開始,到無窮多個都可以。

  使用可變多個形參的方法與方法的形參使用數組是一致的。

  若方法中存在可變個數的形參,那麽一定要聲明在方法形參的最後。

  在一個方法中,最多聲明一個可變個數的形參。

技術分享圖片
package day007;

public class javaArgs {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        javaArgs jargs = new javaArgs();
        jargs.getSum(1,2,3,4);
        new javaArgs().getSum(123,223);
        jargs.getSum("求和是", 2,3,5,8);
    }
//    public int getSum(int ... args){
    public void getSum(int ... args){
        int sum = 0;
        //args使用與數組一致
        for(int i = 0; i<args.length;i++){
            sum += args[i];
        }
        System.out.println(sum);
//        return sum;
        
    }
    //重載,可變個數的形參聲明在方法形參的最後
    public void getSum(String s,int ... args){
        int sum = 0;
        for(int i = 0; i<args.length;i++){
            sum += args[i];
        }
        System.out.println(s + ":"+ sum);
        
    }
}
java的*args的使用

  java中形參與實參

  形參:方法聲明時,方法小括號內的參數,實參:調用方法時,實際傳入的參數的值。

  我們之前做的兩個值轉換:

技術分享圖片
package day007;

public class TestArgsTransfer {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //兩個值轉換
        int i = 10;
        int j = 5;
        System.out.println("i:" + i + " j:" + j);
        int temp = i;
        i = j;
        j = temp;
        System.out.println("i:" + i + " j:" + j);
        
        
    }

}
兩個值交換

技術分享圖片

  然後你可能會想用一個類封裝一個方法完成交換。然後你寫了這樣一個方法。

技術分享圖片
package day007;

public class TestArgsTransfer {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //兩個值轉換
        int i = 10;
        int j = 5;
        
        //封裝到類方法
        TestArgsTransfer tt = new TestArgsTransfer();
        System.out.println("i:" + i + " j:" + j);
        tt.swap(i, j);//將i的值傳遞給m,j的值傳遞給n
        System.out.println("i:" + i + " j:" + j);
    }
    
    //定義一個方法,交換兩個變量的值
    public void swap(int m,int n){
        int temp = m;
        m = n;
        n = temp;
        System.out.println("m:" + m + " n:" + n);
    }

}
你寫的封裝方法

  結果是你的i和j根本就沒有變,為什麽呢?

技術分享圖片

  簡單來說就是i與j是你定義的類屬性,你將i,j作為實參傳到了類方法裏面,類方法swap裏的兩個變量發生了位置轉換,但是main中的兩個值並沒有發生任何變化,在內存中的表現如上圖,調用swap方法時,會在棧中存兩個swap的局部變量,這兩個變量的值交換了,但是main的變量未發生改變。

  那我們要如何做呢。

技術分享圖片

技術分享圖片
package day007;

public class TestArgsTransfer1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestArgsTransfer1 tt = new TestArgsTransfer1();
        DataSwap ds = new DataSwap();
        
        System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
        
        tt.swap(ds);
        System.out.println(ds);
        
        System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
    }
    
    //交換元素的值
    public void swap(DataSwap d){
        int temp = d.i;
        d.i = d.j;
        d.j = temp;
        System.out.println(d);//打印引用變量d的值
    }
}

class DataSwap{
    int i = 10;
    int j = 5;
}
形參是引用數據類型

  這裏swap方法傳入的是一個引用數據類型ds,相當於d與ds一致都指向同一個堆空間,那麽在swap中完成兩個值的交換。

  練習一下,下面代碼的執行結果是什麽:

class Value {
    int i = 15;
}

class TestValue {
    public static void main(String argv[]) {
        TestValue t = new TestValue();
        t.first();
    }

    public void first() {
        int i = 5;
        Value v = new Value();
        v.i = 25;
        second(v, i);
        System.out.println(v.i);
    }

    public void second(Value v, int i) {
        i = 0;
        v.i = 20;
        Value val = new Value();
        v = val;
        System.out.println(v.i + " " + i);
    }
}

  分析:

  第一步,定義了TestValue類,在類的main函數中,生成一個實例t,並在堆中開辟內存(0x0001),在棧中定義t指向堆中內存0x0001。實例調用實例的first方法。

  第二步,在棧中有局部變量i值為5,一個新的變量v,指向堆中新開辟內存(0x0011),v的局部變量i值為25,將v與當前局部變量i=5作為實參傳給second方法。

  第三步,局部變量i的值改為0,v的局部變量i變為20,定義一個新變量val指向堆中先開辟內存(0x0111),second中實參v指向內存(0x0111)

  第四步,此時打印v.i值為內存0x0111中的i,值為15,i為局部空間中的變量i為0,first打印的v.i值為20(實參傳入first,v本身未發生指向的改變)。

技術分享圖片

  面向對象:封裝

  我們考慮不讓對象來直接作用屬性,而是通過"對象.方法"的形式,來控制對象對屬性的訪問。實際情況中,對屬性的要求就可以通過方法來體現。

  兩種方法:①將類的屬性私有化,②提供公共的方法(setter & getter)來實現調用。

技術分享圖片
package day007;

public class java_private {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Animal an = new Animal();
//        an.legs = 4;//飄紅
        an.setLegs(4);
        an.getLegs();
    }

}

class Animal{
    private String name;
    private int legs;
    
    public void setLegs(int l){
        legs = l;
    }
    
    public int getLegs(){
        System.out.println(legs);
        return legs;
    }
}
私有封裝

  權限修飾符

技術分享圖片

  構造器

  也就是構造方法,但是與python的__init__有相似之處,但是不完全一致。

  構造器的作用:①創建對象 ②給創建的對象的屬性賦值(創建對象的話,相當於python中的__new__與__init__的作用)。

  1.設計類時,若不顯式聲明類的構造器的話,程序會默認提供一個空參的構造器

  默認加()就相當於調用了構造器了,類比python加()後實例化即調用了構造方法。

  2.一旦顯式的定義類的構造器,那麽默認的構造器就不再提供。

  3.如何聲明類的構造器。格式:權限修飾符 類名(形參){ }。

   4.類的多個構造器之間構成重載。

  類對象的屬性賦值的先後順序:①屬性的默認初始化 ②屬性的顯式初始化③通過構造器給屬性初始化 ④通過"對象.方法"的方式給屬性賦值。

技術分享圖片
package day007;

public class init {
    public static void main(String[] args) {
        Person p1 = new Person();
        System.out.println(p1.getName() + ":" + p1.getAge());
        String str = new String("hello");
        System.out.println(str);
        
        Person p2 = new Person("jeff");
        System.out.println(p2.getName());
        System.out.println(p2.getAge());
        
        Person p3 = new Person("frank",23);
        System.out.println("name:" + p3.getName() + " age:" + p3.getAge());
        //體會屬性賦值的過程
        Person p4 = new Person();
        System.out.println("name:" + p4.getName() + " age:" + p4.getAge());
        
        Person p5 = new Person(12);
        System.out.println("name:" + p5.getName() + " age:" + p5.getAge());
    }
}


class Person{
    //屬性
    private String name;
    private int age = 1;
    
    //構造器
    public Person(String n){
        name = n;
    }
    public Person(){
//        age = 10;
//        name = "張三";
    }
    public Person(int a){
        age = a;
    }
    public Person(String n,int a){
        name = n;
        age = a;
    }
    
    //方法
    public void setName(String n){
        name = n;
    }
    public void setAge(int a){
        age = a;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
}
構造器

   本節代碼托管到我的github:day007。  

day7 面向對象(二)