终极测试: 源文件: import java.util.*; public class TestAll{ public void foo(){ ArrayList al; while( true ){ al = new ArrayList(); } } public void bar(){ while( true ){ ArrayList al = new ArrayList(); } } }编译成class文件后,用jad反编译得到以下结果:// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://kpdus.tripod.com/jad.html // Decompiler options: packimports(3) // Source File Name: TestAll.javaimport java.util.ArrayList;public class TestAll { public TestAll() { } public void foo() { ArrayList arraylist; do arraylist = new ArrayList(); while(true); } public void bar() { ArrayList arraylist; do arraylist = new ArrayList(); while(true); } }
ArrayList al;
while( true )
{
al = new ArrayList();
...
}
为了提高系统运行效率,也可以这样:
ArrayList al;
while( true )
{
al = new ArrayList();
...
}====================================效率更低
===================================
为了提高系统运行效率,也可以这样:
ArrayList al;
while( true )
{
al = new ArrayList();
...
}====================================效率更低
////////////////////////////////////to maowu(猫呜) : 能解释一下吗?
空间所以不会
答错请谅解 :) 答案仅供参考
sboom(+-LingCh-+)(对不起,爱上你)
fxywkj(fxywkj)
的说法,循环结束只有最有一个对象是有reference的
另外:
我觉得 变量声明在循环内和循环外是一样的(对于本例)
/////////////////////////////////
===================================
为了提高系统运行效率,也可以这样:
ArrayList al;
while( true )
{
al = new ArrayList();
...
}====================================效率更低
////////////////////////////////////to maowu(猫呜) : 能解释一下吗?
==============================================================
理由是最后一个对象更加迟才能被回收。不过这种写法好像也有好处。
/////////////////////////////////
===================================
为了提高系统运行效率,也可以这样:
ArrayList al;
while( true )
{
al = new ArrayList();
...
}====================================效率更低
////////////////////////////////////to maowu(猫呜) : 能解释一下吗?
==============================================================
理由是最后一个对象更加迟才能被回收。不过这种写法好像也有好处。 另外一点,《Effective java》中介绍的原则是“让局部变量的作用域尽可能的小”。
while( true )
{
al = new ArrayList();
...
}while( true )
{
ArrayList al = new ArrayList();
}
其实这两个生成的byte code都是一样的
//==== 1 ====
ArrayList al;
while( true )
{
al = new ArrayList();
...
}//==== 2 ====while( true )
{
ArrayList al = new ArrayList();
}在情况2中,每次循环都需要声明一个新的变量,浪费时间,在内存尚未回收的情况下会更多地占用内存。
而情况1中则只是使用一个变量,没有这些问题。
而且每进行一次新的循环,上次创建的ArrayList也自动失去引用,同情况1没什么区别。
对于“最后一个对象更加迟才能被回收”的问题,只需要在循环完成后,加上一句
al=null;
即可。
public void foo(){
ArrayList al;
while( true ){
al = new ArrayList();
}
} public void bar(){
while( true ){
ArrayList al = new ArrayList();
}
}
}javap -c test.Test88public class test.Test88 extends java.lang.Object {
public test.Test88();
public void foo();
public void bar();
}Method test.Test88()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 returnMethod void foo()
0 goto 3
3 new #2 <Class java.util.ArrayList>
6 dup
7 invokespecial #3 <Method java.util.ArrayList()>
10 astore_1
11 goto 3Method void bar()
0 goto 3
3 new #2 <Class java.util.ArrayList>
6 dup
7 invokespecial #3 <Method java.util.ArrayList()>
10 astore_1
11 goto 3foo()和bar()是一样的!!
我分别编译了两种情况,代码是这样写的://== 1 ==
import java.util.*;
public class Test{
public static void main(String args[]){
ArrayList al;
while( true )
{
al = new ArrayList();
}
}
}//== 2 ==
import java.util.*;
public class Test{
public static void main(String args[]){
while( true )
{
ArrayList al = new ArrayList();
}
}
}编译器版本:1.5.0-beta2
编译的结果:两种情况均为297字节。
但是进行二进制比较时则有两个字节出现差别。比较结果如下:E:\temp>fc/b 1\Test.class 2\Test.class
Comparing files 1\Test.class and 2\TEST.CLASS
0000011A: 07 06
0000011E: 08 07
E:\temp\1>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: returnpublic static void main(java.lang.String[]);
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: goto 0}E:\temp\2>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: returnpublic static void main(java.lang.String[]);
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: goto 0}
反编译结果也是一样的。
但二进制比较为什么出现差别呢?费解ing...另外,字节码的优化方向或许会说明一些问题,可以说明那种想法的方向是对的。
=====================
不一样很正常呀,class文件中可以保存byte code对应src code的line number(行号)以便调试,用javap好了
=====================嗯,你说得对。
我用
javac -g:none Test.java
又编译了一次,进行二进制比较的结果是无差别。
等系统用尽内存时候去回收,已经晚了我觉得应该是,"系统判断内存快要用尽的时候"
指令dup和astore_1具体含义是什么?他们如何工作?
不要钻我字眼嘛。
源文件:
import java.util.*;
public class TestAll{
public void foo(){
ArrayList al;
while( true ){
al = new ArrayList();
}
} public void bar(){
while( true ){
ArrayList al = new ArrayList();
}
}
}编译成class文件后,用jad反编译得到以下结果:// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: TestAll.javaimport java.util.ArrayList;public class TestAll
{ public TestAll()
{
} public void foo()
{
ArrayList arraylist;
do
arraylist = new ArrayList();
while(true);
} public void bar()
{
ArrayList arraylist;
do
arraylist = new ArrayList();
while(true);
}
}