在 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 < 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 的int
s 数组。 因此,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(() -> new A())
就像以 lambda 描述的方式创建的单独 A 元素的工厂,() -> new A()
是 Supplier<A>
的实现 - 它描述了应该如何创建每个新的 A 实例。
limit(4)
设置流将生成的元素数量
toArray(A[]::new)
(也可以改写为toArray(size -> new A[size])
)——它让我们决定/描述应该返回的数组类型。
对于某些原始类型,您可以使用 DoubleStream
、IntStream
、LongStream
,它们还提供了像 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 中创建对象数组的主要内容,如果未能解决你的问题,请参考以下文章