자바 제네릭 T 대 객체


127

다음 두 메서드 선언의 차이점이 무엇인지 궁금합니다.

public Object doSomething(Object obj) {....}

public <T> T doSomething(T t) {....}

하나는 할 수 있지만 다른 것은 할 수없는 일이 있습니까? 이 사이트의 다른 곳에서는이 질문을 찾을 수 없습니다.

답변:


112

문맥에서 분리됨-차이가 없습니다. 둘 다 tobj의 메서드 만 호출 할 수 있습니다 Object.

그러나 컨텍스트-일반 클래스가있는 경우 :

MyClass<Foo> my = new MyClass<Foo>();
Foo foo = new Foo();

그때:

Foo newFoo = my.doSomething(foo);

객체와 동일한 코드

Foo newFoo = (Foo) my.doSomething(foo);

두 가지 장점 :

  • 캐스팅 할 필요가 없습니다 (컴파일러가 이것을 숨 깁니다)
  • 작동하는 컴파일 시간 안전. Object버전이 사용되는 경우 메서드가 항상을 반환하는지 확인할 수 없습니다 Foo. 을 반환 Bar하면 ClassCastException런타임에.

14

여기서 차이점은 첫 번째에서 호출자가 Object 인스턴스 (모든 클래스)를 전달해야하며 다른 Object (같은 유형일 필요는없는 모든 클래스)를 반환하도록 지정한다는 것입니다.

두 번째로 반환되는 유형은 클래스가 정의되었을 때 제공된 유형과 동일합니다.

Example ex = new Example<Integer>();

여기서는 클래스 나 메서드에 더 많은 제약을 적용 할 수있는 T 유형을 지정합니다. 예를 들어 LinkedList<Integer>or 를 인스턴스화 할 수 LinkedList<Example>있으며 이러한 메서드 중 하나를 호출하면 Integer 또는 Example 인스턴스가 반환된다는 것을 알고 있습니다.

여기서 주요 목표는 호출 코드가이를 강제하기 위해 유형 캐스팅에 의존하는 대신 클래스가 작동 할 개체 유형을 지정할 수 있다는 것입니다.

Oracle의 Java Generics *를 참조하십시오 .

* 업데이트 된 링크.


13

차이점은 일반적인 메서드를 사용하면 캐스팅 할 필요가없고 잘못하면 컴파일 오류가 발생한다는 것입니다.

public class App {

    public static void main(String[] args) {

        String s = process("vv");
        String b = process(new Object()); // Compilation error
    }

    public static <T> T process(T val) {

        return val;
    }
}

객체를 사용하여 항상 캐스트해야하며 잘못했을 때 오류가 발생하지 않습니다.

public class App {

    public static void main(String[] args) {

        String s = (String)process("vv");
        String b = (String)process(new Object());
    }

    public static Object process(Object val) {

        return val;
    }
}

안드로이드 6
John Lord

2

추가 클래스 캐스팅을 수행 할 필요가 없습니다. 첫 번째 경우에는 항상 클래스로 캐스트해야하는 java.lang.Object 클래스의 객체를 얻게됩니다. 두 번째 경우 T는 일반 서명에 정의 된 클래스로 대체되며 클래스 캐스팅이 필요하지 않습니다.


2

런타임에는 아무것도 없습니다. 그러나 컴파일 타임에 두 번째는 유형 검사를 수행하여 매개 변수의 유형과 반환 값의 유형이 T 유형이 확인하는 모든 유형과 일치하는지 (또는 하위 유형인지) 확인합니다 (첫 번째 예제도 유형 검사를 수행하지만 모든 개체는 Object의 하위 유형이므로 모든 유형이 허용됩니다).


2

T는 일반 유형입니다. 이는 런타임에 모든 한정된 객체로 대체 될 수 있음을 의미합니다. 다음과 같이 이러한 메서드를 호출 할 수 있습니다.

String response = doSomething("hello world");

또는

MyObject response = doSomething(new MyObject());

또는

Integer response = doSomething(31);

보시다시피 여기에는 다형성이 있습니다.

그러나 Object를 반환하도록 선언 된 경우에는 cast things를 입력하지 않으면이를 수행 할 수 없습니다.


<T>오토 박싱이 없다고 말할 수 있습니까 ?
SMUsamaShah

0

첫 번째 경우에는 egstring 유형의 매개 변수를 취하고 foo 유형을 리턴합니다. 두 번째 경우에는 foo 유형의 매개 변수를 취하고 foo 유형의 객체를 반환합니다.


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