source

파라미터가 리터럴 null 값인 경우 오버로드된 메서드는 어떻게 선택됩니까?

goodcode 2022. 9. 12. 11:38
반응형

파라미터가 리터럴 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

반응형