Reputation: 47
I have a method that compares the value of objects (as string, date, number...) and returns true or false depending of the result.
I've created a unit test for this method, but I'm having a problem testing the clob comparison, because with JUnit I don't have a connection, and if I use SerialClob to create two clobs (with the same content), I get objects with the same reference (so the part that compare clobs is not tested), I don't understand why two "new" generate the same object reference?
And another thing I don't understand, if I compare a string with a clob (identical values), the code that compares the clob is used, whereas instanceof is not supposed to be identical...!
What I expect is: when I compare 2 differents clobs, comparison as objects is false, as string (toString output) is false, it detects that objects are instanceof clobs, so convert them as string, and then compare string values.
Here is my code (simplified for example):
import java.io.*;
import java.sql.*;
import javax.sql.rowset.serial.*;
public class TestClob {
public static void main(String[] args) throws SerialException, SQLException {
boolean result;
Object text1="abcdef", text2="abcdef";
Clob clob1 = new SerialClob(((String) text1).toCharArray());
Clob clob2 = new SerialClob(((String) text2).toCharArray());
Clob clob3 = new SerialClob("abcdefg".toCharArray());
System.out.println("TEST 1, basic string comparison");
System.out.println("-------------------------------");
result = haveSameValue(text1, text2);
System.out.println("result: "+result);
System.out.println("\nTEST 2, clob vs string");
System.out.println("----------------------");
result = haveSameValue(clob1, text1);
System.out.println("result: "+result);
System.out.println("\nTEST 3, different clobs objects but same value");
System.out.println("----------------------------------------------");
result = haveSameValue(clob1, clob2);
System.out.println("result: "+result);
System.out.println("\nTEST 4, different clobs");
System.out.println("-----------------------");
result = haveSameValue(clob1, clob3);
System.out.println("result: "+result);
}
public static boolean haveSameValue(Object obj1, Object obj2) {
String sObj1, sObj2, sObj1Class, sObj2Class;
boolean result = false;
if (obj1!=null && obj2!=null) {
sObj1Class = obj1.getClass().toString().toLowerCase();
sObj2Class = obj2.getClass().toString().toLowerCase();
System.out.println(" Objects class : sObj1Class="+sObj1Class+", sObj2Class="+sObj2Class);
System.out.println(" OBJECT : obj1="+obj1+", obj2="+obj2+", => equal as object? "+obj1.equals(obj2));
if (!obj1.equals(obj2)) {
sObj1=obj1.toString();
sObj2=obj2.toString();
System.out.println(" STRING : sObj1="+sObj1+", sObj2="+sObj2+", => equal as string? "+sObj1.equals(sObj2));
if (!sObj1.equals(sObj2)) {
if (obj1 instanceof java.sql.Clob || obj2 instanceof java.sql.Clob) {
sObj1 = ClobToString(obj1);
sObj2 = ClobToString(obj2);
System.out.println(" CLOB : sObj1="+sObj1+", sObj2="+sObj2+" => equal as clob? "+sObj1.equals(sObj2));
result = sObj1.equals(sObj2);
}
// other comparisons (as a date, timestamp, number...)
}
}
}
return result;
}
public static String ClobToString(Object object) {
if (object==null) {
return null;
}
else if (object instanceof java.sql.Clob) {
StringBuilder sb = new StringBuilder();
try {
Reader reader = ((java.sql.Clob) object).getCharacterStream();
BufferedReader br = new BufferedReader(reader);
String line;
while(null != (line = br.readLine())) {
sb.append(line);
}
br.close();
return sb.toString();
}
catch (Exception e) {
System.out.println("error : "+e.getMessage());
return object.toString();
}
}
else {
return object.toString();
}
}
}
and here is the output:
TEST 1, basic string comparison
-------------------------------
Objects class : sObj1Class=class java.lang.string, sObj2Class=class java.lang.string
OBJECT : obj1=abcdef, obj2=abcdef, => equal as object? true
result: true
TEST 2, clob vs string
----------------------
Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class java.lang.string
OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=abcdef, => equal as object? false
STRING : sObj1=javax.sql.rowset.serial.SerialClob@df59efc3, sObj2=abcdef, => equal as string? false
CLOB : sObj1=abcdef, sObj2=abcdef => equal as clob? true
result: true
TEST 3, different clobs objects but same value
----------------------------------------------
Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class javax.sql.rowset.serial.serialclob
OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=javax.sql.rowset.serial.SerialClob@df59efc3, => equal as object? true
result: true
TEST 4, different clobs
-----------------------
Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class javax.sql.rowset.serial.serialclob
OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=javax.sql.rowset.serial.SerialClob@bd7d1c2, => equal as object? false
STRING : sObj1=javax.sql.rowset.serial.SerialClob@df59efc3, sObj2=javax.sql.rowset.serial.SerialClob@bd7d1c2, => equal as string? false
CLOB : sObj1=abcdef, sObj2=abcdefg => equal as clob? false
result: false
Upvotes: 0
Views: 64
Reputation: 19555
The variables clob1
and clob2
are referencing different objects, since new objects are created with the new
keyword. However, these objects have the same "value" in them. The SerialClob.equals()
method is defined in such a way, that two SerialClob
instances are equal to each other, when they have the same value:
Compares this SerialClob to the specified object. The result is
true
if and only if the argument is notnull
and is aSerialClob
object that represents the same sequence of characters as this object.
This is the case here, they have the same value "abcdef"
in them. This means that the if
block
if (!obj1.equals(obj2)) {
...
}
is not entered. And therefore, no further check is executed since you already know they are "equal".
Upvotes: 2