2016-07-16 7 views
1

제네릭 (Java)에서 바운드 형식 매개 변수를 사용하고 있습니다.기본적으로 자식 클래스 개체를 수락하는 경우 제한된 형식의 매개 변수를 제네릭으로 사용하는 이유는 무엇입니까?

class First<T extends Use>{ 
    T s; 
    First(T s){ 
     this.s=s; 
    } 
    void setS(T s){ 
     this.s=s; 
    } 
    void getS(){ 
     System.out.println(s); 
    } 
} 

class UseChild extends Use{ 
    public String toString(){ 
     return "I am UseChild"; 
    } 
} 

class Use{ 
    public String toString(){ 
     return "I am Use"; 
    } 
    public static void main(String[] args){ 
     First <Use> f1 = new First <Use> (new Use()); 
     f1.getS(); 
     f1.setS(new UseChild()); 
     f1.getS(); 
    } 
} 

출력은 다음의 확인 지금까지

I am Use 
I am UseChild 

. "T extends Use"가 Type 매개 변수에 있기 때문에 setS()에 자식 클래스 객체를 전달할 수 있다고 생각했습니다. 그렇지 않으면 I could not.

class First<T> 
{ 
//Same code as above 
} 

내 의심은 다음과 같습니다 : 내가 설정에 자식 클래스 개체를 전달할 수 있다면 무엇에 대한 특별한 것은 키워드를 확장()없이

하지만하지 않고 형식 매개 변수를 사용하고있는 경우 출력은 동일 같이 키워드를 확장 키워드를 확장합니까?

답변

0

여기서 <T extends Use>은 제한 사항의 역할을합니다. 이 유형은 Use 유형 또는 Use 유형의 오브젝트 만 전달할 수 있음을 지정합니다.

<T>으로 변경하면 <T extends Object>과 동일합니다. 즉, 모든 개체를 전달할 수 있습니다.

차이점은 First<T> 인 경우 어떤 객체라도 전달할 수 있습니다 (예 : LinkedList 또는 JFrame). First<T extends Use>을 사용하면 Use 유형 또는 Use 유형의 오브젝트 만 전달할 수 있습니다.

매우 유용한 한 가지 방법은 유형 Use에 클래스 First을 사용하려는 특정 방법이있는 경우입니다. 이 경우 FirstUse 클래스의 메서드와 속성을 인식하도록 <T extends Use>을 지정해야합니다.

+0

감사합니다.하지만 나는 다른 의심을 가지고 있습니다. 처음으로 어떤 물건이라도 건네 줄 수 있습니다. 하지만 클래스 f1의 객체를 이미 통과 시켰습니다. 이 type 매개 변수 컴파일러 인 경우 주어진 f1에 UseChild 객체가 아닌 Use 객체 만 허용해야합니다. 매개 변수 유형이 이면 둘 다 허용 될 수 있습니다. –

+0

@mynameisGYAN'UseChild'는 객체이므로 type 매개 변수가 ''일 때 전달 될 수 있습니다. 'Use'를 확장하지만'Use'도'Object'를 확장합니다 (모든 객체가 확장). 그래서 간접적으로'UseChild'는'Object'를 상속합니다. 따라서 type 매개 변수가 ''일 때 전달 될 수 있습니다. – nhouser9

+0

내가 틀릴 수도 있지만, 내가 얻는 것은 : f1 = new First (). f1.setS (new Integer (10))는 컴파일러 오류입니다. 그래서 f1.setS (new UseChild())는 T가 타입 파라미터에서 Use를 확장하지 않으면 컴파일러 에러가되어야합니다. –

1

의이 Use이 (대신 최우선 toString의) 새로운 방법을 정의한다고 가정 해 봅시다 :

class Use { 
    ... 
    public void printMe() { // Some nonsensical method for demonstration 
     System.out.println("printing Use"); 
    } 
} 

당신이 First 클래스에서이 메소드를 호출 할 수 있도록 할이 바운드 :

class First<T extends Use> { 
    T s; 
    ... 
    public void getS() { 
     s.printMe(); // not possible without the bound. 
    } 
} 

당신이 First을 사용하고 있다면, 제네릭이 전혀 필요하지 않습니다. 유형 Use 대신 T의를 사용하여 동일하게 작동합니다 :

class First { 
    Use s; 
    First(Use s) { 
     this.s = s; 
    } 
    void setS(Use s) { 
     this.s = s; 
    } 
    void getS() { 
     System.out.println(s); 
    } 
} 

출력은 동일 할 것이다.

0

일반 클래스의 유형 매개 변수 (T)는 유형 인수와 유형 인수의 하위를 허용합니다. type-argument로 Use를 사용하여 First 클래스의 객체가 생성 되더라도 UseSild의 객체를 setS()에 전달할 수 있습니다. UseChild는 Use 하위 클래스이기 때문입니다. 따라서 다음 문장은 함께 사용하면 완벽하게 유효합니다.

First<Use>f = new First<Use>(new Use()); 
f.setS(newUseChild()); 

제한된 유형과 제한되지 않은 유형의 차이점은 질문에 언급 된 내용과 다릅니다.실제 차이는 다음과 같습니다.

경계 형을 사용하지 않으면 T는 Object를 확장하고 s는 객체 유형의 참조 변수가됩니다.

import java.lang.reflect.*; 
class First<T> 
{ 
     T s; 
     First(T s) 
     { 
       this.s=s; 
     } 
     void setS(T s) 
     { 
       this.s=s; 
     } 
     void getS() 
     { 
       Field[] flds = this.getClass().getDeclaredFields(); 
       for(Field f:flds) 
       { 
         String name = f.getName(); 
         String type = f.getType().getName(); 
         int i = f.getModifiers(); 
         String modifier = Modifier.toString(i); 
         System.out.println("Name = "+name+" type= "+type); 
       } 
       System.out.println(s.getClass().getName()); 
     } 
    } 

출력은 다음과 같습니다 :

Name = s type= java.lang.Object 
Use 

그래서 T는 java.lang.Object 상위를 확장

class Use 
{ 
     public String toString() 
     { 
       return "I am Use"; 
     } 
     public void call() 
     { 
       System.out.println("I am call of Use"); 
     } 
     public static void main(String[] args) 
     { 
       First <Use> f1 = new First <Use> (new Use()); 
       f1.getS(); 
     } 
} 

클래스 최초의 다양한 분야를 확인할 수 있습니다. s는 java.lang.Object 유형의 참조 변수입니다. 변수를 사용하여 특정 메소드 사용을 호출 할 수 없습니다.

먼저 제한된 유형의 클래스의 다양한 분야를 확인할 수 있습니다 :

import java.lang.reflect.*; 
class First<T extends Use> 
{ 
     T s; 
     First(T s) 
     { 
       this.s=s; 
     } 
     void setS(T s) 
     { 
       this.s=s; 
     } 
     void getS() 
     { 
       Field[] flds = this.getClass().getDeclaredFields(); 
       for(Field f:flds) 
       { 
         String name = f.getName(); 
         String type = f.getType().getName(); 
         int i = f.getModifiers(); 
         String modifier = Modifier.toString(i); 
         System.out.println("Name = "+name+" type= "+type); 
       } 
       System.out.println(s.getClass().getName()); 
     } 
    } 

출력은 다음과 같습니다

Name = s type= Use 
Use 

는 이제 T 대신 java.lang.Object 상위의, 사용 확장합니다. s는 Use 유형의 참조 변수입니다. @ jorn vernee가 말했듯이 이제 우리는 First from Use라는 특정 메소드를 호출 할 수 있습니다.