结论: 在java函数里面创建局部对象,当返回这个对象时这个对象不会被销毁。
参考:
Class ObjectA{}
Public Class Test{
Public static ObjectA Factory(){
return new ObjectA();
}
}
上面例子中Test类中Factory方法返回一个局部的ObjectA对象,我就产生疑问,局部对象在方法外不是销毁了吗,这样返回是不是有问题.
这样写肯定是没有问题的,我查了资料,这样返回的是新ObjectA对象的Reference,就像对象的赋值操作一样,赋的是对象的Reference,而引用是个整型的,方法外值是不会变的.返回的新对象是由GC来回收的,只要有引用还指向这个对象,它就不会被回收.明显的,对象的引用在返回后还指向这个对象.所以,java中函数把一个局部对象作为返回值是可以的.
---------------------
作者:shkkhd
来源:CSDN
原文:
版权声明:本文为博主原创文章,转载请附上博文链接!
先写一个测试用例.
PasswordItem类
public class PasswordItem {
public int zjc_1;
public int zjc_2;
PasswordItem() {
}
public int getZjc_1() {
return zjc_1;
}
public void setZjc_1(int zjc_1) {
this.zjc_1 = zjc_1;
}
public int getZjc_2() {
return zjc_2;
}
public void setZjc_2(int zjc_2) {
this.zjc_2 = zjc_2;
}
}
Main.class
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
PasswordItem passwordItem = returnLocalObj();
int zjc_1 = passwordItem.getZjc_1();
int zjc_2 = passwordItem.getZjc_2();
// List<PasswordItem> zjc = zjc_func();
// zjc.get(1).setZjc_1(100000);
System.out.println("Hello World!");
}
private static PasswordItem returnLocalObj() {
PasswordItem passwordItem = new PasswordItem();
passwordItem.setZjc_1(100000);
passwordItem.setZjc_2(123456);
return passwordItem;
}
}
从上面的调试结果看出从局部函数返回的passwordItem:PasswordItem@506 并未被销毁,而是被返回到了主函数的passwordItem对象里面。由此可见函数返回的对象不会被回收,我的理解是只要有指针指向这个对象的地址,就不会被java虚拟机回收这一点和c不一样,c语言里面在函数里面的局部参数在返回时会被销毁(除了new分配的堆空间)。而在java则是将其(准确的说函数返回对象的引用值)返回到了主函数。内存里面也会有一个PasswordItem空间。
还有一个有趣的事情。在写数据库的时候遇到的:
代码本意将数据库查询的条目返回到一个对象的数组里面。
代码如下:
PasswordItem passwordItem = new PasswordItem();
if (cursor.moveToFirst()) {
do {
passwordItem.setId(id);
passwordItem.setAccount(cursor.getString(cursor.getColumnIndex("account")));
/*-------------------------------------------*/
//解密password
/*-------------------------------------------*/
ciperText = cursor.getString(cursor.getColumnIndex("password"));
passwordItem.setPassword(encryption.decode(ciperText));
passwordItem.setType(cursor.getInt(cursor.getColumnIndex("type")));
passwordItem.setUri(cursor.getString(cursor.getColumnIndex("uri")));
passwordItem.setNote(cursor.getString(cursor.getColumnIndex("note")));
passwordItemList.add(passwordItem);
id++;
} while (cursor.moveToNext());
}
其实上面的代码是个bug,原因在于这个函数只有一个PasswordItem对象,passwordItemList每次添加这个passwordItem是始终是添加的同一个引用值A。假设循环执行100次 password依次返回1…100 那么最后的结果是List里面存储了100个A,A指向同一块内存空间---->List由于全是同一块A,即是最后 List里面有100个相同的对象 结果List里面的元素的password全为100。下面的demo可以看到:
先随便写一个dmeo就可以测试到。
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
List<PasswordItem> zjc = zjc_func();
System.out.println("Hello World!");
}
public static List<PasswordItem> zjc_func() {
List<PasswordItem> list = new ArrayList<PasswordItem>();
PasswordItem passwordItem = new PasswordItem();
passwordItem.setZjc_1(1);
passwordItem.setZjc_2(2);
list.add(passwordItem);
passwordItem.setZjc_1(3);
passwordItem.setZjc_2(4);
list.add(passwordItem);
return list;
}
}
上图看出 修改任意一个List元素 等价于修改全部
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
List<PasswordItem> zjc = zjc_func();
zjc.get(1).setZjc_1(100000);
System.out.println("Hello World!");
}
public static List<PasswordItem> zjc_func() {
List<PasswordItem> list = new ArrayList<PasswordItem>();
PasswordItem passwordItem = new PasswordItem();
passwordItem.setZjc_1(1);
passwordItem.setZjc_2(2);
list.add(passwordItem);
passwordItem = new PasswordItem();
passwordItem.setZjc_1(3);
passwordItem.setZjc_2(4);
list.add(passwordItem);
return list;
}
}
if (cursor.moveToFirst()) {
do {
PasswordItem passwordItem = new PasswordItem();
passwordItem.setId(id);
passwordItem.setAccount(cursor.getString(cursor.getColumnIndex("account")));
/*-------------------------------------------*/
//解密password
/*-------------------------------------------*/
ciperText = cursor.getString(cursor.getColumnIndex("password"));
passwordItem.setPassword(encryption.decode(ciperText));
passwordItem.setType(cursor.getInt(cursor.getColumnIndex("type")));
passwordItem.setUri(cursor.getString(cursor.getColumnIndex("uri")));
passwordItem.setNote(cursor.getString(cursor.getColumnIndex("note")));
passwordItemList.add(passwordItem);
id++;
} while (cursor.moveToNext());
}