English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java 기본 튜토리얼

Java 흐름제어

Java 배열

Java 객체지향(I)

Java 객체지향(II)

Java 객체지향(III)

Java 예외 처리

Java 목록(List)

Java 큐(큐)

Java Map集合

Java Set集合

Java 입력출력(I/O)

Java Reader/Writer

Java 다른 주제

Java 접근 제한자

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 종류의 접근 권한이 있습니다.

  • default (즉 기본, 아무것도 적지 않음): 동일한 패키지 내에서 visible하며, 어떤 접근 기호도 사용하지 않습니다. 사용 대상: 클래스, 인터페이스, 변수, 메서드。

  • private : 동일한 클래스 내에서만 visible합니다. 사용 대상: 변수, 메서드。 주의: 클래스(외부 클래스)를修饰할 수 없습니다

  • public : 모든 클래스에 대해 visible합니다. 사용 대상: 클래스, 인터페이스, 변수, 메서드

  • protected : 동일한 패키지 내의 클래스와 모든 자손 클래스에 대해 visible합니다. 사용 대상: 변수, 메서드。 주의: 클래스(외부 클래스)를修饰할 수 없습니다

접근 권한을 설명하기 위해 다음 표를 사용할 수 있습니다:

접근 제어

수식자현재 클래스동일한 패키지 내자손 클래스(동일한 패키지)자손 클래스(다른 패키지)다른 패키지
publicYYYYY
protectedYYYY/N(설명N
defaultYYYNN
privateYNNNN

기본 접근 기호-어떤 키워드도 사용하지 않습니다

기본 접근 기호로 선언된 변수와 메서드는 동일한 패키지 내의 클래스에 대해 visible합니다. 인터페이스 내의 변수는 기본적으로 public static final로 선언되며, 인터페이스 내의 메서드는 기본적으로 public 접근 권한을 가집니다.

예제에서 보면, 변수와 메서드의 선언에는 접근 기호를 사용하지 않을 수 있습니다.

package defaultPackage;
class Logger {
    void message(){
        System.out.println("This is a message");
    }
}

이 경우 Logger 클래스는 기본 접근 기호를 가지고 있습니다. 그리고 이 클래스는 defaultPackage 패키지에 속한 모든 클래스에 대해可见합니다. 하지만, defaultPackage 외의 다른 클래스에서 Logger 클래스를 사용하려고 시도하면 컴파일 오류를 받을 것입니다.

private 접근 기호-private

private 접근 기호는 가장 깊은 접근 수준이므로, 선언된 것은 private 의 메서드, 변수 및 생성자는 소속 클래스에서만 접근할 수 있으며, 클래스와 인터페이스는 private 접근 기호로 선언될 수 없습니다. private

private 접근 유형의 변수는 외부 클래스에서는 클래스 내 공개된 getter 메서드를 통해 접근할 수 있습니다.

Private 접근 지정자의 사용은 주로 클래스의 구현 세부 사항을 숨기고 클래스의 데이터를 보호하는 데 사용됩니다.

아래 클래스는 프라이빗 접근 지정자를 사용했습니다:

public class Logger {
   private String format;
   public String getFormat() {
      return this.format;
   }
   public void setFormat(String format) {
      this.format = format;
   }
}

예제에서 Logger 클래스의 format 변수는 프라이빗 변수이므로, 다른 클래스는 직접 이 변수의 값을 가져오거나 설정할 수 없습니다. 다른 클래스가 이 변수를操作할 수 있도록 두 개의 public 메서드를 정의했습니다: getFormat() (format의 값을 반환)과 setFormat(String) (format의 값을 설정)

공유 접근 지정자-public

public으로 선언된 클래스, 메서드, 생성자 및 인터페이스는 어떤 다른 클래스에도 접근할 수 있습니다.

또한, 다른 패키지에 분포된 여러 개의 상호 참조하는 public 클래스가 있다면, 해당 public 클래스가 있는 패키지를 가져와야 합니다. 클래스의 상속성으로 인해, 클래스의 모든 공유 메서드와 변수는 자식 클래스에서 상속될 수 있습니다.

다음 함수는 공유 접근 제어를 사용했습니다:

public static void main(String[] arguments) {
   // ...
}

Java 프로그램의 main() 메서드는 공유로 설정되어야 하며, 그렇지 않으면 Java 인터프리터는 해당 클래스를 실행할 수 없습니다.

protected 접근 지정자-protected

protected는 다음 두 점에서 분석하고 설명해야 합니다:

  • 자식 클래스와 부모 클래스가 같은 패키지에 있습니다.protected로 선언된 변수, 메서드, 생성자는 같은 패키지에 있는 모든 다른 클래스에 접근할 수 있습니다;

  • 자식 클래스와 부모 클래스가 같은 패키지에 없습니다.그렇다면 자식 클래스에서는 부모 클래스에서 상속받은 protected 메서드에 접근할 수 있지만, 부모 클래스 예제의 protected 메서드에 접근할 수 없습니다.

protected는 데이터 멤버, 생성자, 메서드 멤버를修饰할 수 있습니다.클래스(내부 클래스를 제외하고)에 사용할 수 없습니다.

인터페이스와 인터페이스의 멤버 변수와 멤버 메서드는 protected로 선언할 수 없습니다.

자식 클래스는 protected 접근 지정자로 선언된 메서드와 변수에 접근할 수 있으며, 이렇게 하면 관련이 없는 클래스가 이 메서드와 변수를 사용하지 못하게 할 수 있습니다.

자식 클래스는 protected 접근 지정자를 사용한 부모 클래스를 상속했으며, 부모 클래스의 openSpeaker() 메서드를 재정의했습니다.

class AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {}
      // 实现细节
   }
}
 
class StreamingAudioPlayer extends AudioPlayer {
   protected boolean openSpeaker(Speaker sp) {}
      // 实现细节
   }
}

如果把openSpeaker()方法声明为private,那么除了AudioPlayer之外的类将不能访问该方法。

如果把openSpeaker()声明为public,那么所有的类都能够访问该方法。

如果我们只想让该方法对其所在类的子类可见,则将该方法声明为protected。

protected是最难理解的一种Java类成员访问权限修饰词。

访问控制和继承

请注意以下方法继承的规则:

  • 父类中声明为public的方法在子类中也必须为public。

  • 父类中声明为protected的方法在子类中要么声明为protected,要么声明为public,不能声明为private。

  • 父类中声明为private的方法,不能被继承。

非访问修饰符

为了实现一些其他的功能,Java也提供了许多非访问修饰符。

static修饰符,用来修饰类方法和类变量。

final修饰符,用来修饰类、方法和变量,final修饰的类不能被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

abstract修饰符,用来创建抽象类和抽象方法。

synchronized和volatile修饰符,主要用于线程的编程。

static修饰符

  • 静态变量:

    static关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为static变量。

  • 静态方法:

    static关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。

对类变量和方法的访问可以直接使用 classname.variablenameclassname.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("从 ", +
      InstanceCounter.getCount() + "개의 인스턴스로부터 시작");
      for(int i = 0; i < 500; ++i){
         new InstanceCounter();
          }
      System.out.println("Created ", +
      InstanceCounter.getCount() + "instances");
   }
}

위 예제의 실행 결과는 다음과 같습니다:

0개의 인스턴스로부터 시작
생성 500实例

final修饰자

final 변수:

final은 "최종적인, 결정된" 의미를 가리키며, 변수가 할당된 후에는 다시 할당할 수 없습니다. 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 메서드는 자식 클래스에 의해 상속될 수 있지만, 자식 클래스에 의해 재정의될 수 없습니다.

final 메서드를 선언하는 주요 목적은 이 메서드의 내용이 변경되지 않도록 하기 위함입니다.

다음과 같이 final修饰자를 사용하여 메서드를 선언합니다.

public class Test{
    public final void changeName(){
       // 메서드 본문
    }
}

final 클래스

final 클래스는 상속될 수 없으며, 어떤 클래스도 final 클래스의 어떤 특성도 상속할 수 없습니다.

public final class Test {
   // 클래스 본문
}

abstract修饰자

추상 클래스:

추상 클래스는 객체를 인스턴스화할 수 없으며, 추상 클래스를 선언하는 유일한 목적은 향후 해당 클래스를 확장하기 위함입니다.

한 클래스는 abstract와 final로 동시에 DECORATE될 수 없습니다. 하나의 클래스가 추상 메서드를 포함하고 있을 때, 그 클래스는 추상 클래스로 선언되어야 하며, 그렇지 않으면 컴파일 오류가 발생합니다.

추상 클래스는 추상 메서드와 비추상 메서드를 모두 포함할 수 있습니다.

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(){
          .......
      }
}

synchronized DECORATE

synchronized 키워드를 사용한 메서드는 동시에 하나의 스레드만 접근할 수 있습니다. synchronized DECORATE는 네 가지 접근 DECORATE에 적용될 수 있습니다.

public synchronized void showDetails(){
.......
}

transient DECORATE

serializable 객체가 transient DECORATE된 변수를 포함하고 있을 때, Java virtually 마신(JVM)은 해당 특정 변수를 건너뜁니다.

이 DECORATE는 변수 정의 문장에 포함되어 있으며, 클래스와 변수의 데이터 타입을 사전 처리하는 데 사용됩니다.

public transient int limit =; 55;   // 지속성이 없습니다.
public int b; // 지속성

volatile DECORATE

volatile 가DECORATE 한 멤버변수는 각 스레드가 그 멤버변수를 접근할 때마다 공유메모리에서 멤버변수의 값을 다시 읽어들입니다. 그리고 멤버변수가 변경될 때마다 변경된 값을 공유메모리로 반드시 쓰게 됩니다. 이렇게 하면 언제든지 두 개의 다른 스레드가 동일한 멤버변수의 값을 볼 수 있습니다.

volatile 객체 참조가 null일 수 있다.

public class MyRunnable implements Runnable
{
    private volatile boolean active;
    public void run()
    {
        active = true;
        while (active) // 첫 번째 줄
        {
            // 코드
        }
    }
    public void stop()
    {
        active = false; // 두 번째 줄
    }
}

일반적으로,Runnable을 통해 run() 메서드를 호출하는 한 thread와 다른 thread를 통해 stop() 메서드를 호출하는 경우가 많다. 만약 첫 번째 줄 缓冲区的 active 값이 사용되면, 두 번째 줄 의 active 값이 false일 때 루프는 중지되지 않는다.

하지만 위 코드에서는 volatile 접 heads active를 사용했기 때문에 이 루프는 중지된다.