널 인수에 대한 메소드 오버로드


133

매개 변수와 함께 세 가지 방법을 추가했습니다.

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

내가 호출 할 때 doSomething(null)컴파일러는 모호한 메소드 로 오류를 발생시킵니다 . 그래서 문제 때문에 Integerchar[]방법이나 IntegerObject방법?


3
그냥 변경 Integerint.
Mudassir

2
@ Mudassir : 정확히 어떻게 해결됩니까?
Joachim Sauer

2
@Joachim Sauer : Integer에서 int로 변경되면 null은 Java에서 기본 유형을 참조하지 않으므로 컴파일러에서 오류가 발생하지 않습니다.
Phani

@Joachim Sauer : reference to doSomething is ambiguous오류가 발생 하지 않습니다 .
Mudassir

답변:


211

Java는 항상 사용 가능한 가장 구체적인 해당 버전의 메소드를 사용하려고합니다 ( JLS §15.12.2 참조 ).

Object, char[]그리고 Integer모두 걸릴 수 null유효한 값으로. 따라서 3 가지 버전 모두 적용 가능하므로 Java는 가장 구체적인 버전을 찾아야합니다.

Object의 슈퍼 유형 이므로 char[]배열 버전이 Object-version 보다 더 구체적 입니다. 따라서이 두 가지 방법 만 있으면 char[]버전이 선택됩니다.

두 때 char[]Integer버전을 사용할 수 있습니다, 다음 그들보다 더 구체적입니다 Object하지만 자바 전화를 어느 결정할 수 없음, 다른보다 더 구체적입니다. 이 경우 인수를 적절한 유형으로 캐스팅하여 호출하려는 것을 명시 적으로 언급해야합니다.

실제로이 문제는 생각보다 훨씬 드물게 발생합니다. 그 이유는 null특정 유형이 아닌 변수 (예 :)를 사용 하거나 변수를 사용하여 메서드를 명시 적으로 호출 할 때만 발생하기 때문입니다 Object.

반대로 다음 호출은 완벽하게 모호하지 않습니다.

char[] x = null;
doSomething(x);

여전히 값을 전달하고 있지만 nullJava는 변수 유형을 고려하므로 호출 할 메소드를 정확하게 알고 있습니다.


1
이것은 Java 7에 명시되어 있습니다. 이전 Java 버전에도 적용됩니까? 의미 : 유형 계층 구조에만 매개 변수가있는 여러 메소드 서명이있는 경우 실제 값으로 null을 사용하여 저장 측에 있습니까? 그리고 여기 예제와 같이 "계층 구조"를 구축했다면 그렇지 않습니까?
Christian Gosch

2
Java 1.1 이후의 모든 규칙에 대해 규칙이 동일하다고 확신합니다 (일반 제네릭 추가 제외).
Joachim Sauer 2019

doSomething (null)을 사용하여 런타임 중에 컴파일러가 doSomething (String str)과 doSomething (Object obj) 중에서 선택해야하는 경우 doSomething (String str)이 호출됩니다.
Sameer

43

이 세 가지 메소드의 각 쌍은 null인수 와 함께 호출 될 때 자체적으로 모호합니다 . 각 매개 변수 유형은 참조 유형이기 때문입니다.

다음은 하나의 특정 메소드를 null로 호출하는 세 가지 방법입니다.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

실제로 이러한 메소드를 null인수 와 함께 호출하려는 경우이 모호성을 제거하는 것이 좋습니다 . 이러한 디자인은 미래에 오류를 불러 일으킨다.


1
Integer- char[]@JoachimSauer 설명처럼 다른 두 경우에, 자바 컴파일러는 가장 구체적인 선택을 선택할 수 있기 때문에 쌍 모호합니다.
kajacx

1
@kajacx : OPs 원래 질문은 null매개 변수로 이러한 메소드를 호출하는 것 입니다. 이 전제 조건에서 세 쌍 모두 모호합니다. 일반적인 경우, 나는 Integer - char[]쌍만이 모호하다는 것에 동의 합니다.
jmg

이것 에 doSomething(null)대해 public static void doSomething(String str) { System.out.println("String called"); }이것은 호출 된 문자열을 반환합니다.
Sameer

"nullable"또는 "not nullable"과 같은 어노테이션을 사용하고 선언을 설정하여 명시적인 "null"(아직 암시 적 널 유형) 인수가 항상 명확하게 선택되도록 널을 가져 오려는 하나의 메소드 만 가능 특정 과부하 ??
peterk

4

null세 가지 유형 중 하나에 유효한 값입니다. 따라서 컴파일러는 사용할 함수를 결정할 수 없습니다. 같은 것을 사용 doSomething((Object)null)하거나 doSomething((Integer)null)대신.


Integer 매개 변수를 사용하여 메서드를 제거하면 함수를 호출하고 출력을 "Array Called" 로 반환 하므로 Array와 Object 간의 계약은 무엇 입니까?
Phani

2
Java 배열도 Object입니다.
Zds

2

Java의 모든 클래스는 Object 클래스를 확장하고 Integer 클래스도 Object를 확장합니다. 따라서 Object와 Integer는 모두 Object 인스턴스로 간주됩니다. 따라서 매개 변수로 null을 전달하면 컴파일러보다 호출 할 객체 메소드 즉, Object 또는 Parameter Integer로 호출하는 객체 메소드가 객체이며 해당 참조가 모두 null 일 수 있기 때문에 혼동됩니다. 그러나 Java의 기본 요소는 Object를 확장하지 않습니다.


1

나는 이것을 시도했고 정확히 한 쌍의 오버로드 된 메소드가 있고 그중 하나에 매개 변수 유형 Object가있는 경우 컴파일러는 항상 더 구체적인 유형의 메소드를 선택합니다. 그러나 둘 이상의 특정 유형이있는 경우 컴파일러는 모호한 메소드 오류를 발생시킵니다.

이것은 컴파일 타임 이벤트이므로 의도적으로이 메소드에 널을 전달할 때만 발생할 수 있습니다. 의도적으로 수행 된 경우 매개 변수없이이 메서드를 다시 오버로드하거나 다른 메서드를 모두 만드는 것이 좋습니다.


0

doSomething (char [] obj) 및 doSomething (Integer obj)로 인해 모호성이 있습니다.

char []와 Integer는 모두 null보다 우수하므로 애매 모호합니다.


0
class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

출력은 Int이며 null이므로 모호함은 char [] 및 Integer입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.