精华内容
下载资源
问答
  • 下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲:  一.static关键字的用途  二.static关键字的误区  三.常见的笔试...

    static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一。下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲:

      一.static关键字的用途

      二.static关键字的误区

      三.常见的笔试面试题

      若有不正之处,希望谅解并欢迎批评指正。

      请尊重作者劳动成果,转载请标明原文链接:

      http://www.cnblogs.com/dolphin0520/p/3799052.html

    一.static关键字的用途

      在《Java编程思想》P86页有这样一段话:

      “static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”

      这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:

      方便在没有创建对象的情况下来进行调用(方法/变量)。

      很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。

      static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。

    1)static方法

      static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

      但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。举个简单的例子:

      在上面的代码中,由于print2方法是独立于对象存在的,可以直接用过类名调用。假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:

      MyObject.print2();

      此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以也禁止在静态成员方法中访问非静态成员方法。

      而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。

      因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

      另外记住,即使没有显示地声明为static,类的构造器实际上也是静态方法

    2)static变量

      static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

      static成员变量的初始化顺序按照定义的顺序进行初始化。

    3)static代码块

      static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

      为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。下面看个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class  Person{
         private  Date birthDate;
         
         public  Person(Date birthDate) {
             this .birthDate = birthDate;
         }
         
         boolean  isBornBoomer() {
             Date startDate = Date.valueOf( "1946" );
             Date endDate = Date.valueOf( "1964" );
             return  birthDate.compareTo(startDate)>= 0  && birthDate.compareTo(endDate) <  0 ;
         }
    }

      isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class  Person{
         private  Date birthDate;
         private  static  Date startDate,endDate;
         static {
             startDate = Date.valueOf( "1946" );
             endDate = Date.valueOf( "1964" );
         }
         
         public  Person(Date birthDate) {
             this .birthDate = birthDate;
         }
         
         boolean  isBornBoomer() {
             return  birthDate.compareTo(startDate)>= 0  && birthDate.compareTo(endDate) <  0 ;
         }
    }

      因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

    二.static关键字的误区

    1.static关键字会改变类中成员的访问权限吗?

      有些初学的朋友会将java中的static与C/C++中的static关键字的功能混淆了。在这里只需要记住一点:与C/C++中的static不同,Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。看下面的例子就明白了:

      提示错误"Person.age 不可视",这说明static关键字并不会改变变量和方法的访问权限。

    2.能通过this访问静态成员变量吗?

      虽然对于静态方法来说没有this,那么在非静态方法中能够通过this访问静态成员变量吗?先看下面的一个例子,这段代码输出的结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public  class  Main {  
         static  int  value =  33 ;
     
         public  static  void  main(String[] args)  throws  Exception{
             new  Main().printValue();
         }
     
         private  void  printValue(){
             int  value =  3 ;
             System.out.println( this .value);
         }
    }

     

    33

      这里面主要考察队this和static的理解。this代表什么?this代表当前对象,那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象。而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是33。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。

    3.static能作用于局部变量么?

      在C/C++中static是可以作用域局部变量的,但是在Java中切记:static是不允许用来修饰局部变量。不要问为什么,这是Java语法的规定。

    三.常见的笔试面试题

      下面列举一些面试笔试中经常遇到的关于static关键字的题目,仅供参考,如有补充欢迎下方留言。

    1.下面这段代码的输出结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public  class  Test  extends  Base{
     
         static {
             System.out.println( "test static" );
         }
         
         public  Test(){
             System.out.println( "test constructor" );
         }
         
         public  static  void  main(String[] args) {
             new  Test();
         }
    }
     
    class  Base{
         
         static {
             System.out.println( "base static" );
         }
         
         public  Base(){
             System.out.println( "base constructor" );
         }
    }
    base static
    test static
    base constructor
    test constructor

      至于为什么是这个结果,我们先不讨论,先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。

    2.这段代码的输出结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public  class  Test {
         Person person =  new  Person( "Test" );
         static {
             System.out.println( "test static" );
         }
         
         public  Test() {
             System.out.println( "test constructor" );
         }
         
         public  static  void  main(String[] args) {
             new  MyClass();
         }
    }
     
    class  Person{
         static {
             System.out.println( "person static" );
         }
         public  Person(String str) {
             System.out.println( "person " +str);
         }
    }
     
     
    class  MyClass  extends  Test {
         Person person =  new  Person( "MyClass" );
         static {
             System.out.println( "myclass static" );
         }
         
         public  MyClass() {
             System.out.println( "myclass constructor" );
         }
    }
    复制代码
    test static
    myclass static
    person static
    person Test
    test constructor
    person MyClass
    myclass constructor
    复制代码

      类似地,我们还是来想一下这段代码的具体执行过程。首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。

    3.这段代码的输出结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public  class  Test {
         
         static {
             System.out.println( "test static 1" );
         }
         public  static  void  main(String[] args) {
             
         }
         
         static {
             System.out.println( "test static 2" );
         }
    }
    test static 1
    test static 2

      虽然在main方法中没有任何语句,但是还是会输出,原因上面已经讲述过了。另外,static块可以出现类中的任何地方(只要不是方法内部,记住,任何方法内部都不行),并且执行是按照static块的顺序执行的。

      参考资料:

      http://lavasoft.blog.51cto.com/62575/18771/

      http://www.51cto.com/specbook/24/35011.htm

      http://blog.csdn.net/zhu_apollo/article/details/1888219

      http://blog.sina.com.cn/s/blog_70b845780100n9zz.html

      http://hi.baidu.com/yuiezt/item/b71ff5fbfe9c385cc8f3370d

      http://bbs.csdn.net/topics/330251070

      http://yezixingchen.iteye.com/blog/1597186

      《Java编程思想》

    作者: 海子
             
    本博客中未标明转载的文章归作者 海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


    展开全文
  • C++ static关键字作用

    千次阅读 多人点赞 2019-06-18 16:04:14
    C++ static关键字作用 1.static修饰全局变量 当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。 未加static的全局变量,在符号表中是global符号,其他目标文件...

    C++ static关键字作用

    1.static修饰全局变量

    当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。

    未加static的全局变量,在符号表中是global符号,其他目标文件可见,这样的符号是要参与符号解析的。加了static之后,是local符号,其他目标文件不可见,只在当前文件中可见,不参与符号解析过程。所以多个源文件可以定义同名的static全局变量,不会产生重定义错误。

    修饰全局变量是改变变量的作用域,让它只能在本文件中使用。

    2. 修饰局部变量时使它放在.data 或者.bss段,默认初始化为0,初始化不为0放在.data段,没有初始化或初始化为0放在.bss段。程序一运行起来就给他分配内存,并进行初始化,也是唯一一次初始化。它的生存期为整个源程序,程序结束,它的内存才释放。但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。

    修饰局部变量是改变它的生存期,变为和整个程序的生命周期一样。

    3.修饰普通函数时,和修饰全局变量一样。函数经过编译产生一个函数符号,被static修饰后,就变为local符号,不参与符号解析,只在本文件中可见。

    4、修饰类的成员变量时。就变成静态成员变量,不属于对象,而属于类。不能在类的内部初始化,类中只能声明,定义需要在类外。类外定义时,不用加static关键字,只需要表明类的作用域。

      修饰类的成员函数时。变成静态成员函数,也不属于对象,属于类。形参不会生成this指针,仅能访问类的静态数据和静态成员函数。调用不依赖对象,所以不能作为虚函数。用类的作用域调用。

     

    如果你希望在一个函数中对一个变量只执行一次初始化,以后不再初始化,使用上一次结果,就应该使用静态局部变量。
    例如: static int n; 
    其他类型都可以。

     

     

    展开全文
  • C语言中static关键字的作用

    千次阅读 2014-10-05 17:16:27
    C语言中static关键字的作用 华清远见2014-10-05 北京海淀区 张俊浩 一、C源程序编译后的可执行文件(elf) 存储空间 布局 1)正文段——CPU执行的机器指令部分;一个程序只有一个副本;只读,防止...

    C语言中static关键字的作用

    华清远见2014-10-05   北京海淀区 张俊浩

    一、C源程序编译后的可执行文件(elf)存储空间布局


    1)正文段——CPU执行的机器指令部分;一个程序只有一个副本;只读,防止程序由于意外事故而修改自身指令;

    2)初始化数据段(数据段)——在程序中所有赋了初值的全局变量,存放在这里。

    3)非初始化数据段(bss段)——在程序中没有初始化的全局变量;内核将此段初始化为0。

    4)栈——增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回

    地址,局部变量,环境信息)。

    5)堆——动态存储分。是向高地址扩展的数据类型,是自下向上的扩展方式。

    二、C语言中的变量存储类型 

    存储说明符autoregisterexternstatic,对应两种存储期模式:自动存储期和静态存储期。

    autoregister对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。

    关键字externstatic用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。

    auto 

        auto称为自动变量 如果函数不做其他说明的话 均为自动变量

    static 

        static称为静态变量。根据变量的类型可以分为静态局部变量和静态全程变量。【详见四、C语言中static关键字的作用】 

    extern 

        extern称为外部变量。为了使变量除了在定义它的源文件中可以使用外, 还要被其它文件使用。因此,   必须将全程变量通知每一个程序模块文件,   此时可用extern来说明。

    register 
        register称为寄存器变量。它只能用于整型和字符型变量。定义符register说明的变量被Turbo C2.0存储在CPU的寄存器中,  而不是象普通的变量那样存储在内存中, 这样可以提高运算速度。但是Turbo C2.0只允许同时定义两个寄存器变量,一旦超过两个, 编译程序会自动地将超过限制数目的寄存器变量当作非寄存器变量来处理。因此, 寄存器变量常用在同一变量名频繁出现的地方。


    三、生存周期

    (1)局部变量在每次函数调用的时候分配空间,在函数调用结束之后销毁。

    (2)全局变量在程序开始运行时分配空间,在程序结束时销毁。

    (3)如果局部变量和全局变量重名,局部变量会暂时覆盖掉全局变量。

    (4)全局变量只能用常量表达式初始化,因为程序开始运行时要用适当的值来初始化全局变量,所以初始值必须保存在编译生成的可执行文件中,因此初始值在编译时要计算出来。c语言从语法上规定,全局变量只能用常量表达式初始化

     

    四、C语言中static关键字的作用

    1static作用的变量

    1.static修饰全局变量:在全局变量前加static,全局变量就被定义成为一个全局静态变量。

    特点如下:

    1)存储区(内存中的位置):静态存储区没变(静态存储区在整个程序运行期间都存在);

    2)初始化:未经初始化的全局静态变量会被程序自动初始化为0。(自动对象的值是任意的,除非他被显示初始化)

    3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。非静态全局 变量的作用域是整个源程序(多个源文件可以共同使用); 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。好处:   

    1)不会被其他文件所访问,修改;

    2)其他文件中可以使用相同名字的变量,不会发生冲突。

     

    2.static修饰局部变量:在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。特点如下:

    1) 存储区(内存中的位置):由栈变为静态存储区(初始化的局部静态变量存放在.data段,未初始化的局部静态变量存放在.bss段),生存期为整个源程序,只能在定义该变量的函数内使用。退出该函数后,尽管该变量还继续存在,但不能使用它;

    2)初始化:为静态局部变量赋初值是在编译时进行的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而为自动变量赋初值,不是在编译时进行的,而是在函数调用时进行,每调用函数重新给一次值,相对于执行一次赋值语句。如果在定义局部变量是不赋初值的话,对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符型变量)。而对自动变量来说,如果不赋初值,则它的值是不确定的值。这是由于每次函数调用结束后存储单元已被释放,下次调用时又重新分配存储单元,而所分配的单元中的值是不确定的。

    3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束,尽管该变量还继续存在,但不能使用它。

     

    2static作用的函数

     在函数的返回类型前加上关键字static,函数就被定义成为静态函数。

     函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。好处:

    1)其他文件中可以定义相同名字的函数,不会发生冲突

    2)静态函数不能被其他文件所用。

     

    五、static作用的变量、函数与普通变量和函数区别

    1static作用的变量普通变量和函数区别

     

    1)static全局变量与普通的全局变量有什么区别 ?

    全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。

    全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。

    Turbo C2.0允许将大型程序分成若干独立模块文件分别编译, 然后将所有模块的目标文件连接在一起, 从而提高编译速度, 同时也便于软件的管理和维护。静态全程变量就是指只在定义它的源文件中可见而在其它源文件中不可见的变量。

    这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,程变量可以再说明为外部变量(extern), 被其它源文件使用, 非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,不能再被说明为外部的,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。 

    static全局变量只初使化一次,防止在其他文件单元中被引用

      

    2)static局部变量和普通局部变量有什么区别 ?

    把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。  

    static局部变量只被初始化一次,下一次依据上一次结果值;

       

    2static作用的函数与普通函数有什么区别?

     

    static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static修饰的函数),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件.static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

     

    展开全文
  • 下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲: 被static静态修饰的成员方法,成员变量,成员内部类都是随着类文件的加载而...

    static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一。下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲:

    被static静态修饰的成员方法,成员变量,成员内部类都是随着类文件的加载而加载到方法区中,且只加载一次。如果需要调用,直接用类名去调用。
      所以此处:恶汉模式中,获取是方法区中已经创建好的对象的地址,而不是创建新的对象。说的通俗一点,因为单例模式是在处理对象唯一性的问题,拿孙悟空举个例子,因为悟空只有唯一一个,调用时的命名相当于不同人对该对象的不同叫法,有人叫猴子,有人叫悟空,有人叫徒儿,有人叫妖怪。而悟空却只有一个。

      一.static关键字的用途

      二.static关键字的误区

      三.常见的笔试面试题

      若有不正之处,希望谅解并欢迎批评指正。

      请尊重作者劳动成果,转载请标明原文链接:

      http://www.cnblogs.com/dolphin0520/p/3799052.html

    一.static关键字的用途

      在《Java编程思想》P86页有这样一段话:

      “static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”

      这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:

      方便在没有创建对象的情况下来进行调用(方法/变量)。

      很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。

      static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。

    1)static方法

      static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

      但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。举个简单的例子:

      在上面的代码中,由于print2方法是独立于对象存在的,可以直接用过类名调用。假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:

      MyObject.print2();

      此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以也禁止在静态成员方法中访问非静态成员方法。

      而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。

      因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

      另外记住,关于构造器是否是static方法可参考:http://blog.csdn.net/qq_17864929/article/details/48006835

    2)static变量

      static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

      static成员变量的初始化顺序按照定义的顺序进行初始化。

    3)static代码块

      static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

      为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。下面看个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class  Person{
         private  Date birthDate;
         
         public  Person(Date birthDate) {
             this .birthDate = birthDate;
         }
         
         boolean  isBornBoomer() {
             Date startDate = Date.valueOf( "1946" );
             Date endDate = Date.valueOf( "1964" );
             return  birthDate.compareTo(startDate)>= 0  && birthDate.compareTo(endDate) <  0 ;
         }
    }

      isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class  Person{
         private  Date birthDate;
         private  static  Date startDate,endDate;
         static {
             startDate = Date.valueOf( "1946" );
             endDate = Date.valueOf( "1964" );
         }
         
         public  Person(Date birthDate) {
             this .birthDate = birthDate;
         }
         
         boolean  isBornBoomer() {
             return  birthDate.compareTo(startDate)>= 0  && birthDate.compareTo(endDate) <  0 ;
         }
    }

      因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

    二.static关键字的误区

    1.static关键字会改变类中成员的访问权限吗?

      有些初学的朋友会将java中的static与C/C++中的static关键字的功能混淆了。在这里只需要记住一点:与C/C++中的static不同,Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。看下面的例子就明白了:

      提示错误"Person.age 不可视",这说明static关键字并不会改变变量和方法的访问权限。

    2.能通过this访问静态成员变量吗?

      虽然对于静态方法来说没有this,那么在非静态方法中能够通过this访问静态成员变量吗?先看下面的一个例子,这段代码输出的结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public  class  Main {  
         static  int  value =  33 ;
     
         public  static  void  main(String[] args)  throws  Exception{
             new  Main().printValue();
         }
     
         private  void  printValue(){
             int  value =  3 ;
             System.out.println( this .value);
         }
    }

     

    33

      这里面主要考察队this和static的理解。this代表什么?this代表当前对象,那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象。而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是33。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。

    3.static能作用于局部变量么?

      在C/C++中static是可以作用域局部变量的,但是在Java中切记:static是不允许用来修饰局部变量。不要问为什么,这是Java语法的规定。

      具体原因可以参考这篇博文的讨论:http://www.debugease.com/j2se/178932.html

    三.常见的笔试面试题

      下面列举一些面试笔试中经常遇到的关于static关键字的题目,仅供参考,如有补充欢迎下方留言。

    1.下面这段代码的输出结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public  class  Test  extends  Base{
     
         static {
             System.out.println( "test static" );
         }
         
         public  Test(){
             System.out.println( "test constructor" );
         }
         
         public  static  void  main(String[] args) {
             new  Test();
         }
    }
     
    class  Base{
         
         static {
             System.out.println( "base static" );
         }
         
         public  Base(){
             System.out.println( "base constructor" );
         }
    }
    base static
    test static
    base constructor
    test constructor

      至于为什么是这个结果,我们先不讨论,先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。

    2.这段代码的输出结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public  class  Test {
         Person person =  new  Person( "Test" );
         static {
             System.out.println( "test static" );
         }
         
         public  Test() {
             System.out.println( "test constructor" );
         }
         
         public  static  void  main(String[] args) {
             new  MyClass();
         }
    }
     
    class  Person{
         static {
             System.out.println( "person static" );
         }
         public  Person(String str) {
             System.out.println( "person " +str);
         }
    }
     
     
    class  MyClass  extends  Test {
         Person person =  new  Person( "MyClass" );
         static {
             System.out.println( "myclass static" );
         }
         
         public  MyClass() {
             System.out.println( "myclass constructor" );
         }
    }
    复制代码
    test static
    myclass static
    person static
    person Test
    test constructor
    person MyClass
    myclass constructor
    复制代码

      类似地,我们还是来想一下这段代码的具体执行过程。首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。

    3.这段代码的输出结果是什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public  class  Test {
         
         static {
             System.out.println( "test static 1" );
         }
         public  static  void  main(String[] args) {
             
         }
         
         static {
             System.out.println( "test static 2" );
         }
    }
    test static 1
    test static 2

      虽然在main方法中没有任何语句,但是还是会输出,原因上面已经讲述过了。另外,static块可以出现类中的任何地方(只要不是方法内部,记住,任何方法内部都不行),并且执行是按照static块的顺序执行的。

    转载于:https://www.cnblogs.com/mark5/p/11128063.html

    展开全文
  • C语言中static关键字的作用详解,全网最透彻

    万次阅读 多人点赞 2018-07-09 09:41:29
    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。(1)先来介绍它的第一条也是最重要的一条:隐藏。当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解...
  • C语言中static关键字的作用详解

    千次阅读 2018-11-07 14:17:09
    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。 (1)先来介绍它的第一条也是最重要的一条:隐藏。 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为...
  • static关键字总结

    2019-04-01 11:55:02
    下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲: static关键字的用途 static关键字的误区 常见的笔试面试题 一.static关键字的...
  • static关键字的作用

    2014-06-01 14:21:20
    一 普通的static关键字 1. 静态全局变量  在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。我们先举一个静态全局变量的例子,如下: 1.1 该变量在全局数据区分配内存;  (1)未经初始...
  • 原文转载自网络:面试季,Java中的static关键字解析 1. static 关键字的用途 在《Java 编程思想》P86 页有这样一段话: “static 方法就是没有 this 的方法。在 static 方法内部不能调用非静态方法,反过来是可以的...
  • C++ 中的static关键字

    千次阅读 多人点赞 2014-10-11 11:15:09
    在这我要系统地讲述一下有关static关键字的作用,当然主要是讲述它在开发语言C与C++的作用,在其他方面的作用请另找资料。在讲解中肯定有不恰当之处,请大家大胆地扔砖,不要手软,文中的内容引用了不少网上的资料。...
  • 深入理解java的static关键字

    千次阅读 2015-08-18 21:00:46
    下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲:  一.static关键字的用途  二.static关键字的误区  三.常见的笔试面试题 ...
  • java中static关键字

    2019-08-10 16:26:50
    下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲: 一.static关键字的用途 二.static关键字的误区 三.常见的笔试面试题 一.sta...
  • 深入理解java的static关键字
  • 1.下面有关static类变量和实例变量的描述,正确的有? static类变量又叫静态成员变量,它不需要创建对象就可以已经在内存中存在了 在创建实例对象的时候,内存中会为每一个实例对象的每一个非静态成员变量...
  • 【Java】static关键字

    2020-01-13 18:25:27
    1.static关键字 1.1静态变量 传统属性所具备的特征:保存在内存中,且每个对象独享属性。 在定义一个类时,只是在描述某类事物的特征和行为,并没有产生具体的数据。只有通过new关键字创建该类的实例化对象后,...
  • 下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题。以下是本文的目录大纲: static关键字的用途 static关键字的误区 常见的笔试面试题 一、static...
  • 方法的参数传递(值传递 引用传递)  基本数据类型:值传递:当参数类型为基本数据类型的时候 传递的是值 出了方法 原有...static关键字  static静态  优点,  1.节省资源,可以把共性的东西抽取出来设置为静态
  • 一、static关键字 1、static关键字的基本概念 被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。也就是说,被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,...
  • java static关键字

    2019-12-16 11:34:12
    本文将从 static修饰成员变量 修饰成员方法以及执行的优先顺序等角度去讨论static关键字,如果有什么错误的地方还希望大家能够及时指正。 在《Java 编程思想》中又这么一段话 static方法就是没有this的方法。static...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 91,517
精华内容 36,606
关键字:

关于static关键字描述错误的是