오늘은 자바 언어의 static 키워드에 대해서 주로 배워보겠습니다.
정적 키워드의 의미와 사용 시나리오
static은 Java의 50개 키워드 중 하나입니다. static 키워드를 사용하면 코드 블록을 수정하여 정적 코드 블록을 나타내고, 멤버 변수를 수정하여 전역 정적 멤버 변수를 나타내고, 메서드를 수정하여 정적 메서드를 나타낼 수 있습니다. (참고: 내부 클래스를 제외하고 일반 클래스는 수정할 수 없습니다. 왜 그럴까요?)
class A { static { System.out.println("A : 静态代码块"); } static int i ; // 静态变量 static void method() { System.out.println("A: 静态方法"); } }
간단히 static 키워드로 수정되는 내용은 정적입니다.
정적은 동적에 상대적입니다. 동적은 Java 프로그램이 JVM에서 실행될 때 프로그램의 요구에 따라 객체를 동적으로 생성하고 저장(메모리 할당)한다는 의미입니다. 즉, 메모리 재활용은 JVM에 의해 균일하게 관리되고 새로 생성된 다른 객체에 할당됩니다. 정적이란 Java 프로그램이 아직 실행되지 않을 때 JVM이 로드된 클래스에 공간을 할당한다는 것을 의미합니다. 정적 멤버 변수와 같은 정적 키워드로 수정된 내용을 저장합니다. Java 클래스가 JVM에 로드되면 JVM은 클래스와 해당 정적 멤버 변수를 메서드 영역에 저장합니다. 스레드에 의해 공유되고 GC가 거의 발생하지 않으므로 static 키워드로 수정된 콘텐츠는 전역적으로 공유되며 저장 공간은 한 번만 할당됩니다.
그래서 클래스의 일부 내용이 객체에 속하지 않지만 객체에 의해 공유되어 클래스에 속하는 경우 static 키워드를 사용하여 수정할지 여부를 고려할 수 있습니다.
정적 키워드의 역할
1 코드 블록 수정
클래스에서 정적 키워드로 수정된 코드 블록을 정적 코드, 정적 키워드로 수정되지 않은 코드 블록을 인스턴스 코드라고 합니다. 차단하다.
인스턴스 코드 블록은 개체가 생성될 때 실행됩니다. 즉, 각 개체에는 고유한 인스턴스 코드 블록이 있습니다. 즉, 인스턴스 코드 블록의 실행 결과가 현재 개체의 내용에 영향을 미치고 다음과 같이 사라집니다. 객체는 소멸되고(메모리 재활용), 정적 코드 블록은 Java 클래스가 JVM 메모리에 로드될 때 실행되는 코드 블록입니다. 정적 코드 블록은 한 번만 실행됩니다.
정적 코드 블록의 주요 기능은 복잡한 초기화 작업을 수행하는 것이기 때문에 정적 코드 블록은 클래스 다음의 메서드 영역에 저장됩니다. 정적 코드 블록의 실행 결과는 메서드 영역에 저장됩니다. 즉, 초기화 양이 메소드 영역에 저장됩니다. 영역은 스레드에서 공유됩니다.
2 멤버 변수 수정
클래스에서 static 키워드로 수정된 멤버 변수를 정적 멤버 변수라고 합니다. static은 지역 변수를 수정할 수 없기 때문에(왜?) 정적 멤버 변수는 정적 변수라고도 합니다. 정적 변수는 코드 블록과 유사합니다. 클래스가 JVM 메모리에 로드되면 JVM은 정적 변수를 메서드 영역에 배치하고 스레드에서 공유하는 메모리를 할당합니다. 액세스 형식은 클래스 이름.정적 멤버 이름입니다.
public class StaticTest { public static void main(String[] args) { System.out.println(D.i); System.out.println(new D().i); } } class D { static { i = 2; System.out.println("D : 静态代码块1"); } static int i; }
정적 변수는 클래스 정보에 저장되며 스레드 간에 공유될 수 있습니다. 물론 클래스의 모든 개체에도 속하므로 개체를 통해 정적 변수에 액세스할 수 있지만 컴파일러는 이를 지원하지 않으며 경고.
참고:
클래스의 정적 변수 및 클래스의 정적 코드 블록 로드 순서입니다. 클래스는 정적 변수를 먼저 로드한 다음 정적 코드 블록을 로드합니다. 그러나 정적 변수와 코드 블록이 여러 개 있는 경우 작성된 순서대로 로드됩니다.
class D { static { i = 2; System.out.println("D : 静态代码块1"); } static { i = 6; System.out.println("D : 静态代码块2"); } static int i; }
수술 결과를 생각해보시면 됩니다.
정적 변수는 명시적으로 초기화할 필요가 없으며 JVM은 기본적으로 해당 기본값을 제공합니다. 예를 들어 byte의 기본 데이터 유형은 0, short는 0, char은 u0000, int는 0, long은 0L, float는 0.0f, double은 0.0d, boolean은 false이고 참조 유형은 균일하게 null입니다.
정적 변수는 JVM 메모리에서 공유되고 변경될 수 있으므로 이에 액세스하면 스레드 안전 문제가 발생합니다(스레드 A가 다시 쓰는 동안 스레드 B가 해당 값을 얻은 다음 얻은 값은 수정 전 또는 수정 후의 값입니다). ), 따라서 정적 변수를 사용할 때는 멀티스레딩을 고려해야 합니다. 정적 변수가 불변임을 확인할 수 있는 경우 final 키워드를 사용하여 스레드 안전 문제를 방지할 수 있습니다. 그렇지 않으면 동기화를 사용하여 휘발성 키워드와 함께 사용하는 등 스레드 안전 문제를 방지해야 합니다.
정적 키는 인스턴스 메서드 및 정적 메서드를 포함한 지역 변수를 수정할 수 없습니다. 그렇지 않으면 정적 키워드의 원래 의도인 공유를 위반하게 됩니다.
3 수정된 메서드
static 키워드로 수정된 메서드를 정적 메서드라고 하며, 그렇지 않으면 인스턴스 메서드라고 합니다. 클래스 이름.메소드 이름을 통해 호출되지만 정적 메서드는 클래스의 정적 변수 및 기타 정적 메서드를 직접 호출할 수 있지만 멤버 변수 및 인스턴스 메서드를 직접 호출할 수는 없습니다(객체를 통해 호출하지 않는 한).
class D { static { i = 2; System.out.println("D : 静态代码块"); } static final int i; int j; static void method() { System.out.println(i); System.out.println(new D().j); method1(); new D().method2(); } static void method1() { System.out.println(i); } void method2() { System.out.println(i); } }
참고: 클래스의 인스턴스 메서드에 액세스하려면 개체 호출이 필요하고 정적 메서드는 클래스 이름을 통해 직접 액세스할 수 있는데 어떻게 배포 서버를 고려하지 않고 클래스 실행을 시작합니까? 가장 큰 가능성은 "클래스 이름.정적 메소드"를 통해 Java를 시작하는 것인데, 그렇게 많은 정적 메소드를 정의하는데 JVM이 정문을 어떻게 알 수 있을까요?
아마도 메인 메소드를 생각하셨을 겁니다.
예, 기본 메소드는 Java 사양에 따라 Java 클래스의 기본 입구로 정의됩니다. Java 클래스의 작업은 기본 메소드에 의해 시작됩니다:
public static void main(String[] args) { for (String arg : args) { // 参数由外部定义 System.out.println(arg); }}
但注意main并不是Java关键字,它只是一个规定的程序入口的方法名字;另外main方法可以重载。
注意:static关键字虽然不能修饰普通类,但可以用static关键字修饰内部类使其变成静态内部类。static关键字本身的含义就是共享,而Java类加载到JVM内存的方法区,也是线程共享的,所以没必要用static关键字修饰普通类。
4 静态导入
在用import导入包或者类时,可以用static修饰包名或者类,表示静态导入。静态导入可以与动态导入放在一起比较来加深理解。
动态导入是当你程序运行时需要new一个不在此包中的类的对象时,才会根据全路径类名加载类;而静态导入则是随着类的加载而加载静态导入的类,所以它是提前导入的。
public class StaticTest { static void method1() { System.out.println("static method1"); } static void method2() { System.out.println("static method2"); } }
静态导入:
import static com.starry.staticImport.StaticTest.method1; public class Client { public static void main(String[] args) { method1(); // StaticTest.method2(); } }
注意method1()是静态导入,所以可以不需要通过类名访问;而method2()没有导入,则需要通过类名调用。那么什么时候需要静态导入呢?
静态导入常用于静态方法以及含有静态方法的类,枚举类等的导入,可以在编译阶段确定导入类的信息或者方法信息。
static关键字的缺点
封装是Java类的三大特性之一,也是面向对象的主要特性。因为不需要通过对象,而直接通过类就能访问类的属性和方法,这有点破坏类的封装性;所以除了Utils类,代码中应该尽量少用static关键字修饰变量和方法
위 내용은 static 키워드는 무엇을 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!