zoukankan      html  css  js  c++  java
  • static

    static

    在类中,用static声明的成员变量为静态成员变量,也成为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效。

    这里要强调一下:

    • static修饰的成员变量和方法,从属于类(意思是这些人都有这个属性与方法)

    • 普通变量和方法从属于对象:这个对象所具有的属性方法,,狗:属性:名字 方法:吃。。。。

    • 静态方法不能调用非静态成员,编译会报错,因为它还没有实例化。

    static关键字的用途

    一句话描述就是:方便在没有创建对象的情况下进行调用(方法/变量)。

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

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

    static方法

    static方法也成为静态方法,由于静态方法不依赖于任何对象就可以直接访问,因此对于静态方法来说,是没有this的,因为不依附于任何对象,既然都没有对象,就谈不上this了,并且由于此特性,在静态方法中不能访问类的非静态成员变量和非静态方法,因为非静态成员(变量和方法)属于类的对象,所以只有在对象实例化之后才存在,然后通过类的对象去访问。因为每个人所拥有的方法不一样,你会弹琴但他不一定会)。

    虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法和静态成员变量。

     1  public class Student {
     2  3      private static int age;//静态的变量,静态属性
     4      private double score;//非静态变量
     5  6      public static void main(String[] args) {
     7          Student s1 = new Student();
     8  9          System.out.println(Student.age);//类变量
    10          //System.out.println(Student.score);会报错。这是因为,在编译期并没有对象生成,score变量根本就不存在
    11          
    12          System.out.println(s1.age);
    13          System.out.println(s1.score);
    14      }
    15  }
    16  /*从上编代码看出

    static变量

    static变量也称为静态变量,静态变量和非静态变量的区别:

    • 静态变量被所有对象共享,在内存中只有一个副本,在类初次加载的时候才会初始化

    • 非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响

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

    static块

    构造方法用于对象的初始化。静态初始化块,用于类的初始化操作。

    在静态初始化块中不能直接访问非staic成员。

    static块的作用

    静态初始化块的作用就是:提升程序性能。

     1  public class Student {
     2  3      private static int age;//静态的变量,静态属性
     4      private double score;//非静态变量
     5      
     6      public void run(){
     7          
     8      }
     9      public static void go(){
    10          
    11      }
    12      
    13      //静态方法不能调用非静态方法
    14      public static void main(String[] args) {
    15          Student s1 = new Student();
    16          s1.run();
    17          //run();会报错
    18          Student.go();
    19          go();
    20      }
    21  }
    22  public class Person {
    23      
    24      //2.:赋初值
    25      {
    26          //代码块(匿名代码块)
    27          System.out.println("匿名代码块");
    28      }
    29      //1.只执行一次
    30      static {
    31          //静态代码块:只执行一次
    32          System.out.println("静态代码块");
    33      }
    34      
    35      //3
    36      public Person(){
    37          System.out.println("构造方法");
    38      }
    39 40      public static void main(String[] args) {
    41          Person person1 = new Person();
    42          System.out.println("==================");
    43          Person person2 = new Person();
    44      }
    45  }
    46  /*
    47  输出结果:
    48  静态代码块
    49  匿名代码块
    50  构造方法
    51  ==================
    52  匿名代码块
    53  构造方法
    54  */

    static关键字的误区

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

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

      1  public class Person {
      2 3      public String name = "李四";
      4 5      private static String address = "中国";
      6  }

      图片

      说明static关键字不能改变变量和方法的访问权限

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

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

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

      static是不允许用来修饰局部变量。不要问为什么,这是Java语法的规定

    static常见笔试面试题

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

     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类的时候,发现Base类有static块,而是先执行static块,输出base static结果

    • Base类加载完成后,再去加载Test类,发现Test类也有static块,而是执行Test类中的static块,输出test static结果

    • Base类和Test类加载完成后,然后执行main方法中的new Test(),调用子类构造器之前会先调用父类构造器

    • 调用父类构造器,输出base constructor结果

    • 然后再调用子类构造器,输出test constructor结果

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

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

    输出结果为:

     test static
     myclass static
     person static
     person Test
     test constructor
     person MyClass
     myclass constructor

    为什么输出结果是这样的?我们来分析下这段代码的执行过程:

    • 找到main方法入口,main方法是程序入口,但在执行main方法之前,要先加载Test类

    • 加载Test类的时候,发现Test类有static块,而是先执行static块,输出test static结果

    • 然后执行new MyClass(),执行此代码之前,先加载MyClass类,发现MyClass类继承Test类,而是要先加载Test类,Test类之前已加载

    • 加载MyClass类,发现MyClass类有static块,而是先执行static块,输出myclass static结果

    • 然后调用MyClass类的构造器生成对象,在生成对象前,需要先初始化父类Test的成员变量,而是执行Person person = new Person("Test")代码,发现Person类没有加载

    • 加载Person类,发现Person类有static块,而是先执行static块,输出person static结果

    • 接着执行Person构造器,输出person Test结果

    • 然后调用父类Test构造器,输出test constructor结果,这样就完成了父类Test的初始化了

    • 再初始化MyClass类成员变量,执行Person构造器,输出person MyClass结果

    • 最后调用MyClass类构造器,输出myclass constructor结果,这样就完成了MyClass类的初始化了

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

     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块的顺序执行的。

  • 相关阅读:
    ng机器学习视频笔记(八) ——机器学习系统调试(cv、查准率与召回率等)
    ng机器学习视频笔记(七) ——神经网络的代价函数、反向传播、梯度检验、随机初始化
    post body 传输参数
    laravel队列使用
    nginx配置框架问题
    中大型网站架构之路一
    mongo笔记2
    架构4(lvs lb集群解决方案二 lvs+keepalived)
    架构3(基于LVS LB集群解决方案一:piranha)
    YII2 BUG记录
  • 原文地址:https://www.cnblogs.com/FettersLove/p/13741609.html
Copyright © 2011-2022 走看看