The following code is not creating shallow copy as the Javadoc mentioned about clone() method
// Do the same with object arrays
obj O[] = new obj[5];
obj Oc[] = O.clone();
System.out.println("Identity hashcode of obj arrays");
System.out.println(System.identityHashCode(O));
System.out.println(System.identityHashCode(Oc));
// check objects equalness
if(O.equals(Oc)){
System.out.println("Objects are equal!");
}
Output:
Identity hashcode of obj arrays
2018699554
1311053135
Where am I going wrong?
Yes, the output is as expected. The identity hashcodes of both arrays will be different because they are 2 different Objects (being pointed to by 2 different references) at the top level. So, the if.. condition fails as well.
What shallow copy means is : The container (Array, List etc) will be created but ht elements / references inside them will not be created newly, instead, the original references will be used / copied.
You seem to expect that the cloned array will be equal to the original array, as determined by calling O.equals(Oc).
But since arrays don't override Object.equals (JLS 10.7) this call only tests if O == Oc.
Therefore even if O.equals(Oc) does return false, this does not mean that Oc is not a shallow copy of O.
To test equality of array elements, you can use Arrays.equals(O, Oc)
The clone method will return a reference to a new array, which
references the same objects as the source array
HashCode of both the arrays will not be same, these two are two different objects.
Related
In Java, I understand primitive data types are stored as a value and the rest are stored as references. Then why is it that I get the actual value but not the memory address when I print ArrayList instance variable? I have an array variable just for comparing purposes.
public static void main(String[] args) {
Object[] a = new Object[3];
a[0] = 0;
a[1] = 1;
a[2] = 2;
ArrayList<Object> b = new ArrayList<Object>();
b.add(3);
b.add(4);
System.out.println(a);
System.out.println(b);
}
Two reasons
Because the Object.toString() method has been overridden.
Because the javadocs says that the toString() method for any type that extends the AbstractCollection class will display the collection's contents, not its "address".
And besides Object.toString() doesn't actually display the address anyway. It displays the identity hashcode with might be related to the address of the object, or it might not. (And two distinct objects can have the same identity hashcode, so it is not a reliable indicator that objects are the same.)
If you want to test if two object references (of any type) refer to the same object, use ==.
You don't need to look at addresses, and even if you figure out how to get the real address of an object ... object addresses change when the GC moves them, so this may not a 100% reliable way to test the objects.
You can discover why on your own. Just follow the documentation.
The println method takes a String object. See its Javadoc. To quote:
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
That means a call is made to the toString method on the collection object you pass to println.
So look at the Javadoc for the toString method inherited by ArrayList. To quote:
Returns a string representation of this collection. The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (comma and space). Elements are converted to strings as by String.valueOf(Object).
It's because it implements the toString() method. The default output is the hash code. Memory Address of Objects in Java documents how to get the memory address
Trying to check a method which adds a module object to an array works correctly. How do I write a JUnit test which tests to see if an object has indeed been added to the array?
Here is what I have so far:
#Test
public void testAddModule() {
Student chris = new Student("Chris", "1");
Module csc8001 = new Module("CSC8001", "Programming and data structures", 5, 5, 0, 7);
Module csc8002 = new Module("CSC8002", "Programming II", 5, 5, 0, 7);
chris.addModule(csc8001);
chris.addModule(csc8002);
Module [] expectedResult = {csc8001,csc8002};
ModuleRecord[] resultArray = Student.moduleRecords;
Assert.assertArrayEquals( expectedResult, resultArray );
}
The problem I have is the array is just storing references to the objects, how do I test to see if the array is storing the correct information?
You're on the right track: assertArrayEquals should work. The concept you're looking for is the difference between shallow equals ("==") and deep equals (".equals"), which is related to the difference between reference equality ("==") and object equality (".equals").
If two arrays have the same length, and contain the exact same primitive values and references, it's easy to say that they're equal: [0, 1] equals [0, 1] even if the arrays themselves are different objects, and the same happens for [csc8001, csc8002] and [csc8001, csc8002]. This is known as "shallow" equality, and it's very very fast to compute.
If you're actually looking to compare the objects using their equals methods, you need "deep" equality. This checks the proper number of entries, and checks that x[n].equals(y[n]) for all n. This may take longer, because Java can't just compare the references; it actually calls a method on the objects. This is only of value to you if you override equals, though; if your Module doesn't override equals it uses Object's built-in equals method, which acts the same way == does.
In any case, it's not very clear in the documentation, but Assert.assertArrayEquals calls Assert.internalArrayEquals, which basically does a deep comparison using .equals.
That leaves you with three options:
Keep using assertArrayEquals. That's what it's there for, and because equal references imply equal objects, it's the right thing to do.
Keep using assertArrayEquals but also write a Module.equals method to prove the data itself is identical. Remember, this is only an issue if you want to prove that two different instances behave as if they were equal based on their data, and you probably don't have to worry about that right now.
Break out what you're testing for, as Jason mentioned, which confirms that the data is correct without having you write an equals method:
assertEquals(2, resultArray.length);
Module addedModule = resultArray[1];
assertEquals("CSC8002", addedModule.code); /* ... */
If you ever do try overriding equals, be careful: You'll need to uphold some rules and you'll also need to override hashCode. Read more here.
The brute force method is to check that the array has the expected number of entries, then each object stored in the array has the expected attribute values.
Can someone explain why, A.equals(B) is false, when I initiate B using int[] B = A.clone() BUT true if I initiate B using int[] B = A?
int[] A = {1, 2, 3, 4, 5};
int[] B = A;
//int[] B = A.clone();
if(A==B){//true
System.out.println("Equal");
}
if(A.equals(B)){//true
System.out.println("Equal");
}
Apparently, equals method for arrays in Java is comparing reference equality (same as ==).
If you clone it, you have a reference different object - the clone array. But, if you just point another reference to it it's the same.
Well if you use
int[] B = A;
then B and A refer to the same object, so trivially they're equal. The first comparison (==) would certainly return false between A and A.clone() as the values refer to different objects. It sounds like arrays don't override equals (e.g. as ArrayList does), hence the clone not being equal to the original under the equals method either.
EDIT: Indeed, from the language specification section 10.7, Array Members:
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
In other words, the array overrides clone() but not toString / hashCode / equals.
For comparing arrays in Java, you might want to try
java.util.Arrays.equals(a,b);
If you use a == b they should be different- this compares their memory references.
If you use a.equals(b), it probably inherits from Object, which simply uses ==.
That probably explains why they made Arrays.equals() in the first place. Now why they chose a.equals(b) to not compare elements... hard to say.
Your question is answered precisely by the Javadoc for clone():
http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29
specifically:
[ The clone() method ] Creates and
returns a copy of this object. The
precise meaning of "copy" may depend
on the class of the object. The
general intent is that, for any object
x, the expression:
x.clone() != x
will be true, and that the expression:
x.clone().getClass() == x.getClass()
will be true, but these are not
absolute requirements. While it is
typically the case that:
x.clone().equals(x)
will be true, this is not an absolute
requirement.
int[] B = A;
Makes B point to the same object in memory as A, so not only are they equal, they are the same.
when you assign B = A, you assign the reference to the same object. With clone() you get a copy of the object. The equality operator (==) tests if both symbols reference the same object where .equals method checks if the two objects have the same value (defined by the implementation of the class)
I have a byte array which i want to copy/clone to avoid calling code from modifying my internal representation.
How do I clone a java byte array?
JLS 6.4.5 The Members of an Array Type
The members of an array type are all of the following:
The public final field length, which contains the number of components of the array (length may be positive or zero).
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[].
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
Thus:
byte[] original = ...;
byte[] copy = original.clone();
Note that for array of reference types, clone() is essentially a shallow copy.
Also, Java doesn't have multidimensional arrays; it has array of arrays. Thus, a byte[][] is an Object[], and is also subject to shallow copy.
See also
Wikipedia/Object copy
Java Nuts and Bolts/Arrays
Related questions
Deep cloning multidimensional arrays in Java… ?
How to effectively copy an array in java ?
How to deep copy an irregular 2D array
How do I do a deep copy of a 2d array in Java?
Other options
Note that clone() returns a new array object. If you simply want to copy the values from one array to an already existing array, you can use e.g. System.arraycopy (jdk 1.0+).
There's also java.util.Arrays.copyOf (jdk 1.6+) that allows you to create a copy with a different length (either truncating or padding).
Related questions
Difference between various Array copy methods
System.arraycopy(src, 0, dst, 0, src.length);
It's easy, and it's a great idea to do it.
byte[] copy = arr.clone();
Note that the return type of the clone() method of arrays is the type of the array, so no cast is required.
In order to avoid a possible Null Pointer Exception I use the following syntax:
byte[] copy = (arr == null) ? null : arr.clone();
What is the difference between identity and equality in OOP (Object Oriented Programming)?
identity: a variable holds the
same instance as another variable.
equality: two distinct objects can
be used interchangeably. they often
have the same id.
Identity
For example:
Integer a = new Integer(1);
Integer b = a;
a is identical to b.
In Java, identity is tested with ==. For example, if( a == b ).
Equality
Integer c = new Integer(1);
Integer d = new Integer(1);
c is equal but not identical to d.
Of course, two identical variables are always equal.
In Java, equality is defined by the equals method. Keep in mind, if you implement equals you must also implement hashCode.
Identity determines whether two objects share the same memory address. Equality determines if two object contain the same state.
If two object are identical then they are also equal but just because two objects are equal dies not mean that they share the same memory address.
There is a special case for Strings but that is off topic and you'll need to ask someone else about how that works exactly ;-)
Identity means it is the same object instance while equality means the objects you compare are to different instances of an object but happen to contain the same data.
Illustration (in java)
Date a = new Date(123);
Date b = new Date(123);
System.out.println(a==b); //false
System.out.println(a.equals(b)); //true
So a and b are different instances (different allocations in memory) but on the "data" level they are equal.
For instance,
In StackOverFlow:
identity: I am Michael, you are
sevugarajan, so we are not same.
equality: if we have same reputation
scores, we are equal in some ways.
In Java and similar languages which 'leak' the abstraction of a reference of an object, you can test whether two references refer to the same object. If they refer to the same object, then the references are identical. In Java, this is the == operator.
There is also an equals method which is used to test whether two objects have the same value, for example when used as keys of a HashSet (the hash code of equal objects should also be equal). Equal objects should have the same 'value' and semantics when used by client code.
Purer object-oriented languages do not have an identity comparison, as client code generally shouldn't care whether or not two objects have the same memory address. If objects represent the same real-world entity, then that is better modelled using some ID or key value rather than identity, which then becomes part of the equals contract. Not relying on the memory address of the object to represent real-world identity simplifies caching and distributed behaviour, and suppressing == would remove a host of bugs in string comparison or some uses of boxing of primitives in Java.
Think about the words "identical" and "equivalent". If two things are identical, they have the same identity; they are same thing. If they are equivalent, one can be substituted for the other without affecting the outcome; they have the same behavior and properties.
Identity: Two references to the same object (o1 == o2).
Equality: The method o1.equals( o2 ) returns true. This doesn't necessarily mean that the two objects contain (all) the same data.
In theory it's possible to override a method equals() to return false even for identical objects. But this would break the specification of Object.equals():
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
Identity concept is quite philosophical, that's why you shouldn't reconduce it just to references.
You can say that two identities are the same if a change to the first is reflected on the second and vice-versa. Of course this includes also sharing the same memory address but in general while identity is related to the attributes of the object, equality is used to check whenever two objects are identical, but this doesn't include identity.
The viceversa is quite obvious, if two items have the same identity they are also equal (in equality terms of being interchangeable).
For primitive types ( int , boolean , char, long , float ... )
== and != is equality test
and for Objects
== and != is identity test. [ it compares only the reference ]
equals method is used for equality test of Objects [ it can be overridden to compare specific attributes]
i found an excellent article on this
http://www.cs.cornell.edu/courses/cs211/2006sp/Lectures/L14-Comparison/L14cs211sp06.pdf
http://ocw.mit.edu/NR/rdonlyres/Electrical-Engineering-and-Computer-Science/6-170Fall-2005/D659DC53-FB1D-403C-8E35-2CAECBED266E/0/lec12.pdf
Quote
I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals. :D
Sir Winston Churchill
x == y is true only if there's the same object referenced by variables x and y.
x.equals(y) depends on the implementation of x.equals(), and is usually less strict that the above, as it compares the content of the object. (In Java, if x.equals(y), it must also be true that x.hashCode() == y.hashCode();)
Example:
Integer w = new Integer(3);
Integer x = new Integer(1);
Integer y = x;
Integer z = new Integer(1);
// all of these evaluate to true
y.equals(x) // it's the same object, of course the content is same
x.equals(z) // different objects, same content (`1`)
z.equals(y)
!w.equals(x); // the content is different (`3` vs `1`)
!w.equals(y);
!w.equals(z);
x == y // same object
z != x // different objects
y != z
w != x
Identical vs. Equal objects
Two objects are said to have identical states (deep equality) if the graphs representing their states are identical in every respect, including the OIDs at every level.
Two objects are said to have equal states (shallow equality) if the graphs representing their states are same, including all the corresponding atomic values. However, some corresponding internal nodes in the two graphs may have objects with different OIDs.
Example: This example illustrates the difference between the two definitions for comparing object
states for equality.
o2 = (i 2 , tuple, <a 1 :i 5 , a 2 :i 6 >)
o3 = (i 3 , tuple, <a 1 :i 4 , a 2 :i 6 >)
o4 = (i 4 , atom, 10)
o5 = (i 5 , atom, 10)
o6 = (i 6 , atom, 20)
In this example, the objects o1 and o2 have equal states (shallow equality), since their states at the atomic level are the same but the values are reached through distinct objects o 4 and o 5 .
However, the objects o1 and o3 have identical states (deep equality), even though the objects themselves are not because they have distinct OIDs. Similarly, although the states of o4 and o5 are identical, the actual objects o4 and o5 are equal but not identical, because they have distinct OIDs.
To add, identity is also known as referential check (references to objects, get it?) and equality as structural check by some authors. At the end of the day an object in memory abstract is just a map/table structure indexed at certain memory address. There can be one or many references (memory addresses) pointing to it. They all are referential-ly identical. When contents of same object is copied to another counterpart then both are structurally equal.