[java] 자바 제네릭 T 대 객체

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

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

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

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



답변

문맥에서 분리됨-차이가 없습니다. 둘 다 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런타임에.

답변

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

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

Example ex = new Example<Integer>();

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

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

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

* 업데이트 된 링크.


답변

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

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;
    }
}


답변

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


답변

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


답변

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

String response = doSomething("hello world");

또는

MyObject response = doSomething(new MyObject());

또는

Integer response = doSomething(31);

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

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


답변

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