谦谦君子,温润如玉!桃李不言,下自成蹊!

why example

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

posted @ 2020-09-27 20:22  FettersLove  阅读(180)  评论(0)    收藏  举报
Live2D