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