Why does Arrays.asList(…).toArray().getClass() give different results in JDK 8 and 9? [duplicate]












43
















This question already has an answer here:




  • array cast Java 8 vs Java 9

    2 answers




Why does the following condition return true with JDK 8, whereas it returns false with JDK 9?



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









share|improve this question















marked as duplicate by Michael java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 10 '18 at 9:43


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.























    43
















    This question already has an answer here:




    • array cast Java 8 vs Java 9

      2 answers




    Why does the following condition return true with JDK 8, whereas it returns false with JDK 9?



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









    share|improve this question















    marked as duplicate by Michael java
    Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

    StackExchange.ready(function() {
    if (StackExchange.options.isMobile) return;

    $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
    var $hover = $(this).addClass('hover-bound'),
    $msg = $hover.siblings('.dupe-hammer-message');

    $hover.hover(
    function() {
    $hover.showInfoMessage('', {
    messageElement: $msg.clone().show(),
    transient: false,
    position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
    dismissable: false,
    relativeToBody: true
    });
    },
    function() {
    StackExchange.helpers.removeMessages();
    }
    );
    });
    });
    Dec 10 '18 at 9:43


    This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.





















      43












      43








      43


      5







      This question already has an answer here:




      • array cast Java 8 vs Java 9

        2 answers




      Why does the following condition return true with JDK 8, whereas it returns false with JDK 9?



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









      share|improve this question

















      This question already has an answer here:




      • array cast Java 8 vs Java 9

        2 answers




      Why does the following condition return true with JDK 8, whereas it returns false with JDK 9?



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




      This question already has an answer here:




      • array cast Java 8 vs Java 9

        2 answers








      java java-8 java-9






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 10 '18 at 9:36









      Michael

      19.9k83471




      19.9k83471










      asked Dec 9 '18 at 20:51









      FelixFelix

      41319




      41319




      marked as duplicate by Michael java
      Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

      StackExchange.ready(function() {
      if (StackExchange.options.isMobile) return;

      $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
      var $hover = $(this).addClass('hover-bound'),
      $msg = $hover.siblings('.dupe-hammer-message');

      $hover.hover(
      function() {
      $hover.showInfoMessage('', {
      messageElement: $msg.clone().show(),
      transient: false,
      position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
      dismissable: false,
      relativeToBody: true
      });
      },
      function() {
      StackExchange.helpers.removeMessages();
      }
      );
      });
      });
      Dec 10 '18 at 9:43


      This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









      marked as duplicate by Michael java
      Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

      StackExchange.ready(function() {
      if (StackExchange.options.isMobile) return;

      $('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
      var $hover = $(this).addClass('hover-bound'),
      $msg = $hover.siblings('.dupe-hammer-message');

      $hover.hover(
      function() {
      $hover.showInfoMessage('', {
      messageElement: $msg.clone().show(),
      transient: false,
      position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
      dismissable: false,
      relativeToBody: true
      });
      },
      function() {
      StackExchange.helpers.removeMessages();
      }
      );
      });
      });
      Dec 10 '18 at 9:43


      This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


























          2 Answers
          2






          active

          oldest

          votes


















          50














          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 9+ 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 9+ 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 9+ it returns Object, so in JDK 9+ 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





















          • 3





            It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

            – Holger
            Dec 10 '18 at 9:28











          • Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

            – Felix
            Dec 11 '18 at 10:19



















          12














          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



















          • 4





            That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

            – Konrad Rudolph
            Dec 10 '18 at 8:58








          • 2





            The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

            – Alan Bateman
            Dec 10 '18 at 9:12


















          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          50














          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 9+ 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 9+ 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 9+ it returns Object, so in JDK 9+ 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





















          • 3





            It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

            – Holger
            Dec 10 '18 at 9:28











          • Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

            – Felix
            Dec 11 '18 at 10:19
















          50














          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 9+ 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 9+ 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 9+ it returns Object, so in JDK 9+ 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





















          • 3





            It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

            – Holger
            Dec 10 '18 at 9:28











          • Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

            – Felix
            Dec 11 '18 at 10:19














          50












          50








          50







          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 9+ 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 9+ 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 9+ it returns Object, so in JDK 9+ 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 9+ 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 9+ 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 9+ it returns Object, so in JDK 9+ 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 Dec 10 '18 at 9:38









          Michael

          19.9k83471




          19.9k83471










          answered Dec 9 '18 at 21:11









          Jorn VerneeJorn Vernee

          20.3k33658




          20.3k33658








          • 3





            It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

            – Holger
            Dec 10 '18 at 9:28











          • Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

            – Felix
            Dec 11 '18 at 10:19














          • 3





            It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

            – Holger
            Dec 10 '18 at 9:28











          • Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

            – Felix
            Dec 11 '18 at 10:19








          3




          3





          It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

          – Holger
          Dec 10 '18 at 9:28





          It’s so funny that the ArrayList(Collection) constructor contains a protection against this misbehavior with reference to this bug report (it’s from 2005) for a long time now, whereas no-one came to the idea of fixing the misbehavior in the first place, apparently…

          – Holger
          Dec 10 '18 at 9:28













          Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

          – Felix
          Dec 11 '18 at 10:19





          Great, thanks for explanation. Unfortunately the method is called within a serialization code of GWT RPC 2.6.1 so I cannot easily switch to the parameterized toArray overloading.

          – Felix
          Dec 11 '18 at 10:19













          12














          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



















          • 4





            That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

            – Konrad Rudolph
            Dec 10 '18 at 8:58








          • 2





            The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

            – Alan Bateman
            Dec 10 '18 at 9:12
















          12














          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



















          • 4





            That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

            – Konrad Rudolph
            Dec 10 '18 at 8:58








          • 2





            The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

            – Alan Bateman
            Dec 10 '18 at 9:12














          12












          12








          12







          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 Dec 9 '18 at 21:11









          Thomas KlägerThomas Kläger

          6,3172718




          6,3172718








          • 4





            That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

            – Konrad Rudolph
            Dec 10 '18 at 8:58








          • 2





            The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

            – Alan Bateman
            Dec 10 '18 at 9:12














          • 4





            That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

            – Konrad Rudolph
            Dec 10 '18 at 8:58








          • 2





            The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

            – Alan Bateman
            Dec 10 '18 at 9:12








          4




          4





          That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

          – Konrad Rudolph
          Dec 10 '18 at 8:58







          That's incorrect. The method has always returned Object (just look at its return type declaration). It never violated its declared type. Instead it violated its documented runtime behaviour. The difference is a nuance, but an important one.

          – Konrad Rudolph
          Dec 10 '18 at 8:58






          2




          2





          The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

          – Alan Bateman
          Dec 10 '18 at 9:12





          The JDK 9 release note on this change is here: oracle.com/technetwork/java/javase/…

          – Alan Bateman
          Dec 10 '18 at 9:12



          Popular posts from this blog

          Probability when a professor distributes a quiz and homework assignment to a class of n students.

          Aardman Animations

          Are they similar matrix