java如何初始化对象

当一个对象被创建之后,虚拟机会为其分配内存,主要用来存放对象的实例变量及其从超类继承过来的实例变量(即使这些从超类继承过来的实例变量有可能被隐藏也会被分配空间)。在为这些实例变量分配内存的同时,这些实例变量也会被赋予默认值。

 

引用

 

关于实例变量隐藏

 

1
2
3
4
5
6
7
8
9       
10
11
class Foo {
     int i = 0 ;
}
 
class Bar extends Foo {
     int i = 1 ;
     public static void main(String... args) {
         Foo foo = new Bar();
         System.out.println(foo.i);//0
System.out.println(((Bar)foo).i);//1
         
     }
}

 

上面的代码中,Foo和Bar中都定义了变量i,在main方法中,我们用Foo引用一个Bar对象,如果实例变量与方法一样,允许被覆盖,那么打印的结果应该是1,但是实际的结果确是0。
但是如果我们在Bar的方法中直接使用i,那么用的会是Bar对象自己定义的实例变量i,这就是隐藏,Bar对象中的i把Foo对象中的i给隐藏了,这条规则对于静态变量同样适用。

 

在内存分配完成之后,java的虚拟机就会开始对新创建的对象执行初始化操作,因为java规范要求在一个对象的引用可见之前需要对其进行初始化。在Java中,三种执行对象初始化的结构,分别是实例初始化器、实例变量初始化器以及构造函数。

 

,如果我们显式调用超类的构造函数,那么调用指令必须放在构造函数所有代码的最前面,是构造函数的第一条指令。这么做才可以保证一个对象在初始化之前其所有的超类都被初始化完成。

如果我们在一个构造函数中调用另外一个构造函数,如下所示,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ConstructorExample {
     private int i;
 
     ConstructorExample() {
         this ( 1 );
         ....
     }
 
     ConstructorExample( int i) {
         ....
         this .i = i;
         ....
     }
}

 

对于这种情况,Java只允许在ConstructorExample(int i)内出现调用超类的构造函数,也就是说,下面的代码编译是无法通过的,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ConstructorExample {
     private int i;
 
     ConstructorExample() {
         super ();
         this ( 1 );
         ....
     }
 
     ConstructorExample( int i) {
         ....
         this .i = i;
         ....
     }
}

 

或者,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ConstructorExample {
     private int i;
 
     ConstructorExample() {
         this ( 1 );
         super ();
         ....
     }
 
     ConstructorExample( int i) {
         ....
         this .i = i;
         ....
     }
}

Java对构造函数作出这种限制,目的是为了要保证一个类中的实例变量在被使用之前已经被正确地初始化,不会导致程序执行过程中的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值