파라미터가 리터럴 null 값인 경우 오버로드된 메서드는 어떻게 선택됩니까?
퀴즈에서 이 문제를 발견했는데
public class MoneyCalc {
public void method(Object o) {
System.out.println("Object Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
이 프로그램의 출력은 "String Version"입니다.그러나 오버로드된 메서드에 null을 전달하면 문자열 버전을 선택한 이유를 이해할 수 없었습니다.null은 String 변수가 아무것도 가리키지 않습니까?
하지만 코드가 바뀌면
public class MoneyCalc {
public void method(StringBuffer sb) {
System.out.println("StringBuffer Verion");
}
public void method(String s) {
System.out.println("String Version");
}
public static void main(String args[]) {
MoneyCalc question = new MoneyCalc();
question.method(null);
}
}
MoneyCalc 타입의 메서드(StringBuffer)가 애매합니다.라고 하는 컴파일 에러가 표시됩니다.
null은 String 변수가 아무것도 가리키지 않습니까?
null 참조는 임의의 클래스 유형의 식으로 변환할 수 있습니다.그래서 의 경우String
, 이것은 괜찮습니다.
String x = null;
그String
여기서 overload가 선택된 이유는 Java 컴파일러가 JLS 섹션 15.12.2.5에 따라 가장 구체적인 과부하를 선택하기 때문입니다.특히:
비공식적인 직관은 첫 번째 메서드에 의해 처리되는 호출이 컴파일 시간 유형 오류 없이 다른 메서드에 전달될 수 있다면 한 메서드가 다른 메서드보다 더 구체적이라는 것입니다.
두 번째 경우 두 가지 방법을 모두 사용할 수 있지만 둘 다 해당되지 않습니다.String
도 아니다StringBuffer
는 다른 메서드보다 구체적이기 때문에 어느 메서드도 다른 메서드보다 구체적이지 않기 때문에 컴파일러 오류가 발생합니다.
또한 JLS 3.10.7은 "null"이 "null type"의 리터럴 값임을 선언합니다.따라서 "null"이라는 유형이 존재합니다.
이후 JLS 4.1에서는 변수를 선언할 수 없는 눌타입이 존재하지만 눌리터럴을 통해서만 사용할 수 있습니다.나중에 다음과 같이 표시됩니다.
null 참조는 항상 모든 참조 유형으로 확대된 참조 변환을 수행할 수 있습니다.
컴파일러가 String으로 확장하기로 선택한 이유는 Jon의 답변에서 충분히 설명될 수 있습니다.
를 할당할 수 있습니다.string
에 대해서null
값이 유효하고 Java 및 대부분의 프로그래밍 언어의 순서가 가장 가까운 유형에 적합하며 다음으로 오브젝트에 적합합니다.
제목에 있는 질문에 답하려면:null
둘 다 아니다String
어느 쪽도Object
단, 에 대한 참조는 다음 중 하나에 할당할 수 있습니다.null
.
난 사실 이 코드가 컴파일 된 것조차 놀랍다.이전에 비슷한 것을 시도했는데, 콜이 애매하다는 컴파일러 에러가 발생했습니다.
그러나 이 경우 컴파일러는 먹이사슬에서 가장 낮은 방법을 선택하는 것으로 보입니다.이 방법은 가장 일반적이지 않은 버전의 메서드를 사용하는 것을 전제로 하고 있습니다.
이 (아마도) 완전히 같은 시나리오에서 컴파일러 오류가 발생한 예를 찾을 수 있는지 확인해야 합니다.
편집: 알겠습니다.제가 만든 버전에서는 두 가지 오버로드된 메서드가 있습니다.String
★★★Integer
('가장 구체적인' 파라미터는 Object
★★★★★★★★★★★★★★★★★」String
코드와 달리 둘 중 하나를 선택할 수 없습니다.
아주 멋진 질문입니다!
개체 유형보다 문자열 유형이 더 구체적입니다.Integer 유형을 사용하는 메서드를 하나 더 추가했다고 가정합니다.
public void method(Integer i) {
System.out.println("Integer Version");
}
콜이 애매하다고 하는 컴파일러 에러가 표시됩니다.지금과 같이 우선순위가 동일한 두 가지 방법을 동일하게 구체화했습니다.
Java 컴파일러는 null을 할당하기 위한 대부분의 파생 클래스 유형을 제공합니다.
다음으로 이를 이해하는 예를 제시하겠습니다.
class A{
public void methodA(){
System.out.println("Hello methodA");
}
}
class B extends A{
public void methodB(){
System.out.println("Hello methodB");
}
}
class C{
public void methodC(){
System.out.println("Hello methodC");
}
}
public class MyTest {
public static void fun(B Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
output :
한편, 다음과 같습니다.
public class MyTest {
public static void fun(C Obj){
System.out.println("B Class.");
}
public static void fun(A Obj){
System.out.println("A Class.");
}
public static void main(String[] args) {
fun(null);
}
}
결과 : MyTest 타입에서는 메서드 fun(C)이 애매합니다.
이 사건을 더 잘 이해하는 데 도움이 되기를 바랍니다.
★★★★https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5httpsdocs.oracle.com/javase/specs/jls/se8/html/jls-15.html#.12.2.5
컨셉:가장 구체적인 방법
: 에 적용할 수 디스패치의 를 선택해야 합니다.여러 멤버 메서드가 접근 가능하고 메서드 호출에 적용할 수 있는 경우 런타임 메서드 디스패치의 디스크립터를 제공할 멤버 메서드를 선택해야 합니다.Java 프로그래밍 언어에서는 가장 구체적인 메서드가 선택된다는 규칙을 사용합니다.호출됩니다.null은 자동으로 호출됩니다.
난 둘 다 말하지 않을 거야.NULL은 값이 아닌 상태입니다.자세한 내용은 이 링크를 참조하십시오(이 문서는 SQL에 적용되지만 질문에도 도움이 될 수 있습니다).
언급URL : https://stackoverflow.com/questions/13033037/how-is-an-overloaded-method-chosen-when-a-parameter-is-the-literal-null-value
'source' 카테고리의 다른 글
Panda DataFrame 열 머리글에서 목록 가져오기 (0) | 2022.09.12 |
---|---|
MySQL 쿼리 - 오늘에서 최근 30일 사이의 레코드 (0) | 2022.09.12 |
도커 볼륨 mariadb에 루트 권한이 있습니다. (0) | 2022.09.12 |
플롯 배경색을 변경하는 방법 (0) | 2022.09.12 |
PEP8에 준거하여 E501을 방지하는 매우 긴 문자열 작성 방법 (0) | 2022.09.12 |