static

发布于 2026-07-29 08:41 更新于 2026-07-29 08:41 1838 字 10 min read ... 访问量

文章系统介绍了Java中几个核心关键字的使用场景和原理:static修饰的静态成员属于类本身,共享且在类加载时初始化;实例和静态初始化块按特定顺序执行,影响对象创建过程;单例模式通过饿汉式和懒汉式实现共享实例;abstract用于定义抽象类和方法,抽象类不能实例化但可包含抽象方法,子类需实现其抽象方法;final用于禁止继承、重写或多次赋值,常用于常量声明;内部类分为成员、局部、静态和匿名类,各有作用域和访问限制,适用于不同场景的代码封装。

static(静态)

static 关键字

static 可以修饰成员变量、成员方法、代码块和嵌套类。被 static 修饰的成员属于类本身,不属于某一个具体对象。

静态成员变量

静态成员变量在同一个类的所有对象之间共享,通常使用类名访问。

public class Person {
    private String name;
    private static int count;

    public Person(String name) {
        this.name = name;
        count++;
    }

    public static int getCount() {
        return count;
    }

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

类第一次被主动使用时,JVM 会完成类加载、连接和初始化。静态字段的显式赋值语句和静态代码块会在类初始化阶段按书写顺序执行。

静态成员方法

静态方法可以直接通过类名调用。

public class Person {
    public static void evolve() {
        System.out.println("人类的进化");
    }

    public static void main(String[] args) {
        Person.evolve();
    }
}

静态方法没有当前对象,因此不能使用 thissuper,也不能直接访问实例成员。需要访问实例成员时,必须先获得对象引用。

实例初始化块

直接写在类中、没有方法名的普通代码块称为实例初始化块,也常被称为构造代码块。每次创建对象时,它都会在构造器主体之前执行。

public class Person {
    {
        System.out.println("执行实例初始化块");
    }

    public Person() {
        System.out.println("执行无参构造器");
    }

    public Person(String name) {
        System.out.println("执行有参构造器:" + name);
    }
}

实例初始化块适合放置多个构造器都需要执行的初始化代码。编译器会把它合并到各构造器中,并保证先执行父类构造器,再执行当前类实例初始化代码。

静态初始化块

静态初始化块使用 static 修饰,在类初始化时执行,并且每个类加载器通常只执行一次。

public class Person {
    static {
        System.out.println("执行静态初始化块");
    }
}

创建子类对象时,常见初始化顺序如下:

  1. 父类静态字段和静态初始化块。

  2. 子类静态字段和静态初始化块。

  3. 父类实例字段和实例初始化块。

  4. 父类构造器。

  5. 子类实例字段和实例初始化块。

  6. 子类构造器。

同一类中的字段初始化语句和初始化块按照源代码中的顺序执行。

单例设计模式

单例模式用于保证一个类对外只提供一个共享实例,并提供统一的访问入口。

饿汉式

饿汉式在类初始化时创建对象,实现简单且天然具备类初始化阶段的线程安全性。

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

实现要点如下:

  1. 构造器私有化,阻止外部直接创建对象。

  2. 使用静态字段保存唯一实例。

  3. 使用静态方法返回该实例。

懒汉式

最简单的懒汉式写法在多线程环境中可能创建多个对象,因此不能直接用于并发场景。

public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

使用 synchronized 可以保证正确性,但每次调用都需要进入同步方法。实际项目还可以使用静态内部类或枚举实现单例。

abstract(抽象)

abstract 可以修饰类和方法。

抽象类

抽象类不能直接实例化,可以包含字段、构造器、普通方法和抽象方法。只要类中存在抽象方法,该类就必须声明为抽象类;抽象类也可以不包含抽象方法。

抽象方法

抽象方法只有方法声明,没有方法体。具体子类必须实现继承到的抽象方法,否则子类也必须声明为抽象类。

public abstract class TestAbstract {
    private String name;
    private int age;

    public TestAbstract() {
    }

    public TestAbstract(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public abstract void method();
}
public class TestSub extends TestAbstract {
    @Override
    public void method() {
        System.out.println("实现抽象方法");
    }
}

抽象类可以定义公共流程,把必须由子类决定的步骤声明为抽象方法。

public abstract class Shape {
    public abstract double area();

    public static double areaSum(Shape[] shapes) {
        double sum = 0;
        for (Shape shape : shapes) {
            sum += shape.area();
        }
        return sum;
    }
}

final 关键字

final 可以修饰类、方法和变量。

final 类

final 修饰的类不能被继承。

public final class Utility {
}

final 方法

final 修饰的方法不能被子类重写。

final 变量

final 修饰的变量只能赋值一次。

final int age = 18;

如果 final 修饰引用变量,不能把该变量重新指向另一个对象,但仍可能修改原对象内部可变的属性。

final StringBuilder builder = new StringBuilder("Java");
builder.append(" SE");
// builder = new StringBuilder(); // 编译错误

没有在声明处赋值的实例 final 字段称为空白 final 字段,必须在实例初始化块或每一个构造器中完成赋值。

public class Person {
    private final int age;

    public Person() {
        age = 0;
    }

    public Person(int age) {
        this.age = age;
    }
}

常量通常使用 public static final 修饰,名称使用全大写和下划线。

public class Person {
    public static final String BIRTH_PLACE = "中国";
}

内部类

定义在另一个类内部的类称为内部类或嵌套类。它通常用于封装只服务于外部类的辅助逻辑。

成员内部类

成员内部类属于外部类对象,可以直接访问外部类的实例成员。

public class TestOuter {
    private String outerName;

    class TestInner {
        public void test() {
            outerName = "test";
        }
    }
}

在外部类之外创建成员内部类对象时,需要先创建外部类对象。

TestOuter outer = new TestOuter();
TestOuter.TestInner inner = outer.new TestInner();

局部内部类

定义在方法或其他局部作用域中的类称为局部内部类,只能在该作用域中使用。

public void method() {
    class TestInner {
        public void test() {
            System.out.println("局部内部类");
        }
    }

    new TestInner().test();
}

局部内部类访问的局部变量必须是 final 或事实上的 final

静态嵌套类

static 修饰的嵌套类不依赖外部类对象,只能直接访问外部类的静态成员。

public class TestOuter {
    private static String outerName;

    static class TestInner {
        public void test() {
            outerName = "test";
        }
    }
}

创建对象时不需要外部类实例。

TestOuter.TestInner inner = new TestOuter.TestInner();

匿名内部类

当某个接口或父类的实现只使用一次时,可以使用匿名内部类。

Person person = new Person() {
    @Override
    public void eat() {
        System.out.println("执行 eat 方法");
    }
};
person.eat();

匿名内部类没有显式类名,但编译器仍会生成对应的类。需要重复创建同一种实现时,应定义具名类,避免重复代码。

事件监听示例

public class Cal {
    private final JButton button1 = new JButton("1");
    private final JButton button2 = new JButton("2");
    private final JButton buttonAdd = new JButton("+");

    public Cal() {
        buttonAdd.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                // 实现相加功能
            }
        });

        button1.addActionListener(new NumberAction());
        button2.addActionListener(new NumberAction());
    }

    class NumberAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            // 把按钮文字显示到显示区域
        }
    }
}

喜欢的话,留下你的评论吧~

... 访问量
© 2026 跨越星轨的客 @Hoshiumi
Powered by theme astro-koharu · Inspired by Shoka