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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 周斌 中级黑马   /  2012-11-2 18:49  /  1487 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 周斌 于 2012-11-7 12:06 编辑

    无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此只能作用于域。
    在定义出进行初始化,采取的方法与非静态数据有什么不同么?为什么呢{:soso_e181:}

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

4 个回复

倒序浏览
生命周期不同,
static类成员在class文件加载进内存就分配内存
非static成员必须等到new一个对象才分配内存

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
二楼说的不错,我也受教了

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
调用static类成员时不需要实例化,使用非static成员节约内存空间,希望对楼主有帮助!
回复 使用道具 举报
无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始化值就是null。

   如果想在定义处进行初始化,采用的方法与非静态数据没什么不同。要想了解静态存储区域是何时初始化的,就请看下面这个例子:   

class Bowl{
      Bowl(int marker){
         System.out.print("Bowl("+marker+")");
      }
      void f1(int marker){
         System.out.print("f1("+marker+")");
      }
   }   

class Table{
      static Bowl bowl1=new Bowl(1);
      Table(){
         System.out.pring("Table()");
         bowl2.f1(1);
      }
      void f2(int marker){
         System.out.print("f2("+marker+")");
      }
      static Bowl bowl2=new Bowl(2);
   }   

class Cupboard{
      Bowl bowl3=new Bowl(3);
      Cupboard(){
         System.out.pring("Cupboard()");
         bowl4.f1(2);
      }
      void f3(int marker){
         System.out.print("f3("+marker+")");
      }
      static Bowl bowl5=new Bowl(5);
   }   

public class SraticInitialization{
      public static void main(String[]args){
         System.out.print("Creating new Cupboard()in main");
         new Cupboard();
         System.out.print("Creating new Cupboard()in main");
         new Cupboard();
         table.f2(1);
         cupboard.f3(1);
      }
      static Table table=new Table();
      static Cupboard=new Cupboard();
   }

   结果输出:   

Bowl(1)
   Bowl(2)
   Table()
   f1(1)
   Bowl(4)
   Bowl(5)
   Bowl(3)
   Cupboard()
   f1(2)
   Creating new Cupboard()in main
   Bowl(3)
   Cupboard()
   f1(2)
   Creating new Cupboard()in main
   Bowl(3)
   Cupboard()
   f1(2)
   f2(1)
   f3(1)  

Bowl类使得看到类的创建,而Table类和Cupboard类在它们的类定义中加入了Bowl类型的静态数据成员。注意,在静态数据成员定义之前,Cupboard类先定义了一个Bowl类型的非静态数据成员b3。  

由输出可见,静态初始化只有在必要时刻才会进行。如果不创建Table对象,也不引用Table.b1或Table.b2,那么静态的Bowl b1和b2永远都不会被创建。只有在第一个Table对象被创建(或者第一次访问静态数据)的时候,它们才会被初始化。此后,静态对象不会再次被初始化。  

初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化),而后是“非静态”对象。从输出结果中可以观察到这一点。要执行main()(静态方法),必须加载StaticInitialization类,然后其静态域table和cupboard被初始化,这将导致它们对应的类也被加载,并且由于它们也都包含静态的Bowl对象,因此Bowl随后也被加载。这样,在这个特殊的程序中的所有类在main()开始之前就都被加载了。实际情况通常并非如此,因为在典型的程序中,不会像在本例中所做的那样,将所有的事物都通过static联系起来。      

总结一下对象的创建过程,假设有个名为Dog的类:   

1、即使没有显示地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。   

2、然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。   

3、当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。   

4、这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说就是0,对布尔型和字符型也相同),而引用则被设置成了null。  

5、执行所有出现于字段定义处的初始化动作。   

6、执行构造器。这可能会牵涉到很多动作,尤其是涉及继承的时候。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马