Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2008

Tip: Looking for answers? Try searching our database.

arrays and cloning, where is it described?

Thread view: 
Andreas Leitgeb - 05 Mar 2008 11:58 GMT
It seems to be quite a basic thing, but I found myself
unsure about how it works, and where it is described.
(I didn't find it in JLS nor in the description of
Cloneable or Object.clone() in the javadoc)

According to JLS, arrays are Serializable and Cloneable,
and for multidimensional arrays, the JLS says:
 " A clone of a multidimensional array is shallow,
 "   which is to say that it creates only a single
 "   new array. Subarrays are shared..
I'm not sure if this should be understood to imply
shallowness also in my case. Why would it have to
explicitly mention multidimensional arrays otherwise?

If I want to deep-copy an array of some Cloneable class,
what would be the best way to do it?

I'd be glad about answers, but even more I'd be glad
about pointers to any of sun's java-documents (jls,
api), where this behaviour or some "deepCopy" method
for arrays of cloneable types is directly described.  

Is array's clone/copy altogether the wrong way, and
do I need to create a new array and fill it with
clones of each element, myself?

PS: In my task at hand I do not need to worry about
 compiletime/runtime-type: they're the same.
Sanny - 05 Mar 2008 12:35 GMT
> According to JLS, arrays are Serializable and Cloneable,
> and for multidimensional arrays, the JLS says:
[quoted text clipped - 4 lines]
> shallowness also in my case. Why would it have to
> explicitly mention multidimensional arrays otherwise?

I tried to copy Single dimensional Array and it works correctly. For
multidimensional Array it do not copy all elements as you think.

int[] array1 = new int[100];
int[] source = new int[100];

array1=source.clone() Works correctly.

int[][] array1 = new int[100][100];
int[][] source = new int[100][100];

array1=source.clone() Does not Copy all elements correctly.

Bye
Sanny

Looking for Experts: http://www.GetClub.com/Experts.php
Patricia Shanahan - 05 Mar 2008 14:45 GMT
> It seems to be quite a basic thing, but I found myself
> unsure about how it works, and where it is described.
[quoted text clipped - 24 lines]
> PS: In my task at hand I do not need to worry about
>   compiletime/runtime-type: they're the same.

The key to understanding this is to accept that Java does not really
have multidimensional arrays. It does have arrays whose elements are of
another array type, and sometimes pretends they are multidimensional
arrays, but not to the extent of making one work consistently as though
it were a single array with multiple dimensions.

Thus "new int[3][4]" is a three element array. Each element is a
reference to a four element array of int.

Cloning it creates a new three element array. Element n of the new array
refers to the same int[4] as element n of the original.

Patricia
Andreas Leitgeb - 05 Mar 2008 17:38 GMT
>> According to JLS, arrays are Serializable and Cloneable,
>> and for multidimensional arrays, the JLS says:
[quoted text clipped - 7 lines]
> The key to understanding this is to accept that Java does not really
> have multidimensional arrays....

Sorry for obviously being higly misunderstandable.

My problem isn't about arrays of primitive types.
Not even really "multidimensional" ones.

The docu says: (in other words)
 if you clone an "array of array-types" (which are,
 btw., also Cloneable) then the referenced arrays
 are *not* cloned.
So far so good.

While it almost seems like implied, it doesn't say:
 if you clone an array of *any Object-type*,
 (which would effectively include array-types)
 then only the references, not the objects are
 cloned.

Why does it say so specifically about arrays of
arrays, but not about arrays of *any* objects?

Is it, because people might otherwise think that
"arrays of arrays" would be more likely to be deep-
cloned than arrays of other objects?
Patricia Shanahan - 05 Mar 2008 17:43 GMT
...
> Why does it say so specifically about arrays of
> arrays, but not about arrays of *any* objects?
>
> Is it, because people might otherwise think that
> "arrays of arrays" would be more likely to be deep-
> cloned than arrays of other objects?

I suspect so. Java pretends just enough multidimensional array support
to be confusing.

Patricia
Daniel Pitts - 06 Mar 2008 05:35 GMT
> ....
>> Why does it say so specifically about arrays of
[quoted text clipped - 8 lines]
>
> Patricia
I think it also makes a mention because array references are special.
Even though they can be assigned to an Object reference, they aren't
really an object.  The JLS has to be specific about anything that might
be ambiguous otherwise.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Mike Schilling - 06 Mar 2008 07:21 GMT
>> ....
>>> Why does it say so specifically about arrays of
[quoted text clipped - 13 lines]
> really an object.  The JLS has to be specific about anything that
> might be ambiguous otherwise.

In what ways are arrays not objects?
Andreas Leitgeb - 06 Mar 2008 07:34 GMT
>>>> Why does it say so specifically about arrays of
>>>> arrays, but not about arrays of *any* objects?
[quoted text clipped - 8 lines]
>> really an object.  The JLS has to be specific about anything that
>> might be ambiguous otherwise.

But then it is still unspecific about cloning arrays of Objects.
...or I've just still failed to find that mentioned.

> In what ways are arrays not objects?

Don't know, if that's what Daniel meant, but arrays are not
accessed through get-/putfield (except for length) or invoke...
opcodes, but through <x>aload/<x>astore opcodes for <x> any
of [abcdfils].

The JLS has some strange wording, such as "can be assigned to
variables of types Object, Cloneable, Serializable", instead
of saying that an array *was* all these.
Lew - 06 Mar 2008 08:16 GMT
> The JLS has some strange wording, such as "can be assigned to
> variables of types Object, Cloneable, Serializable", instead
> of saying that an array *was* all these.

Actually, the JLS does say that an array is all these, in ss. 4.10.3
<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10.3>
and in 10.7
<http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.7>
> Every array implements the interfaces Cloneable and java.io.Serializable.
and 10.8
> The direct superclass of an array type is Object.
> Every array type implements the interfaces Cloneable and java.io.Serializable.

The combination of Cloneable and Serializable is somewhat rare outside arrays,
because Cloneable is rare.  The combination is implemented by various
java.util classes: ArrayList, Calendar, Date, HashMap, HashSet.

Also in java.sql: Date, Time, Timestamp, by dint of subclassing java.util.Date.

There are a number of additional references in the JLS to the relationship
between Cloneable & Serializable and arrays such as ss. 5.1.6 (Narrowing
Reference Conversion), 5.5 (Casting Conversion), 10 (Arrays), and 5.2
(Assignment Conversion), from whence  your paraphrase seems to come.

<http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.2>
> An array can be assigned only to a variable of a compatible array type,
> or to a variable of type Object, Cloneable or java.io.Serializable.

That quote makes sense there because it has to do with assignment conversion.

It is also clearly not instead of saying that an array is "all these" but in
addition to several such mentions.

Signature

Lew

Andreas Leitgeb - 06 Mar 2008 18:15 GMT
>> The JLS has some strange wording, such as "can be assigned to
>> variables of types Object, Cloneable, Serializable", instead
>> of saying that an array *was* all these.
> There are a number of additional references in the JLS to the relationship
> between Cloneable & Serializable and arrays ...

I skimmed over all of these, but still missed any mention of what
clone really does for an array of Objects (or Cloneables, if it
made a difference)

It only says, what it does for an array of arrays, but, as has been
pointed out in this thread,  arrays are not normal Objects ... for
some definition of "being" :-)

The other question was, if there exists some method for deepCopying
an array of Cloneables.
Lew - 07 Mar 2008 01:03 GMT
>>> The JLS has some strange wording, such as "can be assigned to
>>> variables of types Object, Cloneable, Serializable", instead
[quoted text clipped - 5 lines]
> clone really does for an array of Objects (or Cloneables, if it
> made a difference)

The references were only by way of showing that the JLS does say "that an
array *was* all these", not that it explains what clone() does.

What clone() does is, strangely, documented in the Javadocs for clone(),
specifically,

> To achieve this independence, it may be necessary to modify one or more fields
> of the object returned by super.clone before returning it.
> Typically, this means copying any mutable objects that comprise the internal
> "deep structure" of the object being cloned and replacing the references to
> these objects with references to the copies.

The details of what it does to an array are covered in one of the JLS links I
mentioned:
<http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.7>
>  public T[] clone() {
>  try {
>    return (T[])super.clone(); // unchecked warning
>  } catch (CloneNotSupportedException e) {
>    throw new InternalError(e.getMessage());
>  }

Taken together, these two sources answer your question.

Signature

Lew

Andreas Leitgeb - 07 Mar 2008 10:14 GMT
> What clone() does is, strangely, documented in the Javadocs for clone(),
> specifically,
...which doesn't mention arrays at all.

For a normal class I can override .clone and provide for deep-copying,
but how could I override an array's clone()?

>> To achieve this independence, it may be necessary to modify one or more fields
>> of the object returned by super.clone before returning it.
Which I cannot do with arrays.

> The details of what it does to an array are covered in one of the JLS links I
> mentioned:
[quoted text clipped - 9 lines]
>>  }
>> ...

I saw that, but I found it nowhere near explicitly saying
that this was the actual implementation of an array's clone().
It rather says that if it *were* the implementation then
soem warning would occur.

> Taken together, these two sources answer your question.

It gives lots of hints, but nothing explicit.
I'm "quite" sure, that array clones are shallow, but I already
was so at start of this thread. The "quite" is still there.
Lew - 07 Mar 2008 12:30 GMT
> It gives lots of hints, but nothing explicit.
> I'm "quite" sure, that array clones are shallow, but I already
> was so at start of this thread. The "quite" is still there.

Good thing you are correct, then.

Signature

Lew

Piotr Kobzda - 07 Mar 2008 15:37 GMT
> The other question was, if there exists some method for deepCopying
> an array of Cloneables.

I don't know of any standard method to do that.  However, it's not so
hard to roll your own.

Here is one possible approach presented:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Map;

public class ArraysCloning {

  public static void main(String[] args) {
    String[][] a0 = {{"a"}, {"b", "c"}};
    String[][] a1 = a0.clone();
    String[][] a2 = Arrays.copyOf(a0, a0.length);
    String[][] a3 = deepClone(a0);

    a0[1][1] = "c'";

    System.out.println("a0=" + Arrays.deepToString(a0));
    System.out.println("a1=" + Arrays.deepToString(a1));
    System.out.println("a2=" + Arrays.deepToString(a2));
    System.out.println("a3=" + Arrays.deepToString(a3));
  }

  public static <T> T[] deepClone(T[] a) {
    return deepClone(a, new IdentityHashMap<Object, Object>());
  }

  @SuppressWarnings("unchecked")
  private static <T> T deepClone(T a, Map<Object, Object> cloned) {
    if (a == null) return null;  // null clones to null
    if (! a.getClass().isArray()) return a;  // non-array clones to self
    T c = (T) cloned.get(a);
    if (c != null) return c;  // already cloned clones to clone
    // clone...
    try {
      c = (T) cloneMethod.invoke(a, (Object[])null);
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e.getCause());
    }
    // remember clone
    cloned.put(a, c);
    // clone non-primitive array elements...
    if (! c.getClass().getComponentType().isPrimitive()) {
      Object[] ca = (Object[]) c;
      for(int i = 0, len = ca.length; i < len; ++i) {
        ca[i] = deepClone(ca[i], cloned);
      }
    }
    return c;
  }

  private static final Method cloneMethod;
  static {
    try {
      cloneMethod = Object.class
          .getDeclaredMethod("clone", (Class<?>[])null);
      cloneMethod.setAccessible(true);
    } catch (Exception e) {
      throw new Error(e);
    }
  }
}

Which prints out the following:
a0=[[a], [b, c']]
a1=[[a], [b, c']]
a2=[[a], [b, c']]
a3=[[a], [b, c]]

(To make an example shorter it utilizes reflective clone() invocation
for each array type -- primitive and reference arrays.  When maximum
speed (and safety) is needed it may be reimplemented to directly call
clone() depending on a component type of array being cloned -- just a
bit more of "ugly coding" needed...)

piotr
Andreas Leitgeb - 11 Mar 2008 08:46 GMT
>> The other question was, if there exists some method for deepCopying
>> an array of Cloneables.
> I don't know of any standard method to do that.  However, it's not so
> hard to roll your own.

Thanks for your code sample.
I didn't yet think of the case where several array-elements might
refer to the same Object. While it won't happen in my case, it is
now clear to me that a general solution is more than just a loop
cloning each Element to the new array. Now, I'm somewhat less
surprised by the lack of such a method in "Arrays".

Meanwhile in my case I noticed that I don't really need to clone
the whole array, but only generate a "digest" from it, but now
having a deepCopy-implementation findable in google is still a
good thing :-)
Daniel Pitts - 06 Mar 2008 15:19 GMT
>>>>> Why does it say so specifically about arrays of
>>>>> arrays, but not about arrays of *any* objects?
[quoted text clipped - 18 lines]
> opcodes, but through <x>aload/<x>astore opcodes for <x> any
> of [abcdfils].
Actually, "length", is not a field on an array "object".  To access the
length of an array, you use a specific opcode.
<http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html>
> arraylength
> Description
>
>     The arrayref must be of type reference and must refer to an array. It is popped from the operand stack. The length of the array it references is determined. That length is pushed onto the operand stack as an int.

> The JLS has some strange wording, such as "can be assigned to
> variables of types Object, Cloneable, Serializable", instead
> of saying that an array *was* all these.

That strange wording is *because* an array is not actually an Object.
Programmers are "tricked" into thinking it is, because it can be
assigned to an Object/Cloneable/Serializable reference.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Andreas Leitgeb - 06 Mar 2008 18:29 GMT
>> Don't know, if that's what Daniel meant, but arrays are not
>> accessed through get-/putfield (except for length) ...
> Actually, "length", is not a field on an array "object".  To access the
> length of an array, you use a specific opcode.
><http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html>

Sorry, my fault.  Thanks for correcting!

//TODO: insert excuse for not checking back *before* posting. ;-)
Patricia Shanahan - 06 Mar 2008 16:20 GMT
...
>> In what ways are arrays not objects?
>
> Don't know, if that's what Daniel meant, but arrays are not
> accessed through get-/putfield (except for length) or invoke...
> opcodes, but through <x>aload/<x>astore opcodes for <x> any
> of [abcdfils].

That is an implementation detail in compilers that target bytecode, not
a Java language feature.

Patricia
Mike  Schilling - 06 Mar 2008 18:11 GMT
> ...
>>> In what ways are arrays not objects?
[quoted text clipped - 6 lines]
> That is an implementation detail in compilers that target bytecode, not
> a Java language feature.

What Patricia said.

All of the array types (i.e. array of X) are subclasses [1] of Object; to
me, that says that arrays are objects.

1. Descendents, anyway.  Do we know for a fact that their immediate
superclass is Object?
Daniel Pitts - 06 Mar 2008 18:24 GMT
Mike Schilling wrote:
>> ...
>>>> In what ways are arrays not objects?
[quoted text clipped - 12 lines]
> 1. Descendents, anyway.  Do we know for a fact that their immediate
> superclass is Object?

public class Foo {
    public static void main(String[] args) {
        System.out.println("Class: " + args.getClass());
        System.out.println("Super: " + args.getClass().getSuperclass());
        final List<? extends Class<?>> interfaces =
Arrays.asList(args.getClass().getInterfaces());
        System.out.println("Interfaces: " + interfaces);
        final List<Field> fields =
Arrays.asList(args.getClass().getFields());
        System.out.println("Fields:" + fields);
        final List<Field> declaredFields =
Arrays.asList(args.getClass().getDeclaredFields());
        System.out.println("Declared Fields:" + declaredFields);

    }
}

Class: class [Ljava.lang.String;
Super: class java.lang.Object
Interfaces: [interface java.lang.Cloneable, interface java.io.Serializable]
Fields:[]
Declared Fields:[]

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Mike  Schilling - 06 Mar 2008 19:54 GMT
> Mike Schilling wrote:
>>> ...
[quoted text clipped - 36 lines]
> Fields:[]
> Declared Fields:[]

Yes, I know that the superclass is Object *now*, but I don't know whether
this is guaranteed.
Patricia Shanahan - 06 Mar 2008 20:12 GMT
Mike Schilling wrote:
...
> Yes, I know that the superclass is Object *now*, but I don't know whether
> this is guaranteed.

http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.8

"The direct superclass of an array type is Object."

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()

"If this object represents an array class then the Class object
representing the Object class is returned."

Patricia
Lew - 07 Mar 2008 01:08 GMT
> Mike Schilling wrote:
> ....
>> Yes, I know that the superclass is Object *now*, but I don't know
>> whether this is guaranteed.
>
> http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.8

/op. cit./, /supra/.

> "The direct superclass of an array type is Object."
>
> http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()
>
> "If this object represents an array class then the Class object
> representing the Object class is returned."

If we keep repeating the information enough, eventually it will get through.
It certainly is mentioned in enough places in the JLS:

<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10.3>
> 4.10.3 Subtyping among Array Types
> The following rules define the direct subtype relation among array types:
[quoted text clipped - 7 lines]
>           o Cloneable >1 p[]
>           o java.io.Serializable >1 p[]

/op. cit./, /supra/.

Signature

Lew

Mike Schilling - 07 Mar 2008 07:12 GMT
>> Mike Schilling wrote:
>> ....
[quoted text clipped - 14 lines]
> If we keep repeating the information enough, eventually it will get
> through. It certainly is mentioned in enough places in the JLS:

Not very good OO programmers, are they?  Every array class has the
same "length" field, so it should be moved up into an abstract
superclass. :-)
Lew - 07 Mar 2008 12:41 GMT
> Not very good OO programmers, are they?  Every array class has the
> same "length" field, so it should be moved up into an abstract
> superclass. :-)

Actually, it's each array /instance/ that has a 'length'.  Such a field is an
instance member, not a class member.

Furthermore, it isn't actually a field.  Even were 'length' actually a field,
and there were an actual superclass that defined it, its behavior would be the
same, from the Java language perspective, as observed today.

The implementation of 'length' does provide that abstractness, in that the
implementation is not specific to each array, but general for all arrays.
Conceptually, it's just precisely exactly quite as if indeed there were an
abstract array superclass that defines 'length'.  The definition of 'length'
lives in the (imaginary) abstract superclass of array, the instance and
initialization of a 'length' live in each array instance.

So I have to disagree, 'they" are pretty good OO programmers.

Signature

Lew

Mike Schilling - 07 Mar 2008 16:13 GMT
>> Not very good OO programmers, are they?  Every array class has the
>> same "length" field, so it should be moved up into an abstract
>> superclass. :-)
>
> Actually, it's each array /instance/ that has a 'length'.  Such a
> field is an instance member, not a class member.

OK, say "defines" instead of "has", if you want to be a stickler.
Andreas Leitgeb - 06 Mar 2008 18:45 GMT
> ...
>>> In what ways are arrays not objects?
>>
>> Don't know, if that's what Daniel meant, but arrays are not
>> accessed through get-/putfield or invoke... opcodes, but
>> through <x>aload/<x>astore opcodes for <x> any of [abcdfils].

> That is an implementation detail in compilers that target bytecode, not
> a Java language feature.

Well there is special syntax for arrays, that cannot be mimicked
by objects... but then, this is also true for enums and collections...
Nah! let's stop this hairsplitting :-)


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.