인터페이스 변수가 기본적으로 정적 및 최종적인 이유는 무엇입니까?


274

Java에서 인터페이스 변수가 기본적으로 정적 및 최종적인 이유는 무엇입니까?


41
인터페이스 안에 변수를 넣지 마십시오.
— cherouvim

34
인터페이스는 다양한 방식으로 구현할 수있는 계약을 정의하기 때문입니다. 변수의 가치는 구현입니다.
— cherouvim

10
인터페이스를 구현하는 모든 클래스에 일정한 변수 (예 : 필드 이름)가 있다는 것을 알면 분명히 가능합니다.
— Aniket Thakur

클래스의 변수를 클래스가 구현하는 인터페이스의 인스턴스로 만드는 것이 좋은 생각입니까? 나는 이것을 전에 들었다.
— Doug Hauf 2016 년

Java의 인터페이스는 ACID 원칙을 따릅니다. C의 정규화로 인해 마지막입니다. @cherouvim 변수의 유형은 구현이며, 값이 있거나없는 변수를 선언해야하며 변수의 정의는 값입니다. 변수 값을 변경하면 재 구현되지 않고 재정의됩니다.
— Grim

답변:


264

Philip Shaw의 Java 인터페이스 디자인 FAQ에서 :

Java 인터페이스는 자체적으로 인스턴스화 할 수 없으므로 인터페이스 변수는 정적입니다. 변수의 값은 인스턴스가 존재하지 않는 정적 컨텍스트에서 할당되어야합니다. 최종 수정자는 인터페이스 변수에 지정된 값이 프로그램 코드로 재 할당 할 수없는 진정한 상수인지 확인합니다.

출처


39
추상 클래스는 "자신의 권리로"인스턴스화 할 수 없으며 인스턴스 변수를 가질 수 없습니다.
— macias

18
static수정 자에 대한이 설명 은 완전히 허구입니다. 클래스의 퍼블릭 인스턴스 변수는 인터페이스의 일부이므로 interface인스턴스 메소드와 마찬가지로 Java에서 추상화되지 않아야 할 이유가 없습니다 . Java interface를 직접 인스턴스화 할 수 없다는 것은 중요하지 않습니다. 이를 구현하는 클래스 인스턴스를 계속 보유 할 수 interface있으며 특정 공용 인스턴스 변수가 있어야하는 것이 합리적입니다. 에 대한 부분은 final설명을 전혀 제공하지 않으며 final의미가 무엇인지 설명 합니다.
— 불꽃 놀이

3
위의 인용문은 문맥 상 더 좋습니다. 그것이주는 이유는 "인터페이스 변수는 Java 상수가되기"때문입니다. 인용문은 왜 그러한 상수가 정적이고 최종적인지에 대해 자세히 설명하고있었습니다. 사실이지만 실제 질문은 변수가 실제 인터페이스의 일부로 허용되지 않는 이유는 무엇입니까 (즉, 구현 클래스에서 발생해야하는 비 개인 멤버의 이름과 유형 지정). 특수한 "인터페이스 상수"를 원한다면 새로운 구문을 사용했거나 인터페이스에 실제로 정의 된 변수 가 인터페이스 상수 라고 결정했을 수 있습니다.
— 불꽃 폭발

6
상태 문제의 다중 상속을 피하기 위해 인터페이스는 인스턴스 변수를 가질 수 없습니다. docs.oracle.com/javase/tutorial/java/IandI/…를 참조하십시오 . 같은 이유로 클래스는 둘 이상의 클래스를 확장 할 수 없습니다.
— 데니스

1
어떻게 기본 방법을 소개하고이 인스턴스가 수행 아직 인스턴스 변수는 지원되지 않습니다는 ...
— M.kazem Akhgary

41

인터페이스에는 직접적인 객체가 없으므로 클래스 / 인터페이스를 사용하는 것이 유일한 방법입니다. 따라서 인터페이스 변수가 존재하는 경우 정적이어야합니다. 그렇지 않으면 외부 세계에 전혀 액세스 할 수 없습니다. 정적이기 때문에 하나의 값만 가질 수 있으며 구현하는 모든 클래스는 값을 변경할 수 있으므로 모든 엉망이 될 것입니다.

따라서 인터페이스 변수가 있으면 암시 적으로 정적이며 최종적이며 명백하게 공개됩니다!


물론 Java에서 허용 된 인스턴스 변수는 액세스 할 수 있습니다 interface. 클래스는 인터페이스에 필요한 인스턴스 변수를 선언하여 인터페이스를 구현합니다. 생성자 (또는 다른 메소드)는 인스턴스 변수를 설정합니다. 클래스의 인스턴스가 인스턴스화되면 인스턴스 변수에 액세스 할 수 있습니다.
— 불꽃 폭발

Java를 사용하면 본문이있는 정적 메소드가 인터페이스에 존재할 수 있습니다. 그것들은 정적 변수에 액세스 할 수 있습니다. 그것들은 단지 그것들을 바꿀 수 없습니다. 이것은 정적 함수가 데이터를 저장할 수 없다는 것을 의미합니다
— simpleuser

36

public : 인터페이스에 존재하는 메소드와 마찬가지로 모든 클래스의 액세스 가능성

static : interface는 객체를 가질 수 없으므로 interfaceName.variableName을 사용하여이를 참조하거나이를 구현하는 클래스에서 variableName을 직접 사용할 수 있습니다.

final : 상수로 만듭니다. 두 클래스가 동일한 인터페이스를 구현하고 둘 다 값을 변경할 권한을 부여하면 var의 현재 값에서 충돌이 발생하므로 한 번만 초기화가 허용됩니다.

또한 이러한 모든 수정자는 인터페이스에 암시 적이므로 실제로 지정할 필요는 없습니다.


15

( 이것은 철학적 인 대답이 아니라 실용적인 것입니다 ). static다른 사람들이 대답 한 수정 자 요구 사항 은 분명합니다. 기본적으로 인터페이스를 인스턴스화 할 수 없으므로 해당 필드에 액세스하는 유일한 방법은 인터페이스를 클래스 필드로 만드는 것 static입니다.

interface필드 뒤에서 자동으로 final(일정하게) 되는 이유 는 다른 구현이 우연히 다른 구현의 동작에 영향을 줄 수있는 인터페이스 변수의 값을 실수로 변경하는 것을 방지하기위한 것입니다. 자바 interface가 속성을 명시 적으로 만들지 않은 아래 시나리오를 상상해보십시오 final.

public interface Actionable {
    public static boolean isActionable = false;

    public void performAction();
}

public NuclearAction implements Actionable {

    public void performAction() {
        // Code that depends on isActionable variable
        if (isActionable) {
            // Launch nuclear weapon!!!
        }
    }
}

이제 구현하는 다른 클래스가 Actionable인터페이스 변수의 상태를 변경하면 어떻게 될지 생각해보십시오 .

public CleanAction implements Actionable  {

    public void performAction() {
        // Code that can alter isActionable state since it is not constant
        isActionable = true;
    }
}

이러한 클래스는 클래스 로더에 의해 단일 JVM 내에로드 된 경우의 동작을 NuclearAction다른 클래스에 의해 영향을받을 수는 CleanAction, 그 때 performAction()뒤에있는 invoke이다 CleanAction의 최악이 경우 어떤 일 수있다 (그렇지 않으면 동일한 스레드 또는) 실행 (의미 적으로 그것은)입니다.

각 구현에서 interface이러한 변수를 어떻게 사용할지 알 수 없으므로 암시 적으로이어야합니다 final.


9

다른 것은 구현의 일부이므로 인터페이스에는 구현이 포함될 수 없습니다.


1
그렇다면 최종 이유는 무엇입니까?
— Jothi

7
상수임을 나타냅니다. Java에는 const 키워드가 없습니다. static final은 상수를 선언하는 방법입니다.
— Amir Afghani

5
Java 8부터 구현을 포함 할 수 있지만 백 워드 호환성이 필요하지 않은 경우에는 사용하지 않는 것이 좋습니다. :)
— codepleb

6
public interface A{
    int x=65;
}
public interface B{
    int x=66;
}
public class D implements A,B {
    public static void main(String[] a){
        System.out.println(x); // which x?
    }
}

해결책은 다음과 같습니다.

System.out.println(A.x); // done

인터페이스 변수가 정적 인 이유 중 하나라고 생각합니다.

인터페이스 내에서 변수를 선언하지 마십시오.


3
실제로, "Ax"라는 스펙이 없으면 컴파일조차 할 수 없으므로 인터페이스에서 변수를 사용하는 것이 안전합니다 (암시 적으로 공개 정적 최종)
— Marco

@Marco가 컴파일조차하지 않는다고 말 했으므로 대답에 동의하지 않습니다. 나는 지금까지 다른 단점을 찾지 못했습니다. 어쩌면 static final실제로 정적이고 최종적인 변수 앞에 쓰여지는 것을 보지 못할 수도 있습니다 .
— Micer

5

static-인터페이스는 인스턴스를 가질 수 없기 때문입니다. 마지막으로 변경할 필요가 없기 때문입니다.


15
"우리는 필요하지 않습니다"== "허용되지 않습니다", 의미를 혼용하지 마십시오.
— peterh-Reinstate Monica

3

때문에:

Static : 인터페이스의 객체를 가질 수 없으므로 객체 레벨 멤버 변수를 사용하지 말고 클래스 레벨 변수 즉 정적을 사용해야합니다.

Final : 변수에 대한 모호한 값이 없어야합니다 (Diamond problem-Multiple Inheritance).

그리고 문서 인터페이스에 따르면 계약이 아니라 구현입니다.

참조 : quora에 대한 Abhishek Jain의 답변


2

Java는 인터페이스에서 추상 변수 및 / 또는 생성자 정의를 허용하지 않습니다. 솔루션 : 인터페이스와 구현 사이에 추상 클래스를 연결하면 다음과 같이 추상 클래스 만 확장됩니다.

 public interface IMyClass {

     void methodA();
     String methodB();
     Integer methodC();

 }

 public abstract class myAbstractClass implements IMyClass {
     protected String varA, varB;

     //Constructor
     myAbstractClass(String varA, String varB) {
         this.varA = varA;
         this.varB = VarB;
     }

     //Implement (some) interface methods here or leave them for the concrete class
     protected void methodA() {
         //Do something
     }

     //Add additional methods here which must be implemented in the concrete class
     protected abstract Long methodD();

     //Write some completely new methods which can be used by all subclasses
     protected Float methodE() {
         return 42.0;
     }

 }

 public class myConcreteClass extends myAbstractClass {

     //Constructor must now be implemented!
     myClass(String varA, String varB) {
         super(varA, varB);
     }

     //All non-private variables from the abstract class are available here
     //All methods not implemented in the abstract class must be implemented here

 }

나중에 다른 인터페이스와 함께 구현하지 않으려는 경우 인터페이스 없이 추상 클래스 를 사용할 수도 있습니다 . 추상 클래스의 인스턴스를 만들 수 없으므로 먼저 확장해야합니다.

"protected"키워드는 확장 클래스 만 이러한 메소드 및 변수에 액세스 할 수 있음을 의미합니다.

스파이로


1

인터페이스는 변하지 않고 석재에 새겨진 두 당사자 간의 계약이므로 최종입니다. 계약 별 설계를 참조하십시오 .


1

인터페이스 : 시스템 요구 사항 서비스.

인터페이스에서 변수는 기본적으로 공개, 정적, 최종 액세스 수정 자에 의해 지정됩니다 . 때문에 :

public : 인터페이스가 다른 패키지에 배치 될 수도 있습니다. 따라서 프로젝트의 어느 곳에서나 변수에 액세스해야합니다.

static : 불완전한 클래스는 객체를 만들 수 없습니다. 따라서 프로젝트에서 객체없이 변수에 액세스해야합니다.interface_filename.variable_name

final : 하나의 인터페이스가 많은 클래스에 의해 구현되고 모든 클래스가 인터페이스 변수에 액세스하고 업데이트하려고한다고 가정하십시오. 따라서 데이터 변경이 일관되지 않고 다른 모든 클래스에 영향을 미칩니다. 따라서 final로 액세스 수정자를 선언해야합니다.


0

에서는 Java, 인터페이스는 인스턴스 변수를 선언 할 수 없습니다. 인터페이스에서 선언 된 변수를 인스턴스 변수로 사용하면 컴파일 타임 오류가 반환됩니다.

static final인스턴스 변수와 다른 상수 변수를 선언 할 수 있습니다 .


이것은 명백한 잘못입니다. 컴파일러는 개인용 또는 보호용으로 만들지 않는 한 불평하지 않습니다. 다른 사람들이 이미 언급했듯이, 그들은 공개 정적 결승으로 변환됩니다. 그리고 나는 그것이 왜 명백한 지 추측합니다. 인터페이스는 상태가 아닌 동작을 지시하기 때문입니다.
— Mikayil Abdullayev 2014 년

0

인터페이스는 모든 클래스에 의해 구현 될 수 있으며 구현 클래스 중 하나에 의해 값이 변경되면 다른 구현 클래스에 대한 오해가 발생할 수 있습니다. 인터페이스는 기본적으로 서로 관련이 있지만 서로 다른 두 엔티티를 결합하는 참조이므로 인터페이스 내부의 선언 변수는 암시 적으로 최종적이고 정적이며 인터페이스를 인스턴스화 할 수 없기 때문에 정적입니다.


0

인터페이스가 정의되어 있고 다른 클래스가이를 구현하는 웹 응용 프로그램을 생각해보십시오. 변수에 액세스하기 위해 인터페이스 인스턴스를 작성할 수 없으므로 정적 키워드가 필요합니다. 정적이므로 값의 변경 사항은 해당 값을 구현 한 다른 인스턴스에 반영됩니다. 따라서이를 방지하기 위해이를 최종으로 정의합니다.


0

Eclipse에서 방금 시도했지만 인터페이스의 변수는 기본적으로 최종 변수이므로 변경할 수 없습니다. 부모 클래스와 비교할 때 변수는 확실히 변경 가능합니다. 왜? 내 생각에 클래스의 변수는 어린이가 상속하는 속성이며 어린이는 실제 필요에 따라 변수를 변경할 수 있습니다. 반대로 인터페이스는 속성이 아닌 동작 만 정의합니다. 인터페이스에 변수를 넣는 유일한 이유는 해당 인터페이스와 관련된 const로 변수를 사용하는 것입니다. 그러나 이것은 다음 발췌에 따르면 좋은 습관이 아닙니다.

"인터페이스에 상수를 배치하는 것은 Java 초기에 널리 사용 된 기술 이었지만 이제는 인터페이스가 데이터가 아닌 객체가 제공하는 서비스를 처리해야하므로 인터페이스를 불쾌하게 사용하는 것으로 간주하고 있습니다. 클래스 별 구현은 일반적으로 구현 세부 사항이지만 인터페이스에 배치하면 클래스의 공용 API로 승격됩니다. "

또한 정적을 넣거나 전혀 차이를 만들지 않았습니다. 코드는 다음과 같습니다.

public interface Addable {
    static int count = 6;

    public int add(int i);

}

public class Impl implements Addable {

    @Override
    public int add(int i) {
        return i+count;
    }
}

public class Test {

    public static void main(String... args) {
        Impl impl = new Impl();

        System.out.println(impl.add(4));
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.