2017-02-09 92 views
0

我有以下类向对象数组投射null是否比投射到对象花费更多?

public void dump(Integer value){ 
    //do soemthing with value 
} 
public void dump(Integer[] values){ 
    //do soemthing with values 
} 

,我想打电话给dump(null),也无所谓什么我选择投,因为工作都按计划与空值:

dump((Integer[]) null); 
    dump((Integer) null); 
  1. 哪一个更好地使用资源(更少的内存,CPU使用率)?
  2. 我认为Java会预分配4个字节为空整数和8个字节双,这是真的吗?
  3. 有关被置空其它(更复杂)的对象,如果没有构造函数的调用,然后如何被存储在什么空?
+1

在呼叫地点都不会使用更多的资源。哪个将使用较少的cpu是两个函数在接收时如何处理'null'值的函数。 'null'没有被分配,所以'(Integer)null'和'(Double)null'使用完全相同的堆空间量......零。 – AJNeufeld

+1

我认为你的问题大部分是通过http://stackoverflow.com/questions/2430655/java-does-null-variable-require-space-in-memory – azurefrog

回答

8
  1. 哪一个是更好地利用资源明智的(较少的内存,CPU使用率)?

它不会产生任何可测量的差异。

  • 我认为Java将预先分配为空整数和8个字节为双人4个字节,这是真的?
  • No.空值为空。只有一种格式。您在这里混淆了对象和引用。 null是一个参考。所有参考都是相同的大小。

    什么其它(更复杂)对象被置空

    有作为“被清零对象”没有这样的事。

    如果没有构造函数调用那么如何存储在空?

    为空值。

    +0

    回答的,这些对象是无效的,我的意思是像“TextView textView = null“而不是简单的数字 –

    +2

    @ThenEnok再一次令人困惑的是对象和引用。 'textView'是一个参考。 – EJP

    +0

    我明白你的意思,我应该说什么'其他(更复杂)对象的变量'' –

    1

    我相信它们的成本相等,因为在这两种情况下您都没有实际的对象(Integer对象,既没有Integer[]对象,它们在内存中的大小肯定也不相同)。

    你在这里什么是仅有4个字节的参考,它指向什么,因为它空。从这个角度来看,您正在铸造这些null-s的类型之间没有区别。

    2

    类型铸造的,不影响由空使用的内存。在反编译类:

    aconst_null 
    checkcast  #4     // class java/lang/Integer 
    invokevirtual #5     // Method dump:(Ljava/lang/Integer;)V 
    

    VS

    aconst_null 
    checkcast  #6     // class "[Ljava/lang/Integer;" 
    invokevirtual #7     // Method dump:([Ljava/lang/Integer;) 
    

    所以无论是在内存使用方面是相同的。

    +1

    'checkcast' *是* cast,它在运行时执行。它就在字节码中。 – EJP

    +0

    够公平,纠正了评论。 – user3486184

    -2
    1. 哪一个更好地使用资源明智(少RAM,CPU使用率)?

    如果你需要问自己这个问题,你可以写一个简单的测试。

    public class Main { 
        private static Integer x = 0; 
        private static final int n = 500000000; 
    
        public static void dump(Integer value){ 
         x += 1; 
        } 
        public static void dump(Integer[] values){ 
         x += 1; 
        } 
    
        public static void main(String[] args) { 
         long t = System.currentTimeMillis(); 
         for (int i = 0; i < n; i++) { 
          dump((Integer[]) null); 
         } 
         long array_time = System.currentTimeMillis() - t; 
         t = System.currentTimeMillis(); 
         for (int i = 0; i < n; i++) { 
          dump((Integer) null); 
         } 
         long int_time = System.currentTimeMillis() - t; 
         System.out.println("array_time: " + array_time + " ms"); 
         System.out.println("int_time: " + int_time + " ms"); 
        } 
    } 
    

    输出:

    array_time: 2578 ms 
    int_time: 2045 ms 
    

    不是显著差异。

    +1

    更好的测试是:“javap -c Main”比较字节码 – user3486184

    +1

    无效的基准测试。您没有预热JVM。你还将一个相当复杂的操作放到'dump()中,这两个都是不必要的,并且降低了结果的重要性。请参阅另一个答案中提供的字节码。时代没有理由甚至稍有不同。 – EJP

    0

    所有参考值(以及盒装整数和数组都是参考值)具有相同的表示形式,因此根本没有差异。如果成本存在差异,那么执行被调用的函数就可以了。

    1
    1. 没有区别。
    2. 没有。 Java根本没有为null对象分配任何空间,因为根据定义,null根本就不是对象的引用。根本没有任何物体完全没有空间。参考本身总是32或64位长。
    3. “存储”是什么意思?一个引用变量保存一个指针值,它总是与指向的对象无关。无论对象的大小如何,即使参考指向非值,参考大小始终都是相同的,不管它引用的是什么类型。这是地址的大小。我还没有看,但我敢打赌,null参考是一个特殊的地址值,如0,根据定义没有任何意义。

    铸造参考不会改变参考。它仍然具有完全相同的价值,一点点,它没有演员。

    唯一的例外是64位Java的32位优化。通常你会希望64位Java中的所有引用都是64位长。但是,如果对程序的某些假设成立,您可以打开或关闭以32位保存引用的功能。但无论哪种方式,一旦JVM决定参考的宽度是多少,即32位或64位,这将在程序中保持真实。

    因此,底线,不,铸造对其他类型的引用对引用所消耗的内存没有影响。

    如果对象的所有引用超出范围或成为null,则该对象消耗的内存可能会变为零。