今天带着自己的兴趣看了java-对象和内存控制有关的资料,对以前习以为常的代码写法如:
public class Entity1 {
private String fieldx ;
public Entity1() {
super();
}
public Entity1(String fieldx) {
super();
this.fieldx = fieldx;
}
public String getFieldx() {
return fieldx;
}
public void setFieldx(String fieldx) {
this.fieldx = fieldx;
}
}
对带参数的构造函数的理解知之甚少,总感觉大家这样写都是真理完全没有必要推敲其中的原因,今天有幸带着自己的灵感看了关于java对象的内存控制,感觉豁然开朗。
原来使用构造函数创建对象实例的过程中也对实例变量做了初始化的操作。对实例变量可以指定初始值的情况有三处分别是:定义实例变量时指定初始值、非静态初始化块指定初始值、构造函数指定初始值。
关键点就在“构造函数指定初始值”。定义实例变量时赋值、非静态初始化块赋值最终都会合并到构造函数中。因此我以前的疑惑来了,为何在构造函数中使用 this.field1 = field1 ;就能为实例变量赋值了。还要注意的是:上述两种为实例变量赋值的语句总是位于构造器的所有语句之前、两种为变量赋值的语句出现顺序为在其源代码中出现的顺序。
类变量的初始化过程和内存分配:
类变量的初始化过程和实例变量相同不同的是对类变量的初始化只能有两种情况:
1、在定义初始化变量的时候为其赋值。
2、在静态初始化块中为其赋值。两种赋值也是按照顺序的。
理解一下语句:在同一个JVM内每一个类只对应一个Class对象,但每一个类可创建多个java对象。
好了为了更加深入的理解类变量的初始化改编一道别人的面试题如下:
public class Question {
public final static Question INITQ = new Question(100);
public static int initValue = 100 ;
public int currentValue ;
public Question(int value) {
super();
this.currentValue = initValue - value;
}
public static void main(String[] args) {
System.out.println( Question.INITQ.currentValue ); // 猜猜此处输出值为?
Question q = new Question(100);
System.out.println( q.currentValue ); // 再猜猜此处输出值为?
}
}
如果你能果断直接的回答出答案说明你java基础还是可以的最起码比本人强多了。
国庆后来上班又看了看此道面试题顿时懵了,又找不到问题的答案了,仔细读了自己的笔记后还是没有发现端倪可见本人技术多菜没办法只有果断运行了。
运行后发现结果和自己想的有出入仔细分析和查看后发现:对实例变量or类变量赋值顺序是非常重要的,果断将上述代码对类变量定义的顺序调换:
public class Question {
public static int initValue = 100 ; //调换后代码
public final static Question INITQ = new Question(100);
// public static int initValue = 100 ; 调换前代码
public int currentValue ;
public Question(int value) {
super();
this.currentValue = initValue - value;
}
public static void main(String[] args) {
System.out.println( Question.INITQ.currentValue ); // 猜猜此处输出值为?
Question q = new Question(100);
System.out.println( q.currentValue ); // 再猜猜此处输出值为?
}
}
再次运行!!!哈哈