2016-09-18 2 views
0

나는 일반적인 것을 이해한다고 생각했지만 정말 미안하다. 나에게 수치 스럽다.T는 매개 변수 유형 또는 클래스 유형입니까?

List <Integer> l1 = Arrays.asList(new Integer[]{1,2,3}); 
Gen.c(l1); 
Gen.d(l1); 

복귀 동일한 출력 [1,2,3]

만큼 두

public static <T> void c(T obj) { 
    System.out.println(obj.toString()); 
} 

public static <T> void d(List<T> obj) { 
    System.out.println(obj.toString()); 
} 

차이는 무엇

List<T> obj는 T obj와 동일하게 동작합니다.

T는 매개 변수 유형 또는 유형/개체 유형을 나타냅니다.

+2

왜 다르게 행동 할 것이라고 기대합니까? 두 경우 모두 목록에서 toString을 호출합니다. C에서는 T 형 객체에 대해 호출하고 있습니다.이 객체는 목록입니다. d에서는 목록으로 전달 된 목록에서이 함수를 호출합니다. –

+0

이 예제의 문제점은 제네릭이 실제로 작동하지 않아도된다는 것입니다 (매개 변수 유형을'Object'로 간단하게 만들 수 있음). 그래서 왜 다른지를 알기 어렵습니다. 'List '가 아닌'd'를 전달하려고하면 작동하지 않지만'c'는 작동 할 것입니다. –

+0

안녕하세요, 고마워요, 그 논쟁 자체가 다르다는 것을 말해 줄 수있는 방법이 있습니까? –

답변

2

c의 경우 T은 목록을 포함하는 모든 항목이 될 수 있습니다. 그러나 Java가 무엇인지 모르기 때문에 목록에서 특정 작업을 수행 할 수 없습니다.

d의 경우 T은 목록이어야합니다. Java가 무엇인지 알고 있기 때문에 추가 및 제거 등의 작업을 수행 할 수 있습니다.

1

<T><T extends Object과 동일합니다. 따라서 TObject에서 연장되는 모든 항목이 될 수 있습니다. 모든 항목은 Java입니다. 예를 들어 <T extends Animal>으로 작성한 다음 Animal의 모든 내용을 넣을 수 있습니다 (예 : Cat 또는 Dog). 중요한 것은 메소드 안에는 Animal의 일부 유형 만 있다는 것입니다. 따라서 메서드에 Dog 개체를 지정해도 Cat 또는 Dog 메서드를 사용할 수 없습니다. 방법은 Animal입니다.

실제로 이것은 casting과 같이 지정된 객체에 대한보기 만 제한합니다. 다음 예를 참조하십시오.

Dog dog = new Dog(); 
dog.bark(); // Works as it is a dog 
Animal dogAsAnimal = (Animal) dog; 
dogAsAnimal.bark(); // Does not compile, dogAsAnimal is restricted to Animal though it is a Dog 

귀하의 예에서도 마찬가지입니다. c 메서드는 Object에서 확장되는 T을 허용하므로 모든 객체는 Java입니다. d 메서드는 List<T> 유형의 개체를받습니다. 이들은 유형의 요소 만 포함하는 객체입니다 (T). 다시 T은이 경우 T extends Object을 의미합니다. 따라서 d은 을 포함하는 List을 허용합니다.

제네릭의 이점은 무엇입니까? 수정 유형 T에서만 작동하도록 오브젝트를 제한 할 수 있습니다. T은 임의적 일 수 있지만 한번 선택하면 해결됩니다.
Javas List 클래스를 살펴보십시오. 제네릭을 사용하기 전에 CatsDogs과 같은 내용을 List 안에 넣을 수 있습니다.너 DogsLists에만 허용하려면 DogList implements List 클래스를 특수화해야합니다. 이제 하나의 List 클래스를 코딩하여 하나의 변수 T으로 제한 할 수 있습니다.

List<Dog> dogList = new LinkedList<Dog>(); 
dogList.add(new Dog()); // Works fine 
dogList.add(new Cat()); // Does not compile, Cat is no Dog 
List<Animal> animalList = new LinkedList<Animal>(); 
animalList.add(new Dog()); // Works 
animalList.add(new Cat()); // Also works 

을하지만 우리는 단지 하나 개의 코드 클래스 사용 :이 예를 살펴 LinkedList을. LinkedList이 일반이므로 다른 클래스를 코딩 할 필요가 없으며 LinkedList<T>을 사용할 수 있습니다.

또 다른 예 : 우리는 AnimalList을 코딩하고 싶지만 사용자가 Dog 같은 수정 AnimalAnimalList을 제한 할 수있을 것이다. 그래서 그는 Cats을 받아들이지 않는 AnimalList을 사용할 수 있습니다.
우리는 클래스를 코딩하여 수행 : public class AnimalList<T extends Animal> extends LinkedList<T>

// Only dogs can be added 
AnimalList<Dog> dogList = new AnimalList<Dog>(); 

// Not possible as String does not extend from Animal 
AnimalList<String> strangeList = new AnimalList<String>(); 

그런데, AnimalList 우리의 요소 유형 T에서있는 클래스의 내부. T extends Animal과 같이 이러한 객체는 Animal의 모든 메소드에 대한 액세스를 제공합니다. 예를 들어, AnimalListisEveryoneAlive() 같은 방법을 가질 수있다, 그것은 다음과 같을 수 있습니다 :

당신이 볼
public boolean isEveryoneAlive() { 
    for (T animal : getAllElements()) { 
     if (!animal.isAlive()) { 
      return false; 
     } 
    } 
    return true; 
} 

animalAnimal에서 확장 유형 T,이다. 따라서 우리는 방법 Animal#isAlive에 접근 할 수 있습니다.

관련 문제