黑马程序员技术交流社区
标题: 静态块问题 黑马们来帮我看下啊 [打印本页]
作者: walkonby 时间: 2013-1-20 01:56
标题: 静态块问题 黑马们来帮我看下啊
本帖最后由 张政 于 2013-1-20 22:32 编辑
- class Test{
- static{
- System.out.println("b");
- }
- public static void main(String args[]){
- new Test1();
- new Test1();
- System.out.println(11);
- }
- static{
- System.out.println("c");
- }
- }
- class Test1{
- static{
- System.out.println("a");
- }
- }
复制代码 执行结果:
b
c
a
11
看了老师讲的我还不信 又自己写代码试了一下 还真是老师那个结果
但是这样我就想不通了 我想问的是为什么不输出两次a呢 前面我new 一个对象在堆中出现了一个对象 然后执行静态块输出a 这个我能理解 但是到后面这个对象在堆中开辟的内存不是没人指向吗 应该就被回收了啊 然后下面又继续new 一个对象 应该又执行一次输出a啊 但是结果又不是这样 彻底懵了 求解答啊
作者: 夏振博 时间: 2013-1-20 02:23
本帖最后由 arno942 于 2013-1-20 02:31 编辑
在这个类第一次被调用或实例化的时候就会被执行。
静态代码块只会执行一次,一般会用来初始化一些值,并且在所有对象中全局共享
也就是说:
第一步是类加载,静态块在类加载的时候就执行了,只执行一次,因为不可能进行第二次类加载,
用法:
有些代码需要在类加载时就必须完成的时候,使用静态块。
对静态属性的初始化很复杂时(不是一条语句能完成的时候),使用静态块。
作者: 唐晓 时间: 2013-1-20 08:21
静态代码块只会执行一次,而且比类加载还早,只要调用先执行静态代码块。就算你new多个,加载完一次后就不会再加载了。
作者: 折纸时代 时间: 2013-1-20 09:28
本帖最后由 司懿卓 于 2013-1-20 09:29 编辑
静态成员是类所属的,不会因为对象的消失而回收的.
你创建两次对象,第一次创建时,静态初始化块会先进行初始化,然后才是非初始化块(如果有执行语句的话)和构造器,创建对象.
很显然,上面代码中没有非静态初始化块,也就是多次创建对象,没有显示结果.
代码帮你修改了下,现在第二次创建对象, 是打印 "d" .- class Test{
- static{
- System.out.println("b");
- System.out.println("c");
- }
- public static void main(String args[]){
- new Test1();
- new Test1();
- System.out.println(11);
- }
- /*static{ //一个类中,静态初始化块和非静态初始化块最好一样出现一个,.多了无意义.
- System.out.println("c");
- }*/
- }
- class Test1{
- static{
- System.out.println("a");
- }
- { //非静态初始化块是随着对象的创建而执行初始化的.
- System.out.println("d");
- }
- }
复制代码
作者: 卢浩 时间: 2013-1-20 10:03
你的会不会被回收的疑问我是这么想的哈,既然是静态嘛肯定是随着类的加载而存在的,随着类的消亡而消亡的,他应该是跟类同生共死的,所以不会被回收的,他并不是实例出来的东西,你可以类比下静态变量去理解,大前提都是静态嘛,这也是静态的特点,生命周期过长。执行一次用来初始化的。
作者: 卢浩 时间: 2013-1-20 10:03
你的会不会被回收的疑问我是这么想的哈,既然是静态嘛肯定是随着类的加载而存在的,随着类的消亡而消亡的,他应该是跟类同生共死的,所以不会被回收的,他并不是实例出来的东西,你可以类比下静态变量去理解,大前提都是静态嘛,这也是静态的特点,生命周期过长。执行一次用来初始化的。
作者: 高浩 时间: 2013-1-20 12:34
关于静态的,静态代码块,静态成员,都会随着类的加载而加载上,就是只要编译了该类文件,它里面的静态成员都会先跟着加载,存在内存中,而对象则是当你什么时候调用它的构造函数,它才会在堆内存中开辟一块空间。
作者: walkonby 时间: 2013-1-20 15:30
司懿卓 发表于 2013-1-20 09:28
静态成员是类所属的,不会因为对象的消失而回收的.
你创建两次对象,第一次创建时,静态初始化块会先进行初 ...
他这个类又是在哪里的呢 是堆中还是栈中 或者就是我在本地磁盘上的哪个class文件? 是本地的class文件的话是不是我每执行一次main方法都会重新生成class而执行静态块呢? 还有就是我看到楼下写的 类的消亡 我想问下这个到底是什么时候开始被加载然后又什么时候消亡的呢?还是就是我想的执行一次main就是一次加载 消亡呢?
作者: 折纸时代 时间: 2013-1-20 16:52
本帖最后由 司懿卓 于 2013-1-20 16:55 编辑
张政 发表于 2013-1-20 15:30
他这个类又是在哪里的呢 是堆中还是栈中 或者就是我在本地磁盘上的哪个class文件? 是本地的class文件的 ...
静态成员,就是使用static修饰的成员。非静态成员就是没有static修饰的成员。成员包括成员变量(Field),方法(函数),初始化块,内部类等。
b.静态成员和非静态成员的区别:
静态成员也是类成员,是属于类的。可以通过类名直接调用。非静态成员是属于对象的,必须创建对象后才可以调用。
因为java运行的机制问题,和静态、非静态的区别,所以其运行顺序是有很大的差别的。先浅显说下java运行机制,首先呢,在编译后,运行时,JVM会寻找主方法入口,也就是程序的开始。这时,如果创建对象,创建对象之前,会先加载主方法(main方法)所在的类,因为静态成员都是类所属的。所以,在主类加载后呢,所有的静态成员都会随着加载。这时呢,因为对象还没有创建成功,非静态成员还不存在。比如,我网购买了个手机,但是手机还没到我手上,我怎么去使用呢? 肯定需要等到手机到了后才可以。 这就是java中静态成员不能访问非静态成员的原因。
其实,随着主类的加载,还有一系列的动作在之前操作。那就是,该类的所有父类进行初始化。因为,该类继承了父类,如要需要调用到父类的成员,肯定要知道父类中的情况。这样,该类的最高父类开始进行初始化,然后是其子类,最后才是该类。其实,非静态成员的初始化和静态成员的一样。不过,是需要创建对象后才执行的。而且,初始化块是在构造器之前执行的。
上面有说到成员所属问题,和子父类的先后初始化问题。下面就简单的说下顺序,然后通过代码来表现跟直观。
初始化相关的成员有:
静态初始化块;非静态初始化块;构造器;
静态初始化块是类成员,类加载,就进行初始化操作。
非静态初始化块是对象所属,创建对象,就进行初始化操作。
构造器,通过
new来调用构造器创建对象。调用后,是先执行初始化块,然后才是构造器。- class Root
- {
- static //静态初始化块
- {
- System.out.println("Root的静态初始化块");
- }
- { //非静态初始化块
- System.out.println("Root的普通初始化块");
- }
- public Root() //构造器
- {
- System.out.println("Root的无参数的构造器");
- }
- }
- class Mid extends Root
- {
- static{
- System.out.println("Mid的静态初始化块");
- }
- {
- System.out.println("Mid的普通初始化块");
- }
- public Mid()
- {
- System.out.println("Mid的无参数的构造器");
- }
- public Mid(String msg)
- {
- //通过this调用同一类中重载的构造器
- this();
- System.out.println("Mid的带参数构造器,其参数值:"
- + msg);
- }
- }
- class Leaf extends Mid
- {
- static{
- System.out.println("Leaf的静态初始化块");
- }
- {
- System.out.println("Leaf的普通初始化块");
- }
- public Leaf()
- {
- //通过super调用父类中有一个字符串参数的构造器
- super("黑马程序员");
- System.out.println("执行Leaf的构造器");
- }
- }
- public class Test
- {
- public static void main(String[] args)
- {
- new Leaf();
- new Leaf();
- }
- }
复制代码上面代码运行结果是:
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:黑马程序员
Leaf的普通初始化块
执行Leaf的构造器
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:黑马程序员
Leaf的普通初始化块
执行Leaf的构造器
上面程序创建了两次对象,但是为什么静态成员只执行了一次呢?
是因为,静态成员是类所属的,随着类的加载而执行。第一次创建对象的时候,就被初始化了。那么第二次创建还有必要再次进行初始化么?完全不用的。其实,它们的运行顺序很简单,清楚了成员所属、和继承、运行机制也就清楚了。
-------------------------------------------------------------------------------------------------
这是我之前的一篇博客,但是感觉很不满意. 就重写了.. 你参考下吧.
还有,创建的对象都是在堆中的. 静态的是在方法区中. 只有局部变量等临时数据是在栈中的.
如果还不太懂,就把视频多看几遍吧.
作者: walkonby 时间: 2013-1-20 22:32
司懿卓 发表于 2013-1-20 16:52
静态成员,就是使用static修饰的成员。非静态成员就是没有static修饰的成员。成员包括成员变量(Field) ...
OK 谢了
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |