JAVA對象的值與引用

JAVA編程思想,最近主要學習對象和引用的關係。

在內存中,引用主要存放在堆棧中,而JAVA對象主要存放在堆中。

在堆棧中方便管理儲存分配與清理,而在堆中的數據,編譯器並不需要知道其存活的週期,有JVM的垃圾回收機制進行統一管理。

 

基本類型,並不是創建引用,而是直接在堆棧中進行保存,比較高效;但是其封裝類必須是會創建引用的。

同時這裏又引出了基本類型的自動裝箱和自動拆箱的概念,如下:

Integer a = new Integer(8);
Integer b = new Integer(8);
int c = 8;
int d = 8;
System.out.println(a == b);//false;
System.out.println(a == c);//true;
System.out.println(d == c);//true;

 

那麼上面代碼的對象a和對象b如何比較呢,應該通過

 

a.equals(b);//true


來進行比較。

這是因爲int的封裝類Integer,重寫了equals的比較方法。

如果是自定義的類,而且沒有重寫equals方法的話

public class JDKTest {

    /**
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @param args
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public static void main(String[] args) {
        Value v1 = new Value();
        Value v2 = new Value();
        v1.i = v2.i = 100;
        System.out.println(v1.equals(v2));//false;
    }

}

class Value{
    int i;
}

重寫equals方法後

public class JDKTest {

    /**
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @param args
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public static void main(String[] args) {
        Value v1 = new Value();
        Value v2 = new Value();
        v1.i = v2.i = 100;
        System.out.println(v1.equals(v2));//true;
    }

}

class Value{
    int i;
    @Override
    public boolean equals(Object arg0) {
        if(this == arg0){
            return true;
        }
        if(! (arg0 instanceof Value) ){
            return false;
        }
        else if(this.i == ((Value)arg0).i){
            return true;
        }
        else {
            return false;
        }
    }
}


 


 

 

 

同時參數的傳遞,如果不是基本類型,傳遞的也是引用

public class JDKTest {

    static void f(Letter y){
        y.c = 'Z';
    }
    
    /**
     * 功能描述: <br>
     * 〈功能詳細描述〉
     *
     * @param args
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本](可選)
     */
    public static void main(String[] args) {
      Letter x = new Letter();
      x.c = 'a';
      System.out.println(x.c);

      f(x);
      System.out.println(x.c);
        
    }

}

class Letter{
    char c;
}

 

輸出的結果:

a
Z

都是引用,更新的都是堆中對象的值,同時所有對這個對象的引用的值都會改變(因爲只是“引用而已”)。

 

如果需要傳遞對象而不是傳遞對象的引用的話,就需要重新new一個新的對象,並把原對象中的值賦給新的對象。

Letter x = new Letter();
x.c = 'a';
Letter y = new Letter();
y.c = x.c;//通過這種方式傳遞值


補充:

找了下,發現已經有工具類可以實現這個功能(需要jar包commons-beanutils-1.8.3.jar)

org.apache.commons.beanutils.BeanUtils.copyProperty(Object bean, String name, Object value)
        throws IllegalAccessException, InvocationTargetException;

 

T t;
        try {
            t = clazz.newInstance();
            for (Field field : fields) {
                List<String> fieldValues = map.get(field.getName());
                if (fieldValues != null && fieldValues.size() > 0) {
                    if(field.getType().getName().equals("java.math.BigDecimal")){
                        if(!"".equals(fieldValues.get(0))){
                            BeanUtils.copyProperty(t, field.getName(), fieldValues.get(0));
                        }
                    }else {
                        BeanUtils.copyProperty(t, field.getName(), fieldValues.get(0));
                    }
                }
            }

        } catch (Exception e) {
            return null;
        }
        return t;


以下內容轉自他人博客:apache.commons.beanutils.BeanUtils的使用

 

該class提供了一系列的靜態方法操作業已存在的符合JavaBean規範定義的Java Class.這裏強調的JavaBean規範,簡單來說就是一個Java Class通過一系列getter和setter的方法向外界展示其內在的成員變量(屬性).通過BeanUtils的靜態方法,我們可以:

  • 複製一個JavaBean的實例--BeanUtils.cloneBean();
  • 在一個JavaBean的兩個實例之間複製屬性--BeanUtils.copyProperties(),BeanUtils.copyProperty();
  • 爲一個JavaBean的實例設置成員變量(屬性)值--BeanUtils.populate(),BeanUtils.setProperty();
  • 從 一個一個JavaBean的實例中讀取成員變量(屬性)的值 --BeanUtils.getArrayProperty(),BeanUtils.getIndexedProperty(),BeanUtils.getMappedProperty(),BeanUtils.getNestedProperty(),BeanUtils.getSimpleProperty(),BeanUtils.getProperty(),BeanUtils.describe();

總的來看BeanUtils類提供了兩大類的功能:讀,寫成員變量.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章