Java 언어는 주로 다음 두 가지 범주로 구분되는 다양한 수정자를 제공합니다.
수정자는 클래스, 메소드 또는 변수를 정의하는 데 사용되며 일반적으로 명령문 앞에 배치됩니다. 다음 예를 통해 이를 설명합니다.
public class className { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String[] arguments) { // 方法体}
Java에서는 액세스 제어를 사용하여 클래스, 변수, 메소드 및 생성자에 대한 액세스를 보호할 수 있습니다. Java는 4가지 액세스 권한을 지원합니다.
기본값이라고도 하는 기본값은 동일한 패키지 내에서 표시되며 수정자를 사용하지 않습니다.
비공개(private 한정자로 지정됨)는 동일한 클래스 내에서 표시됩니다.
public은 public 수정자로 지정되며 모든 클래스에 표시됩니다.
protected 한정자로 지정된 Protected는 동일한 패키지의 클래스 및 모든 하위 클래스에 표시됩니다.
기본 액세스 한정자로 선언된 변수와 메서드는 동일한 패키지의 클래스에 표시됩니다. 인터페이스의 변수는 암시적으로 public static final
로 선언되는 반면, 인터페이스의 메서드는 기본적으로 public
액세스 권한을 갖습니다.
예:
다음 예제와 같이 변수와 메서드는 수정자 없이 선언될 수 있습니다.
String version = "1.5.1"; boolean processOrder() { return true; }
private 액세스 한정자는 가장 제한적인 액세스 수준이므로 private으로 선언된 메서드, 변수 및 생성자는 해당 클래스가 속한 클래스에서만 액세스할 수 있으며 클래스와 인터페이스는 private으로 선언할 수 없습니다.
개인용 액세스 유형으로 선언된 변수는 클래스의 공용 getter 메소드를 통해 외부 클래스에서만 액세스할 수 있습니다.
개인 액세스 수정자의 사용은 주로 클래스의 구현 세부 사항을 숨기고 클래스의 데이터를 보호하는 데 사용됩니다.
다음 클래스는 개인 액세스 한정자를 사용합니다.
public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }
예제에서 Logger 클래스의 형식 변수는 전용 변수이므로 다른 클래스에서 변수 값을 직접 가져오고 설정할 수 없습니다. 다른 클래스가 이 변수를 작동할 수 있도록 하기 위해 getFormat()
(형식 값 반환) 및 setFormat(String)
(형식 값 설정)이라는 두 개의 public
메서드가 정의됩니다.
public으로 선언된 클래스, 메서드, 생성자 및 인터페이스는 다른 모든 클래스에서 액세스할 수 있습니다.
서로 접근하는 여러 퍼블릭 클래스가 서로 다른 패키지에 배포되어 있는 경우 해당 퍼블릭 클래스가 위치한 패키지를 가져와야 합니다. 클래스 상속으로 인해 클래스의 모든 공개 메서드와 변수는 해당 하위 클래스에서 상속될 수 있습니다.
다음 함수는 공개 액세스 제어를 사용합니다.
public static void main(String[] arguments) { // ... }
Java 프로그램의 main() 메소드는 공개로 설정되어야 합니다. 그렇지 않으면 Java 인터프리터가 클래스를 실행할 수 없습니다.
protected로 선언된 변수, 메서드 및 생성자는 동일한 패키지의 다른 클래스나 다른 패키지의 하위 클래스에서 액세스할 수 있습니다.
Protected 액세스 한정자는 클래스와 인터페이스를 수정할 수 없습니다. 메서드와 멤버 변수는 protected로 선언할 수 있지만 인터페이스의 멤버 변수와 멤버 메서드는 protected로 선언할 수 없습니다.
서브클래스는 Protected 한정자로 선언된 메서드와 변수에 액세스할 수 있으므로 관련 없는 클래스가 이러한 메서드와 변수를 사용하지 못하도록 보호합니다.
다음 상위 클래스는 protected 액세스 한정자를 사용하고 하위 클래스는 상위 클래스의 openSpeaker() 메서드를 재정의합니다.
class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节} } class StreamingAudioPlayer extends AudioPlayer { boolean openSpeaker(Speaker sp) { // 实现细节} }
openSpeaker() 메서드가 비공개로 선언되면 AudioPlayer 이외의 클래스는 이 메서드에 액세스할 수 없습니다.
openSpeaker()가 public으로 선언되면 모든 클래스가 이 메서드에 액세스할 수 있습니다.
메서드가 해당 클래스의 하위 클래스에만 표시되도록 하려면 해당 메서드를 protected로 선언하세요.
메서드 상속에 대한 다음 규칙을 참고하세요.
상위 클래스에서 public으로 선언된 메서드는 하위 클래스에서도 public이어야 합니다.
상위 클래스에서 protected로 선언된 메서드는 하위 클래스에서 protected 또는 public으로 선언됩니다. 비공개로 선언할 수 없습니다.
상위 클래스에서 비공개로 선언된 메서드는 상속될 수 없습니다.
다른 기능을 구현하기 위해 Java는 많은 비액세스 수정자를 제공합니다.
클래스 메서드와 클래스 변수를 생성하는 데 사용되는 정적 수정자입니다.
final 수정자는 클래스, 메소드 및 변수를 수정하는 데 사용됩니다. final로 수정된 클래스는 상속될 수 없고, 수정된 메소드는 상속된 클래스로 재정의될 수 없으며, 수정된 변수는 상수이므로 수정할 수 없습니다.
추상 클래스와 추상 메소드를 생성하는 데 사용되는 추상 수정자.
동기화 및 휘발성 수정자는 주로 스레드 프로그래밍에 사용됩니다.
정적 변수:
static 키워드는 객체와 독립적인 정적 변수를 선언하는 데 사용됩니다. 클래스가 인스턴스화하는 객체 수에 관계없이 정적 변수의 복사본은 하나만 있습니다. 정적 변수는 클래스 변수라고도 합니다. 지역 변수는 정적 변수로 선언할 수 없습니다.
정적 방법:
static 키워드는 객체와 독립적인 정적 메서드를 선언하는 데 사용됩니다. 정적 메서드는 클래스의 비정적 변수를 사용할 수 없습니다. 정적 메서드는 매개변수 목록에서 데이터를 가져온 다음 데이터를 계산합니다.
클래스 변수 및 메소드에 대한 액세스는 classname.variablename
및 classname.methodname
사용하여 직접 액세스할 수 있습니다.
다음 예제에서 볼 수 있듯이 static 한정자는 클래스 메서드와 클래스 변수를 만드는 데 사용됩니다.
public class InstanceCounter { private static int numInstances = 0; protected static int getCount() { return numInstances; } private static void addInstance() { numInstances++; } InstanceCounter() { InstanceCounter.addInstance(); } public static void main(String[] arguments) { System.out.println("Starting with " + InstanceCounter.getCount() + " instances"); for (int i = 0; i < 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }
위 예제를 실행한 편집 결과는 다음과 같습니다.
Started with 0 instances Created 500 instances
최종 변수:
최종 변수는 명시적으로 한 번만 초기화할 수 있습니다. final로 선언된 객체에 대한 참조는 다른 객체를 가리킬 수 없습니다. 그러나 최종 개체의 데이터는 변경될 수 있습니다. 즉, 최종 객체의 참조는 변경할 수 없지만 내부의 값은 변경할 수 있습니다.
final 수정자는 클래스 상수를 생성하기 위해 static 수정자와 함께 사용되는 경우가 많습니다.
예:
public class Test{ final int value = 10; // 下面是声明常量的实例public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //将输出一个错误} }
클래스의 Final 메서드는 하위 클래스에서 상속될 수 있지만 하위 클래스에서 수정할 수는 없습니다.
최종 메소드를 선언하는 주된 목적은 메소드의 내용이 수정되는 것을 방지하는 것입니다.
아래와 같이 final 수식자를 사용하여 메소드를 선언합니다.
public class Test{ public final void changeName(){ // 方法体} }
최종 클래스는 상속될 수 없으며 어떤 클래스도 최종 클래스의 특성을 상속받을 수 없습니다.
예:
public final class Test { // 类体}
추상 클래스:
추상 클래스는 객체를 인스턴스화하는 데 사용할 수 없습니다. 추상 클래스를 선언하는 유일한 목적은 나중에 클래스를 확장하는 것입니다.
클래스는 abstract와 final을 동시에 수정할 수 없습니다. 클래스에 추상 메소드가 포함된 경우 해당 클래스를 추상 클래스로 선언해야 합니다. 그렇지 않으면 컴파일 오류가 발생합니다.
추상 클래스에는 추상 메서드와 비추상 메서드가 포함될 수 있습니다.
예:
abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //抽象方法public abstract void changeColor(); }
추상 메소드는 구현이 없는 메소드입니다. 메소드의 특정 구현은 서브클래스에서 제공됩니다. 추상 메서드는 final 및 static으로 선언할 수 없습니다.
추상 클래스를 상속하는 모든 하위 클래스는 해당 하위 클래스가 추상 클래스가 아닌 한 상위 클래스의 모든 추상 메서드를 구현해야 합니다.
클래스에 여러 추상 메서드가 포함되어 있는 경우 클래스를 추상 클래스로 선언해야 합니다. 추상 클래스에는 추상 메서드가 포함될 필요가 없습니다.
추상 메서드 선언은 세미콜론으로 끝납니다. 예를 들면 다음과 같습니다. public abstract sample();
예:
public abstract class SuperClass{ abstract void m(); //抽象方法} class SubClass extends SuperClass{ //实现抽象方法void m(){ ......... } }
동기화 키워드로 선언된 메서드는 동시에 하나의 스레드에서만 액세스할 수 있습니다. 동기화 수정자는 4개의 액세스 수정자에 적용될 수 있습니다.
예:
public synchronized void showDetails(){ ....... }
직렬화된 객체에 일시적으로 수정되는 인스턴스 변수가 포함되어 있으면 JVM(Java Virtual Machine)은 해당 특정 변수를 건너뜁니다.
이 수정자는 변수를 정의하는 명령문에 포함되며 클래스 및 변수의 데이터 유형을 전처리하는 데 사용됩니다.
예:
public transient int limit = 55; // will not persist public int b; // will persist
스레드가 휘발성으로 수정된 멤버 변수에 액세스할 때마다 멤버 변수의 값이 공유 메모리에서 강제로 다시 읽혀집니다. 또한 멤버 변수가 변경되면 스레드는 변경된 값을 공유 메모리에 다시 써야 합니다. 이러한 방식으로 언제든지 두 개의 서로 다른 스레드가 항상 동일한 멤버 변수 값을 볼 수 있습니다.
휘발성 개체 참조는 null일 수 있습니다.
예:
public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) // line 1 { // 代码} } public void stop() { active = false; // line 2 } }
일반적으로 한 스레드에서는 run() 메서드가 호출되고 다른 스레드에서는 stop() 메서드가 호출됩니다. 버퍼의 라인 1에 있는 active 값이 사용되면 라인 2의 active 값이 false로 설정되어도 루프가 중지되지 않습니다.