static关键字

概述

static 关键字方便在没有创建对象的情况下来进行调用方法和变量(优先级高于对象),可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能

static变量

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

public class PersonDemo {
    public static void main(String[] args) {
        Person person1 = new Person("张三", 16);
        Person person2 = new Person("李四", 17);
        Person person3 = new Person("王五", 18);
        Person person4 = new Person("赵六", 19);

        /*
         * The static field Person.address should be accessed in a static way
         * 静态成员变量应该通过静态的方式访问(注意这里是应该,不是必须)
         * 
         * Change access to static using 'Person' (declaring type)
         * 使用Person声明类型来更改对静态的访问
         * 通过类名来操作成员变量:Person.address
         */
        System.out.println("姓名:" + person1.name + " 年龄:" + person1.age + " 地址:" + Person.address);
        System.out.println("姓名:" + person2.name + " 年龄:" + person2.age + " 地址:" + Person.address);
        System.out.println("姓名:" + person3.name + " 年龄:" + person3.age + " 地址:" + Person.address);
        System.out.println("姓名:" + person4.name + " 年龄:" + person4.age + " 地址:" + Person.address);
    
        // 通过类名直接调用static修饰的成员变量,此时是没有对象的
        System.out.println("没有对象:" + Person.address);
        
        /*
         *  Cannot make a static reference to the non-static field Person.name
         *  
         *  将name添加static后没有报错
         */
//        System.out.println("没有对象:" + Person.name);
        
        /*
         * 通过对象调用statice修饰的成员方法
         * 
         * The static method test() from the type Person should be accessed in a static way
         */
        // person1.testStatic();
        
        // 通过类名直接调用静态方法
        Person.testStatic();
    }
}

总结

1、通过类名调用静态成员变量,因为静态变量与对象无关
2、静态变量被所有对象共享,一处更改处处更改

static方法

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

public class Person {
    public String name = "张三";
    public int age;
    public static String address = "郑州";

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    // 自定义static修饰的成员方法
    public static void testStatic() {
        /*
         * 静态方法不能调用非静态方法
         * Cannot make a static reference to the non-static method test() from the type Person
         */
        // test();
        System.out.println("static mothed");
        
        /*
         * 不能再静态方法中使用this关键字
         * 
         * Cannot use this in a static context
         */
        // this.name;
    }
    
    public void test() {
        System.out.println("method");
    }
}

总结

1、static修饰的方法不能访问本类中的非静态变量和方法,不能使用this
2、通过类名来调用静态成员方法,工具类的应用很广泛

总结

1、static修饰的成员变量和方法都是对象所共享的资源,对其进行的操作会作用于所有对象。

2、static修饰的成员变量和方法依赖于类不依赖于对象,即没有对象

3、static修饰的成员变量和成员方法都可以通过类名调用,没有对象

4、静态不能调用非静态,不能使用this关键字,没有对象

5、静态成员变量常和final关键字搭配作为常量使用,静态方法常用于工具类

代码块

在 Java 中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程)

构造代码块

格式:
    {
    
    }

注意

1、用于给对象初始化,多个构造方法中相同的代码存放到一起,每次调用构造方法都会执行,并且在构造方法前执行
2、只有创建对象时调用,类不能调用
3、构造代码块可以有多个,建议只写一个
class Person {
    {
        System.out.println("Person构造代码块执行");
    }

    public Person() {
        System.out.println("Person构造方法执行");
    }
}

public class TestPerson {
    public static void main(String[] args) {
        System.out.println("main方法");
        new Person();
        new Person();
    }
}

静态代码块

格式:
    static {
    
    }

注意

1、用于给类进行初始化,在加载的时候就执行,并且只执行一次
2、优先级高于主函数
3、静态代码块可以有多个,顺序执行,建议只写一个
class Person {
    static {
        System.out.println("Person静态代码块执行");
    }

    public Person() {
        System.out.println("Person构造方法执行");
    }
}

public class TestPerson {
    static {
        System.out.println("静态代码块1执行");
    }

    public static void main(String[] args) {
        System.out.println("main方法");
        new Person();
        new Person();
    }

    static {
        System.out.println("静态代码块2执行");
    }
}

结果

静态代码块1执行
静态代码块2执行
main方法
Person静态代码块执行
Person构造方法执行
Person构造方法执行

代码块相关执行顺序

public class Father {
    public Father() {
        System.out.println("父类构造方法执行~~~");
    }
    
    {
        System.out.println("父类构造代码块执行~~~");
    }
    
    static {
        System.out.println("父类静态代码块执行~~~");
    }
    
    public static void function() {
        System.out.println("父类静态成员方法执行~~~");
    }
}

public class Son extends Father{
    public Son() {
        System.out.println("子类构造方法执行~~~");
    }
    
    {
        System.out.println("子类构造代码块执行~~~");
    }
    
    static {
        System.out.println("子类静态代码块执行~~~");
    }
    
    public static void function() {
        System.out.println("子类静态成员方法执行~~~");
    }
    
    public static void main(String[] args) {        
        System.out.println("main方法执行~~~");
        new Son();
    }
}

结果

父类静态代码块执行~~~
子类静态代码块执行~~~
main方法执行~~~
父类构造代码块执行~~~
父类构造方法执行~~~
子类构造代码块执行~~~
子类构造方法执行~~~

面试题

执行顺序

public class Test {
    static Test test1 = new Test();
    static Test test2 = new Test();

    static {
        System.out.println("静态代码块");
    }

    {
        System.out.println("构造代码块");
    }

    public Test() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        System.out.println("main方法");
        new Test();
    }
}

结果

构造代码块
构造方法
构造代码块
构造方法
静态代码块
main方法
构造代码块
构造方法

总结

1、构造代码块用于给对象初始化,每次创建对象都会调用构造代码块,并且执行顺序在构造方法之前

2、静态代码块用于给类初始化,当类被加载的时候就会调用静态代码块(只执行一次),执行顺序在main方法之前

最后修改:2021 年 01 月 24 日 12 : 29 PM
如果觉得此文章有用,请随意打赏