instanceof 대 getClass ()


114

내가 사용하는 경우 성능을 얻을 참조 getClass()==이상 연산자 instanceOf연산자.

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("its string");
} else {
    if (str instanceof Integer) {
        System.out.println("its integer");

    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("its string in equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("its integer");
    }
}

System.out.println((System.nanoTime()-starttime));

어떤 가이드 라인 하나를 사용할 수 있는가 getClass()또는 instanceOf?

시나리오가 주어지면 : 일치해야 할 정확한 클래스, 즉 String, Integer(이것들은 최종 클래스입니다) 등을 알고 있습니다 .

instanceOf운영자가 나쁜 습관을 사용 하고 있습니까?


3
이것은 stackoverflow.com/questions/596462/…에 설명되어 있습니다.
Clement P

2
타이밍 방법으로 인해 인위적인 지연이 발생하고 잘못된 타이밍 결과가 생성됩니다. 수표를 수행하는 순서를 바꾸면 첫 번째 수표 (== 또는 instanceof)가 항상 더 길다는 것을 알 수 있습니다. 나는 그것이 println () s라고 생각한다. 타이밍 블록에 그 내용을 포함해서는 안됩니다.
kurtzmarc

하나의 주석 만 따로두고 성능을 비교하려면 정확도를 높이기 위해 여러주기 반복 (예 : 10000)을 사용하십시오. 한 번의 호출은 좋은 측정이 아닙니다.
martins.tuga 2010 년

답변:


140

instanceof과 의 성능 getClass() == ...이 다른 이유 는 서로 다른 일을하고 있기 때문입니다.

  • instanceof왼쪽 (LHS)의 객체 참조가 오른쪽 (RHS) 유형의 인스턴스 인지 아니면 일부 하위 유형 인지 테스트합니다 .

  • getClass() == ... 유형이 동일한 지 테스트합니다.

따라서 권장 사항은 성능 문제를 무시하고 필요한 답변을 제공하는 대안을 사용하는 것입니다.

instanceOf운영자를 사용하는 것이 나쁜 습관입니까?

반드시 그런 것은 아닙니다. 과용 instanceOf또는 "디자인 냄새" getClass() 일 수 있습니다 . 주의하지 않으면 새 하위 클래스를 추가하면 상당한 양의 코드 재 작업이 발생하는 디자인이됩니다. 대부분의 상황에서 선호되는 접근 방식은 다형성을 사용하는 것입니다.

그러나 이것이 "디자인 냄새"가 아닌 경우가 있습니다. 예를 들어, equals(Object)인수의 실제 유형을 테스트하고 false일치하지 않으면 반환 해야합니다. 이것은 getClass().


"모범 사례", "나쁜 사례", "디자인 냄새", "반 패턴"등과 같은 용어는 아껴서 사용하고 의심스럽게 다루어야합니다. 그들은 흑백 사고를 장려합니다. 순전히 교리에 근거하는 것보다 맥락에서 판단을 내리는 것이 좋습니다. 예를 들어 누군가가 말한 것이 "모범 사례"입니다.


@StephenC 말했듯이 code smell둘 중 하나를 사용하는 것입니다. 즉, 둘 중 하나를 사용하게 만드는 잘못된 디자인 (비다 형성) 코드의 결과입니다. 이 방법 중 하나의 사용법을 추론 할 수 있습니까?
overexchange

@overexchange-1) "사용"이 아니라 "과용"이라고 말했습니다. 2) 그 외에는 당신이 요구하는 것을 이해하지 못합니다. "용도 추론 ..."이란 무엇을 의미합니까 ??? 코드는 이러한 것들을 사용하거나 사용하지 않습니다.
Stephen C

기존의 잘못된 코드 설계 (비다 형성)로 인해 instanceof&의 사용이 getClass()그림으로 나왔다고 추론합니다 . 나 맞아?
overexchange

5
@overexchange- instanceof예를 들어 모든 사용 이 잘못된 디자인 이라고 정당하게 추론 할 수 없습니다 . 최상의 솔루션이 될 수있는 상황이 있습니다. 동일에 대한 getClass(). 나는 내가 "남용"이 아니라 " 남용" 이라고 말한 것을 반복 할 것이다 . 모든 사건은 근거없는 독단적 규칙을 맹목적으로 적용하는 것이 아니라 그 장점으로 판단되어야합니다.
Stephen C

44

클래스를 정확히 일치 시키 시겠습니까? 예를 들어, FileInputStream의 하위 클래스 대신 일치 만 FileInputStream하시겠습니까? 그렇다면 getClass()==. 저는 일반적으로에서이 작업을 수행 equals하므로 X의 인스턴스가 X의 하위 클래스의 인스턴스와 같지 않은 것으로 간주됩니다. 그렇지 않으면 까다로운 대칭 문제가 발생할 수 있습니다. 반면에 두 개체가 특정 클래스보다 같은 클래스 라는 것을 비교하는 데 일반적으로 더 유용합니다 .

그렇지 않으면 instanceof. 에 있습니다 getClass()당신은 당신이 시작하는 null 이외의 참조를 가지고 있는지 확인해야합니다, 또는 당신이를 얻을 수 있습니다 NullPointerException반면, instanceof단지 리턴 false첫 번째 피연산자가 null 인 경우.

개인적 instanceof으로 더 관용적 이라고 말하고 싶지만 둘 중 하나 를 광범위하게 사용 하는 것은 대부분의 경우 디자인 냄새입니다.


18

이 질문을받은 지 오랜만이라는 것을 알고 있지만 어제 대안을 배웠습니다.

우리 모두는 당신이 할 수있는 일을 알고 있습니다 :

if(o instanceof String) {   // etc

하지만 어떤 종류의 수업이 필요한지 정확히 모른다면 어떨까요? 일반적으로 다음을 수행 할 수 없습니다.

if(o instanceof <Class variable>.getClass()) {   

컴파일 오류가 발생합니다.
대신, 여기에 대안이 있습니다-isAssignableFrom ()

예를 들면 :

public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {

    return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
}

8
사용하지 마십시오 isAssignableFrom. o instanceof String리플렉션을 사용하여 작성 하는 올바른 방법 은 String.getClass().isInstance(o). javadoc은 이렇게 말합니다. 이 메소드는 Java 언어 instanceof연산자 와 동적 인 동등합니다 .
Andreas

3

getClass ()에는 아래 코드의 출력에 설명 된대로 객체가 동일한 클래스, 동일한 런타임 유형의 다른 객체와 만 동일하다는 제한이 있습니다.

class ParentClass{
}
public class SubClass extends ParentClass{
    public static void main(String []args){
        ParentClass parentClassInstance = new ParentClass();
        SubClass subClassInstance = new SubClass();
        if(subClassInstance instanceof ParentClass){
            System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
        }
        if(subClassInstance.getClass() != parentClassInstance.getClass()){
            System.out.println("Different getClass() return results with subClassInstance and parentClassInstance ");
        }
    }
}

출력 :

SubClass는 ParentClass를 확장합니다. subClassInstance는 instanceof ParentClass입니다.

다른 getClass ()는 subClassInstance 및 parentClassInstance와 함께 결과를 반환합니다.

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