黑马程序员技术交流社区
标题: 求分析此程序(这个问题比较好) [打印本页]
作者: 郝少普 时间: 2012-11-20 22:21
标题: 求分析此程序(这个问题比较好)
- class Price{
- // 类成员是 Price 的实例
- final static Price ISDO = new Price(2.8);
- // 定义一个类变量
- static double num = 20;
- // 一个 Price 的实例变量
- double nump;
- public Price(double n){
- // 计算实例变量的值
- nump = num - n;
- }
- }
- public class PriceTest {
- public static void main(String[] args) {
- System.out.println(Price.ISDO.nump); // 1
- Price p = new Price(2.8);
- System.out.println(p.nump); // 2
- }
- /* 结果 : 为何为此结果?
- -2.8
- 17.2*/
- }
复制代码
作者: 奚华 时间: 2012-11-20 22:44
在初始化ISDO时num的值为0,所以ISDO.nump=-2.8;初始化一个对象的时候他的数据域的初始化要早于构造方法,并且按数据域的声明顺序来初始化这些数据域,当ISDO初始化的时候num还没被初始化为20,它为0.
作者: 王震阳老师 时间: 2012-11-20 22:45
本帖最后由 王震阳 于 2012-11-20 22:55 编辑
这个问题我想明白了,还是final和静态的问题。这也是java中的一个难点。
//该句话是静态的因此当该类加载的时候,就去调用构造函数了,这时候num的值还没有被赋予,因此此时num=0,n=2.8,因此被final修饰的ISDO的nump变量
//的值就成了0-2.8=2.8了,并且在final的作用写,该值被固定下来,直到该类的生命周期结束才释放。对于p。nump的值就好理解多了
//因为new Price()的时候,重新创建了一个实例给P了,此时num=20,p.nump=20-2.8=17.2.- class Price{
- // 类成员是 Price 的实例
- final static Price ISDO = new Price(2.8);//该句话是静态的因此当该类加载的时候,就去调用构造函数了,这时候num的值还没有被赋予,因此此时num=0,n=2.8,因此被final修饰的ISDO的nump变量
- //的值就成了0-2.8=2.8了,并且在final的作用写,该值被固定下来,直到该类的生命周期结束才释放。对于p。nump的值就好理解多了
- //因为new Price()的时候,重新创建了一个实例给P了,此时num=20,p.nump=20-2.8=17.2.
- // 定义一个类变量
- static double num = 20;
- // 一个 Price 的实例变量
- double nump;
- public Price(double n){
- // 计算实例变量的值
- nump = num - n;
- }
- }
- public class PriceTest {
- public static void main(String[] args) {
- System.out.println("1:"+Price.ISDO.nump); // 1
- Price p = new Price(2.8);
- System.out.println(p.nump); // 2
- }
- /* 结果 : 为何为此结果?
- -2.8
- 17.2*/
- }
复制代码
作者: 奚华 时间: 2012-11-20 22:46
你们去参考类初始化时初始化的顺序
作者: 张学永 时间: 2012-11-20 22:47
本帖最后由 张学永 于 2012-11-20 22:57 编辑
package com.itheima.zxyio;
class Price{
// 类成员是 Price 的实例
final static Price ISDO = new Price(2.8);
// 定义一个类变量
static double num = 20;
// 一个 Price 的实例变量
double nump;
public Price(double n){
// 计算实例变量的值
System.out.println("num="+num);
nump = num - n;
}
}
public class Test {
public static void main(String[] args) {
System.out.println("Price.ISDO.nump="+Price.ISDO.nump); // 1
Price p = new Price(2.8);
System.out.println("p.nump="+p.nump); //2
}
}
将以上代码做测试,输出结果为:
num=0.0
Price.ISDO.nump=-2.8
num=20.0
p.nump=17.2
可以分析了:
刚开始的时候final static Price ISDO = new Price(2.8)是类的成员,它随着类的加载而加载。
final static Price ISDO = new Price(2.8);
static double num = 20;
而你的ISDO是比num先加载的,而ISDO加载的时候,num只有默认值0;
类的成员被加载的时候都有默认初始化值。而static double num 的默认值为0;所以ISDO在加载的时候用到的num为0,得到的nump为-2.8
当ISDO加载完毕后,num才被赋值为20,被所有对象所共享。
而如果把上面加载顺序改为
static double num = 20;
final static Price ISDO = new Price(2.8);
这时候num是优先于ISDO加载的,这样输出结果就都是17.2了。。。
作者: 王亚运 时间: 2012-11-20 23:02
本帖最后由 王亚运 于 2012-11-20 23:07 编辑
说明:google找到的答案。
还是没看懂,分享下。- class Price{
- final static Price INSTANCE = new Price(2.8);
- static double initPrice = 20;
- double currentPrice;
- public Price(double discount){
- currentPrice = initPrice - discount;
- }
- }
- public class PriceTest{
- public static void main(String[] args){
- System.out.println(Price.INSTANCE.currentPrice); //1
- Price p = new Price(2.8);
- System.out.println(p.currentPrice); //2
- }
- }
复制代码[size=14.44444465637207px]程 序中1、2行代码都访问到Price实例的currentPrice实例变量,而且程序都是通过new Price(2.8);来创建Price实例的。 表明上看,程序输出两个Price的currentPrice都应该返回17.2,但实际上程序并没有输出两个17.2,而是输出了-2.8和17.2.下面从内存角度来分析这个程序。第一次用到Price类时,程序开始对Price类进行初始化,初始化分成以下两个阶段:a、系统为Price的两个类变量分配内存空间。b、按初始化代码的排列顺序对类变量执行初始化。在 a阶段,系统纤维INSTANCE、initPrice两个变量分配内存空间,此时INSTANCE、initPrice的值为默认值null和0.0. 接着初始化进入b阶段,程序按顺序依次为INSTANCE和initPrice进行赋值。对INSTANCE赋值时要调用Price(2.8),创建 Price实例,此时立即执行代码:currentPrice = initPrice - discount;为currentPrice进行赋值,此 时initPrice类变量的值还是默认值0.0,因此赋值的结果是currentPrice等于-2.8.接着,程序再将initPrice赋值为 20,但此时对INSTANCE的currentPrice的实例变量已经不起作用了。 当Price类初始化完成后 INSTANCE类变量引用到一个currentPrice为-2.8的Price实例,而initPrice的类变量值为20.0.以后再创建 Price实例时,currentPrice的实例变量的值才等于20.0-discount
不明白,final static Price INSTANCE = new Price(2.8);
什么意思。。。。
源地址:http://www.cnblogs.com/yangfengtao/archive/2012/10/18/2729838.html
作者: 郝少普 时间: 2012-11-20 23:13
张学永 发表于 2012-11-20 22:47
package com.itheima.zxyio;
class Price{
// 类成员是 Price 的实例
不错 +1
哈哈
作者: 郝少普 时间: 2012-11-20 23:13
王亚运 发表于 2012-11-20 23:02
说明:google找到的答案。
还是没看懂,分享下。程 序中1、2行代码都访问到Price实例的currentPrice实例变 ...
看楼上的回答,他回答的不错
作者: 郝少普 时间: 2012-11-20 23:14
奚华 发表于 2012-11-20 22:44
在初始化ISDO时num的值为0,所以ISDO.nump=-2.8;初始化一个对象的时候他的数据域的初始化要早于构造方法, ...
嗯,是这个道理
作者: 郝少普 时间: 2012-11-20 23:14
王震阳 发表于 2012-11-20 22:45
这个问题我想明白了,还是final和静态的问题。这也是java中的一个难点。
//该句话是静态的因此当该类加载的 ...
具体来说,应该是属于初始化的问题
作者: 张超 时间: 2012-11-21 07:18
奚华 发表于 2012-11-20 22:44
在初始化ISDO时num的值为0,所以ISDO.nump=-2.8;初始化一个对象的时候他的数据域的初始化要早于构造方法, ...
你好 有点疑问 ,
final static Price ISDO = new Price(2.8);
这句的创建new Price(2,8)创建对象的时候,难道只对num和nump初始化,而不对他们赋值吗
作者: 王阳 时间: 2012-11-21 20:25
个人理解这个就是final静态变量和静态变量的问题,还有就是初始化顺序的问题,首先,final定义的变量是不可被修改的。不过这里定义的是一个是实例对象,不过它依然是不可修改的,包括里面的值,由于初始化顺序的问题,final静态变量会在静态变量之前,所以即便静态变量的值被初始化了,也无法改变在他之前已经初始化了的final静态变量了,而且在初始化final静态变量时候里面的值已经被初始化结束了。这也就是前后两次输出结果不一致的原因,不过如果换一下顺序就没有问题了。所以总结了下,这个问题就是静态变量初始化的顺序,已经final不可以被修改的问题
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |