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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李力 中级黑马   /  2013-4-3 13:28  /  2407 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Cup
{
        Cup(int marker)
        {
                System.out.println("Cup("+marker+")");
        }
void f(int marker)
        {
                System.out.println("f("+marker+")");
        }
}
class Cups
{
        static Cup cup1;
        static Cup cup2;
        static
        {
                cup1 = new Cup(1);
                cup2 = new Cup(2);
        }
        Cups()
        {
                System.out.println("Cups()");

        }
}

public class Test

{
        public static void main(String[] args)
        {
                System.out.println("Inside main()");
                Cups.cup1.f(99);
        }
        static Cups cup1 = new Cups();
        static Cups cup2 = new Cups();
}

运行结果:
Cup(1)
Cup(2)
Cups()
Cups()
INside main()
f(99)

怎么会这样呢?请大神指教!


评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1 新人加油

查看全部评分

12 个回复

倒序浏览
个人感觉是你的15 16行出错了  要不就是最后两行出错了

我刚看到这里 能看懂 但是看不出有啥毛病
回复 使用道具 举报
首先你要明确这么一个东西。
被static修饰的东西是属于类的东西,也就是说在编辑期就会被创建。
你要执行
  1. public class Test

  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 System.out.println("Inside main()");
  6.                 Cups.cup1.f(99);
  7.         }
  8.         static Cups cup1 = new Cups();
  9.         static Cups cup2 = new Cups();
  10. }
复制代码
首先会首先执行
static Cups cup1 = new Cups();

执行这条语句时;
static Cups cup1 = new Cups();
回去调用在堆内存生成好的Cpus.class文件,所以会
输出
Cup(1)
Cup(2)
Cpp()
这么三个东西。
然后再去执行
static Cups cup2 = new Cups();
这条语句,
因为
  1. class Cups
  2. {
  3.         static Cup cup1;
  4.         static Cup cup2;
  5.         static
  6.         {
  7.                 cup1 = new Cup(1);
  8.                 cup2 = new Cup(2);
  9.         }
  10.         Cups()
  11.         {
  12.                 System.out.println("Cups()");

  13.         }
  14. }
复制代码
因为这个类中的class文件,已经存在于堆内存中,就不会去执行这个类的静态代码块。
所以会输出
Cups()
然后开始执行
public static void main(String[] args)
        {
                System.out.println("Inside main()");
                Cups.cup1.f(99);
        }
首先输出INside main();
然后去z执行Cups.cup1.f(99);
输出f(99);
你可以在Cup中添加一个静态代码块,里面写一个System.out.println("Cup First");
则你的运行结果的第一句一定是“Cup First”;

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
static 关键字
static(静态)关键字用于修饰成员(成员变量和成员函数).
被修饰后的成员具备以下特点:随着类的加载而加载,优先于对象存在,被所有对象所共享,可以被类名直接调用。
回复 使用道具 举报
本帖最后由 无奈№追夜 于 2013-4-3 14:12 编辑

当程序执行的时候首初始化静态的语句,这个程序的执行顺序是:static Cups cup1 = new Cups();——        static Cup cup1;
        static Cup cup2;——到static语句块里的cup1 = new Cup(1);——调用cup的构造方法,这时会打印出Cup(1) ——到static语句块里的cup2 = new Cup(2);——调用cup的构造方法,这里打印Cup(2) ——这里到Cups构造方法  Cups(){System.out.println("Cups()");  }这里会打印Cups() ——static Cups cup2 = new Cups();——这时Cups里的所有静态语句都不会被重新执行,因为静态的东西只被初始化一次,因此直接调用Cups构造方法  Cups(){System.out.println("Cups()");  }这里会打印Cups() —— main方法时面的语句System.out.println("Inside main()");打印Inside main() ——Cups.cup1.f(99);调用f这个方法打印出f(99)











回复 使用道具 举报
Test 类加载时首先执行被static修饰的成员
       static Cups cup1 = new Cups();
        static Cups cup2 = new Cups();
执行static Cups cup1 = new Cups();调用Cups类对其初始化
Cups类加载进来时也是先执行被static修饰的成员
        static Cup cup1
        static Cup cup2
结果为:
        Cup(1)
       Cup(2)
再调用构造函数对对应的对象初始化
结果:Cups()
由于静态代码存在于方法区中,只初始化一次。
所以在执行static Cups cup2 = new Cups(); 时static Cup cup1    static Cup cup2 将不再被初始化, 这条语句输出的结果只有构造函数对cup2初始化的结果 :Cups()
最后在类都加载完成后执行main中的打印语句结果为:Inside main()   f(99)


评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
静态代码块随着类的加载只执行一次
回复 使用道具 举报
本帖最后由 奋斗2013 于 2013-4-3 14:53 编辑

你在main主线程中只进行了如下操作:
public static void main(String[] args)
        {
                System.out.println("Inside main()");//输出Inside main()
                Cups.cup1.f(99);//这句似乎有问题。

        }
static 修饰的静态类,不用实例化对象就可直接调用其里面的方法。
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说他不依赖于类的特定实例,被类的所有实例共享。
只要这个类被加载,JAVA 虚拟机就能根据类名在运行是数据区内找到他们。因此static对象可以在他创建的任何对象之前访问他们。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
当执行Test类时 就会加载Test.class文件 会执行他的
static Cups cup1 = new Cups();
当new Cups() 是会加载Cups.class文件并执行他静态语句块
static
        {
                cup1 = new Cup(1);
                cup2 = new Cup(2);
        }
就会加载Cup.class文件执行他的构造函数输出结果是Cup(1) Cup(2)
然后执行Cups类构造函数 结果是Cup()
执行 static Cups cup2 = new Cups();时是不执行静态语句块和静方法的因为第一次已执行过,
所以结果是Cup()
然后是 System.out.println("Inside main()");
                Cups.cup1.f(99);

结果是INside main()
f(99)


综上结果为:
Cup(1)
Cup(2)
Cups()
Cups()
INside main()
f(99)
回复 使用道具 举报
谢谢各位!
回复 使用道具 举报
鉴于前面各楼层的友友们已经回答的很晚上了,我在这儿只补充说明一点前面没有提到的,一面楼主可以更详细的理解类的加载过程。
1,类加载时,是先加载静态成员的,并按代码顺序进行类的静态初始化。然后才从主函数开始执行的。
2,如果把Cups里面的cup1,cup2给初始化,即改为:
  1. static Cup cup1= new Cup(88);
  2.                                 static
  3.         {
  4.                 cup1 = new Cup(1);
  5.                 cup2 = new Cup(2);
  6.         }
  7.         
  8.         static Cup cup2= new Cup(88);
复制代码
则执行结果就是:

Cup(88)
Cup(1)
Cup(2)
Cup(88)
Cups()
Cups()
Inside main()
f(99)
3.类的加载和静态初始化只有一次。
回复 使用道具 举报
鉴于前面各楼层的友友们已经回答的很完善了,我在这儿只补充说明一点前面没有提到的,以便楼主更详细的理解类的加载过程。
1,类加载时,是先加载静态成员的,并按代码顺序进行类的静态初始化。然后才从主函数开始执行的。
2,如果把Cups里面的cup1,cup2给初始化,即改为:
复制代码
则执行结果就是:
  1. static Cup cup1= new Cup(88);
  2.                                 static
  3.         {
  4.                 cup1 = new Cup(1);
  5.                 cup2 = new Cup(2);
  6.         }
  7.         
  8.         static Cup cup2= new Cup(88);
复制代码
执行结果:
  1. Cup(88)
  2. Cup(1)
  3. Cup(2)
  4. Cup(88)
  5. Cups()
  6. Cups()
  7. Inside main()
  8. f(99)
复制代码
3.类的加载和静态初始化只有一次。


详细执行过程如下:
用java命令运行Test时,先加载Test.clss;然后对静态成员cup1初始化,加载Cups.class(如果此处之声明Cups 类型成员cup1而没有等号右边的初始化语句,就不会加载Cups类);Cups类加载过程中,按顺序做静态初始化,先是cup1/cup2,但因为只声明而没有初始化语句故跳过,继续执行static静态代码块初始化;调用了Cup类,故再将Cup.class加载进来,调用Cup(int maker)分别对cup1,cup2进行初始化,打印出Cup1 Cup2; 然后调用构造函数Cups(),打印出Cups(),至此,Test中的cup1已经初始化完毕。开始初始化cup2,因为Cups已经加载进内存,所以可以直接调用构造方法Cups(),打印出Cups(),Test中的cup2初始化完毕。这是才开始执行main()函数。后面的执行顺序楼主都懂,此处省略。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
若还有问题,继续追问; 没有的话,尽量及时将帖子分类改成【已解决】~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马