Java 何时为实例变量指定对象
考虑一个简单的代码:Java 何时为实例变量指定对象,java,Java,考虑一个简单的代码: public class Graph { private final List<ArrayList<Integer>> adjList = new ArrayList<ArrayList<Integer>>(); private final int vertexCount; private int edgeCount; public Graph(int vertexCount) {
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;
}
}
private final List adjList=new ArrayList();
私人最终国际结算;
私人帐户;
公共图形(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;
}
私有最终列表;
私人最终国际结算;
私人帐户;
公共图形(int vertexCount){
adjList=新的ArrayList();
edgeCount=0;
this.vertexCount=vertexCount;
}
默认内存在调用new
之后分配,之后JVM调用构造函数。从那里,所有实例变量都在构造函数中实例化。编译器会将显式定义移到构造函数体中。private final List adjList=new ArrayList();
私人最终国际结算;
私人帐户;
公共图形(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;
}
私有最终列表;
私人最终国际结算;
私人帐户;
公共图形(int vertexCount){
adjList=新的ArrayList();
edgeCount=0;
this.vertexCount=vertexCount;
}
默认内存在调用new
之后分配,之后JVM调用构造函数。从那里,所有实例变量都在构造函数中实例化。编译器将显式定义移动到构造函数体中。
每当创建一个新的类实例时,都会为其分配内存空间,并为该类类型中声明的所有实例变量和该类类型的每个超类中声明的所有实例变量留出空间,包括所有可能隐藏的实例变量(§8.3)
每当创建一个新的类实例时,都会为其分配内存空间,并为该类类型中声明的所有实例变量和该类类型的每个超类中声明的所有实例变量留出空间,包括所有可能隐藏的实例变量(§8.3)
我的问题是何时创建adjList对象,换句话说,何时创建
分配给adjList的内存
作为实例变量,它将在创建实例时创建
是在构造函数调用之后(不太可能)
它将作为构造函数调用的一部分创建,因为构造函数将确保根据实例变量在内存中创建对象
之前(因为类可以是静态的,并且带有私有构造函数)
不,在构造函数调用之前只创建静态变量。静态变量是在加载类时创建的
我的问题是何时创建adjList对象,换句话说,何时创建
分配给adjList的内存
作为实例变量,它将在创建实例时创建
是在构造函数调用之后(不太可能)
它将作为构造函数调用的一部分创建,因为构造函数将确保根据实例变量在内存中创建对象
之前(因为类可以是静态的,并且带有私有构造函数)
不,在构造函数调用之前只创建静态变量。静态变量是在加载类时创建的。重要的是要理解
adjList
不是对象。这是一个变量-一个字段。adjList
变量的空间几乎是创建Graph
实例时发生的第一件事。。。在任何构造函数调用开始之前
接下来,VM沿着继承层次结构向上走,评估所需的任何构造函数参数,直到到达对象
类,然后在那里执行构造函数体。。。然后堆栈弹出以执行子类的构造函数体。因此,如果你有:
class Foo extends Object
class Bar extends Foo
然后首先执行对象的构造函数体,然后执行Foo
,然后执行Bar
只有在构造函数体执行时,才会执行实例初始值设定项。此时会发生此呼叫:
new ArrayList<ArrayList<Integer>>()
newarraylist()
这将创建另一个对象,然后初始值设定项将对新对象的引用指定给adjList
变量。重要的是要理解,adjList
的值不是一个对象,而是一个引用。因此现在有两个对象(一个Graph
和一个ArrayList
)和Graph
对象中对ArrayList
对象的引用。(实际上,ArrayList
也会引用数组。)了解adjList
不是对象很重要。这是一个变量-一个字段。adjList
变量的空间几乎是创建Graph
实例时发生的第一件事。。。在任何构造函数调用开始之前
接下来,VM沿着继承层次结构向上走,评估所需的任何构造函数参数,直到到达对象
类,然后在那里执行构造函数体。。。然后堆栈弹出以执行子类的构造函数体。因此,如果你有:
class Foo extends Object
class Bar extends Foo
然后首先执行对象的构造函数体,然后执行Foo
,然后执行Bar
只有在构造函数体执行时,才会执行实例初始值设定项。此时会发生此呼叫:
new ArrayList<ArrayList<Integer>>()
newarraylist()
这将创建另一个对象,然后初始值设定项将对新对象的引用指定给adjList
变量。重要的是要理解adjList
的值不是对象,而是一个引用。因此现在有两个对象(一个是Graph
,一个是ArrayList
)和一个引用