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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 壁虎 中级黑马   /  2013-3-22 15:06  /  3010 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 tuo1254 于 2013-3-23 14:53 编辑
  1. public class Student{
  2.           static{
  3.                   name="世界";
  4.          }
  5.          private static String name="你好";
  6. }
复制代码
上面的这段代码没有问题,编译OK
但是下面的这段代码就报错了:
  1. public class Student{
  2.            static{
  3.                    System.out.println(name);
  4.           }
  5.           private static String name="你好";
  6. }
复制代码
求解释,这是为什么。赋值却可以,引用却会报错??不过你只要把name声明在这个静态块前面,赋值引用都没问题了,我想static成员应该是从上往下加载进入内存的。

点评

如果问题未解决,请继续追问回复者,如果问题已经解决,请将分类改为“已解决”,谢谢  发表于 2013-3-22 23:00

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

13 个回复

倒序浏览
这个涉及到对象在内存中加载顺序的一个问题。你的Student对象创建后首先加载的是static{System.out.println(name);}静态块,然后才是加载默认构造函数。
但是你这个静态块在加载时用到了成员变量name,这个时候的name还没有在构造函数中赋予NULL值,所以编译时候会报错。
回复 使用道具 举报
谢威 发表于 2013-3-22 15:32
这个涉及到对象在内存中加载顺序的一个问题。你的Student对象创建后首先加载的是static{System.out.println ...

貌似你回答错了,类被加载到内存中时,静态的成员就进来了。这个跟对象无关
回复 使用道具 举报
  先static  对name 进行了初始化。然后 静态代码块是用于给类初始化的。相当如默认初始化。这个时候name 应该是默认空,但是 已经先被静态给初始化了,出现冲突。
回复 使用道具 举报
静态成员加载进入内存顺序问题,当优先级别相同时,就和一般语句一样按先后顺序加载,还是那个访问原则,先来的不能访问后来的。或者叫不能向后引用
不只是静态代码,你在主函数中,写 a= a+2; 把int a= 0;写后边也是不可以的,一个道理

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
上面的说的不错,同样是静态的,所以初始化的时候是按顺序来的,打印输出name的时候name还没有定义或者说是初始化。
回复 使用道具 举报
壁虎 中级黑马 2013-3-22 16:12:05
7#
王军行 发表于 2013-3-22 16:03
静态成员加载进入内存顺序问题,当优先级别相同时,就和一般语句一样按先后顺序加载,还是那个访问原则,先 ...

为什么可以赋值呢?
回复 使用道具 举报
谢威 中级黑马 2013-3-22 16:38:53
8#
我测试了下,我确实讲错了,sorry
回复 使用道具 举报
tuo1254 发表于 2013-3-22 16:12
为什么可以赋值呢?

那个不是赋值,你在后面加上System.out.println(name); 会编译失败,非法向前引用。那句name = “世界”有什么用我就不知道了,我验证没有发生赋值
回复 使用道具 举报
public class Student{
          static{
                  name="世界";
                  //静态代码块的作用就是给类初始化的,Student类一加载进内存就进行了初始化动作,给name赋了内存地址值,让name指向了"世界"这个对象
         }
         private static String name="你好";
}
上面的这段代码没有问题,编译OK
但是下面的这段代码就报错了:
public class Student{
           static{
                   System.out.println(name);
                   //你这么写,name连初始化值都没有,虚拟机怎么访问name,虚拟机完全不知道该怎么给这个变量分配内存空间,编译当然失败。
          }
          private static String name="你好";
//当你把这句话写在静态代码块的前面时,name就有了初始化值,这个值是"你好"这个对象的内存地址值,虚拟机才知道可以给name分配内存空间, 把对象"你好"的地址值赋给了name,
//让name指向了"你好"这个对象。
}
总结一句话就是:方法和代码块中的变量都必须显示初始化,否则JVM完全不知道该怎么给它们分配内存空间,它们不能在内存中安家,JVM就访问不了他们。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
因为静态代码块是类一建立就建立的,而你下面是输出语句, System.out.println,是调用里面的System的类,所以会找不到这个方法 里面放的是类共性的属性
回复 使用道具 举报
    public class Student{
              static{                             //当你定义这一句的时候  你的代码块内存中已经有了一个name的变量 并赋予了一个值(地址值)
                      name="世界";
             }
             private static String name="你好";   // 这一句中,你又在静态内存中声明了一个name 并且赋予了一个值(地址值)    这两句操作的并不是同一个对象
    }                                                                                                                                                                       你可以输出一下这两个name的地址值
————————————————————————————————————————————————————————————————————
    public class Student{
               static{
                       System.out.println(name);    //这一句中,你直接就调用了一个name变量,但是这个name变量是在此之后才被声明的 固然无法编译通过
              }
              private static String name="你好";        //如果你把这句调到第一句 那么一定能通过的
    }
总之,对内存的分析很重要,可以多下点功夫。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
谢谢各位的分析
回复 使用道具 举报
看到楼主的昵称和我要自学网的一个JAVA讲师一样,想问下是不是一个人啊
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马