A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 孙飞 中级黑马   /  2012-6-28 21:38  /  2945 人查看  /  14 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 feigecal 于 2012-6-29 07:47 编辑

class data
{
        private static final data mInstance = new data();
        private static int mx = 0;
        private data()
        {
                System.out.println("mx=" + mx);
                mx = getVersion();
        }
        public static data getInstance()
        {
                return mInstance;
        }
        public int getVersion()
        {
                int v = 0;
                if (v == 0)
                {
                        v = 7;
                        
                }
                return v;
        }
        public int getmx()
        {
                return mx;
        }
}

class Test2
{
        public static void main(String args[])
        {
                System.out.println(data.getInstance().getmx());
        }
}

为什么最后mx的值不是7?运行详细过程?如果把private static final data mInstance = new data();中的final去掉,能不能加上一个setInstance方法给mInstance赋一个值,用那个get方法输出?如果可以怎么写?如果不行,为什么?

评分

参与人数 1技术分 +3 收起 理由
刘蕴学 + 3 超赞的问题

查看全部评分

14 个回复

倒序浏览
本帖最后由 薄炳鑫 于 2012-6-28 22:18 编辑

你这是用的单例模式的思想所以是不能对对象进行修改的。
private data()
        {
                System.out.println("mx=" + mx);
                mx = getVersion();
                System.out.println("+++++++");//这里确定你上面的一句getVersion()执行了。效果如图:

        }
当把mx前面的静态去了以后:执行结果就会和你想的一样了如下图:
回复 使用道具 举报
不能
因为如果要写setInstance(mInstance m)就势必要在Test2方法中new 一个mInstance实例作为参数传进去,
而事实上data类采用的是单例模式,外部不能创建mInstance实例。
回复 使用道具 举报
哥们看看这个解释,
package com.heima.changjiajie;

public class Test13 {
                public static void main(String args[])
                {
                            System.out.println(data.getVersion());//这儿也能证明返回的是7
                            //System.out.println(data.getInstance());
                        System.out.println(data.getInstance().getmx());//data.getInstance().getmx()这个方法
                                                                      //先是执行了getInstance,再就是getmx()了,没实例化对象所以没掉用构造函数,就没执行private data(),getversion()等,所以return的是mx的初始值...

                }
        }
        class data
        {
                private static final data mInstance = new data();
                private static int mx = 0;
                private data()
                {
                        System.out.println("mx=" + mx);
                        mx = getVersion();
                       //System.out.println(mx);//这儿打印的也是7
                }
                public static data getInstance()
                {
                        return mInstance;
                }
                public static int getVersion()//加个static用来证明是不是返回的是多少,主函数里调用这个方法..
                {
                        int v = 0;
                        if (v == 0)
                        {
                                v = 7;
                        }
                       // System.out.println(v);//这儿打印的是7,也就证明返回的也就是7了,
                                        return v;
                }
                public int getmx()
                {
                        return mx;
                }
        }

       
       
       
回复 使用道具 举报
常佳杰 发表于 2012-6-28 22:44
哥们看看这个解释,
package com.heima.changjiajie;

如果没调用 构造函数怎么会执行构造函数中的语句System.out.println("mx=" + mx);呢?
回复 使用道具 举报
想了半天我感觉是这样的,不知道对不?首先类加载的时候,运行第一句的初始化,new一个对象也就是private static final data mInstance = new data();这句。因为new了一个对象,所以构造函数运行,执行System.out.println("mx=" + mx);输出"mx"=0。然后构造函数中的mx = getVersion();调用下面的方法,返回了7.然后运行第二名 private static int mx = 0;又给mx赋值了0.所以最后输出的是0。
但如果是这样的话,静态初始化不是优先于构造函数执行吗?为什么第一句运行后不是运行第二个静态初始化,而是运行构造函数呢?不太明白



回复 使用道具 举报
class data
{
private static final data mInstance = new data();  //去掉final之后也是不可以对mInstance赋值的
    private static int mx = 0;   //如果把static去掉会得到你想要的结果,参考截图:第二个执行结果为去掉static之后的情况
    private data()
    {
        mx = getVersion();   //java编译时是逐行编译,当编译该行代码的时候getVersion()并没有返回值,mx还是默认的值0,所以打印的结果是0  。
                                        //但是,在执行main函数的时候getVersion()函数会被执行,打印的结果为v=7,下图可以说明该情况。
        System.out.println("data()中:mx = " + mx);
    }
    public static data getInstance()
    {
        return mInstance;
    }
    public int getVersion()
    {
        int v = 0;
        if (v == 0)
        {
   v = 7;      
        }
  System.out.println("执行时:v = "+v);
        return v;
    }
    public int getmx()
    {
        return mx;
    }
}
class TestDataDemo
{
    public static void main(String args[])
    {
        System.out.println("main中:mx = "+data.getInstance().getmx());
    }
}
如图

点评

我也差点让你带沟里。。。看看10楼  发表于 2012-6-29 15:37

评分

参与人数 1技术分 +1 收起 理由
刘蕴学 + 1

查看全部评分

回复 使用道具 举报
调用
public int getmx()
                {
                        return mx;
                }
方法时,return的是mx,mx的值是初始值0,所以返回的是0
输出的也就是0了
回复 使用道具 举报
想了半天就只有这种可能了..
按流程应该是..
回复 使用道具 举报
本帖最后由 rslheima 于 2012-6-29 02:23 编辑

首先要了解类的初始化顺序:(参考 http://www.cnblogs.com/jackyrong/archive/2008/08/12/1266161.html)
  • 静态变量
  • 静态初始化块
  • 变量
  • 初始化块
  • 构造器
根据我自己的理解:
(1)data.getInstance().getmx()
              |---mInstance = new data()  会初始化一个构造函数 new data(),  但在这之前会先初始化静态变量,(按顺序)
                                                                                                                                                           |--private static (final )data mInstance  = new data();  
                                                                                                                                                           |                                                                  |--调用getVersion使得mx为7
                                                                                                                                                           |-- private static int mx =0;//这里又重新给mx赋值为0了

(2)之后调用getmx() ,这时mx等于0,所以返回了0



评分

参与人数 1技术分 +3 收起 理由
刘蕴学 + 3

查看全部评分

回复 使用道具 举报
rslheima 发表于 2012-6-29 02:22
首先要了解类的初始化顺序:(参考 http://www.cnblogs.com/jackyrong/archive/2008/08/12/1266161.html)
...

我感觉 也是这样的运行
回复 使用道具 举报
常佳杰 发表于 2012-6-29 00:14
想了半天就只有这种可能了..
按流程应该是..

我想应该是十楼说的那样
回复 使用道具 举报
本帖最后由 刘蕴学 于 2012-6-29 15:34 编辑
  1. class data
  2. {
  3.                
  4.         private static final data mInstance = new data();
  5.         
  6.         private static int mx;
  7.         
  8.         //这么初始化比较安全
  9.         static
  10.         {
  11.                 mx = getInstance().getVersion();
  12.         }
  13.         
  14.         public static data getInstance()
  15.         {
  16.                 return mInstance;
  17.         }
  18.         
  19.         public int getVersion()
  20.         {
  21.                 int v = 0;
  22.                 if (v == 0)
  23.                 {
  24.                         v = 7;
  25.                         
  26.                 }
  27.                 return v;
  28.         }
  29.         
  30.         public int getmx()
  31.         {
  32.                 return mx;
  33.         }
  34. }

  35. class Test21
  36. {
  37.         public static void main(String args[])
  38.         {
  39.                 System.out.println(data.getInstance().getmx());
  40.         }
  41. }
复制代码
把我都整乱了。。。。10楼的解释确实木有问题,不过我还是建议你不在构造方法里初始化静态变量,写静态块吧
回复 使用道具 举报
成员属性初始化分为显示初始化和隐士初始化  private static final data mInstance = new data();
                private static int mx =0;  首先执行   private static final data mInstance =null;   private static int max=0;  这是影视初始化  相当于写代码是写的
private static final data mInstance;  private static int mx;   接下来显示初始化  把new data();的结果返回给minstance 在这之前mx已经隐士初始化了所以不会出现找不到mx的情况  minstance把 mx赋值了7   接下来mix的显示初始化又把mx赋值了0  在调用getInstance返回对象 调用对象的getMax打印 现在max=0 所以结果是mx=0   0
回复 使用道具 举报
执行流程  首先 定义声明了的静态变量 private static final data mInstance;        private static int mx;  接着把new data()结果赋值给  中途把7赋值给mx 因为mx被声明了所以不会报错 mx=7 接下来把mx显示赋值  把0赋值给mx所以mx 的值为0  调用getInstance  返回对象 调用getMx 打印所以结果为mx=0   0
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马