2016-07-16 5 views
1

Я использую параметры ограниченного типа в generic (JAVA).Зачем использовать параметры ограниченного типа в generic, если он принимает объект дочернего класса по умолчанию?

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 

До сих пор его нормально. Я думал, что могу передать дочерний объект класса setS(), потому что «T extends Use» присутствует в параметре «Тип», иначе я не смог.

Но выход такой же, если я использую тип-параметр не распространяется ключевое слово как:

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. В этом случае вам нужно будет указать <T extends Use>, так что First будет знать методы и свойства класса Use.

+0

Спасибо .. Но у меня разные сомнения. Впервые я могу передать любой объект. Но я уже передал объект класса Use для переменной f1. Если - это компилятор типа-параметра, то для данного f1 должен использовать объект Использовать объект не UseChild. Если параметр типа , то оба могут быть разрешены. –

+0

@mynameisGYAN 'UseChild' - это объект, поэтому его можно передать, когда параметр типа« ». Он расширяет 'Use', но' Use' также расширяет 'Object' (все объекты делают). Поэтому косвенно 'UseChild' расширяет' Object', поэтому его можно передать, когда параметр типа ''. – nhouser9

+0

Может быть, я ошибаюсь, но то, что я получаю, это: First f1 = new First (). f1.setS (new Integer (10)) - ошибка компилятора. Таким образом, f1.setS (new UseChild()) также должен быть ошибкой компилятора, если T не расширяет использование в параметре типа. –

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

Параметр Type (T) любого общего класса принимает аргументы типа-аргумента и дочерние элементы типа. Мы можем передать объект UseChild в setS(), даже если объект класса First создан с использованием Use as type-argument. Поскольку UseChild является дочерним классом Use. Поэтому следующие утверждения совершенно справедливы вместе:

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

Разница между ограниченными и неограниченными типов не так, как указано в этом вопросе.Фактическая разница между обсуждается ниже:

Если мы не используем ограниченный тип, то T расширяет Object, а s становится ссылочной переменной типа объекта.

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

Позволяет проверить различные поля класса First:

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. s является ссылочной переменной типа java.lang.Object. Мы не можем вызывать использование специальных методов с помощью переменной s.

Позволяет проверить различные поля класса С первых ограниченного типа:

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.