12 Replies Latest reply: Sep 14, 2009 1:31 PM by jschellSomeoneStoleMyAlias RSS

    generics

    807580
      hi,
      while definng:
      class Cell<T>
      {
           private T value;
           public T get(){ return value;}
           public void set(T param){value = param;}
           private String toString(Integer i){return value.toString();}
           private String toString(Object i){return "ha-ha-ha";}
           public String toString(){return value.toString();}
           public String print(){return toString(value);}
      }
       
       public class Fruit{
            public static void main ( String[] args ) 
            {
                 Cell<Integer> i = new Cell<Integer>();
                 i.set(2);
                 String s = i.print();
                 System.out.print(s);
            }
       }
      The "ha0ha-ha" is printed...
      And indeed the runtime value type is Object...So,how value.toString() prints the correct value(2)?
      (While executing this value type is Object also)

      Thank you in advance
        • 1. Re: generics
          807580
          Because, although at compile time T is effectively equivalent to Object, if there's actually an Integer then the overloaded toString() of integer will be the one called. The method signatures are selected at compile time but, as far as instance methods are concerned, the specific implementation of that signature that gets called depends on the actual object class at run time.

          You'd get exactly the same thing if your class wasn't generic.
          • 2. Re: generics
            807580
            The actual type of 'value' while runtime is Object!(as was checked in toString)[Java generics runtime type doesn`t correspond to instantianated type,but due to erasure is Object)
            Instantianated typeis is known only while compiling and the annotation for the type is created.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
            • 3. Re: generics
              807580
              No, the reference type is Object, but the referenced object is of type Integer, and that's what controls the choice of toString() method.
              • 4. Re: generics
                807580
                Hi,
                The books write differently....I don`t want to argue - just to understand...
                Please take a look: at OReilly.Java.Generics.and_Collections

                Copied from the book:
                import java.util.*;
                public abstract class AbstractList<E>
                  extends AbstractCollection<E> implements List<E>
                {
                  public boolean equals(Object o) {
                    if (o instanceof List<E>) {  // compile-time error
                      Iterator<E> it1 = iterator();
                      Iterator<E> it2 = ((List<E>)o).iterator();  // unchecked cast
                      while (it1.hasNext() && it2.hasNext()) {
                        E e1 = it1.next();
                        E e2 = it2.next();
                        if (!(e1 == null ? e2 == null : e1.equals(e2)))
                          return false;
                      }
                      return !it1.hasNext() && !it2.hasNext();
                    } else return false;
                  }
                  ...
                }
                Again, the equality method takes an argument of type Object, checks whether the object is an instance of type List<E>, and, if so, casts it to List<E> and compares corresponding elements of the two lists. This code does not work because List<E> is not a reifiable type: some of the information needed to check whether an object is an instance of List<E> is not available at run time. You can test whether an object implements the interface List, but not whether its type parameter is E. Indeed, information on E is missing doubly, as it is not available for either the receiver or the argument of the equals method.

                Edited by: bil050 on Sep 14, 2009 6:28 AM
                • 5. Re: generics
                  Puce
                  Try:
                  package testproject;
                  
                  public class Main<E> {
                  
                      /**
                       * @param args the command line arguments
                       */
                      public static void main(String[] args) {
                          // TODO code application logic here
                      }
                  
                      public String toString(E value){
                          return value.toString();
                      }
                  
                      public String toString(Object value){
                          return value.toString();
                      }
                  }
                  You will get the compilation error:

                  [..]\testproject\Main.java:25: toString(E) is already defined in testproject.Main
                  public String toString(Object value){                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
                  • 6. Re: generics
                    807580
                    bil050 wrote:
                    Hi,
                    The books write differently....I don`t want to argue - just to understand...
                    No, that's a different issue again. The compiler erases the generic type. Effectively it compiles
                    T value;
                    as if it were
                    Object value;
                    (Actually the real reference type will be the "lower bound" of the type variable if you'd declared <T extends Number> it would be of type Number).

                    Generics basically doesn't change the code, it just does a lot of checks source code checks and inserts some type casts.

                    However you set
                    value = Integer.valueOf(someNumber);
                    So when you do value.toString() you get the Integer version of toString(), it's no different from if you had actually declared value as Object.
                    • 7. Re: generics
                      807580
                      Puce wrote:
                      Try:
                      package testproject;
                      
                      public class Main<E> {
                      
                      /**
                      * @param args the command line arguments
                      */
                      public static void main(String[] args) {
                      // TODO code application logic here
                      }
                      
                      public String toString(E value){
                      return value.toString();
                      }
                      
                      public String toString(Object value){
                      return value.toString();
                      }
                      }
                      You will get the compilation error:

                      [..]\testproject\Main.java:25: toString(E) is already defined in testproject.Main
                      public String toString(Object value){
                      Yes,it due to erasure - two methods toString with the same signature :
                       public String toString(Object value)
                      • 8. Re: generics
                        807580
                        No, that's a different issue again. The compiler erases the generic type. Effectively it compiles
                        T value;
                        as if it were
                        Object value;
                        (Actually the real reference type will be the "lower bound" of the type variable if you'd declared <T extends Number> it would be of type Number).

                        Generics basically doesn't change the code, it just does a lot of checks source code checks and inserts some type casts.

                        However you set
                        value = Integer.valueOf(someNumber);
                        So when you do value.toString() you get the Integer version of toString(), it's no different from if you had actually declared value as Object.
                        Ok,This answer was very helpful
                        • 9. Re: generics
                          Puce
                          >
                          Yes,it due to erasure - two methods toString with the same signature :
                           public String toString(Object value)
                          So, then you agree, that
                          toString(E value)
                          is the same method as
                          toString(Object value)

                          and that
                          E e;
                          toString(e);

                          will pick toString(Object) ?
                          • 10. Re: generics
                            807580
                            May be in this tread I can ask additional question ,regarding the code I have added before
                            In this code I tried to implement copyTo method ,which as I understand has to obtain contravariant parametr
                            so the code is:
                             class Cell<T>
                            {
                                 private T value;
                                 public T get(){ return value;}
                                 public void set(T param){value = param;}
                                 private String toString(Integer i){return value.toString();}
                                 private String toString(Object i){return "ha-ha-ha";}
                                 public String print(){return toString(value);}
                                 void copyTo(Cell<? super T> to)
                                 {
                                      to.set(value);
                                 }
                                 
                            }
                             class Base
                             {
                                protected int x;
                                public void set(int _x){x = _x;}
                             }
                             class Derived extends Base{
                                  private int y;
                                  public void set(int _y){super.set(6);y = _y;}
                             }
                             
                             public class Fruit{
                                  public static void main ( String[] args ) 
                                  {
                                       Base b_param = new Base();b_param.set(2);
                                       Derived d_param = new Derived();d_param.set(8);
                                       
                                       Cell<Base> b = new Cell<Base>();b.set(b_param);
                                       Cell<Derived> d = new Cell<Derived>();d.set(d_param);
                                       
                                       d.copyTo(b);
                                       b.print();
                                       
                                       //Cell<Integer> i = new Cell<Integer>();
                                       //Cell<Object> o = (Cell<Object>) i;
                                       //i.set(2);
                                       //String s = i.print();
                                       //System.out.print(s);
                                  }
                             }
                            But hole d is copied to b ...b gets bigger tan defined.How I implement it correctly?
                            Thank you!
                            • 11. Re: generics
                              807580
                              >
                              So, then you agree, that
                              toString(E value)
                              is the same method as
                              toString(Object value)
                              Yes - it`s erasure
                              and that
                              E e;
                              toString(e);

                              will pick toString(Object) ?
                              Sure E e -will be compiled to Object e
                              • 12. Re: generics
                                jschellSomeoneStoleMyAlias
                                Note - there is a forum specifically for questions about generics.