Why is Arrays.asList(…).toArray().getClass() giving different results in JDK 1.8 and 11?











up vote
16
down vote

favorite
1












Why does the following condition return true with JDK 1.8.0_131, whereas it returns false with JDK 11.0.1?



String.class == Arrays.asList("a", "b").toArray().getClass()









share|improve this question




























    up vote
    16
    down vote

    favorite
    1












    Why does the following condition return true with JDK 1.8.0_131, whereas it returns false with JDK 11.0.1?



    String.class == Arrays.asList("a", "b").toArray().getClass()









    share|improve this question


























      up vote
      16
      down vote

      favorite
      1









      up vote
      16
      down vote

      favorite
      1






      1





      Why does the following condition return true with JDK 1.8.0_131, whereas it returns false with JDK 11.0.1?



      String.class == Arrays.asList("a", "b").toArray().getClass()









      share|improve this question















      Why does the following condition return true with JDK 1.8.0_131, whereas it returns false with JDK 11.0.1?



      String.class == Arrays.asList("a", "b").toArray().getClass()






      java java-11






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 49 mins ago









      Boann

      36.6k1287121




      36.6k1287121










      asked 4 hours ago









      Felix

      2567




      2567
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          21
          down vote













          The List type returned by asList is Arrays$ArrayList. The toArray method in jdk 8 on that class is:



          @Override
          public Object toArray() {
          return a.clone();
          }


          But in jdk 11 it is:



          @Override
          public Object toArray() {
          return Arrays.copyOf(a, a.length, Object.class);
          }


          In both cases a String is passed to asList, but in the jdk 8 case it is cloned, which retains its array type (String), and in jdk 11 it is copied using Arrays.copyOf with the explicit new array type of Object.



          This difference means that in jdk 8 Arrays.asList("a", "b").toArray().getClass() returns String and in jdk 11 it returns Object, so in jdk 11 your expression will evaluate to false.



          The reason for this change comes from JDK-6260652 with the motivation:




          The Collection documentation claims that



          collection.toArray()


          is "identical in function" to



          collection.toArray(new Object[0]);


          However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String), its toArray() will return an array of the same type (because it use clone()) instead of an Object.



          If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.




          So this change was made to fix the previous behaviour.





          If this is a problem for you, the related release note offers this as a work-around:




          If this problem occurs, rewrite the code to use the one-arg form toArray(T), and provide an instance of the desired array type. This will also eliminate the need for a cast.



          String array = list.toArray(new String[0]);






          share|improve this answer






























            up vote
            5
            down vote













            I would say that this was a bug in JDK 8 and before that has been fixed.



            List<T>.toArray() was always declared as returning Object (see JavaDoc) - that it did in effect return String in a special case was a mistake.






            share|improve this answer




























              up vote
              0
              down vote













              There are couple of reasons here



              1) It is a bug in jdk-8 where should return java.lang.Object but it is not and it is fixed in jdk-11



              @Override
              public Object toArray() {
              return a.clone();
              }


              2) == operator is always used for reference comparison, so java.lang.String or java.lang.Object are objects which are singleton and immutable loaded at the time of JVM starts



              System.out.println(String.class.hashCode()); //2018699554
              System.out.println(Arrays.asList("a", "b").toArray().getClass().hashCode()); //2018699554





              share|improve this answer























              • String pools have nothing to do with what's going on here.
                – Boann
                1 hour ago










              • is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                – Deadpool
                1 hour ago












              • Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                – Boann
                50 mins ago












              • sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                – Deadpool
                45 mins ago










              • That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                – Boann
                35 mins ago











              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: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              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%2f53696569%2fwhy-is-arrays-aslist-toarray-getclass-giving-different-results-in-jdk-1%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              21
              down vote













              The List type returned by asList is Arrays$ArrayList. The toArray method in jdk 8 on that class is:



              @Override
              public Object toArray() {
              return a.clone();
              }


              But in jdk 11 it is:



              @Override
              public Object toArray() {
              return Arrays.copyOf(a, a.length, Object.class);
              }


              In both cases a String is passed to asList, but in the jdk 8 case it is cloned, which retains its array type (String), and in jdk 11 it is copied using Arrays.copyOf with the explicit new array type of Object.



              This difference means that in jdk 8 Arrays.asList("a", "b").toArray().getClass() returns String and in jdk 11 it returns Object, so in jdk 11 your expression will evaluate to false.



              The reason for this change comes from JDK-6260652 with the motivation:




              The Collection documentation claims that



              collection.toArray()


              is "identical in function" to



              collection.toArray(new Object[0]);


              However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String), its toArray() will return an array of the same type (because it use clone()) instead of an Object.



              If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.




              So this change was made to fix the previous behaviour.





              If this is a problem for you, the related release note offers this as a work-around:




              If this problem occurs, rewrite the code to use the one-arg form toArray(T), and provide an instance of the desired array type. This will also eliminate the need for a cast.



              String array = list.toArray(new String[0]);






              share|improve this answer



























                up vote
                21
                down vote













                The List type returned by asList is Arrays$ArrayList. The toArray method in jdk 8 on that class is:



                @Override
                public Object toArray() {
                return a.clone();
                }


                But in jdk 11 it is:



                @Override
                public Object toArray() {
                return Arrays.copyOf(a, a.length, Object.class);
                }


                In both cases a String is passed to asList, but in the jdk 8 case it is cloned, which retains its array type (String), and in jdk 11 it is copied using Arrays.copyOf with the explicit new array type of Object.



                This difference means that in jdk 8 Arrays.asList("a", "b").toArray().getClass() returns String and in jdk 11 it returns Object, so in jdk 11 your expression will evaluate to false.



                The reason for this change comes from JDK-6260652 with the motivation:




                The Collection documentation claims that



                collection.toArray()


                is "identical in function" to



                collection.toArray(new Object[0]);


                However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String), its toArray() will return an array of the same type (because it use clone()) instead of an Object.



                If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.




                So this change was made to fix the previous behaviour.





                If this is a problem for you, the related release note offers this as a work-around:




                If this problem occurs, rewrite the code to use the one-arg form toArray(T), and provide an instance of the desired array type. This will also eliminate the need for a cast.



                String array = list.toArray(new String[0]);






                share|improve this answer

























                  up vote
                  21
                  down vote










                  up vote
                  21
                  down vote









                  The List type returned by asList is Arrays$ArrayList. The toArray method in jdk 8 on that class is:



                  @Override
                  public Object toArray() {
                  return a.clone();
                  }


                  But in jdk 11 it is:



                  @Override
                  public Object toArray() {
                  return Arrays.copyOf(a, a.length, Object.class);
                  }


                  In both cases a String is passed to asList, but in the jdk 8 case it is cloned, which retains its array type (String), and in jdk 11 it is copied using Arrays.copyOf with the explicit new array type of Object.



                  This difference means that in jdk 8 Arrays.asList("a", "b").toArray().getClass() returns String and in jdk 11 it returns Object, so in jdk 11 your expression will evaluate to false.



                  The reason for this change comes from JDK-6260652 with the motivation:




                  The Collection documentation claims that



                  collection.toArray()


                  is "identical in function" to



                  collection.toArray(new Object[0]);


                  However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String), its toArray() will return an array of the same type (because it use clone()) instead of an Object.



                  If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.




                  So this change was made to fix the previous behaviour.





                  If this is a problem for you, the related release note offers this as a work-around:




                  If this problem occurs, rewrite the code to use the one-arg form toArray(T), and provide an instance of the desired array type. This will also eliminate the need for a cast.



                  String array = list.toArray(new String[0]);






                  share|improve this answer














                  The List type returned by asList is Arrays$ArrayList. The toArray method in jdk 8 on that class is:



                  @Override
                  public Object toArray() {
                  return a.clone();
                  }


                  But in jdk 11 it is:



                  @Override
                  public Object toArray() {
                  return Arrays.copyOf(a, a.length, Object.class);
                  }


                  In both cases a String is passed to asList, but in the jdk 8 case it is cloned, which retains its array type (String), and in jdk 11 it is copied using Arrays.copyOf with the explicit new array type of Object.



                  This difference means that in jdk 8 Arrays.asList("a", "b").toArray().getClass() returns String and in jdk 11 it returns Object, so in jdk 11 your expression will evaluate to false.



                  The reason for this change comes from JDK-6260652 with the motivation:




                  The Collection documentation claims that



                  collection.toArray()


                  is "identical in function" to



                  collection.toArray(new Object[0]);


                  However, the implementation of Arrays.asList does not follow this: If created with an array of a subtype (e.g. String), its toArray() will return an array of the same type (because it use clone()) instead of an Object.



                  If one later tries to store non-Strings (or whatever) in that array, an ArrayStoreException is thrown.




                  So this change was made to fix the previous behaviour.





                  If this is a problem for you, the related release note offers this as a work-around:




                  If this problem occurs, rewrite the code to use the one-arg form toArray(T), and provide an instance of the desired array type. This will also eliminate the need for a cast.



                  String array = list.toArray(new String[0]);







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 27 mins ago









                  Dave Newton

                  139k18208253




                  139k18208253










                  answered 3 hours ago









                  Jorn Vernee

                  19.4k33156




                  19.4k33156
























                      up vote
                      5
                      down vote













                      I would say that this was a bug in JDK 8 and before that has been fixed.



                      List<T>.toArray() was always declared as returning Object (see JavaDoc) - that it did in effect return String in a special case was a mistake.






                      share|improve this answer

























                        up vote
                        5
                        down vote













                        I would say that this was a bug in JDK 8 and before that has been fixed.



                        List<T>.toArray() was always declared as returning Object (see JavaDoc) - that it did in effect return String in a special case was a mistake.






                        share|improve this answer























                          up vote
                          5
                          down vote










                          up vote
                          5
                          down vote









                          I would say that this was a bug in JDK 8 and before that has been fixed.



                          List<T>.toArray() was always declared as returning Object (see JavaDoc) - that it did in effect return String in a special case was a mistake.






                          share|improve this answer












                          I would say that this was a bug in JDK 8 and before that has been fixed.



                          List<T>.toArray() was always declared as returning Object (see JavaDoc) - that it did in effect return String in a special case was a mistake.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 3 hours ago









                          Thomas Kläger

                          5,8592717




                          5,8592717






















                              up vote
                              0
                              down vote













                              There are couple of reasons here



                              1) It is a bug in jdk-8 where should return java.lang.Object but it is not and it is fixed in jdk-11



                              @Override
                              public Object toArray() {
                              return a.clone();
                              }


                              2) == operator is always used for reference comparison, so java.lang.String or java.lang.Object are objects which are singleton and immutable loaded at the time of JVM starts



                              System.out.println(String.class.hashCode()); //2018699554
                              System.out.println(Arrays.asList("a", "b").toArray().getClass().hashCode()); //2018699554





                              share|improve this answer























                              • String pools have nothing to do with what's going on here.
                                – Boann
                                1 hour ago










                              • is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                                – Deadpool
                                1 hour ago












                              • Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                                – Boann
                                50 mins ago












                              • sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                                – Deadpool
                                45 mins ago










                              • That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                                – Boann
                                35 mins ago















                              up vote
                              0
                              down vote













                              There are couple of reasons here



                              1) It is a bug in jdk-8 where should return java.lang.Object but it is not and it is fixed in jdk-11



                              @Override
                              public Object toArray() {
                              return a.clone();
                              }


                              2) == operator is always used for reference comparison, so java.lang.String or java.lang.Object are objects which are singleton and immutable loaded at the time of JVM starts



                              System.out.println(String.class.hashCode()); //2018699554
                              System.out.println(Arrays.asList("a", "b").toArray().getClass().hashCode()); //2018699554





                              share|improve this answer























                              • String pools have nothing to do with what's going on here.
                                – Boann
                                1 hour ago










                              • is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                                – Deadpool
                                1 hour ago












                              • Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                                – Boann
                                50 mins ago












                              • sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                                – Deadpool
                                45 mins ago










                              • That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                                – Boann
                                35 mins ago













                              up vote
                              0
                              down vote










                              up vote
                              0
                              down vote









                              There are couple of reasons here



                              1) It is a bug in jdk-8 where should return java.lang.Object but it is not and it is fixed in jdk-11



                              @Override
                              public Object toArray() {
                              return a.clone();
                              }


                              2) == operator is always used for reference comparison, so java.lang.String or java.lang.Object are objects which are singleton and immutable loaded at the time of JVM starts



                              System.out.println(String.class.hashCode()); //2018699554
                              System.out.println(Arrays.asList("a", "b").toArray().getClass().hashCode()); //2018699554





                              share|improve this answer














                              There are couple of reasons here



                              1) It is a bug in jdk-8 where should return java.lang.Object but it is not and it is fixed in jdk-11



                              @Override
                              public Object toArray() {
                              return a.clone();
                              }


                              2) == operator is always used for reference comparison, so java.lang.String or java.lang.Object are objects which are singleton and immutable loaded at the time of JVM starts



                              System.out.println(String.class.hashCode()); //2018699554
                              System.out.println(Arrays.asList("a", "b").toArray().getClass().hashCode()); //2018699554






                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited 44 mins ago

























                              answered 2 hours ago









                              Deadpool

                              3,2482324




                              3,2482324












                              • String pools have nothing to do with what's going on here.
                                – Boann
                                1 hour ago










                              • is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                                – Deadpool
                                1 hour ago












                              • Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                                – Boann
                                50 mins ago












                              • sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                                – Deadpool
                                45 mins ago










                              • That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                                – Boann
                                35 mins ago


















                              • String pools have nothing to do with what's going on here.
                                – Boann
                                1 hour ago










                              • is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                                – Deadpool
                                1 hour ago












                              • Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                                – Boann
                                50 mins ago












                              • sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                                – Deadpool
                                45 mins ago










                              • That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                                – Boann
                                35 mins ago
















                              String pools have nothing to do with what's going on here.
                              – Boann
                              1 hour ago




                              String pools have nothing to do with what's going on here.
                              – Boann
                              1 hour ago












                              is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                              – Deadpool
                              1 hour ago






                              is that wrong java.lang.String is string object that created while JVM loading in object heap memory or String pool, is that wrong? String constants are stored in pool, objects are stored in heap @Boann
                              – Deadpool
                              1 hour ago














                              Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                              – Boann
                              50 mins ago






                              Nothing in the question is comparing any strings; it's comparing two java.lang.Class objects. Its behavior would be the same even if there were no such thing as the string constant pool.
                              – Boann
                              50 mins ago














                              sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                              – Deadpool
                              45 mins ago




                              sorry you are right, my intention is to explain == opeartor will always comapre references and java.lang.Object or java.lang.String objects are singleton and immutable and load at JVM starts @Boann
                              – Deadpool
                              45 mins ago












                              That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                              – Boann
                              35 mins ago




                              That == compares object references is true, but misses the point of the question. The behavior of the code in the question would be exactly the same if the two Class objects were being compared via .equals. Or simply running System.out.println(Arrays.asList(1, 2, 3).toArray()); also illustrates the behavior change between JDK 8 and JDK 9+.
                              – Boann
                              35 mins ago


















                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53696569%2fwhy-is-arrays-aslist-toarray-getclass-giving-different-results-in-jdk-1%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Trompette piccolo

                              Slow SSRS Report in dynamic grouping and multiple parameters

                              Simon Yates (cyclisme)