Java 오토박싱이 오토박싱된 유형의 메소드 호출로 확장되지 않는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

문제

기본 요소를 문자열로 변환하고 싶어서 다음을 시도했습니다.

myInt.toString();

다음 오류로 인해 실패합니다.

int cannot be dereferenced

이제 프리미티브는 참조 유형(즉, 객체가 아님)이 아니므로 메서드를 가질 수 없다는 것을 알게 되었습니다.그러나 Java 5에서는 자동박싱 및 언박싱(C#과 마찬가지로...)을 도입했습니다.나는 C#에서 결코 좋아하지 않았지만 그것은 요점을 벗어났습니다.)따라서 오토박싱을 사용하면 위의 내용이 myInt를 Integer로 변환한 다음 그에 대해 toString()을 호출할 것으로 예상됩니다.

또한, 제가 잘못 기억하지 않는 한 C#에서는 이러한 호출이 허용된다고 생각합니다.이것은 단지 Java의 autoboxing/unboxing 사양의 불행한 단점입니까, 아니면 이에 대한 타당한 이유가 있습니까?

도움이 되었습니까?

해결책

Java autoboxing/unboxing은 기본 요소를 역참조할 수 있는 정도까지 진행되지 않으므로 컴파일러에서 이를 방지합니다.당신의 컴파일러는 여전히 알고 있습니다 myInt 원시인으로서.이 문제에 관한 논문이 있습니다. jcp.org.

오토박싱은 주로 할당이나 매개변수 전달 중에 유용합니다. 즉, 기본 요소를 객체로 전달하거나(또는 그 반대로) 기본 요소를 객체에 할당(또는 그 반대로)할 수 있도록 해줍니다.

불행하게도 다음과 같이 해야 합니다.(패트릭에게 찬사를 보냅니다. 당신의 방식으로 바꿨습니다)

Integer.toString(myInt);

다른 팁

Justin이 말한 것과 동일하지만 대신 다음을 수행해야 합니다.

Integer.toString(myInt);

할당을 한두 개 저장하고 더 읽기 쉽습니다.

이를 수행하는 또 다른 방법은 다음을 사용하는 것입니다.

String.valueOf(myInt);

이 메소드는 모든 기본 유형에 대해 오버로드되며 Object.이렇게 하면 사용 중인 유형에 대해 생각할 필요조차 없습니다.메소드 구현은 주어진 유형의 적절한 메소드를 호출합니다. Integer.toString(myInt).

보다 http://java.sun.com/javase/6/docs/api/java/lang/String.html.

나에게 사양의 단점처럼 보인다

더 많은 단점이 있으며 이것은 미묘한 주제입니다.확인하다 이것 밖으로:

public class methodOverloading{
   public static void hello(Integer x){
      System.out.println("Integer");
   }

   public static void hello(long x){
      System.out.println("long");
   }

   public static void main(String[] args){
      int i = 5;
      hello(i);
   }
}

여기서 "long"이 인쇄됩니다(직접 확인하지 않았습니다). 왜냐하면 컴파일러가 자동 박싱보다 확장을 선택했기 때문입니다.오토박싱을 사용할 때는 주의하거나 전혀 사용하지 마세요!

귀하의 예에 가장 가까운 유효한 구문은 다음과 같습니다

((Integer) myInt).toString();

컴파일러가 끝나면 이는 다음과 같습니다.

Integer.valueOf(myInt).toString();

그러나 이는 기존 사용법만큼 성능이 좋지 않습니다. String.valueOf(myInt), 특별한 경우를 제외하고는 새로운 Integer 인스턴스를 생성한 후 즉시 버려서 불필요한 쓰레기가 더 많아지기 때문입니다.(작은 범위의 정수가 캐시되고 배열 액세스로 액세스됩니다.) 아마도 언어 설계자는 성능상의 이유로 이러한 사용을 권장하지 않았을 것입니다.

편집하다:이것이 도움이 되지 않는 이유에 대해 반대 투표자들이 의견을 제시해 주시면 감사하겠습니다.

C#에서 정수는 참조 유형이 아니며 이를 위해 박싱할 필요도 없습니다. ToString() 호출됩니다.그들 ~이다 그러나 프레임워크에서는 개체를 ValueType으로 간주하므로 값 의미 체계를 갖습니다.CLR에서는 기본 요소에 대한 메서드를 스택(ldind)에 "간접적으로" 로드하여 호출합니다.

모두가 지적했듯이 오토박싱을 사용하면 일부 코드를 단순화할 수 있지만 기본 형식이 복잡한 유형인 척할 수는 없습니다.

또한 흥미로운 점은 다음과 같습니다. "오토박싱은 컴파일러 수준의 해킹입니다" 자바에서.Autoboxing은 기본적으로 Java에 추가된 이상한 클러지입니다.확인해 보세요 이 게시물 얼마나 이상한지 자세히 알아보세요.

Java가 기본 유형에서 작동하는 특정 정적 메소드를 정의하고 컴파일러에 일부 구문 설탕을 내장하면 도움이 될 것입니다.

5.asInteger

와 동등할 것이다

some.magic.stuff.Integer.asInteger(5);

나는 그러한 기능이 현재 규칙에 따라 컴파일되는 코드와 호환되지 않을 것이라고 생각하며 많은 경우 구문의 혼란을 줄이는 데 도움이 될 것입니다.Java가 역참조된 프리미티브를 자동 박싱하는 경우 사람들은 역참조 구문을 정적 메서드 호출에 매핑한다고 가정할 수 있으며(이는 사실상 .NET에서 발생하는 일입니다) 따라서 해당 형식으로 작성된 작업은 비용이 많이 들지 않습니다. 동등한 정적 메소드 호출.사람들이 나쁜 코드를 작성하도록 장려하는 새로운 언어 기능을 추가합니다(예:자동 복싱 역참조 기본 형식)은 좋은 생각이 아닌 것 같지만 역참조 스타일 메서드를 허용하는 것은 가능할 수도 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top