• Post Reply Bookmark Topic Watch Topic
  • New Topic

Array cloning  RSS feed

 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There was a question today about copying arrays, and my advice was to use array.clone(), which I'm pretty sure is correct for most cases. However, apart from this example in the JLS, I'm finding it hard to find any documentation about clone() as it applies to arrays - and in particular, how it changed in v5 or v6 (not sure which it was). I know it did, because you no longer have to cast the result.

Does anyone know of a definitive description of exactly how array.clone() does its stuff?

Cheers.

Winston
 
Bill Gorder
Bartender
Posts: 1682
7
Android IntelliJ IDE Linux Mac OS X Spring
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I haven't researched it much beyond what Joshua Bloch says in his book ( I am pretty sure from your past posts that you have also read that). Based on his suggestions though cloning arrays is about the only time he recommends using clone at all. If you wanted to learn more of the inner workings I suppose you would have to crawl through the native code for the pre and post 1.5 JVMs and compare them.

Here is a start though:
http://stackoverflow.com/questions/12032292/is-it-possible-to-find-source-for-java-native-method
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Things like [LFoo#clone() and MyEnum#values() are well hidden. I think you can find them in the JLS and Java Tutorials, but I don’t remember finding them in the API documentation.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bill Gorder wrote:Based on his suggestions though cloning arrays is about the only time he recommends using clone at all. If you wanted to learn more of the inner workings I suppose you would have to crawl through the native code for the pre and post 1.5 JVMs and compare them.

Yeah. I did find a nifty little article a while ago that pointed out that not only is clone() good for an array, but also that it compares favourably with Arrays.copy() (and indeed System.arrayCopy()) for performance. It also 'feels' right, since it documents exactly what's being done.

But thanks for the link.

Camplbell Ritchie wrote:Things like [LFoo#clone() and MyEnum#values() are well hidden. I think you can find them in the JLS and Java Tutorials, but I don’t remember finding them in the API documentation.

Odd, I can't find them in either (apart from the link I posted), but maybe I'm just being thick.

As it turns out, I managed to do what I wanted (make a generic deepCopy() method for any type of array with minimal reflection), and it seems to work fine.

Thanks all.

Winston
 
Seetharaman Venkatasamy
Ranch Hand
Posts: 5575
Eclipse IDE Java Windows XP
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
not sure this is what you want
Winston Gutkowski wrote:
Does anyone know of a definitive description of exactly how array.clone() does its stuff?

From Object#clone JavaDoc:

the contents of the fields are not themselves cloned. Thus, this method
performs a "shallow copy" of this object, not a "deep copy" operation
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Seetharaman Venkatasamy wrote:not sure this is what you want...

Not really, but thanks.

What I really wanted was to confirm that array's clone() method returns the identical runtime type to the original.

So, for example, if I have an int[][][][], and I pass it to a methodwill it return an int[][][][]?

It seems like it should, but arrays can be darn tricky, especially when it comes to casting.

Winston

PS: Don't worry. That's not how I wrote the method, but hopefully it illustrates the problem.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:I'm finding it hard to find any documentation about clone() as it applies to arrays - and in particular, how it changed in v5 or v6 (not sure which it was). I know it did, because you no longer have to cast the result.

Does anyone know of a definitive description of exactly how array.clone() does its stuff?

Well, JLS 10.7 does say " The return type of the clone method of an array type T[] is T[]." That's true for both the Java 5 and Java 7 versions. I don't have an easy-to-find link for the previous JLS versions, but covariant returns were only introduced in Java 5. Prior to that any clone() method would have to return Object, just like the one declared in the Object class.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
What I really wanted was to confirm that array's clone() method returns the identical runtime type to the original.

So, for example, if I have an int[][][][], and I pass it to a methodwill it return an int[][][][]?

It seems like it should, but arrays can be darn tricky, especially when it comes to casting

The type is guaranteed to be int[][][][], based on the JLS line I just quoted. T is int[][][], and T[] is T[][][][]. I suppose the runtime type could be a subtype of the return type, if there were any - but int[][][][] has no subtypes. So int[][][][] is the only option.

The bigger problem is that clone() does not actually return a deep copy. But you probably know that, and that's the basis for your "don't worry" disclaimer above.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:Well, JLS 10.7 does say " The return type of the clone method of an array type T[] is T[]." That's true for both the Java 5 and Java 7 versions. I don't have an easy-to-find link for the previous JLS versions, but covariant returns were only introduced in Java 5. Prior to that any clone() method would have to return Object, just like the one declared in the Object class.

Yeah. That was my thought too (that array.clone() changed when covariants came in).

And don't worry, I spotted the "deliberate mistake" that you did and changed my method to
public static final <A> A deepCopy(A array) { ...

Marginally clunkier, but no casting required for the return value; and still seems to work just fine.

Thanks.

Winston
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:And don't worry, I spotted the "deliberate mistake"...

Actually, no mistake. I reverted to the previous signature and it works fine - with the added benefit that I don't need to check that the passed argument is, in fact, an array.

Sometimes, generics takes me a couple of cracks - even after 3 years.

Winston
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yeah, I wasn't sure what you were referring to, but I was perfectly willing to believe that there was some subtle mistake there that I had not noticed.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:The type is guaranteed to be int[][][][], based on the JLS line I just quoted...

Fair enough, but why not just publicize its API in Javadocs? Surely some pseudo-package name like java.native or java.anonymous could be exploited for this purpose.

Publish its public API, Oracle. After all, it IS an Object subtype, .

Winston
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, where exactly would they put it? Package names aside, there's an infinite number of possible array types, and no common superclass besides Object. I wouldn't know where to try to look it up, other than in Object or in the JLS. If they had created a common Array supertype for all arrays, that would be a good place to put the relevant documentation. But maybe it's hard to add that now without breaking backwards compatibility. Anyway, having it in the JLS rather than the API (under Object?) seems OK to me, if they're not going to retroactively insert a new supertype.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:Well, where exactly would they put it?...

Unfortunately, an "Array" is an aberration, and basically the equivalent of an anonymous type. They have, however, managed to publish the API for an enum via the invention of an Enum class that you can neither extend, use as a static name, nor instantiate directly; why not the same thing for an array?

Arrays ARE objects, and they have a specific public API, which now (especially after changes to the behaviour of one of its methods) deserves to be published just like any other type. I don't have to trawl through the JLS to find the API for any other type, so why for arrays?

A few people have asked recently "why can't we have protected top-level classes?" and the answer is always "protected from what?". Well here's a possibility: what about allowing them as a documentation aid? ie, for a class that you will never actually use directly, but you want to document.

Maybe not, but just braiin-whirring...

Winston
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello again sir Winston...

Winston Gutkowski wrote:Unfortunately, an "Array" is an aberration, and basically the equivalent of an anonymous type.

I'm not sure what you mean by this. Though I agree that arrays are aberrations, not handled consistently with classes or primitives. If that's part of what you mean.

Winston Gutkowski wrote:They have, however, managed to publish the API for an enum via the invention of an Enum class that you can neither extend, use as a static name, nor instantiate directly; why not the same thing for an array?

Good question - I'm not sure. But I think there's an important difference with enums - they simply didn't exist before. Sun or Oracle could implement the new type however they wanted. With existing types, the trick is to change the implementation without breaking the code that uses it. Offhand I can't think of any times when Sun or Oracle has added a new base class to an existing library class. I suspect it would cause problems, though I'm not sure what those would be (if any). I think it might cause binary compatibility problems, where you'd have to recompile everything against the newer JDK. Existing jar files would fail in strange ways. I think. Or maybe I'm making that up. I'll have to think more about that later.

Winston Gutkowski wrote:Arrays ARE objects, and they have a specific public API, which now (especially after changes to the behaviour of one of its methods) deserves to be published just like any other type. I don't have to trawl through the JLS to find the API for any other type, so why for arrays?

I mostly agree. If we were in a postion to redesign Java from the ground up, this is one of many things I would change. But not being in that postion myself, I suspect it's pretty hard to do for an existing, widely used language, without breaking things.

Winston Gutkowski wrote:A few people have asked recently "why can't we have protected top-level classes?" and the answer is always "protected from what?". Well here's a possibility: what about allowing them as a documentation aid? ie, for a class that you will never actually use directly, but you want to document.

I didn't really follow this, sorry.

Cheers!
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:Hello again sir Winston...

Blimey. I haven't been called Sir Winston since 1945.

Mike Simmons wrote:I didn't really follow this, sorry.

Yeah, I was kind of turning things over in my head when I wrote that. Basically, what I was trying to say is that there are specific situations (like arrays) where regular API-style documentation would be extremely useful, and since Java has no real use for protected top-level classes, that one might be able to create one specifically for such a purpose.

Perhaps another keyword like "api" might be better to designate a 'dummy' class that has been created only to publish its API; but wouldn't you like to see, for example, a java.lang.Array class that contains proper descriptions of its length field and toString() and clone() methods, and highlights the fact that it implements Cloneable and Serializable?

Obviously, it's not a 100% solution because arrays use specific operators like [], but to be honest, I'd much rather see that explained in the top section of a standard API doc than have to go trawling through the JLS to find it.

Just my thoughts. I'm still thinking it through and I suspect there may be other/better ways to do it.

Winston
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!