Java의 인터페이스는 클래스와 비슷하지만 인터페이스의 본문에는 추상 메서드 와
final
필드 (상수) 만 포함될 수 있습니다 .
최근에 다음과 같은 질문을 보았습니다.
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
인터페이스 정의에 따라 추상 메서드 만 허용됩니다. 위 코드를 컴파일 할 수있는 이유는 무엇입니까? default
키워드 는 무엇입니까 ?
반면에 아래 코드를 작성하려고 할 때 modifier default not allowed here
default class MyClass{
}
대신에
class MyClass {
}
누구든지 default
키워드 의 목적을 말해 줄 수 있습니까 ? 인터페이스 내에서만 허용됩니까? default
(액세스 수정 자 없음) 과 어떻게 다른 가요?
답변
interface
구현을 제공 할 수있는 Java 8의 새로운 기능입니다 . Java 8 JLS-13.5.6에 설명되어 있습니다. 읽는 인터페이스 메서드 선언 (일부)
default
메서드를 추가 하거나 메서드를에서abstract
로 변경해도default
기존 바이너리와의 호환성이 깨지지는 않지만IncompatibleClassChangeError
기존 바이너리가 메서드를 호출하려고 시도하면이 ( 가) 발생할 수 있습니다 . 이 오류는 한정 유형T
이 두 인터페이스I
및 의 하위 유형 인 경우 발생합니다.J
여기서 둘 다I
및 동일한 서명과 결과를 사용하여 메서드를J
선언하고 둘 다 선언default
하지I
않고J
다른 인터페이스의 하위 인터페이스 도 아닙니다 .
JDK 8의 새로운 기능에는 (일부)
기본 메서드를 사용하면 라이브러리 인터페이스에 새 기능을 추가 할 수 있으며 해당 인터페이스의 이전 버전 용으로 작성된 코드와 바이너리 호환성을 보장 할 수 있습니다.
답변
기본 메서드는 주로 람다 식을 지원하기 위해 Java 8에 추가되었습니다. 디자이너는 (영리하게 생각하기에) 인터페이스의 익명 구현을 만들기 위해 람다 구문을 만들기로 결정했습니다. 그러나 주어진 람다는 단일 메소드 만 구현할 수 있으며, 이는 매우 심각한 제한이 될 단일 메소드가있는 인터페이스로 제한됩니다. 대신 더 복잡한 인터페이스를 사용할 수 있도록 기본 메서드가 추가되었습니다.
default
람다로 인해 도입 된 주장에 대한 설득력이 필요한 경우 , 2009 년 Mark Reinhold가 작성한 Project Lambda 의 스트로 맨 제안 에는 람다를 지원하기 위해 추가해야 할 필수 기능으로 ‘확장 방법’이 언급되어 있습니다.
다음은 개념을 보여주는 예입니다.
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
나는 깨달았지만 default
람다를 지원 하는 방법을 설명해야 합니다. inverse
기본값 이기 때문에 필요한 경우 구현 클래스로 쉽게 재정의 할 수 있습니다.
답변
Java 8에는 기본 메소드라는 새로운 개념이 도입되었습니다. 기본 메서드는 기본 구현이 있으며 기존 코드를 손상시키지 않고 인터페이스를 발전시키는 데 도움이되는 메서드입니다. 예를 살펴 보겠습니다.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements SimpleInterface{
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
출력은 다음과 같습니다.
인터페이스의 DoSomeOtherWork 구현 클래스에서 Do Some Work 구현
답변
다른 답변에서 간과되었던 것은 주석에서의 역할이었습니다. Java 1.5에서 default
키워드는 주석 필드에 기본값 을 제공하는 수단으로 사용 되었습니다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
String value() default "AMD";
}
인터페이스에서 기본 메소드를 정의 할 수 있도록 Java 8의 도입으로 사용량이 오버로드 되었습니다.
간과 된 또 다른 것 : 선언 default class MyClass {}
이 유효하지 않은 이유 는 클래스가 전혀 선언 되는 방식 때문 입니다. 해당 키워드가 여기에 표시되도록 허용하는 언어 조항이 없습니다. 그러나 인터페이스 메서드 선언 에는 나타납니다 .
답변
새로운 Java 8 기능 ( Default Methods )을 사용하면 인터페이스가 default
키워드로 레이블이 지정되었을 때 구현을 제공 할 수 있습니다 .
예를 들면 :
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Interface Test는 인터페이스를 사용하는 클래스에서 이러한 메서드를 구현할 필요없이 인터페이스가 메서드의 기본 구현을 제공 할 수 있도록하는 default 키워드를 사용합니다.
이전 버전과의 호환성 :
인터페이스가 수백 개의 클래스로 구현되어 있다고 상상해보십시오. 인터페이스를 수정하면 인터페이스를 구현하는 다른 많은 클래스에 필수적인 것은 아니지만 모든 사용자가 새로 추가 된 메서드를 구현해야합니다.
사실 및 제한 사항 :
1- 클래스 또는 추상 클래스가 아닌 인터페이스 내에서만 선언 될 수 있습니다.
2- 몸을 제공해야합니다
3- 인터페이스에서 사용되는 다른 일반적인 방법과 같이 public 또는 abstract로 간주되지 않습니다.
답변
인터페이스의 기본 메소드를 사용하면 이전 코드를 손상시키지 않고 새로운 기능을 추가 할 수 있습니다.
Java 8 이전에는 새 메소드가 인터페이스에 추가되면 해당 인터페이스의 모든 구현 클래스가 새 기능을 사용하지 않더라도 새 메소드를 대체하도록 바인딩되었습니다.
Java 8에서는 default
메소드 구현 전에 키워드를 사용하여 새 메소드에 대한 기본 구현을 추가 할 수 있습니다 .
익명의 클래스 또는 기능적 인터페이스를 사용하더라도 일부 코드가 재사용 가능하고 코드의 모든 곳에 동일한 로직을 정의하고 싶지 않다면 기본 구현을 작성하고 재사용 할 수 있습니다.
예
public interface YourInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
답변
The Java ™ Tutorials 에서 아주 좋은 설명을 찾을 수 있습니다 . 설명의 일부는 다음과 같습니다.
자동차를 작동하기 위해 호출 할 수있는 방법을 설명하는 산업 표준 인터페이스를 게시하는 컴퓨터 제어 자동차 제조업체와 관련된 예를 고려하십시오. 컴퓨터로 제어되는 자동차 제조업체가 비행과 같은 새로운 기능을 자동차에 추가하면 어떻게 될까요? 이러한 제조업체는 다른 회사 (예 : 전자 유도 기기 제조업체)가 소프트웨어를 비행 자동차에 적용 할 수 있도록 새로운 방법을 지정해야합니다. 이러한 자동차 제조업체는 이러한 새로운 비행 관련 방법을 어디에서 선언할까요? 원래 인터페이스에 추가하면 해당 인터페이스를 구현 한 프로그래머는 구현을 다시 작성해야합니다. 그것들을 정적 메소드로 추가하면 프로그래머는 그것들을 필수 핵심 메소드가 아닌 유틸리티 메소드로 간주 할 것입니다.
기본 메서드를 사용하면 라이브러리의 인터페이스에 새 기능을 추가하고 해당 인터페이스의 이전 버전 용으로 작성된 코드와 바이너리 호환성을 보장 할 수 있습니다.