【问题标题】:Java array initialization by class constructor(Performance issues)通过类构造函数初始化 Java 数组(性能问题)
【发布时间】:2014-06-07 04:29:08
【问题描述】:

假设我有 A 类和 B 类,代码是这样的:

class A
{
   private int x;
   private int[] y=new int[10];
   private string s;

}

public class B
{
  public static void main(String args[])

{
  A a=new A();
}

我的理解是当A类没有定义构造函数时,JVM会自动定义这样的构造函数:

//Auto generated constructor
A()
{
  x=0;
  s=NULL;
  y[]=//What will come here 
}

我想知道在这个自动生成的构造函数中将为数组数据类型分配什么值。如果它为所有占位符分配零,它不会影响大型数组的程序的性能,因为将零分配给就时间而言,数组的所有成员都不是一项廉价的任务。

注意:(更新)

它不存储空值。What is the default initialization of an array in Java? 它存储零。所以我的问题是它会影响大型数组的性能。

【问题讨论】:

  • 与任何其他对象相同——null。您确实意识到您可以自己尝试一下,对吗?如果您担心初始化数组所需的时间(如果这需要任何时间),那么您也可能过早地进行优化
  • 是的,我可以,但我想知道它将如何完善性能,请完整阅读问题。
  • 我做到了,我回答了你的问题,如果你担心数组是如何初始化的,那么你几乎肯定会过早地优化,除非你对从其他地方获取引用更感兴趣。
  • @user3580294 你没有回答我的问题你只是用你自己的方式回答问题。
  • "我想知道在这个自动生成的构造函数中,数组数据类型会被赋予什么值。"我看不出它变得多么清晰。值为null

标签: java arrays


【解决方案1】:

来自这个测试类:

public class Test {
    int[] x;

    public static void main(final String[] args) {
        System.out.println(new Test().x);
    }
}

你得到这个输出:

null

如果您在编译为字节码之前使用javac -XD-printflat 查看编译器对您的源代码做了什么,您会得到:

public class Test {

    public Test() {
        super();
    }
    int[] x;

    public static void main(final String[] args) {
        System.out.println(new Test().x);
    }
}

由于x从未直接初始化,它将是null(目前找不到相关的JLS段落,但也许我会在某个时候偶然发现它。)


如果您将x 初始化为new int[10],您将在编译为字节码之前立即得到这个处理过的源代码:

public class Test {

    public Test() {
        super();
    }
    int[] x = new int[10];

    public static void main(final String[] args) {
        System.out.println(new Test().x);
    }
}

因此,在任何情况下,该字段都被初始化为与构造函数主体的其余部分分开的步骤。 JLS 12.5 明确说明了这一点——实例初始化程序和实例变量初始化程序在与构造函数的其余部分不同的步骤中执行。


但是,如果您使用 new int[size] 显式初始化数组,您将得到一个全为 0 的数组,正如您所指出的。这是否是性能问题确实是一个没有实际意义的问题,因为 JLS 明确指定了数组的默认值是什么,并且您将无法避免性能损失(如果有的话)。我现在正在查看 JDK 源代码,看看是否可以了解数组是如何创建的,但我怀疑大型数组创建开销应该是您最不关心的问题......

【讨论】:

    【解决方案2】:

    它将为空。数组被视为对象。

    如果您初始化一个数组 (int[] a = new int[10]),它将使用元素的默认值填充元素(例如,零表示整数或 null 表示对象和数组)。

    但是,默认构造函数不会这样做。它只是将整个数组设置为 null。

    【讨论】:

    • 这里接受的答案告诉数组用零填充。stackoverflow.com/questions/3426843/…
    • @user1613360 不。见here。如果你没有明确地创建数组,你最终会得到null
    • 语句 int var[]=new int[10] 将创建一个包含 10 个零的数组。您只是初始化了未创建的数组。
    • @user1613360 除了默认构造函数不这样做。正如您在问题中所问的那样,我正在使用默认构造函数。
    • @user1613360 构造函数没有进行初始化,因为初始化不在构造函数内部
    【解决方案3】:

    我通过调试检查了这一点。

    它将是[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],因为您设置(初始化数组)private int[] y = new int[10];

    如果你不这样初始化这个数组private int[] y,它将是null

    关于您的性能问题,请查看answers

    【讨论】:

      【解决方案4】:

      如果你没有像 private int[] y 这样初始化数组,它会返回 null,但是通过使用像 private int[] y=new int[10]; 这样的新数组,它会使用数组类型的默认值填充数组(在这种情况下它是 int)

      【讨论】:

        【解决方案5】:

        在 java 中,所有原始类型都将被初始化为其默认值。因此,如果您使用大小定义 int 类型的数组,则所有值都将初始化为 0。原始类型的开销比类少。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-22
          • 1970-01-01
          • 1970-01-01
          • 2017-06-23
          • 2017-08-28
          • 2012-09-15
          • 1970-01-01
          • 2014-02-27
          相关资源
          最近更新 更多