Why does this use of Generics not throw a runtime or compile time exception?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite
1












I've got a method in a class that has a return type specified by use of a generic.



public class SomeMain 

public static void main(String args)

Foo<Integer> foo = new Foo<Integer>();
System.out.println(foo.getFoo()); // Works, prints out "Foo"



public static class Foo<E>
public E getFoo()
return (E) "Foo";





With the generic return type, I assumed the return in the above example would evaluate to:



return (Integer) "Foo"; // Inconvertible types !!!


Instead a String is returned and printed correctly.



I get a compilation error if I change the call to be:



String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);


What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.










share|improve this question



























    up vote
    6
    down vote

    favorite
    1












    I've got a method in a class that has a return type specified by use of a generic.



    public class SomeMain 

    public static void main(String args)

    Foo<Integer> foo = new Foo<Integer>();
    System.out.println(foo.getFoo()); // Works, prints out "Foo"



    public static class Foo<E>
    public E getFoo()
    return (E) "Foo";





    With the generic return type, I assumed the return in the above example would evaluate to:



    return (Integer) "Foo"; // Inconvertible types !!!


    Instead a String is returned and printed correctly.



    I get a compilation error if I change the call to be:



    String fooString = foo.getFoo(); // Compile error, incompatible types found
    System.out.println(fooString);


    What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.










    share|improve this question

























      up vote
      6
      down vote

      favorite
      1









      up vote
      6
      down vote

      favorite
      1






      1





      I've got a method in a class that has a return type specified by use of a generic.



      public class SomeMain 

      public static void main(String args)

      Foo<Integer> foo = new Foo<Integer>();
      System.out.println(foo.getFoo()); // Works, prints out "Foo"



      public static class Foo<E>
      public E getFoo()
      return (E) "Foo";





      With the generic return type, I assumed the return in the above example would evaluate to:



      return (Integer) "Foo"; // Inconvertible types !!!


      Instead a String is returned and printed correctly.



      I get a compilation error if I change the call to be:



      String fooString = foo.getFoo(); // Compile error, incompatible types found
      System.out.println(fooString);


      What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.










      share|improve this question















      I've got a method in a class that has a return type specified by use of a generic.



      public class SomeMain 

      public static void main(String args)

      Foo<Integer> foo = new Foo<Integer>();
      System.out.println(foo.getFoo()); // Works, prints out "Foo"



      public static class Foo<E>
      public E getFoo()
      return (E) "Foo";





      With the generic return type, I assumed the return in the above example would evaluate to:



      return (Integer) "Foo"; // Inconvertible types !!!


      Instead a String is returned and printed correctly.



      I get a compilation error if I change the call to be:



      String fooString = foo.getFoo(); // Compile error, incompatible types found
      System.out.println(fooString);


      What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.







      java generics






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 52 mins ago

























      asked 1 hour ago









      Ray

      25.9k958103




      25.9k958103






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          6
          down vote



          accepted










          This is because overload resolution resolved your println call to println(Object), since there is no println(Integer).



          Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo" are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.



          In other words, no casts are performed inside getFoo. The language spec supports this:




          Section 5.5.2 Checked Casts and Unchecked Casts




          • The cast is a completely unchecked cast.



            No run-time action is performed for such a cast.





          After erasure, getFoo returns Object. And that gets passed into println(Object), which is perfectly fine.



          If I call this method and pass foo.getFoo, I will get an error:



          static void f(Integer i) 
          System.out.println(i);

          // ...
          f(foo.getFoo()); // ClassCastException


          because this time it needs to be casted.






          share|improve this answer






















          • Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
            – Maxim
            1 hour ago










          • Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
            – Ray
            55 mins ago

















          up vote
          2
          down vote













          System.out.println does not have an overload that takes Integer. So this statement:



          System.out.println(foo.getFoo());


          Is calling System.out.println(Object);.



          To verify that it would otherwise fail, try:



          Foo<Integer> foo = new Foo<Integer>();
          Integer fooInt = foo.getFoo(); //class cast exception


          The following will fail in the same way:



          public static void main(String args) throws Exception 
          Foo<Integer> foo = new Foo<Integer>();
          print(foo.getFoo()); //Would also fail with a class cast exception

          static void print(Integer in)
          System.out.println(in);



          And this is failing compilation for obvious reasons:



          String fooString = foo.getFoo(); //can't work


          foo is Foo<Integer>, and foo.getFoo() returns an Integer and the compiler can pick this up.






          share|improve this answer




















            Your Answer





            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52458668%2fwhy-does-this-use-of-generics-not-throw-a-runtime-or-compile-time-exception%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            6
            down vote



            accepted










            This is because overload resolution resolved your println call to println(Object), since there is no println(Integer).



            Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo" are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.



            In other words, no casts are performed inside getFoo. The language spec supports this:




            Section 5.5.2 Checked Casts and Unchecked Casts




            • The cast is a completely unchecked cast.



              No run-time action is performed for such a cast.





            After erasure, getFoo returns Object. And that gets passed into println(Object), which is perfectly fine.



            If I call this method and pass foo.getFoo, I will get an error:



            static void f(Integer i) 
            System.out.println(i);

            // ...
            f(foo.getFoo()); // ClassCastException


            because this time it needs to be casted.






            share|improve this answer






















            • Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
              – Maxim
              1 hour ago










            • Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
              – Ray
              55 mins ago














            up vote
            6
            down vote



            accepted










            This is because overload resolution resolved your println call to println(Object), since there is no println(Integer).



            Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo" are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.



            In other words, no casts are performed inside getFoo. The language spec supports this:




            Section 5.5.2 Checked Casts and Unchecked Casts




            • The cast is a completely unchecked cast.



              No run-time action is performed for such a cast.





            After erasure, getFoo returns Object. And that gets passed into println(Object), which is perfectly fine.



            If I call this method and pass foo.getFoo, I will get an error:



            static void f(Integer i) 
            System.out.println(i);

            // ...
            f(foo.getFoo()); // ClassCastException


            because this time it needs to be casted.






            share|improve this answer






















            • Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
              – Maxim
              1 hour ago










            • Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
              – Ray
              55 mins ago












            up vote
            6
            down vote



            accepted







            up vote
            6
            down vote



            accepted






            This is because overload resolution resolved your println call to println(Object), since there is no println(Integer).



            Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo" are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.



            In other words, no casts are performed inside getFoo. The language spec supports this:




            Section 5.5.2 Checked Casts and Unchecked Casts




            • The cast is a completely unchecked cast.



              No run-time action is performed for such a cast.





            After erasure, getFoo returns Object. And that gets passed into println(Object), which is perfectly fine.



            If I call this method and pass foo.getFoo, I will get an error:



            static void f(Integer i) 
            System.out.println(i);

            // ...
            f(foo.getFoo()); // ClassCastException


            because this time it needs to be casted.






            share|improve this answer














            This is because overload resolution resolved your println call to println(Object), since there is no println(Integer).



            Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo" are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.



            In other words, no casts are performed inside getFoo. The language spec supports this:




            Section 5.5.2 Checked Casts and Unchecked Casts




            • The cast is a completely unchecked cast.



              No run-time action is performed for such a cast.





            After erasure, getFoo returns Object. And that gets passed into println(Object), which is perfectly fine.



            If I call this method and pass foo.getFoo, I will get an error:



            static void f(Integer i) 
            System.out.println(i);

            // ...
            f(foo.getFoo()); // ClassCastException


            because this time it needs to be casted.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 1 hour ago

























            answered 1 hour ago









            Sweeper

            55.8k962119




            55.8k962119











            • Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
              – Maxim
              1 hour ago










            • Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
              – Ray
              55 mins ago
















            • Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
              – Maxim
              1 hour ago










            • Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
              – Ray
              55 mins ago















            Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
            – Maxim
            1 hour ago




            Think that new rule should be introduced in lint that highlights generics usage with compile-time constants
            – Maxim
            1 hour ago












            Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
            – Ray
            55 mins ago




            Interesting. So, the E in the method declaration public E getFoo() does nothing at run-time, only acts a compile time checking on uses of the signature, not what's going in inside the method.
            – Ray
            55 mins ago












            up vote
            2
            down vote













            System.out.println does not have an overload that takes Integer. So this statement:



            System.out.println(foo.getFoo());


            Is calling System.out.println(Object);.



            To verify that it would otherwise fail, try:



            Foo<Integer> foo = new Foo<Integer>();
            Integer fooInt = foo.getFoo(); //class cast exception


            The following will fail in the same way:



            public static void main(String args) throws Exception 
            Foo<Integer> foo = new Foo<Integer>();
            print(foo.getFoo()); //Would also fail with a class cast exception

            static void print(Integer in)
            System.out.println(in);



            And this is failing compilation for obvious reasons:



            String fooString = foo.getFoo(); //can't work


            foo is Foo<Integer>, and foo.getFoo() returns an Integer and the compiler can pick this up.






            share|improve this answer
























              up vote
              2
              down vote













              System.out.println does not have an overload that takes Integer. So this statement:



              System.out.println(foo.getFoo());


              Is calling System.out.println(Object);.



              To verify that it would otherwise fail, try:



              Foo<Integer> foo = new Foo<Integer>();
              Integer fooInt = foo.getFoo(); //class cast exception


              The following will fail in the same way:



              public static void main(String args) throws Exception 
              Foo<Integer> foo = new Foo<Integer>();
              print(foo.getFoo()); //Would also fail with a class cast exception

              static void print(Integer in)
              System.out.println(in);



              And this is failing compilation for obvious reasons:



              String fooString = foo.getFoo(); //can't work


              foo is Foo<Integer>, and foo.getFoo() returns an Integer and the compiler can pick this up.






              share|improve this answer






















                up vote
                2
                down vote










                up vote
                2
                down vote









                System.out.println does not have an overload that takes Integer. So this statement:



                System.out.println(foo.getFoo());


                Is calling System.out.println(Object);.



                To verify that it would otherwise fail, try:



                Foo<Integer> foo = new Foo<Integer>();
                Integer fooInt = foo.getFoo(); //class cast exception


                The following will fail in the same way:



                public static void main(String args) throws Exception 
                Foo<Integer> foo = new Foo<Integer>();
                print(foo.getFoo()); //Would also fail with a class cast exception

                static void print(Integer in)
                System.out.println(in);



                And this is failing compilation for obvious reasons:



                String fooString = foo.getFoo(); //can't work


                foo is Foo<Integer>, and foo.getFoo() returns an Integer and the compiler can pick this up.






                share|improve this answer












                System.out.println does not have an overload that takes Integer. So this statement:



                System.out.println(foo.getFoo());


                Is calling System.out.println(Object);.



                To verify that it would otherwise fail, try:



                Foo<Integer> foo = new Foo<Integer>();
                Integer fooInt = foo.getFoo(); //class cast exception


                The following will fail in the same way:



                public static void main(String args) throws Exception 
                Foo<Integer> foo = new Foo<Integer>();
                print(foo.getFoo()); //Would also fail with a class cast exception

                static void print(Integer in)
                System.out.println(in);



                And this is failing compilation for obvious reasons:



                String fooString = foo.getFoo(); //can't work


                foo is Foo<Integer>, and foo.getFoo() returns an Integer and the compiler can pick this up.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 1 hour ago









                ernest_k

                14.5k41429




                14.5k41429



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52458668%2fwhy-does-this-use-of-generics-not-throw-a-runtime-or-compile-time-exception%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    Long meetings (6-7 hours a day): Being “babysat” by supervisor

                    Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

                    Confectionery