Java static 关键字总结

static 关键字的作用

static 可以用于修饰变量,方法,类和代码块。通过 static 声明的成员属于类本身,而不是类的任何特定对象。无论创建多少类的实例,静态成员都只有一份拷贝。

static 修饰变量

static 全局变量

static 可以修饰全局变量,被修饰的变量称为静态变量或者类变量,静态变量属于类而非类的实例。所有实例共享同一个静态变量,也就是说,当某个实例修改了静态变量的值,这个修改会反映到其他所有实例上。

class MyClass {
    static int count = 0;  // 静态变量

	// 每次构造MyClass,都会在静态变量中累加数值
    MyClass() {
        count++;
    }

    static int getCount() {
        return count;
    }
}

public class Test {
    public static void main(String[] args) {
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();
        System.out.println(MyClass.getCount()); // 输出 2
    }
}

static 局部变量

static 不能修饰局部变量。

static 修饰方法

static 可以修饰方法,被修饰的方法称为静态方法,静态方法属于类,而不属于类的任何特定实例。这意味着可以不创建类的实例而直接调用静态方法。静态方法只能直接访问类的静态变量和静态方法。

class MyClass {
    static int count = 0;

    static void increment() {
        count++;
    }
}
public class Test {
    public static void main(String[] args) {
    	// 直接使用类名调用方法,而不需要创建类实例
        MyClass.increment();
        System.out.println(MyClass.count);  // 输出 1
    }
}

static 方法的继承关系

static 方法继承的关键点:

  • 静态方法不能被覆盖:当一个子类有与父类同名的静态方法时,该方法在子类中不是覆盖父类方法,而是隐藏了父类的同名静态方法。
  • 方法调用与类型相关:静态方法的调用取决于它们被调用时的对象类型(声明类型)而非实际对象的类。也就是说,静态方法的行为不依赖于对象的实例,而是与类相关。
class Parent {
    static void show() {
        System.out.println("Parent's show()");
    }
}

class Child extends Parent {
    static void show() {
        System.out.println("Child's show()");
    }
}
public class Test {
    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();

        parent.show();  // 输出 "Parent's show()"
        child.show();  // 也输出 "Parent's show()",因为静态方法的调用取决于声明的类型,而不是实际的类型,child 声明的类型为 Parent。

		Child child2 = new Child();  
		child2.show();  // 输出 "Child's show()",因为静态方法的调用取决于声明的类型,child2 声明的类型为 Child。
        Child.show();  // 输出 "Child's show()",直接通过子类名称调用
    }
}

static 修饰代码块

static 可以修饰代码块,修饰的代码块称为静态代码块,静态代码块只能在全局作用域,无法修饰方法内部的代码块。

public class MyClass {
    static int age;
    static String name;

    // 静态代码块
    static {
        System.out.println("静态代码块执行");
        age = 20;
        name = "Java";
    }

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

    public static void main(String[] args) {
        MyClass obj1 = new MyClass(); // 第一次触发静态代码块和构造方法
        MyClass obj2 = new MyClass(); // 只触发构造方法
    }
}

静态代码块的用途

初始化静态变量

public class MyClass {
    static int age;
    sttaic {
    	age = 20;
    }
}

执行只需要进行一次的操作,例如:配置文件的读取。

public class MyClass {
	private static Properties properties = new Properties();
	static {
		try (FileInputStream input = new FileInputStream("config.properties")) {
            properties.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
}

静态代码块的执行时机和执行顺序

执行时机

  • 静态代码块只在类被加载到 JVM 时执行一次,
  • 与实例初始化块不同,无论创建多少对象实例,静态代码块只执行一次。
    执行顺序
  • 静态代码块的执行优先于实例初始化块和构造方法。
  • 如果类中有多个静态代码块,它们按照在代码中的顺序执行。
public class TestStaticBlock {
    
    static {
        // 这个静态代码块只在类第一次被加载到JVM时执行
        System.out.println("静态代码块1执行了!"); //顺序一
    }
	static {
        // 这个静态代码块只在类第一次被加载到JVM时执行
        System.out.println("静态代码块2执行了!"); //顺序二
    }

    public TestStaticBlock() {
        System.out.println("构造函数执行了!"); //顺序四,五
    }

    public static void main(String[] args) {
        System.out.println("主函数开始执行"); //顺序三
        
        // 创建TestStaticBlock的第一个实例
        TestStaticBlock t1 = new TestStaticBlock();
        
        // 创建TestStaticBlock的第二个实例
        TestStaticBlock t2 = new TestStaticBlock();
        
        System.out.println("主函数执行结束"); //顺序六
    } 
}
//输出结果:
// 静态代码块1执行了!
// 静态代码块2执行了!
// 主函数开始执行
// 构造函数执行了!
// 构造函数执行了!
// 主函数执行结束

static 修饰类

static 关键字不能用于修饰顶层类(外部类)。static 关键字主要用于修饰内部类。当把一个内部类声明为 static,它就成为了一个静态内部类,这意味着可以不必实例化外部类就能创建该内部类的实例。

static 修饰内部类

package com.example.demo;

public class OuterClass {
    private static String outerField = "外部类的静态字段";

    // 静态内部类
    static class StaticInnerClass {
        private String staticInnerField = "静态内部类的字段";

        public void display() {
            // 静态内部类可以访问外部类的静态成员
            System.out.println(outerField);
            System.out.println(staticInnerField);
        }
    }
    // 非静态内部类
	class InnerClass {
		private String innerField = "内部类的字段";

        public void display() {
            System.out.println(outerField);
            System.out.println(innerField);
        }
	}

    public static void main(String[] args) {
        // 无需外部类实例,直接创建静态内部类实例
        StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
        staticInner.display();

        //  创建外部类实例,然后创建内部类实例
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass inner = outerClass.new InnerClass();
        inner.display();
    }
}
// 输出结果:
//  外部类的静态字段
//  静态内部类的字段
//  外部类的静态字段
//  内部类的字段

外部类和内部类的静态代码块执行顺序

  • 当外部类和内部类都定义了静态代码块时,会先执行外部类的静态代码块,再执行内部类的静态代码块
public class OuterClass {

    static {
        System.out.println("OuterClass.staticBlock");
    }

    // 非静态内部类
	class InnerClass {

        static {
            System.out.println("InnerClass.staticBlock");
        }
        public void display() {
            System.out.println("InnerClass.display()");
        }
	}
    
    public static void main(String[] args) {
        //  创建外部类实例,然后创建内部类实例
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass inner = outerClass.new InnerClass();
        inner.display();
    }
}
// 输出结果
// OuterClass.staticBlock
// InnerClass.staticBlock
// InnerClass.display()
  • 外部类和内部静态类都定义了静态代码块,也是县知县外部类的静态代码块,再执行内部类的静态代码快
public class OuterClass {  
    static {  
        System.out.println("OuterClass.staticBlock");  
    }  
  
    // 静态内部类  
    static class StaticInnerClass {  
        static {  
            System.out.println("StaticInnerClass.staticBlock");  
        }  
        public void display() {  
            System.out.println("StaticInnerClass.display()");  
        }  
    }  
  
  
    public static void main(String[] args) {  
        // 无需外部类实例,直接创建静态内部类实例  
        StaticInnerClass staticInner = new OuterClass.StaticInnerClass();  
        staticInner.display();  
    }  
}
// 输出结果
//OuterClass.staticBlock
//StaticInnerClass.staticBlock
//StaticInnerClass.display()
posted @ 2024-10-30 19:08  Jacob-Chen  阅读(524)  评论(0)    收藏  举报