在 Java 中创建对象数组

Posted

技术标签:

【中文标题】在 Java 中创建对象数组【英文标题】:Creating an array of objects in 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],它就会创建四个对象。

【问题讨论】:

我只想说这是一个非常有用的问题;谢谢你的提问。 【参考方案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 中是正确的,有几个步骤可以创建一个对象数组:

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

    A[ ] arr = new A[4];
    

    初始化对象(在这种情况下,您可以初始化 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 SetOfSpublic 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 类对象的引用,并且每次循环运行时都会创建新对象并引用该对象,以便它现在可以访问该对象中的数据。

【讨论】:

以上是关于在 Java 中创建对象数组的主要内容,如果未能解决你的问题,请参考以下文章

java中创建一个客户类数组customer[] 怎么给数组中的变量赋值?

如何在数组中创建一个新对象

如何在 Java 中创建锯齿状二维数组?

在对象中创建一个具有不同数组元素的新数组[关闭]

在 C++ 中创建动态对象的动态数组

如何使用 java spring 注释在 MongoDB 中创建一个完全填充的引用对象