seman198102 2009-09-12 13:04
浏览 369
已采纳

对象数组回收时可能会内存泄漏,primitive 数组不会吗?

在ArrayList中有clear()方法,如下;就是说如果没有显示调用clear(除arraylist实例是局部变量,生命期结束自动调用),即将所有数组的各个元素置为null,则会导致内存泄露

[code="java"]
private transient Object elementData[];
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
[/code]
那么对于像int[]这样的数组,我们为什么只需要将数组引用置为null就可以了呢,请问有何区别,谢谢!

另外,stringbuffer相比string可以变化,只是因为他在数组长度不够的时候,重新申请新的byte数组的原因,那么Stringbuffer本质上也是会产生很多数组对象的,怎么就说stringbuffer的效率高呢?

  • 写回答

2条回答 默认 最新

  • iteye_7822 2009-09-13 00:43
    关注

    int[]是元素类型为原始类型的数组。原始类型(不包括String)中肯定不含有对对象实例的引用。如果把所有对象实例看做一幅有向图的节点,把它们之间的引用关系看作边,那么int[]肯定是叶节点(有入边没有出边)或者是孤立的节点(入边和出边都没有)。元素为对象类型的数组中则可能包含对别的对象实例的节点。

    [quote="bohemia"]第二个问题:
    StringBuffer比String效率高.是因为生成对象的个数不一样.
    比如:
    [code]"aaa"+"bbb"[/code]
    会生成三个String对象.

    [code]sb.append("aaa").append("bbb")[/code]
    只有2个String生成,所以效率会高.

    个人见解.[/quote]
    确实跟创建对象的个数有关系,不过不应该只看String对象的个数。

    首先用常量写的"aaa"和"bbb"在Java源文件被编译为Java class文件后会出现在常量池中。这些字符串会随着它们所在的class文件的类被加载而被创建为String实例,保存在运行时的字符串池里。再说
    [code]"aaa"+"bbb"[/code]
    不会在这个表达式执行时“生成”3个String对象,而是因为连接运算的两个参数都是字面量,而在Java源码编译为Java class文件时被合并为一个"aaabbb"常量。

    其次,从Java 5开始String的连接运算a+b会变为
    [code]StringBuilder sb = new StringBuilder();
    sb.append(a);
    sb.append(b);
    String result = sb.toString();[/code]
    其实至少创建了一个StringBuilder对象,一个char[](StringBuilder的成员),一个String对象(结果)和又一个char[](String的成员)。
    Java 5以前String的连接运算用的是StringBuffer来做的,跟上面的讲解类似。
    现在的Java编译器已经比较聪明,看到同一个表达式内连续出现连接运算时,会使用同一个StringBuilder来处理:
    [code]a + b + c + d[/code]
    会变为
    [code]StringBuilder sb = new StringBuilder();
    sb.append(a);
    sb.append(b);
    sb.append(c);
    sb.append(d);
    String result = sb.toString();[/code]

    要举例说明String的连接运算比StringBuilder/StringBuffer低效,可以在循环里做连接运算:
    [code]String a = "a";
    for (int i = 0; i < 10; i++) {
    a = a + "b";
    }[/code]
    这个等价于
    [code]String a = "a";
    StringBuilder sb = null;
    for (int i = 0; i < 10; i++) {
    sb = new StringBuilder();
    sb.append(a);
    sb.append("b");
    }
    a = sb.toString();[/code]
    与直接使用StringBuilder的例子相比
    [code]String a = "a";
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 10; i++) {
    sb.append("b");
    }
    a = sb.toString();[/code]
    很明显用String的加号的方式创建了更多的StringBuilder对象。但创建StringBuilder对象本身开销并不大,开销大的是其成员的char[]的创建和扩大。直接使用StringBuilder时,连接运算到char[]装不下的时候,会重新分配一个更大的char[],把老数组的内容复制过去。用String的加号时,每次循环都要创建一个新的char[],复制的次数比直接用StringBuilder多很多,因而速度慢。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名