zoukankan      html  css  js  c++  java
  • static关键字详解

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

    一:static 方法

      成为静态方法,可以不依赖对象就访问,没有this关键字,不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。但是非静态成员方法中是可以访问静态成员方法/变量的

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

    二:static变量

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

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

      static变量存在于方法区,静态变量是共享内容,栈是不共享的,堆存放new关键字创建的对象,方法区是共享的区域

    三:static代码块

      在类初始化的时候会执行且只执行1次

      

    static{
       Integer num1=new Integer(5);      
       Integer num2=new Integer(5);  
       System.out.println("b");
    }
    public static void main(String[] args){
       Test t=new Test();
       System.out.println("a");
       Test t2=new Test();
    }

    console:

    b

    a

    a

    四:误区

    Java中的static关键字不会影响到变量或者方法的作用域,在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字

    public class Test1 {
        public static void main(String[] args) throws IOException {
            System.out.println(Person.name);
            System.out.println(Person.age);//此处会报错
        }
    }
    class Person{
        public static String name="zhangsan";
        private static int age=10;
    }

    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);
        }
    }

    console:

    33

    在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。

    static是不允许用来修饰局部变量

    五:面试题

    此处摘自https://www.cnblogs.com/dolphin0520/p/3799052.html

    面试题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类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。

    面试题2

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

    面试题3

    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的构造器。

  • 相关阅读:
    49. 字母异位词分组
    73. 矩阵置零
    Razor语法问题(foreach里面嵌套if)
    多线程问题
    Get json formatted string from web by sending HttpWebRequest and then deserialize it to get needed data
    How to execute tons of tasks parallelly with TPL method?
    How to sort the dictionary by the value field
    How to customize the console applicaton
    What is the difference for delete/truncate/drop
    How to call C/C++ sytle function from C# solution?
  • 原文地址:https://www.cnblogs.com/xhlwjy/p/11245644.html
Copyright © 2011-2022 走看看