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类提供了两大类的功能:读,写成员变量.

猜你喜欢

转载自blog.csdn.net/luoliang2012/article/details/16860955