深入剖析java对象创建
来源:互联网 发布:淘宝网手机客户端 编辑:程序博客网 时间:2024/06/05 03:47
1. new表达式做了什么?
Java语言里,new表达式(new+构造器)负责两个动作:
第一,分配对象空间并对其做默认初始化。默认初始化会将对象的所有成员字段设到其类型对应的默认值(零值)。
第二,初始化对象。
其中构造器只负责第2点,第1点是包含在new表达式里的语义。
2. Java如何初始化对象?
2.1当一个对象被创建时,虚拟机会为其分配内存(主要用来存放对象的实例变量及其从超类继承过来的实例变量)(即使这些从超类继承过来的实例变量有可能被隐藏也会被分配空间)。在为这些实例变量分配内存的同时,会执行默认初始化,这些实例变量也会被赋予默认值(零值)。
public class InstanceInitializer {
private int j = getI();
private int i = 1;
public InstanceInitializer() {
i = 2;
}
private int getI() {
return i;
}
public static void main(String[] args) {
InstanceInitializer ii = new InstanceInitializer();
System.out.println(ii.j);
}
}
如果我们执行上面这段代码,那么会发现打印的结果是0。因此我们可以确信,变量j被赋予了i的默认值0,而不是经过实例变量初始化器和构造函数初始化之后的值。
关于实例变量隐藏的插曲:
先看方法的覆盖(override)
class Foo {
void f(){
System.out.println("Foo");
}
}
public class Bar extends Foo {
void f(){
System.out.println("Bar");
}
public static void main(String[] args) {
Foo foo = new Bar();
Bar bar = new Bar();
foo.f();
bar.f();
}
}
输出:
Bar
Bar
说明,不管引用的类型是什么,只要它引用的是子类对象,调用到的都是子类的方法。然而实例变量只会被隐藏,不会被覆盖,根据引用类型不同,所访问到的实例变量就不一样。
class Foo {
int i = 0;
}
public class Bar extends Foo {
int i = 1;
public static void main(String[] args) {
Foo foo = new Bar();
Bar bar = new Bar();
System.out.println(foo.i);
System.out.println(bar.i);
}
}
上面的代码中,Foo和Bar中都定义了变量i,在main方法中,虽然foo 和bar两个引用都是引用的Bar 对象,但是System.out.println(foo.i)打印0;而System.out.println(bar.i)打印1。说明父类的i在子类对象中依然存在。子类对象只是在父类对象外面又包了一层,加上了自己的变量(父类和子类可以有同名变量)。
实例变量隐藏的插曲完。
在为这些实例变量分配内存的同时,这些实例变量也会被赋予默认值(这是第一次赋值,此赋值不可避免)。
2.2在内存分配完成之后,java的虚拟机就会开始对新创建的对象执行初始化操作。在Java中,有三种执行对象初始化的结构,分别是实例变量初始化器、实例初始化器以及构造函数。
我们可以在定义实例变量的同时,对实例变量进行赋值,赋值语句就是实例变量初始化器了。比如,
publicclassInstanceVariableInitializer {
privateinti = 1;
privateintj = i + 1;
}
我们还可以通过实例初始化器来执行对象的初始化操作,比如,
publicclassInstanceInitializer {
privateinti = 1;
privateintj;
{
j = 2;
}
}
上面代码中花括号内代码,在Java中就被称作实例初始化器。
如果我们定义了实例变量初始化器与实例初始化器,那么编译器会将其中的代码放到类的构造函数中去(实例变量初始化器与实例初始化器地位等同,执行先后顺序依从代码顺序),这些代码会被放在对超类构造函数的调用语句之后(还记得吗?Java要求构造函数的第一条语句必须是超类构造函数的调用语句),构造函数本身的代码之前。
3. 一个实例变量在对象初始化的过程中会被赋值几次?
3.1在本文的前面部分,我们提到过,JVM在为一个对象分配完内存之后,会给每一个实例变量赋予默认值,这个时候实例变量被第一次赋值,这个赋值过程是没有办法避免的。
3.2如果我们在实例变量初始化器中对某个实例x变量做了初始化操作,那么这个时候,这个实例变量就被第二次赋值了。
3.3如果我们在实例初始化器中,又对变量x做了初始化操作,那么这个时候,这个实例变量就被第三次赋值了。
3.4如果我们在类的构造函数中,也对变量x做了初始化操作,那么这个时候,变量x就被第四次赋值。
也就是说,一个实例变量,在Java的对象初始化过程中,最多可以被初始化4次。
- 深入剖析java对象创建
- JavaScript对象系统深入剖析3-创建对象Object.Create
- JavaScript对象系统深入剖析3-创建对象Object.Create
- JavaScript对象系统深入剖析3-创建对象Object.Create
- Java深入 | 对象如何创建&Class对象
- 面向对象深入剖析
- java环境变量深入剖析
- Java ThreadLocal 深入剖析
- 组件设计:补白[深入剖析ASP.NET组件设计]一书中HttpApplication对象创建的细节
- JavaScript对象系统深入剖析-1.对象
- JavaScript对象系统深入剖析-1.对象
- Java学习之【深入理解Java虚拟机---对象的创建】
- Java虚拟机对象的创建-《深入理解Java虚拟机》读书笔记
- Java对象创建—深入理解Java虚拟机(四)
- Java String 对象剖析
- Java String 对象剖析
- 一个深入理解JAVA传统线程对象创建的例子
- 【Java深入】创建对象的5种方式
- 04-树7 二叉搜索树的操作集
- PHP基础(2)---PHP函数
- PAT 乙级 1027. 打印沙漏(20)
- LeetCode算法题——26. Remove Duplicates from Sorted Array
- 【C】c语言模拟实现strcopy函数和strlen函数!!
- 深入剖析java对象创建
- ubuntu安装Mysql的注意事项
- 实战Unity3d-001:界面介绍
- PHP数组转JSON函数json_encode和JSON转数组json_decode函数的使用方法
- 作业六
- hdu 3342 Legal or Not(拓扑)
- 【Web】javascript跨域问题解决
- python列表
- 机器学习笔记——第0篇