I have an object from old Java code, and I now changed the serialized object code. I want to be able to read both the old files and the new files. I need a branching statement in readObject to do something like:
if (next object is int -- just poking, it might be an Object)
{
// we know we are in version 1
} else {
// read new version of object
}
is that possible to do?
Ok so basically the question is "How can we check with an ObjectInputStream whether the next field is a primitive or an object?" and the answer as far as I can see is: You can't.
Which means the best solution I can see to keep backwards compatibility is to never remove primitives from the original version - keeping useless information blows up the size a bit, but otherwise that's easy.
To add new fields, I can see two ways:
Keep the earlier message format identical and only add new objects at the end - you can then easily distinguish different versions by the message size (or more exactly you'll get an IOException when reading data of v2 when you get a v1 object). That's much simpler and generally preferred.
You can change objects from v1 to v2 and then do a simple instanceof check. If you want to add primitives is to store their wrapper versions (i.e. Integer et al). Can save you some bytes, but Java's serialization protocol was never efficient to begin with, so really that's unnecessary complicated.
if (object instanceof Integer) {
... Do stuff
} else {
... Do other stuff
}
EDIT: I suppose I should expand on this. You can check object types using instanceof but I'm not sure about being able to work with primatives like int or char.
The easiest way to do this is to keep the old member variables with their old types and add new member variables for new types. also, you must keep the serialVersionUID of the class the same. then, your readObject() implementation can do any necessary manipulation to transform the old data to new data.
Original Object:
public class MyObject {
private static final long serialVersionUID = 1234L;
private int _someVal;
}
New version:
public class MyObject {
private static final long serialVersionUID = 1234L;
private int _someVal; //obsolete
private String _newSomeVal;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
if(_someVal != 0) {
// translate _someVal to _newSomeVal
}
}
}
I believe there are more complex options available as well using custom ObjectStreamField[] serialPersistentFields, ObjectInputStream.GetField and ObjectOutputStream.PutField.
ObjectInputStream will load and create an instance of the right class.
object = ois.readObject();
if (object instanceof YourNewShiny ){
// new style object
} else if (object instanceof YourOldBusted ){
// convert YourOldBusted to YourNewShiny
} else {
throw new ToyOutOfPram();
}
This is all great if you have a new class, but if you have changed your class in an incompatible manner such that the ObjectInputStream cannot deserialise the old versions of the class into the new form. If this is the case you are pretty much stuffed.
Options:
Revert your changes, and either do them compatibly i.e. add a serialVersionId, don't change the order of fields, only add new field, plus don't assume not null constraints
Using an old version of the code read the serialised data, convert it to some intermediate form (xml,csv,etc) and then import this data into the new class definition and serialise it out
manually re implement the ObjectInputStream to detect your class type (you can use the serialVersionId to stiff the type)
Only the first seems like a good idea to me.
Related
I am trying to implement a copy constructor in java. I am facing a problem with non primitive type fields of the class. While creating a new copy, it is sharing the members. For Example
public class Bad implements Cloneable {
private ArrayList<Integer> a;
private Object c;
public static void main(String[] args) {
Bad b1 = new Bad();
b1.a.add(10);
System.out.println(b1.a);
Bad b2 = b1.clone();
b2.a.add(12);
System.out.println(b1.a);
}
Bad() {
a = new ArrayList<>();
c = null;
}
Bad(Bad b) {
a = b.a;
c = b.c;
}
public Bad clone() {
return new Bad(this);
}
}
And the result is :
[10]
[10, 12]
I don't want this to happen. Take this as an example. My original problem consists of even more fields that are user defined.
Or are there any libraries which do the work for me? Thanks in advance.
Simple rules for a copy constructor:
primitive values may be copied as-is; they are just values without a separate identity
references to immutable types (eg. String, Integer, any enum class constant) may also be copied as-is; although the original and the copied objects will share the same reference, the referred object is immutable and will never change
references to mutable types (eg. Date, ArrayList, any array) must be copied to a new instance of the type; otherwise the original and the copied object will share a reference to the same mutable field object (which is not what you want)
Making a copy of an object that contains only fields with primitive and immutable values is easy mode.
Copying an object whose fields contain mutable objects can make the process arduous and expensive depending on how complex the mutable object is (imagine an ArrayList that contains a Map whose values are also Maps). Making a new copy of the mutable field is, however, essential if you wish to have a safe copy.
Integer is immutable but you need to create a totally new ArrayList, and I mean here :
Bad(Bad b) {
a = b.a;
c = b.c;
}
do instead
Bad(Bad b) {
a = new ArrayList<>(b.a);
c = // this here must be copy constructed too
}
and then you will get
[10]
[10]
The correct way would be creating a new instance of the list instead of passing a reference to the original list.
Bad(Bad b) {
a = new ArrayList<>(b.a);
c = b.c; // this should call clone or something similar as well
}
Also note that if you would have some non-primitive type within the list of b.a, then you would have to copy/clone all the sub-elements as well (it is not needed now as you have Integer in it which is not mutable).
I have N reference to an java object. I wanted to set all reference pointing to this object as null. I don't know how many references are pointing to this object.
This is something which is specifically not possible in Java and most other modern languages. If it were, it would be a very dangerous thing to do which could break the invariants of other objects, like collections containing your object (for example, if a hash table contained it as a key).
However, if you want to ensure that an expensive object goes away promptly when you want it to, there is a simple pattern you can use to ensure this.
// This could also be some built-in class rather than one you write
class ExpensiveObject {
// ... fields holding giant arrays, external resources, etc etc go here ...
void someOperation() {
// ... code ...
}
}
class ExpensiveObjectHolder {
ExpensiveObject target;
ExpensiveObjectHolder(ExpensiveObject target) {
this.target = target;
}
void someOperation() {
if (target == null) {
throw new IllegalStateException(
"This ExpensiveObject has been deleted.");
} else {
target.someOperation();
}
// You can also omit this if/else and just let target.someOperation()
// throw NullPointerException, but that might be annoying to debug.
}
void delete() {
target = null;
}
}
Then you create the wrapper around the object:
ExpensiveObjectHolder h = new ExpensiveObjectHolder(new ExpensiveObject());
and when you want it to go away, you do:
h.delete();
and since target was the only reference to the ExpensiveObject, which is now gone, we know that it is now garbage and will be discarded when the garbage collector notices.
Further notes:
It might be useful to make the ExpensiveObject and ExpensiveObjectHolder implement the same interface, but this can also make it easier to forget to use the holder where it should be.
If the ExpensiveObject has methods which do something like return this;, make sure that the method in the holder returns the holder instead.
I want to "flatten"/transform an instance from a given Java class to another instance containing primitive types only.
Every field from an object that is not already a primitive type will have to be flattened recursively too, so that the resulting object contains a flattened view of the original one, with primitive types only.
For example, given the following classes:
class Element {
int id_;
Position position_;
}
class Position {
int x_;
int y_;
}
The resulting instance would be of type:
class FlattenedElement {
int id_;
int x_;
int y_;
}
And I would expect such a behaviour:
Element e = new Person ( 42, new Position(0, 0) );
FlattenedElement fe = e.flatten();
Is there any tool/library able to do so?
Or do I need to write my own flattener, using the reflection API I take it?
-- edit following most comments --
I changed my example to avoid any confusion with String and byte (I won't have to deal with Strings).
I need to keep the semantics of the data in the resulting conversion. The output primitive types data will be directly involved in a parallel computation using OpenCL, which only understands primitive data types.
In other words, what I need is to break encapsulation to manipulate directly the primitive data types embedded in the class hierarchy.
You can do this, but you will need a third party library to create the new class, like Javaassist. To introspect the class to be flattened, you will use reflection as some users already said. Here is another example that I wrote for you:
public static Class flatten( Class classToFlatten ) {
for ( Field f : classToFlatten.getDeclaredFields() ) {
Class type = f.getType();
String name = f.getName();
int modifiersConfig = f.getModifiers();
// extract all modifiers here (using the isXXX methods of the Modifier class)
System.out.print( Modifier.isPrivate( modifiersConfig ) ? "private" : "" );
System.out.print( " " + type );
System.out.print( " " + name );
System.out.println();
if ( type.isPrimitive() ) {
// primitive type.
// does not need to be converted.
// insert in the new class as it is (using Javaassist).
} else {
// no primitive type.
// needs to be converted and tested.
// insert in the new class after the conversion (using Javaassist).
// convert rules...
switch ( type.getSimpleName() ) {
case "String":
// insert in the new class a array of chars.
break;
// cases to test if the field is a wrapper (Integer, Long, etc.).
// other rules tha you need here...
}
// here you need to use recursion...
// you can use this method, but you will need to create
// a new parameter, passing the class that is been built
// to insert new fields in it (relative to the type that is been
// reflected)
}
}
// return the new class here and outside the method, use the newInstance
// method to create new instances of this class
return null;
}
With this I think you will be able to do what you need, but I thinking why you need this. You will have some problems when you have arrays of some type that will be recursively flettened, because you will maybe need to "backtrack" to resolve their type or to run the flatten algorithm some times. With generics, inner classes, methods and all kinds of class members you will have the same problem. I'm not sayng that this is impossible, but it will consume a lot of your time and maybe you could solve your problem in a simpler way as some users already said. Well, I hope you can do what you need and I want to know the results if possible! Maybe your solution can be the seed of a new library! Ok, enought of brainstorming :D Here are some links.
The Javaassist library can be downloaded here.
Here you can see a simple tutorial. I suggest that you use it only to begin, because the Javaassist API may have been improved since the creation of the tutorial, so, after reading this, refactor your code (if possible), reading the library docs.
Well, from my POV, one way would be this:
public class Person {
String name;
Atring address;
public FlattenedPerson flatten() {
FlattenedPerson fp = new FlattenedPerson(this.name.getBytes(), this.houseNumber, this.address.getStreet.getBytes(), this.address.getTown.getBytes());
return fp;
}
}
You have to use Reflection
Have a look at the little sample, return Field's name.
So to get the value of this Field you have to return f[i].get(Object)
I have an object of type X which I want to convert into byte array before sending it to store in S3. Can anybody tell me how to do this? I appreciate your help.
What you want to do is called "serialization". There are several ways of doing it, but if you don't need anything fancy I think using the standard Java object serialization would do just fine.
Perhaps you could use something like this?
package com.example;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Serializer {
public static byte[] serialize(Object obj) throws IOException {
try(ByteArrayOutputStream b = new ByteArrayOutputStream()){
try(ObjectOutputStream o = new ObjectOutputStream(b)){
o.writeObject(obj);
}
return b.toByteArray();
}
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
try(ByteArrayInputStream b = new ByteArrayInputStream(bytes)){
try(ObjectInputStream o = new ObjectInputStream(b)){
return o.readObject();
}
}
}
}
There are several improvements to this that can be done. Not in the least the fact that you can only read/write one object per byte array, which might or might not be what you want.
Note that "Only objects that support the java.io.Serializable interface can be written to streams" (see java.io.ObjectOutputStream).
Since you might run into it, the continuous allocation and resizing of the java.io.ByteArrayOutputStream might turn out to be quite the bottle neck. Depending on your threading model you might want to consider reusing some of the objects.
For serialization of objects that do not implement the Serializable interface you either need to write your own serializer, for example using the read*/write* methods of java.io.DataOutputStream and the get*/put* methods of java.nio.ByteBuffer perhaps together with reflection, or pull in a third party dependency.
This site has a list and performance comparison of some serialization frameworks. Looking at the APIs it seems Kryo might fit what you need.
Use serialize and deserialize methods in SerializationUtils from commons-lang.
Yeah. Just use binary serialization. You have to have each object use implements Serializable but it's straightforward from there.
Your other option, if you want to avoid implementing the Serializable interface, is to use reflection and read and write data to/from a buffer using a process this one below:
/**
* Sets all int fields in an object to 0.
*
* #param obj The object to operate on.
*
* #throws RuntimeException If there is a reflection problem.
*/
public static void initPublicIntFields(final Object obj) {
try {
Field[] fields = obj.getClass().getFields();
for (int idx = 0; idx < fields.length; idx++) {
if (fields[idx].getType() == int.class) {
fields[idx].setInt(obj, 0);
}
}
} catch (final IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
Source.
As i've mentioned in other, similar questions, you may want to consider compressing the data as the default java serialization is a bit verbose. you do this by putting a GZIPInput/OutputStream between the Object streams and the Byte streams.
To convert the object to a byte array use the concept of Serialization and De-serialization.
The complete conversion from object to byte array explained in is tutorial.
http://javapapers.com/core-java/java-serialization/
Q. How can we convert object into byte array?
Q. How can we serialize a object?
Q. How can we De-serialize a object?
Q. What is the need of serialization and de-serialization?
I would like to call a method which could potentially take on different versions, i.e. the same method for input parameters that are of type:
boolean
byte
short
int
long
The way I would like to do this is by "overloading" the method (I think that is the correct term?):
public void getValue(byte theByte) {...}
public void getValue(short theShort) {...}
... etc ...
... but that would mean that I would have to pass the primitive type in by reference... similar to C++ where the method has external effect, where it can modify the variable outside its scope.
Is there a way to do this without creating new classes or using the Object versions of the primitive types? If not, any suggestions on alternative strategies?
Let me know if I should further explain to clear up any confusion.
UPDATE
What I'm actually trying to do is construct the primitive type from a set of bits. So if I'm dealing with the byte version of the method, I want to pretty much do my work to get 8 bits and return the byte (since I can't pass by reference).
The reason I'm asking this question is because the work I do with bits is very repetitive and I don't want to have the same code in different methods. So I want to find a way for my ONE method to KNOW how many bits I'm talking about... if I'm working with a byte, then 8 bits, if I'm working with a short, 16 bits, etc...
Java is always pass-by-value. There is no pass-by-reference in Java. It's written in the specs!
While Java supports overloading, all parameters are passed by value, i.e. assigning a method argument is not visible to the caller.
From your code snippet, you are trying to return a value of different types. Since return types are not part of a method's signature, you can not overload with different return types. Therefore, the usual approach is:
int getIntValue() { ... }
byte getByteValue() { ... }
If this is actually a conversion, the standard naming is
int toInt() { ...}
byte toByte() { ... }
You can't. In Java parameters are always passed by value. If the parameter is a reference type, the reference is passed by value and you can modify it inside the method while with primitive types this is not possible.
You will need to create a wrapper type.
Primitives are not passed by references (or objects for that matter) so no you cannot.
int i = 1;
moo(i);
public void moo(int bah)
{
bah = 3;
}
System.out.println(i);
Prints out 1
I would say the alternative strategy, if you want to work with primitives, is to do what the Java Libraries do. Just suck it up and have multiple methods.
For example, ObjectInputStream has readDouble(), readByte(), etc.
You're not gaining anything by sharing an implementation of the function, and the clients of your function aren't gaining anything by the variants of your function all having the same name.
UPDATE
Considering your update, I don't think it's necessary to duplicate too much code. It depends on your encoding strategy but I would imagine you could do something like this:
private byte get8Bits();
public byte getByte() {
return get8Bits();
}
public int getInt() {
return (get8Bits() << 24) | (get8Bits() << 16) | (get8Bits() << 8) | get8Bits();
}
Anything that shares code more than that is probably over-engineering.
An alternative could be
private long getBits(int numBits);
public byte getByte() {
return (byte)getBits(8);
}
public int getInt() {
return (int)getBits(32);
}
i.e. I don't think it makes sense to expose the users of your library to anything other than the primitive types themselves.
If you really, really wanted to then you could make a single method for access like this:
#SuppressWarnings("unchecked")
public static <T> T getValue(Class<T> clazz) {
if ( clazz == byte.class ) {
return (T)Byte.valueOf((byte)getBits(8));
} else if ( clazz == int.class ) {
return (T)Integer.valueOf((int)getBits(32));
}
throw new UnsupportedOperationException(clazz.toString());
}
//...
byte b = getValue(byte.class);
int i = getValue(int.class);
But I fail to see how it's any less cumbersome for clients of your library.
The object types of primitive types in Java (Double, Integer, Boolean, etc) are, if I remember correctly, immutable. This means that you cannot change the original value inside a method they are passed into.
There are two solutions to this. One is to make a wrapper type that holds the value. If all you are attempting to do is change the value or get a calculation from the value, you could have the method return the result for you. To take your examples:
public byte getValue(byte theByte) {...}
public short getValue(short theShort) {...}
And you would call them by the following:
Short s = 0;
s = foo.getValue(s);
or something similar. This allows you to mutate or change the value, and return the mutated value, which would allow something like the following:
Short s = foo.getValue(10);
Hope that helps.
Yes, please be more specific about what you want to achieve.
From your description I suggest you have a look at Java generics where you could write something like this:
class SomeClass <GenericType> {
GenericType val;
void setValue(GenericType val) {
this.val = val;
}
GenericType getValue() {
return val;
}
public static void main(String[] args) {
SomeClass<Integer> myObj = new SomeClass<Integer>();
myObj.setValue(5);
System.out.println(myObj.getValue());
SomeClass<String> myObj2 = new SomeClass<String>();
myObj2.setValue("hello?!");
System.out.println(myObj2.getValue());
}
}
Sounds like you have a set of bits that you're parsing through. You should have it wrapped in an object, lets call that object a BitSet. You're iterating through the bits, so you'll have something like an Iterator<Bit>, and as you go you want to parse out bytes, ints, longs, etc... Right?
Then you'll have your class Parser, and it has methods on it like:
public byte readByte(Iterator<Bit> bitit) {
//reads 8 bits, which moves the iterator forward 8 places, creates the byte, and returns it
}
public int readInt(Iterator<Bit> bitit) {
//reads 32 bits, which moves the iterator forward 32 places, creates the int, and returns it
}
etc...
So after you call whichever method you need, you've extracted the value you want in a typesafe way (different return types for different methods), and the Iterator has been moved forward the correct number of positions, based on the type.
Is that what you're looking for?
Only by creating your own value holding types.