Java报错Index 0 out of bounds for length 0的原因及解决
为什么我的ConnectionManager会抛出NullPointerException,而Test类的相同逻辑却正常运行?
先看这段可以正常运行的代码:
class Test { static int size; } public class E08_ConnectionApp { public static void main(String[] args) { Test.size = Integer.parseInt(args[0]); Test[] test = new Test[Test.size]; for (int i = 0; i < Test.size; i++) test[i] = new Test(); } }
但当我实现类似逻辑的ConnectionManager时,却抛出了NullPointerException,错误出现在ConnectionManager构造方法的循环行:
for (int i = 0; i < size; i++) connections[i] = Connection.createNewConnection(i + 1);
以下是无法运行的完整代码:
class Connection { private int ID; private Connection(int ID) { this.ID = ID; print("Connection number " + ID + " created."); } static Connection createNewConnection(int ID) { return new Connection(ID); } Connection getConnection() { return this; } public int getID() { return ID; } } class ConnectionManager { private int size; public ConnectionManager(int size) { this.size = size; for (int i = 0; i < size; i++) connections[i] = Connection.createNewConnection(i + 1); } private Connection[] connections = new Connection[size]; public Connection getAvailableConnection() { for (int i = 0; i < size; i++) if (connections[i] != null) { Connection temp = connections[i].getConnection(); connections[i] = null; print("Connection #" + temp.getID() + " fetched."); return temp; } print("No connections available..."); return null; } } public class E08_ConnectionApp { public static void main(String[] args) { ConnectionManager connectionManager = new ConnectionManager(Integer.parseInt(args[0])); } }
我原本以为是数组虽然分配了空间但都是null引用,但我明明就是要在循环里初始化这些引用。我试过排查项目设置、怀疑IDE bug,但都不是问题,而且Test类的逻辑一直正常,实在搞不懂哪里错了,正确的实现方式应该是什么?
问题原因
核心问题在于Java中类成员的初始化顺序:
- 创建
ConnectionManager对象时,会先初始化所有类成员变量,再执行构造方法。 - 你的
connections数组是在构造方法之后定义的成员变量,初始化connections时,size还没被构造方法赋值(此时size是默认值0),导致connections是一个长度为0的空数组。 - 当构造方法里的循环尝试访问
connections[i]时,数组长度为0,直接触发异常。
而Test类的逻辑之所以正常,是因为Test.size是静态变量,你在创建数组前已经给它赋值,且数组是在main方法里创建的,不存在成员初始化顺序的冲突。
正确的实现方式
调整数组的初始化时机,把数组的创建放到构造方法里,确保使用已经赋值的size:
修改后的ConnectionManager类:
class ConnectionManager { private int size; private Connection[] connections; // 先声明数组,不初始化 public ConnectionManager(int size) { this.size = size; connections = new Connection[size]; // 构造方法内用已赋值的size初始化数组 for (int i = 0; i < size; i++) connections[i] = Connection.createNewConnection(i + 1); } public Connection getAvailableConnection() { for (int i = 0; i < size; i++) if (connections[i] != null) { Connection temp = connections[i].getConnection(); connections[i] = null; print("Connection #" + temp.getID() + " fetched."); return temp; } print("No connections available..."); return null; } }
这样修改后,数组会用正确的size值初始化,后续循环就能正常给数组元素赋值,不会再触发异常。
内容的提问来源于stack exchange,提问作者Нормальный дневник
相关产品推荐
相关产品推荐

