黑马程序员技术交流社区

标题: 关于static静态快 [打印本页]

作者: 壁虎    时间: 2013-3-22 15:06
标题: 关于static静态快
本帖最后由 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 15:32
这个涉及到对象在内存中加载顺序的一个问题。你的Student对象创建后首先加载的是static{System.out.println(name);}静态块,然后才是加载默认构造函数。
但是你这个静态块在加载时用到了成员变量name,这个时候的name还没有在构造函数中赋予NULL值,所以编译时候会报错。
作者: 壁虎    时间: 2013-3-22 15:39
谢威 发表于 2013-3-22 15:32
这个涉及到对象在内存中加载顺序的一个问题。你的Student对象创建后首先加载的是static{System.out.println ...

貌似你回答错了,类被加载到内存中时,静态的成员就进来了。这个跟对象无关
作者: 张君    时间: 2013-3-22 15:56
  先static  对name 进行了初始化。然后 静态代码块是用于给类初始化的。相当如默认初始化。这个时候name 应该是默认空,但是 已经先被静态给初始化了,出现冲突。
作者: 王军行    时间: 2013-3-22 16:03
静态成员加载进入内存顺序问题,当优先级别相同时,就和一般语句一样按先后顺序加载,还是那个访问原则,先来的不能访问后来的。或者叫不能向后引用
不只是静态代码,你在主函数中,写 a= a+2; 把int a= 0;写后边也是不可以的,一个道理
作者: 张文星    时间: 2013-3-22 16:07
上面的说的不错,同样是静态的,所以初始化的时候是按顺序来的,打印输出name的时候name还没有定义或者说是初始化。
作者: 壁虎    时间: 2013-3-22 16:12
王军行 发表于 2013-3-22 16:03
静态成员加载进入内存顺序问题,当优先级别相同时,就和一般语句一样按先后顺序加载,还是那个访问原则,先 ...

为什么可以赋值呢?
作者: 谢威    时间: 2013-3-22 16:38
我测试了下,我确实讲错了,sorry
作者: 王军行    时间: 2013-3-22 19:49
tuo1254 发表于 2013-3-22 16:12
为什么可以赋值呢?

那个不是赋值,你在后面加上System.out.println(name); 会编译失败,非法向前引用。那句name = “世界”有什么用我就不知道了,我验证没有发生赋值
作者: 吴林飞    时间: 2013-3-22 21:11
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就访问不了他们。
作者: 周一川    时间: 2013-3-22 23:43
因为静态代码块是类一建立就建立的,而你下面是输出语句, System.out.println,是调用里面的System的类,所以会找不到这个方法 里面放的是类共性的属性
作者: 芦子骐    时间: 2013-3-23 01:14
    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="你好";        //如果你把这句调到第一句 那么一定能通过的
    }
总之,对内存的分析很重要,可以多下点功夫。
作者: 躺着睡觉    时间: 2013-9-12 22:25
谢谢各位的分析
作者: Uncle.Lee    时间: 2013-10-21 10:45
看到楼主的昵称和我要自学网的一个JAVA讲师一样,想问下是不是一个人啊




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2