자바 의 기본 방법(Default Methods)
다음으로 전송:http://ebnbin.com/2015/12/20/java-8-default-methods/
자바 8 은 새로운 언어 특성 인 기본 방법(Default Methods)을 도입 했다.
Default methods enable new functionality to be added to the interfaces of libraries and ensure binary compatibility with code written for older versions of those interfaces.
기본 방법 은 기 존 라 이브 러 리 인터페이스 에 새로운 기능 을 추가 할 수 있 으 며,기 존 버 전 인터페이스 로 작 성 된 코드 와 의 바 이 너 리 호환성 을 확보 할 수 있 습 니 다.
기본 방법 은 인터페이스 에 서명 하기 전에 추가 하 는 것 입 니 다.
default
키워드 의 실현 방법.간단 한 예
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceA foo"
);
-
}
-
}
-
-
class
ClassA
implements
InterfaceA
{
-
}
-
-
public
class
Test
{
-
public
static
void
main
(
String
[]
args
)
{
-
new
ClassA
().
foo
();
// :“InterfaceA foo”
-
}
-
}
ClassA
결코 실현 되 지 않 았 다. InterfaceA
인터페이스의 foo
방법 인터페이스 에서 제공 되 었 습 니 다. InterfaceA
방법의 기본 구현 이 므 로 직접 호출 할 수 있 습 니 다. foo
클래스 ClassA
방법왜 기본 적 인 방법 이 있어 야 합 니까?
자바 8 이전 인터페이스 와 실제 클래스 사이 의 결합 도 너무 높 습 니 다(tightly coupled).인터페이스 에 방법 을 추가 해 야 할 때 모든 실현 류 는 이에 따라 수정 해 야 합 니 다.기본 적 인 방법 은 이 문 제 를 해결 했다.기 존의 인터페이스의 실현 을 파괴 하지 않 고 인터페이스 에 새로운 방법 을 추가 할 수 있다.이것 은 lambda 표현 식 이 자바 8 언어의 중요 한 특성 으로 나타 날 때 낡은 인 터 페 이 스 를 업그레이드 하고 뒤로 호 환(backward compatibility)하 는 경 로 를 제공 합 니 다.
foo
이것/이것
-
String
[]
array
=
new
String
[]
{
-
"hello"
,
-
", "
,
-
"world"
,
-
};
-
List
<
String
>
list
=
Arrays
.
asList
(
array
);
-
list
.
forEach
(
System
.
out
::
println
);
// jdk 1.8
방법 은 jdk 1.8 에 추 가 된 인터페이스 기본 방법 입 니 다.기본 적 인 방법 이 도입 되 었 기 때문에 그렇지 않 습 니 다. forEach
인터페이스 에 추가 Iterable
방법 은 모든 것 을 수정 해 야 한다. forEach
인터페이스의 실현 류.아래 코드 는 jdk 1.8 의
Iterable
인터페이스의 Iterable
기본 방법:forEach
기본 방법의 계승다른 방법 과 마찬가지 로 인터페이스 기본 방법 도 계승 할 수 있다.
-
package
java
.
lang
;
-
-
import
java.util.Objects
;
-
import
java.util.function.Consumer
;
-
-
public
interface
Iterable
<
T
>
{
-
default
void
forEach
(
Consumer
super
T
>
action
)
{
-
Objects
.
requireNonNull
(
action
);
-
for
(
T
t
:
this
)
{
-
action
.
accept
(
t
);
-
}
-
}
-
}
인터페이스 기본 방법의 계승 은 세 가지 상황 으로 나 뉜 다.
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceA foo"
);
-
}
-
}
-
-
interface
InterfaceB
extends
InterfaceA
{
-
}
-
-
interface
InterfaceC
extends
InterfaceA
{
-
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceC foo"
);
-
}
-
}
-
-
interface
InterfaceD
extends
InterfaceA
{
-
-
void
foo
();
-
}
-
-
public
class
Test
{
-
public
static
void
main
(
String
[]
args
)
{
-
new
InterfaceB
()
{}.
foo
();
// :“InterfaceA foo”
-
new
InterfaceC
()
{}.
foo
();
// :“InterfaceC foo”
-
new
InterfaceD
()
{
-
-
public
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceD foo"
);
-
}
-
}.
foo
();
// :“InterfaceD foo”
-
-
// lambda
-
((
InterfaceD
)
()
->
System
.
out
.
println
(
"InterfaceD foo"
)).
foo
();
-
}
-
}
인터페이스 인터페이스 InterfaceB
인터페이스):기본 방법의 다 중 계승
자바 가 사용 하 는 것 은 단일 계승,다 중 실현 체 제 를 사용 하 는 것 으로 다 중 계승 이 가 져 온 호출 의 미 를 피 하 는 문제 이다.인터페이스의 하위 클래스 가 같은 서명 방법 을 동시에 가지 고 있 을 때 충돌 을 해결 하 는 방안 을 고려 해 야 한다.
InterfaceC
...에 있다 InterfaceD
클래스
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceA foo"
);
-
}
-
}
-
-
interface
InterfaceB
{
-
default
void
bar
()
{
-
System
.
out
.
println
(
"InterfaceB bar"
);
-
}
-
}
-
-
interface
InterfaceC
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceC foo"
);
-
}
-
-
default
void
bar
()
{
-
System
.
out
.
println
(
"InterfaceC bar"
);
-
}
-
}
-
-
class
ClassA
implements
InterfaceA
,
InterfaceB
{
-
}
-
-
//
-
//class ClassB implements InterfaceB, InterfaceC {
-
//}
-
-
class
ClassB
implements
InterfaceB
,
InterfaceC
{
-
-
public
void
bar
()
{
-
InterfaceB
.
super
.
bar
();
// InterfaceB bar
-
InterfaceC
.
super
.
bar
();
// InterfaceC bar
-
System
.
out
.
println
(
"ClassB bar"
);
//
-
}
-
}
인터페이스 ClassA
인터페이스 에 있 는 방법 은 나 쁜 뜻 이 존재 하지 않 고 직접적 으로 많이 실현 할 수 있다....에 있다
InterfaceA
클래스 InterfaceB
인터페이스 ClassB
인터페이스 에 같은 서명 이 있 습 니 다. InterfaceB
방법,충돌 을 수 동 으로 해결 해 야 합 니 다.나 쁜 뜻 이 존재 하 는 방법 을 덮어 쓰 고 사용 할 수 있다. InterfaceC
필요 한 인터페이스 기본 방법 을 수 동 으로 호출 합 니 다.인터페이스 계승 행위 충돌 시 해결 규칙
주의해 야 할 것 은 이런 상황 이다.
foo
...해 야 한다 InterfaceName.super.methodName();
클래스 다 실현
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceA foo"
);
-
}
-
}
-
-
interface
InterfaceB
extends
InterfaceA
{
-
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceB foo"
);
-
}
-
}
-
-
//
-
class
ClassA
implements
InterfaceA
,
InterfaceB
{
-
}
-
-
class
ClassB
implements
InterfaceA
,
InterfaceB
{
-
-
public
void
foo
()
{
-
// InterfaceA.super.foo(); //
-
InterfaceB
.
super
.
foo
();
-
}
-
}
인터페이스 ClassA
인 터 페 이 스 를 연결 할 때 방법 이름 의 오류 가 발생 하지 않 습 니 다....해 야 한다 InterfaceA
복사 InterfaceB
방법 시 통과 불가 ClassB
호출 foo
인터페이스의 InterfaceA.super.foo();
방법....때문에
InterfaceA
인터페이스 가 계승 되 었 다 foo
그러면 InterfaceB
인 터 페 이 스 는 모든 것 을 포함 하고 있 을 것 이다. InterfaceA
인터페이스 의 필드 방법 때문에 동시에 실현 되 었 다. InterfaceB
인터페이스 InterfaceA
인터페이스의 클래스 와 하 나 는 실현 되 었 다. InterfaceA
인터페이스의 종 류 는 완전히 등가 이다.이것 은 이해 하기 쉽다.
InterfaceB
...과 InterfaceB
등가.또는 다른 방식 으로 이해 하기:
class SimpleDateFormat extends DateFormat
여기 class SimpleDateFormat extends DateFormat, Object
같은 호출 은
-
class
ClassC
{
-
public
void
foo
()
{
-
System
.
out
.
println
(
"ClassC foo"
);
-
}
-
}
-
-
class
ClassD
extends
ClassC
{
-
-
public
void
foo
()
{
-
System
.
out
.
println
(
"ClassD foo"
);
-
}
-
}
-
-
public
class
Test
{
-
public
static
void
main
(
String
[]
args
)
{
-
ClassC
classC
=
new
ClassD
();
-
classC
.
foo
();
// :“ClassD foo”
-
}
-
}
클래스 classC.foo();
방법,인쇄 결 과 는"ClassD
"입 니 다.왜냐하면 foo
클래스 ClassD foo
방법 ClassC
클래스 에 복사 되 었 습 니 다.위 에 있어 요.
foo
클래스 에서 방법 이름 의 다른 의미 가 나타 나 지 않 는 이 유 는 이른바'잘못된 의미 가 존재 한다'는 방법 이 모두 ClassD
인터페이스 인터페이스 의'동명 방법'은 계승 일 뿐이다. ClassA
인터페이스 로 와 서 그것 을 복사 했다.InterfaceA
클래스 가 실 현 된 두 인 터 페 이 스 는 서로 무관 한 인터페이스 가 아니 기 때문에 동명 의 다른 의미 방법 은 존재 하지 않 는 다.덮어 쓰 는 것 은 부류 의 방법 에 대한 차단 을 의미 하 는데 이것 도 역시
InterfaceB
의 설계 의도 중 하나 다.그래서 이 루어 지고 있 습 니 다. InterfaceA
인터페이스 클래스 에서 복 사 된 것 에 접근 할 수 없습니다. ClassA
인터페이스의 Override
방법이것 은 인터페이스 계승 행위 가 충돌 할 때의 규칙 중 하나 이다.즉, 다른 형식 으로 덮어 쓰 는 방법 은 무 시 됩 니 다.
하면,만약,만약...
InterfaceB
인터페이스의 InterfaceA
방법 은 사용자 정의 새로운 인터페이스 로 만 계승 할 수 있 습 니 다. foo
인터페이스 및 디 스 플레이 복사 InterfaceA
방법 foo
호출 InterfaceA
인터페이스의 foo
방법,마지막 으로 실현 류 를 동시에 실현 하도록 한다. InterfaceA.super.foo();
인터페이스 와 사용자 정의 새 인터페이스,코드 는 다음 과 같 습 니 다.InterfaceA
주의! 비록...일지 라 도 foo
인터페이스의 InterfaceB
방법 은 부모 인터페이스의 기본 구현 방법 만 호출 했 을 뿐,이 복사 생략 할 수 없다.그렇지 않 으 면
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceA foo"
);
-
}
-
}
-
-
interface
InterfaceB
extends
InterfaceA
{
-
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceB foo"
);
-
}
-
}
-
-
interface
InterfaceC
extends
InterfaceA
{
-
-
default
void
foo
()
{
-
InterfaceA
.
super
.
foo
();
-
}
-
}
-
-
class
ClassA
implements
InterfaceB
,
InterfaceC
{
-
-
public
void
foo
()
{
-
InterfaceB
.
super
.
foo
();
-
InterfaceC
.
super
.
foo
();
-
}
-
}
인터페이스 InterfaceC
인터페이스의 암시 적 foo
방법 역시 InterfaceC
인터페이스 가 덮어 쓰 여 차단 되 어 호출 될 수 있 습 니 다. InterfaceA
시간 착오.이 예 를 통 해 기본 적 인 방법 을 사용 하기 전에 그것 이 정말 필요 한 지 를 고려 해 야 한 다 는 것 을 알 아야 한다....때문에 기본 적 인 방법 은 프로그램 에 나 쁜 의 미 를 가 져 오고 복잡 한 계승 시스템 에서 컴 파일 오류 가 발생 하기 쉽다.기본 적 인 방법 을 남용 하면 코드 에 예상 치 못 하고 이상 한 오 류 를 가 져 올 수 있다.
인터페이스 와 추상 류
인터페이스 계승 행위 가 충돌 할 때 또 다른 규칙 은 이러한 방법 성명 이 인터페이스 기본 방법 보다 우선 하 다 는 것 이다.이 방법 이 구체 적 이 든 추상 적 이 든 간 에.
foo
InterfaceB
클래스 에 수 동 복사 가 필요 하지 않 습 니 다. InterfaceC.super.foo()
방법
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
System
.
out
.
println
(
"InterfaceA foo"
);
-
}
-
-
default
void
bar
()
{
-
System
.
out
.
println
(
"InterfaceA bar"
);
-
}
-
}
-
-
abstract
class
AbstractClassA
{
-
public
abstract
void
foo
();
-
-
public
void
bar
()
{
-
System
.
out
.
println
(
"AbstractClassA bar"
);
-
}
-
}
-
-
class
ClassA
extends
AbstractClassA
implements
InterfaceA
{
-
-
public
void
foo
()
{
-
InterfaceA
.
super
.
foo
();
-
}
-
}
-
-
public
class
Test
{
-
public
static
void
main
(
String
[]
args
)
{
-
ClassA
classA
=
new
ClassA
();
-
classA
.
foo
();
// :“InterfaceA foo”
-
classA
.
bar
();
// :“AbstractClassA bar”
-
}
-
}
상속 ClassA
추상 류 에 존재 합 니 다. bar
방법의 실현 ClassA
추상 적 AbstractClassA
방법 은 추상 적 이기 때문에 bar
클래스 에서 반드시 실현 해 야 합 니 다. AbstractClassA
방법자바 8 의 인터페이스 기본 방법 은 추상 적 인 것 처럼 방법의 실현 을 제공 할 수 있 지만 그들 둘 은 여전히 서로 대체 할 수 없 는:
foo
포인터,구조 함수 가 없 으 면 인 스 턴 스 필드(인 스 턴 스 변수)나 인 스 턴 스 방법 이 있어 서 저장 할 수 없습니다. 상태(state),추상 적 인 방법 에서 가능 합 니 다.인터페이스 정적 방법
기본 방법 을 제외 하고 자바 8 은 인터페이스 에서 정적 방법 을 정의 할 수 있 습 니 다.
ClassA
기타 주의 점foo
키 워드 는 인터페이스 에서 만 사용 할 수 있 습 니 다. this
문장의
-
interface
InterfaceA
{
-
default
void
foo
()
{
-
printHelloWorld
();
-
}
-
-
static
void
printHelloWorld
()
{
-
System
.
out
.
println
(
"hello, world"
);
-
}
-
}
-
-
public
class
Test
{
-
public
static
void
main
(
String
[]
args
)
{
-
InterfaceA
.
printHelloWorld
();
// :“hello, world”
-
}
-
}
분기)추상 류 에 사용 할 수 없다.default
클래스 switch
、 default
화해시키다 Object
방법equals
의,hashCode
장식 부 호 는 생략 할 수 있 습 니 다.toString
수식 부 는 생략 할 수 없다.이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.