8 Replies Latest reply: Jun 16, 2010 9:59 AM by 843793 RSS

    Why does <T extends Integer> not allow int

    843793
      I am experimenting with Generics and I have the following problem:

      When I use <T extends Number> I can simply use an integer (123). When I use <T extends Integer> the compiler gives the following message:

      cannot find symbol
      symbol : method valueOf(int)
      location: bound of type variable T
      System.out.println(tst.test(123));

      Code that compiles correctly:
      class ExperimentClass<T> {
      
          <T extends Number> Integer test(T type) {
              return (Integer) type;
          }
      
          public static void main(String[] args) {
      
              ExperimentClass<Integer> tst = new ExperimentClass<Integer>();
              System.out.println(tst.test(123));
          }
      }
      Code that gives a compilation error:
      class ExperimentClass<T> {
      
          <T extends Integer> Integer test(T type) {
              return (Integer) type;
          }
      
          public static void main(String[] args) {
      
              ExperimentClass<Integer> tst = new ExperimentClass<Integer>();
              System.out.println(tst.test(123));
          }
      }
      I thought that the bounds set by "..extends Integer" also includes int or am I wrong?
        • 1. This Thread is now moved
          791266
          Note: This thread was originally posted in the [New To Java|http://forums.sun.com/forum.jspa?forumID=54] forum, but moved to this forum for closer topic alignment.
          • 2. Re: Why does <T extends Integer> not allow int
            843793
            Godefridus wrote:
            I thought that the bounds set by "..extends Integer" also includes int or am I wrong?
            You are wrong. There is no reason why "... extends Integer" should include int.

            First of "T extends Integer" means that T can be Integer or any type that extends from Integer. Since Integer is a final class, no type can extends Integer, so it can only be Integer.

            "int" is not a reference type, so it's not part of any hierarchy whatsoever: it doesn't extend any class, not even Object and no class (or type) can possibly extend int.

            Generic type arguments can't ever reference primitive types.

            However, autoboxing can make an int look like an Integer:
            public void myIntegerMethod(Integer foo) {
              System.out.println("myIntegerMethod called with " + foo);
            }
            
            // ... later on ...
            int myInt = 3;
            myIntegerMethod(myInt);
            Here the int value will automagically converted into a corresponding Integer object.

            The combination of those two features, however, doesn't always play as nice as possible.

            If you have a method that could take an Integer and try to pass it an int, then Java will complain. You can usually fix that by telling Java to call the Integer variation of the method like this:
            tst.<Integer>test(123);
            • 3. Re: Why does <T extends Integer> not allow int
              843793
              JoachimSauer wrote:
              If you have a method that could take an Integer and try to pass it an int, then Java will complain.
              That doesn't explain why it works for <T extends Number>, where type could actually not be an Integer, but not for <T extends Integer>, where type has to be an Integer.

              By the way, the Eclipse compiler handles this fine, and when it comes to Generics, if Eclipse and javac disagree, there's about a 99% chance that Eclipse is more correct (or at least, more accepting without deviating from the spec).

              Edited by: endasil on 16-Jun-2010 10:27 AM
              • 4. Re: Why does <T extends Integer> not allow int
                791266
                @Op.

                Note that T in <T extends Integer> hides the T in ExperimentClass<T>.

                This will compile with the Sun compiler. Note that your orignal code compiles without any changes if you are using the Eclipse compiler.
                class ExperimentClass<T> {
                 
                    <E extends Integer> Integer test(T type) {
                        return (Integer) type;
                    }
                 
                    public static void main(String[] args) {
                 
                        ExperimentClass<Integer> tst = new ExperimentClass<Integer>();
                        System.out.println(tst.test(123));
                    }
                }
                • 5. Re: Why does <T extends Integer> not allow int
                  791266
                  ... or this (again with the Sun compiler), depending on what you actually wanted to do:
                  class ExperimentClass<T> {
                   
                      <E extends Integer> Integer test(E type) {
                          return (Integer) type;
                      }
                   
                      public static void main(String[] args) {
                   
                          ExperimentClass<Integer> tst = new ExperimentClass<Integer>();
                          System.out.println(tst.test(Integer.valueOf(123)));
                      }
                  }
                  • 6. Re: Why does <T extends Integer> not allow int
                    843793
                    kajbj wrote:
                    @Op.

                    Note that T in <T extends Integer> hides the T in ExperimentClass<T>.
                    Ah, there it is. It's still really weird though. I can't figure out what's going through the Sun compiler's "mind" even with that collision.
                    • 7. Re: Why does <T extends Integer> not allow int
                      843793
                      Many thanks to all of you! Your answer clarified a lot for me.

                      rgds,
                      godefridus
                      • 8. Re: Why does <T extends Integer> not allow int
                        843793
                        >
                        If you have a method that could take an Integer and try to pass it an int, then Java will complain. You can usually fix that by telling Java to call the Integer variation of the method like this:
                        tst.<Integer>test(123);
                        Could You provide an example?