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


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.