(문자열) 또는 .toString ()?


89

Object o매개 변수 가있는 메소드가 있습니다.

이 방법에서는 Stringnull이 아닌 "o" 가 있음을 정확히 알고 있습니다 . 확인하거나 다른 작업을 수행 할 필요가 없습니다. 나는 그것을 String물건 과 똑같이 취급해야 합니다.

그냥 궁금한 것-더 싼 것이 무엇입니까-그것을 캐스팅 String하거나 사용 Object.toString()합니까? 아니면 시간-/ cpu- / mem- 가격으로 동일합니까?

업데이트 :이 메서드는 Object인터페이스의 구현이므로 수락 합니다. 매개 변수 유형을 변경할 수있는 방법이 없습니다.

그리고 그것은 전혀 될 수 없습니다 null. 나는 null이나 비어 있는지 확인할 필요가 없다고 말하고 싶었습니다. 제 경우에는 항상 비어 있지 않은 문자열이 있습니다.


1
.NET 세계에서 우리는 그것을 측정했고 ToString ()이 더 빠릅니다. 그 이유를 감안할 때 지팅 JVM도 마찬가지입니다.
여호수아

답변:


73

String으로 캐스팅 하는 것은 외부 함수 호출이 필요하지 않고 내부 유형 검사 만 필요하기 때문에 저렴 합니다.


4
여러 JRE에서 테스트 했습니까? .NET에서이 상황에 대한 놀라운 결과를 보았습니다. 현실적으로 성능이 실제 생활에서 중요 할 것 같지는 않지만 방어적인 코딩 관점에서 캐스팅이 더 좋습니다.
Jon Skeet

메서드 호출은 인라인되어야합니다. 제네릭을 사용하여 (명시 적) 캐스트를 제거하는 것이 가장 좋습니다.
Tom Hawtin-tackline

@Jon Skeet : 성능 차이가 크지 않다는 데 동의합니다. @Tom Hawtin : 수신 할 객체의 유형을 컴파일 타임에 알 수 없기 때문에 메서드 호출이 어떻게 인라인 될 수 있는지 알 수 없습니다. 당신은 명확히 할 수 있습니까?
euphoria83

@ euphoria83 : javac가 아닌 JIT 컴파일러에 의해 인라인됩니다.
Michael Myers

사실, 방법은 인라인 될 수 없습니다. 유형은 Object로만 알려져 있으며 실제 구현은 런타임 유형에 따라 다릅니다. 어느 것이 더 빠른지는 여전히 구현에 달려 있지만 내가 기억하는 한 (실제로 한 지점에서 마이크로 벤치 마크로 테스트했습니다) 캐스팅이 더 빠른 것 같습니다. 이것은 명백한 대답이 아닙니다. 유형 검사가 항상 빠르지는 않습니다. 문자열 유형의 경우 객체 (인터페이스가 아님)이기 때문에 마지막이 될 수 있습니다.
StaxMan

45

나는 캐스트를 사용합니다. 그것은 그것이 문자열이라는 당신의 "지식"을 검증합니다. 어떤 이유로 든 버그로 끝나고 누군가 문자열이 아닌 다른 것을 전달한다면 결함이있는 데이터로 계속 실행하는 것보다 예외를 던지는 것이 더 나을 것이라고 생각합니다.



7

Object o가 String이라는 것을 알고 있다면 그냥 String으로 캐스트하고 그렇게 강제한다고 말하고 싶습니다. 확실하게 String이라는 것을 알고있는 객체에서 toString ()을 호출하면 혼란을 더할 수 있습니다.

Object o가 String이 아닌 다른 것일 수 있다면 toString ()을 호출해야합니다.


이것은 저에게 정답입니다. 왜? 캐스팅 때문에 (string)Registry.GetValue...반면, 캐스트에 INT32 객체를 시도에 대한 예외가 발생합니다 Registry.GetValue...ToString()예상대로 작동합니다.
중력

3

이 작업이 1 초에 수천 번만 수행된다면 성능에 크게 신경 쓰지 않을 것입니다. 눈에 띄는 차이는 없습니다.

그러나 나는 입력을 "알고있는"것에 대해 걱정할 것입니다. 당신은를 받아들이는 메소드를 가지고 있고 Object그것을 그렇게 취급해야합니다. 즉 , 인터페이스를 준수하는 것 외에는 매개 변수에 대해 아무것도 몰라Object합니다.toString() 메소드 . 이 경우 아무 것도 가정하는 대신 그 방법을 사용하는 것이 좋습니다.

OTOH 입력이있는 경우, 항상 하나 String또는 null단지 받아들이는 방법 변경 String들, 그리고 명시 적으로 확인 null(... 비 프리미티브를 처리 할 때마다 당신이 어쨌든해야하는)의


나는 내 질문에 가치있는 의미가 없다고 말했다 :) 나는 이론적으로 더 저렴한 것이 무엇인지 궁금 합니다. 어쨌든 고맙습니다
Vugluskr

비용은 VM이 가상 메서드 호출과 유형 검사에서 얼마나 효율적인지에 따라 달라집니다. 이는 구현에 따라 다릅니다.
Jon Skeet

2

참조 유형이 Object이고 모든 Object에 toString ()이있는 경우 object.toString ()을 호출하면됩니다. String.toString ()은 이것을 반환합니다.

  • toString ()은 입력 할 코드가 적습니다.
  • toString ()은 바이트 코드가 적습니다.
  • 캐스팅은 비용이 많이 드는 작업 대 다형성 호출입니다.
  • 캐스트가 실패 할 수 있습니다.
  • null이 아닌 경우 object.toString ()을 호출하는 String.valueOf (object)를 사용하십시오.

1

"o"에있는 것이 문자열이면 별다른 차이가 없습니다 (캐스트가 더 빠를 가능성이 있지만 VM / 라이브러리 구현 항목입니다).

"o"가 문자열이 아닐 수도 있지만 문자열이어야한다면 캐스트는 원하는 것입니다 (하지만 메서드가 객체 대신 문자열을 사용하도록해야합니다).

"o"가 모든 유형이 될 수 있다면 toString을 사용해야하지만 먼저 null을 확인해야합니다.

void foo(final Object o)
{
    final String str;

    // without this you would get a class cast exception
    // be wary of using instanceof though - it is usually the wrong thing to do
    if(o instanceof String)
    {
        str = (String)o;
    }    
}

또는

void foo(final Object o)
{
    final String str;

    // if you are 100% sure that o is not null then you can get rid of the else
    if(o != null)
    {
        str = o.toString();
    }
}

차라리 마지막 코드를 다음과 같이 코딩하고 싶습니다.

void foo(final Object o)
{
    final String str;

    if(o == null)
    {
        throw new IllegalArgumentException("o cannot be null");
    }

    str = o.toString();
}

처음 두 조각은 실제로 컴파일되지 않습니다 ( final변수가 초기화되지 않았을 수 있음). 당신은 필요 else하나 예외를 던지거나 초기화 것이다 str뭔가를.
Bruno Reis

1

이상하게도 캐스트가 tostring 호출이 암시하는 vtable 조회보다 느리다는 것을 발견했습니다.


1

'o에 널 문자열'이있을 수 없습니다. o가 널이면 널 문자열을 포함하지 않고 단지 널입니다. 먼저 null에 대해 o를 확인하십시오. null에서 ToString () 을 캐스트 하거나 호출하면 충돌이 발생합니다.


2
null 캐스팅은 충돌하지 않습니다. NullPointerException을 throw하지 않고 새 형식에 대해 null을 호출합니다. :)
Bombe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.