考虑一个简单的代码:
public class Graph {
private final List<ArrayList<Integer>> adjList = new ArrayList<ArrayList<Integer>>();
private final int vertexCount;
private int edgeCount;
public Graph(int vertexCount) {
this.vertexCount = vertexCount;
}
}
我的问题是何时创建了adjList对象,换句话说何时将内存分配给adjList?
它是在构造函数调用之后(不太可能)?
之前(因为私有构造函数可以使用静态类吗?)
如果之前正好考虑代码构造如下:
Graph g = new Graph(10);
答案 0 :(得分:3)
jls-12.5 : Creation of New Class Instances
每当创建一个新的类实例时,为它分配内存空间,为类类型中声明的所有实例变量提供空间,并在类类型的每个超类中声明所有实例变量,包括可能的所有实例变量隐藏(§8.3)。
答案 1 :(得分:3)
了解adjList
不是对象非常重要。这是一个变量 - 一个领域。 adjList
变量的空间被分配为在创建Graph
的实例时发生的第一个事件...在任何构造函数调用之前甚至开始。
接下来,VM遍历继承层次结构,评估所需的构造函数参数,直到它到达Object
类,然后它执行构造函数的主体...然后堆栈弹出执行子类的构造函数体。所以如果你有:
class Foo extends Object
class Bar extends Foo
然后首先执行Object
的构造函数体,然后Foo
,然后Bar
。
只有在构造函数体执行时才执行实例初始值设定项。就在这个召唤发生的时候:
new ArrayList<ArrayList<Integer>>()
创建另一个对象,然后初始化程序将引用分配给adjList
变量的新对象。重要的是要理解adjList
的值不是对象 - 它是一个参考。所以现在有两个对象(一个Graph
和一个ArrayList
)以及Graph
对象中ArrayList
对象的引用。 (实际上ArrayList
也会引用一个数组。)
答案 2 :(得分:0)
private final List<ArrayList<Integer>> adjList = new ArrayList<ArrayList<Integer>>();
private final int vertexCount;
private int edgeCount;
public Graph(int vertexCount) {
this.vertexCount = vertexCount;
}
变为:
private final List<ArrayList<Integer>> adjList;
private final int vertexCount;
private int edgeCount;
public Graph(int vertexCount) {
adjList = new ArrayList<ArrayList<Integer>>();
edgeCount = 0;
this.vertexCount = vertexCount;
}
在调用new
之后立即分配默认内存,然后由JVM调用构造函数。从那里,所有实例变量都在构造函数中实例化。显式定义由编译器在构造函数体内移动。
答案 3 :(得分:0)
我的问题是何时创建了adjList对象,换句话说是什么时候 内存分配给adjList?
作为实例变量,它将在创建实例时创建。
是在构造函数调用之后(不太可能)?
它将作为构造函数调用的一部分创建,因为构造函数将确保根据实例变量在内存中创建对象。
之前(因为私有构造函数可以使用静态类吗?)
不,在构造函数调用之前只创建静态变量。加载类时会创建静态变量。