【问题标题】:Creating an array of objects in Java在 Java 中创建对象数组
【发布时间】:2011-07-18 20:50:26
【问题描述】:

我是 Java 新手,当时我在 Java 中创建了一个对象数组。

例如,我有一个 A 类 -

A[] arr = new A[4];

但这只是创建指向A 的指针(引用),而不是 4 个对象。它是否正确?我看到当我尝试访问创建的对象中的函数/变量时,我得到一个空指针异常。 为了能够操作/访问我必须这样做的对象:

A[] arr = new A[4];
for (int i = 0; i < 4; i++) {
    arr[i] = new A();
}

这是正确的还是我做错了什么?如果这是正确的,那真的很奇怪。

编辑:我觉得这很奇怪,因为在 C++ 中,你只需说 new A[4],它就会创建四个对象。

【问题讨论】:

  • 我只想说这是一个非常有用的问题;谢谢你的提问。

标签: java arrays class


【解决方案1】:

这是正确的。

A[] a = new A[4];

...创建 4 个A 引用,类似于这样做:

A a1;
A a2;
A a3;
A a4;

现在你不能像这样不分配a1 来做a1.someMethod()

a1 = new A();

同样,使用数组你需要这样做:

a[0] = new A();

...在使用之前。

【讨论】:

  • 这个答案为我解开了一大堆困惑,感谢它的存在。
  • 我也有这种困惑,因为我来自 C++ 背景,我一直认为就像在 C++ Java 中的 new 关键字也调用构造函数并分配 I 内存。与 C++ 相比,我猜在 Java new 中只创建引用而不是实际对象。感谢您的回答。
  • @Krishna_Oza,这里与 C++ 没有区别。第一个 new 创建一个数组对象。这些是动态分配的对象(“堆”)。所以类似的 C++ 代码是A **a = new A*[4]; for (int i = 0; i &lt; 4; ++i) { a[i] = new A(); }
  • 我知道 new 创建了引用,但为什么不像在 C++ 中那样为数组的每个元素初始化构造函数。这可能很愚蠢,但我想问一下,如果我们这样做,我们会有什么问题吗? @MeBigFatGuy
  • @Jasser - 你会为元素调用什么构造函数?如果唯一的元素构造函数需要一堆参数怎么办?您将如何创建这些对象?
【解决方案2】:

这是正确的。你也可以这样做:

A[] a = new A[] { new A("args"), new A("other args"), .. };

此语法还可用于在任何地方创建和初始化数组,例如在方法参数中:

someMethod( new A[] { new A("args"), new A("other args"), . . } )

【讨论】:

    【解决方案3】:

    下面是创建包含 10 个员工对象的数组的清晰示例,其构造函数带有参数:

    public class MainClass
    {  
        public static void main(String args[])
        {
            System.out.println("Hello, World!");
            //step1 : first create array of 10 elements that holds object addresses.
            Emp[] employees = new Emp[10];
            //step2 : now create objects in a loop.
            for(int i=0; i<employees.length; i++){
                employees[i] = new Emp(i+1);//this will call constructor.
            }
        }
    }
    
    class Emp{
        int eno;
        public Emp(int no){
            eno = no;
            System.out.println("emp constructor called..eno is.."+eno);
        }
    }
    

    【讨论】:

      【解决方案4】:

      是的,它只创建引用,这些引用设置为默认值 null。这就是为什么你得到一个 NullPointerException 你需要单独创建对象并分配引用。在 Java 中创建数组有 3 个步骤 -

      声明 – 在此步骤中,我们指定要创建的数组的数据类型和维度。但请记住,我们还没有提到尺寸的大小。它们是空的。

      实例化 – 在这一步中,我们使用 new 关键字创建数组或为数组分配内存。正是在这一步中,我们提到了数组维度的大小。

      初始化 – 数组始终初始化为数据类型的默认值。但是我们可以进行自己的初始化。

      在 Java 中声明数组

      这就是我们在 Java 中声明一维数组的方式——

      int[] array;
      int array[];
      

      Oracle 建议您使用前一种语法来声明数组。 以下是其他一些法律声明的示例——

      // One Dimensional Arrays
      int[] intArray;             // Good
      double[] doubleArray;
      
      // One Dimensional Arrays
      byte byteArray[];           // Ugly!
      long longArray[];
      
      // Two Dimensional Arrays
      int[][] int2DArray;         // Good
      double[][] double2DArray;
      
      // Two Dimensional Arrays
      byte[] byte2DArray[];       // Ugly
      long[] long2DArray[];
      

      这些是一些非法声明的例子——

      int[5] intArray;       // Don't mention size!
      double{} doubleArray;  // Square Brackets please!
      

      实例化

      这就是我们“实例化”或为数组分配内存的方式——

      int[] array = new int[5];
      

      当JVM遇到new关键字时,它明白它必须为某事分配内存。通过指定int[5],我们的意思是我们想要一个大小为5 的ints 数组。 因此,JVM 创建内存并将新分配的内存的引用分配给数组,该数组的“引用”类型为int[]

      初始化

      使用循环 – 使用 for 循环来初始化数组的元素是使数组运行的最常用方法。如果您要自己分配默认值,则无需运行 for 循环,因为 JVM 会为您完成。

      All in One..! – 我们可以一次性声明、实例化和初始化我们的数组。这是语法 -

      int[] arr = {1, 2, 3, 4, 5};
      

      这里我们不提大小,因为 JVM 可以看到我们给出了 5 个值。

      所以,在我们实例化之前,引用保持为空。希望我的回答对你有所帮助..! :)

      来源 - Arrays in Java

      【讨论】:

        【解决方案5】:

        是的,在 Java 中是正确的,有几个步骤可以创建一个对象数组:

        1. 声明然后实例化(创建内存来存储“4”个对象):

          A[ ] arr = new A[4];
          
        2. 初始化对象(在这种情况下,您可以初始化 4 个 A 类对象)

          arr[0] = new A();
          arr[1] = new A();
          arr[2] = new A();
          arr[3] = new A();
          

          for( int i=0; i<4; i++ )
            arr[i] = new A();
          

        现在您可以开始从刚刚创建的对象等中调用现有方法了。

        例如:

          int x = arr[1].getNumber();
        

          arr[1].setNumber(x);
        

        【讨论】:

          【解决方案6】:

          对于泛型类,需要创建一个包装类。 例如:

          Set<String>[] sets = new HashSet<>[10]
          

          导致:“无法创建通用数组”

          改用:

                  class SetOfS{public Set<String> set = new HashSet<>();}
                  SetOfS[] sets = new SetOfS[10];  
          

          【讨论】:

          • 这行是否意味着,您正在尝试创建一个 Set 数组,其中 Set 类型为 String?
          【解决方案7】:

          你是对的。除此之外,如果我们想创建由某个“工厂”提供的元素填充的特定大小的数组,因为 Java 8(引入了stream API)我们可以使用这个单行:

          A[] a = Stream.generate(() -> new A()).limit(4).toArray(A[]::new);
          
          • Stream.generate(() -&gt; new A()) 就像以 lambda 描述的方式创建的单独 A 元素的工厂,() -&gt; new A()Supplier&lt;A&gt; 的实现 - 它描述了应该如何创建每个新的 A 实例。
          • limit(4) 设置流将生成的元素数量
          • toArray(A[]::new)(也可以改写为toArray(size -&gt; new A[size]))——它让我们决定/描述应该返回的数组类型。

          对于某些原始类型,您可以使用 DoubleStreamIntStreamLongStream,它们还提供了像 range rangeClosed 这样的生成器以及其他一些生成器。

          【讨论】:

            【解决方案8】:

            java中声明新数组的一般形式如下:

            type arrayName[] = new type[numberOfElements];

            其中 type 是原始类型或对象。 numberOfElements 是您将存储到数组中的元素数量,此值不能更改,因为 Java 不支持动态数组(如果您需要灵活且动态的结构来保存您可能想要的对象使用一些 Java 集合)。

            让我们初始化一个数组来存储一个 5 人的小公司中所有员工的工资:

            int salaries[] = new int[5];

            数组的类型(在本例中为int)适用于数组中的所有值。您不能在一个数组中混合类型。

            现在我们已经初始化了我们的薪水数组,我们想将一些值放入其中。我们可以在初始化期间这样做:

            int salaries[] = {50000, 75340, 110500, 98270, 39400};

            或者稍后再这样做:

            salaries[0] = 50000;
            salaries[1] = 75340;
            salaries[2] = 110500;
            salaries[3] = 98270;
            salaries[4] = 39400;
            

            更直观的数组创建示例:

            要了解有关数组的更多信息,请check out the guide

            【讨论】:

              【解决方案9】:

              假设A类是这样的:

              class A{
              int rollno;
              int DOB;
              }        
              

              并且你想为 A 类创建一个对象数组。所以你这样做,

                  A[] arr = new A[4];    //Statement 1
                  for (int i = 0; i < 4; i++) {
                  arr[i] = new A();      //Statement 2
                  }
              

              这是绝对正确的。

              这里 A 是类,在语句 1 中,类 A 是数组的数据类型。当由于 new 关键字而执行此语句时,将创建一个对象并为其动态分配内存,这将等于数据类型 A 的 4 个块所需的空间,即(数组中的一个块所需的空间为 8 个字节(4+4),我假设 int 占用 4 个字节的空间。因此分配的总空间为数组的 4*4 字节)。 然后将对象的引用赋予 arr 变量。这里需要注意的重要一点是,语句 1 与为 A 类创建对象无关,没有为此类创建对象,它仅用作数据类型,它给出了 A 类的内存分配所需的大小数组。

              然后,当 for 循环运行并执行语句 2 时,JVM 现在为 A 类分配内存(即创建一个对象)并将其引用提供给 arr[i]。每次调用循环时都会创建一个对象并将其引用提供给 arr[i]。

              因此,保存 8 字节空间的 arr[0] 被赋予 A 类对象的引用,并且每次循环运行时都会创建新对象并引用该对象,以便它现在可以访问该对象中的数据。

              【讨论】:

                猜你喜欢
                • 2020-12-17
                • 2013-12-12
                • 2013-04-30
                • 2021-07-30
                • 2019-10-28
                • 1970-01-01
                • 2014-06-03
                • 1970-01-01
                相关资源
                最近更新 更多