How to compare two objects by their fields? - java

I have pretty large number of classes which are Serializable/Externalizable and unfortunately it happens quite often that I forget to serailize/desirialize a new field when adding it to a class or mispell readObject instead of readDouble. So I decided to write some sort of unit test which is ignored and won't run by maven-surefire-plugin. It's only for my own needs. It looks like this:
#Test(enabled = false)
public void testEquality(Object o){
String oPart = o.toString();
try (FileOutputStream fos = new FileOutputStream("/home/myusr/testser/" + oPart);
ObjectOutputStream ous = new ObjectOutputStream(fos)) {
ous.writeObject(o);
} catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
Object oo = null;
try (FileInputStream fis = new FileInputStream("/home/myusr/testser/" + oPart);
ObjectInputStream ois = new ObjectInputStream(fis)) {
Object oo = ois.readObject();
} catch (FileNotFoundException | IOException | ClassNotFoundException e) {
e.printStackTrace();
}
// Need to compare all non-transient fields of o and oo
}
But the question is how to compare all fields which are not transient with the same name. I would not want to override equals method just for testing purpose.
Is there a way to deal with it? Maybe there are some commons/guava libraries which can cope with that.

You can use reflection to do it starting with YourClaas.class.getDeclaredFields(). Then you have to filter the returned fields, retrieve the values from the objects and do the comparison.

Related

How to read all objects from ObjectInputStream

I have a file with some info how can I read all info?
Name names;
try (FileInputStream fileInputStream = new FileInputStream(file)) {
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
names = (Name) objectInputStream.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
You have several solution, all depending on the input:
You can iterate until the stream is fully consumed: I think that is the worse solution out of those I provide you. It is worse because you are checking if EOF was reached, whilst you should know when you're done (eg: your file format is wrong).
Set<Name> result = new HashSet<>();
try {
for (;;) {
result.add((Name)objectInputStream.readObject());
}
} catch (EOFException e) {
// End of stream
}
return result;
When producing the input, serialize a collection and invoke readObject() on it. Serialization should be able to read the collection, as long as each object implements Serializable.
static void write(Path path, Set<Name> names) throws IOException {
try (OutputStream os = Files.newOutputStream(path);
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(names);
}
}
static Set<Name> read(Path path) throws IOException {
try (InputStream is = Files.newInputStream(path);
ObjectInputStream ois = new ObjectInputStream(is)) {
// WARN Files.newInputStream is not buffered; ObjectInputStream might
// be buffered (I don't remember).
return (Set<Name>) ois.readObject();
}
}
When producing the input, you can add a int indicating the number of object to read, and iterate over it: this is useful in case where you don't really care of the collection (HashSet). The resulting file will be smaller (because you won't have the HashSet metadata).
int result = objectInputStream.readInt();
Name[] names = new Name[result]; // do some check on result!
for (int i = 0; i < result; ++i) {
names[i] = (Name) objectInputStream.readObject();
}
Also, Set are good, but since they remove duplicate using hashCode()/equals() you may get less object if your definition of equals/hashCode changed after the fact (example: your Name was case sensitive and now it is not, eg: new Name("AA").equals(new Name("aa"))).

Is there a way to know which type of java object has been send once it is deserialized?

There are methods to serialize or deserialize java objects...
Prepare bytes to send:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(yourObject);
out.flush();
byte[] yourBytes = bos.toByteArray();
bos.close();
}
catch(Exception ex)
{
}
Create object from bytes:
ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = null;
try
{
in = new ObjectInputStream(bis);
Object o = in.readObject();
if (in != null)
{
in.close();
}
}
catch (Exception ex)
{
}
}
However, if someone wants to send different types of objects over the net is there a way to know which type of object has been sent. I guess there is the option to create a class and then serialize and deserialize it.
class SerialObject
{
String type;
Object object;
}
I think the only way to know the type of object being sent is when you use the InstanceOf keyword in java . The java instanceof operator is used to test whether the object is an instance of the specified type (class or subclass or interface). The instanceof in java is also known as type comparison operator because it compares the instance with type. It returns either true or false.
class Demo{
public static void main(String args[]){
Demo s=new Demo();
System.out.println(s instanceof Demo);//true
}
}
this code return true. just use the InstanceOf keyword .it will really help
When you are Serializing you can store the types somewhere - map or cache or somewhere, but still not sure why you want that?
One option is to check with instanceof operator during deserialized . I am not sure if (why?)should there be more?
Object deserialized = in.readObject();
if (deserialized instanceof TypeAbdClass) {
// do something with ..
} else if (deserialized instanceof SomethingElse) {
...
} else if (...) {
...
}
You can use
Object.getClass()
This will return runtime class of an object
Refer java doc
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

Best method for storing contents of an ArrayList for android application?

I know there are a few methods for saving data in an android application, but I'm wondering what is the simplest and/or most effective, or in other words which method would win-out on a scale of complexity/rationality/performance.
Basically I just have two Class ArrayLists (ArrayLists of class objects, not primitive data types). One ArrayList's object's constructor takes three integers,the other four. I basically need to store the value of those integers (I have methods for each set up to return the integers either as strings or ints) with a way of telling what each one belonged to.
For instance, if I have:
arrayListOne.get(1).getNumbers() returning 1, 2, 3
arrayListTwo.get(1).getNumbers() returning 1, 2, 3, 4
and a whole heap of other indexes that would return different numbers, how can I store that data so when the app is closed and restarted it is reloaded and the values stay true to the indexes they were initialized at?
Writing it to internal storage is one solution. You can use the following as a static method inside a Util class:
Retrieve the ArrayList:
final static String OBJECT_1_LIST = "object_1_list";
static ArrayList<MyObject1> object1List = null;
static ArrayList<MyObject1> getObject1List(Context mContext) {
FileInputStream stream = null;
try {
stream = mContext.openFileInput(OBJECT_1_LIST);
ObjectInputStream din = new ObjectInputStream(stream);
object1List = (ArrayList<MyObject1>) din.readObject();
stream.getFD().sync();
stream.close();
din.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
if (object1List == null) {
object1List = new ArrayList<MyObject1>();
}
return object1List;
}
Similarly, to update the ArrayList:
private static void updateObject1List(Context mContext) {
FileOutputStream stream = null;
try {
stream = mContext.openFileOutput(OBJECT_1_LIST,
Context.MODE_PRIVATE);
ObjectOutputStream dout = new ObjectOutputStream(stream);
dout.writeObject(object1List);
stream.getFD().sync();
stream.close();
dout.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
To add an item:
static void addToObject1list(Context mContext, MyObject1 obj) {
Utilities.getObject1List(mContext).add(obj);
Utilities.updateObject1List(mContext);
}
Add methods for removing an item and clearing the ArrayList.
You also need MyObject1 to implement Serializable:
public class MyObject1 implements Serializable {
....
....
}
I have found saving objects as JSON strings to be very simple and effective.
Check out the GSON library. It will convert from JSON to java and java back to JSON with very little fiddling.
https://code.google.com/p/google-gson/
I love GSON for doing this very thing.

Reliably convert any object to String and then back again

Is there a reliable way to convert any object to a String and then back again to the same Object? I've seen some examples of people converting them using toString() and then passing that value into a constructor to reconstruct the object again but not all objects have a constructor like this so that method wont work for all cases. What way will?
Yes, it is called serialization!
String serializedObject = "";
// serialize the object
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(myObject);
so.flush();
serializedObject = bo.toString();
} catch (Exception e) {
System.out.println(e);
}
// deserialize the object
try {
byte b[] = serializedObject.getBytes();
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
MyObject obj = (MyObject) si.readObject();
} catch (Exception e) {
System.out.println(e);
}
This is the code:
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(stringList);
so.flush();
redisString = new String(Base64.encode(bo.toByteArray()));
}
catch (Exception e) {
e.printStackTrace();
}
try {
byte b[] = Base64.decode(redisString.getBytes());
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
List<String> stringList2 = (List<String>)si.readObject();
System.out.println(stringList2.get(1));
}
catch (Exception e) {
e.printStackTrace();
}
Serialize to byte array, convert to Base64. Then decode Base64 back to byte array and deserialize.
None will work in all cases. An object may, e.g., contain references to other JVMs handling their state, and this state may be not available for you to restore.
Additional problems you're going to meet will include open streams, listening sockets, and almost anything else from the outer world.
There's no need to repeat that most at least two of Java core engineers say that serialization was one of the greatest mistakes a single worst feature in Java, that is, after finalization. (I do love serialization nevertheless, it's handy. But it won't always work.)
One way is to use JSON. For implementation specific in Java, the answer might be given in this post:
java code corresponding to Newtonsoft.Json.JsonConvert.SerializeObject(Object source,Newtonsoft.Json.JsonSerializerSettings()) in .net?
Using JSON is reliable enough that it's used for web application development (Ajax).
Yes, it is Serialization You can use, ObjectInputStream.readObject and ObjectOutputStream.writeObject. Please see below example:
MyClass myClass = new MyClass();
FileOutputStream fileStream = new FileOutputStream("myObjectFile.txt");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(os);
os.close();
FileInputStream fileInStream = new FileInputStream("myObjectFile.txt");
ObjectInputStream ois = new ObjectInputStream(fileInStream);
MyClass myClass2 = ois.readObject();
ois.close();
You can use SerializationUtils from org.apache.commons.
It provides the methods serialize and deserialize

Java: how to serialize a 3rd party library produced Java Object?

So I am using a proprietary java library in a project which I don't have access to source code.
It throws a Message object, and obviously I can't implement Serializable. It's generated throughout runtime.
what are my options? Is there a way to serialize the Message object into a byte array and back into the object?
UPDATE: I was able to serialize the object to JSON (http://code.google.com/p/json-io/) but couldn't convert it back to an object as it returns null. So I am trying to convert it to byte array using the code below. Still not working.
public byte[] toByteArray (Object obj)
{
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
oos.close();
bos.close();
bytes = bos.toByteArray ();
}
catch (IOException ex) {
//TODO: Handle the exception
}
return bytes;
}
public Object toObject (byte[] bytes)
{
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream (bytes);
ObjectInputStream ois = new ObjectInputStream (bis);
obj = ois.readObject();
}
catch (IOException ex) {
//TODO: Handle the exception
}
catch (ClassNotFoundException ex) {
//TODO: Handle the exception
}
return obj;
}
You could write a wrapper that is serializable and stores everything you need to recreate the Message object.
XStream is one way to go.
Sure, you just can't use the java.lang.Serializable mechanism.
Choose any format: XML, JSON, protocol buffer, or something else that might work for you.
Now you're responsible for both ends of the conversation: serialization and deserialization.
If the object is a Java bean, you can use java.beans.XMLEncoder and java.beans.XMLDecoder for serialization.

Categories