10 Replies Latest reply on May 24, 2007 2:27 PM by 798701

    Clone method in doc fails

    807600
      In
      http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.1

      I find this example:

      class Test {
           public static void main(String[] args) throws Throwable {
                int ia[][] = { { 1 , 2}, null };
                int ja[][] = ia.clone();
                System.out.print((ia == ja) + " ");
                System.out.println(ia[0] == ja[0] && ia[1] == ja[1]);
           }
      }


      Yet when I cut and paste and compile, it doesn't compile. I get:

      Test.java:4: incompatible types
      found : java.lang.Object
      required: int[]
      int ia2[] = ia1.clone();
      ?
      1 error

      I hate it when the examples in the docs don't work. Anyone have any suggestions?

      TIA for any help.
        • 1. Re: Clone method in doc fails
          807600
          Clone returns an object. You have to cast it back into an array.
          int ia2 = (int[]) ia1.clone();
          • 2. Re: Clone method in doc fails
            807600
            It compiles OK when I try it. As 10.7 says "The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[]."

            But as Sun's Tutorial explains (http://java.sun.com/docs/books/tutorial/java/IandI/override.html) "An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type." Covariant return types have been available since 1.5.
            • 3. Re: Clone method in doc fails
              807600
              Well, that worked. But why didn't the doc have the cast in the example?
              • 4. Re: Clone method in doc fails
                807600
                Reply:
                It compiles OK when I try it.

                -- hmmm. Wonder what's the difference; tried with both 1.4 under
                z/OS and 1.6 under WinXP

                As 10.7 says "The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[]."

                -- Well, I don't understand that (the first sentence is not correct English,
                by any stretch of the imagination). And I don't understand the relevance
                of that quote to the original post. Could you explain the significance of
                those sentences to real code?



                But as Sun's Tutorial explains (http://java.sun.com/docs/books/tutorial/java/IandI/override.html) "An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type." Covariant return types have been available since 1.5.

                -- I'm sorry, but I don't get the point of all that.
                • 5. Re: Clone method in doc fails
                  807600
                  Wonder what's the difference; tried with both 1.4 under
                  z/OS and 1.6 under WinXP
                  What happened when you tried that?

                  By "it compiles OK", I meant that I saw the rather unexceptional:
                  pbrockway@linuxdeskd6off:~/Desktop/jdk$ cat Test.java
                  class Test {
                          public static void main(String[] args) throws Throwable {
                                  int ia[][] = { { 1 , 2}, null };
                                  int ja[][] = ia.clone();
                                  System.out.print((ia == ja) + " ");
                                  System.out.println(ia[0] == ja[0] && ia[1] == ja[1]);
                          }
                  }pbrockway@linuxdeskd6off:~/Desktop/jdk$ javac -version
                  javac 1.6.0
                  pbrockway@linuxdeskd6off:~/Desktop/jdk$ javac -cp . Test.java
                  pbrockway@linuxdeskd6off:~/Desktop/jdk$
                  and with WindowsXP SP2, I just tried and see
                  C:\jdc>javac -version
                  javac 1.6.0

                  C:\jdc>javac -cp . Test.java

                  C:\jdc>
                  > > As 10.7 says "The public method clone, which overrides the
                  method of the same name in class Object and throws no checked
                  exceptions. The return type of the clone method of an array type T[]
                  is T[]."
                  Well, I don't understand that (the first sentence is not correct English,
                  by any stretch of the imagination). And I don't understand the relevance
                  of that quote to the original post.
                  Well the English is as good as it gets in these days where we're increasingly ruled by the bullet. In full it says ... no, but of course you've looked that up!

                  The OP (or at least his compiler message) was talking about the declared type of ja and the return type of ia.clone(). Specifically the type T referred to by the JLS is the type int in the OP's (and the JLS's) code.
                  Could you explain the significance of those sentences to real code?
                  The significance lies in the fact that both ja and ia.clone() are of type int[]. And what it signifies is that the code compiles, as expected, without a cast and without an error.

                  But as Sun's Tutorial explains (http://java.sun.com/docs/books/tutorial/java/IandI/override.html)
                  "An overriding method can also return a subtype of the type returned by the overridden method.
                  This is called a covariant return type." Covariant return types have been available since 1.5.
                  -- I'm sorry, but I don't get the point of all that.
                  I was just wondering if what the OP posted resulted from the fact that he was using a version of java that required ia.clone() to override Object's clone method in the narrow sense of returning exactly the same type (as was required pre 1.5).
                  • 6. Re: Clone method in doc fails
                    807600
                    Sorry - I've just realised that I was replying to you (the OP) in the previous post!

                    OK - you've said what you saw. Did you get that error message with both 1.4 and 1.6? As you can see from what I posted, it's easy enough to check with "javac -version" that you are using the compiler you think you are using.

                    As far as I know the JLS doesn't mention the cast because the cast is not, in fact, necessary.
                    • 7. Re: Clone method in doc fails
                      807600
                      OP here.

                      On my z/OS 1.7, a java -version returns:

                      java version "1.4.2"
                      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2)
                      Classic VM (build 1.4.2, J2RE 1.4.2 IBM z/OS Persistent Reusable VM build cm142ifx-20060209 (SR4-1) (JIT enabled: jitc))

                      If I compile the example exactly as it shows in the doc:

                      class Test {                                    
                      public static void main(String[] args) {     
                      int ia1[] = { 1, 2 };
                      int ia2[] = ia1.clone();
                      System.out.print((ia1 == ia2) + " ");
                      ia1[1]++;
                      System.out.println(ia2[1]);
                      }
                      }

                      I get:

                      Test.java:4: incompatible types
                      found : java.lang.Object
                      required: int[]
                      int ia2[] = ia1.clone();
                      ?
                      1 error

                      Hmmm. I notice your example doesn't quite match the example in the doc:

                      * you have a Throws clause on your main header
                      * you declare a two dimensional array instead of a one dimensional one
                      * your println statement is different
                      * you aren't incrementing the first element

                      when I compile your version, I find:

                      Test.java:4: incompatible types
                      found : java.lang.Object
                      required: int[][]
                      int ja[][] = ia.clone();
                      ?
                      1 error

                      So, I'm baffled again. [BTW, when I simply add the cast as one poster
                      suggested, it compiles clean and runs as the doc says it should.]

                      So, on my WinXP system, I have:

                      java -version
                      java version "1.6.0_01"


                      (how come you said "javac -version" instead of "java -version"?

                      Anyway, if I compile the original code, as found in the doc, I get:

                      Test.java:4: Incompatible types
                      found: : java.lang.Object
                      required: int[]
                      int ia2[] = ia1.clone();
                      ?

                      When I compile the code with the cast added, it compiles clean
                      and runs as expected.

                      When I compile your code, I get:

                      Test.java:4: incompatible types
                      found : java.lang.Object
                      required: int[][]
                      int ja[][] = ia.clone();
                      ?
                      1 error

                      So I don't see how you got a clean compile; and I'm still back to
                      my original dilema: the example in the doc does not seem to
                      compile as is.
                      • 8. Re: Clone method in doc fails
                        798701
                        Before Java 5 the language had no covariant return types, so clone() had to return Object. This means that the statement
                            int ia2[] = ia1.clone(); 
                        was not legal. You needed to cast the return value like this:
                            int ia2[] = (int[]) ia1.clone(); 
                        Since Java 5 the language has contravariant return types and the cast is not needed. The tutorial requires Java 6.
                        (how come you said "javac -version" instead of "java -version"?
                        You need a compiler from Java 5 or later to compile the example. Did "javac -version" give you an error? Then you have several runtime environments on your computer and the compiler javac that you used is from a version before Java 5. Make sure that the Java 6 SDK is mentioned before other versions in the PATH environment variable.

                        In all versions of the SDK you can verify the version of javac with the command "javac -J-version".
                        • 9. Re: Clone method in doc fails
                          807600
                          Thanks for that cogent and coherent explanation. It was just what I needed.
                          • 10. Re: Clone method in doc fails
                            798701
                            Since Java 5 the language has contravariant return types
                            hmm there's an error here: the return types are covariant, not contravariant.
                            http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)