My singleton class be like this:
public class SerializableSingleton implements Serializable {
private static SerializableSingleton instance = new SerializableSingleton();
private SerializableSingleton() {
System.out.println("Constructor is being called");
}
public static SerializableSingleton getInstance() {
return instance;
}
}
Now it's written on the web that when we deserialize this singleton object, it will give a new instance back and not the previous one, and in order to fix this, use the readResolve() method.
But my question is - How is it even possible? When a static class member can't be serialized, how does the question of deserializing it comes at all? and it is all over the net?
Since the singleton object is static:
private static SerializableSingleton instance = new SerializableSingleton();
How is an instance getting serialized in the first place?
Serialization bypasses a lot of things in the language and even does some stuff that is not even possible with ordinary reflection.
When an object is serialized, it's class name and all instance fields (that are not transient) are written to the stream.
The magic happens when deserializing an object.
First, a new instance of the class is allocated.
To do that, the no-argument constructor of the first non-serializable superclass is called. The constructor of the serializable class (and serializable superclasses) are skipped. How? Magic.
Then all instance fields of the serializable classes are set.
(This step can be customized using a private void readObject(ObjectInputStream) method)
Lastly, a readResolve() method is called - if such a method exists. It's result is used as the result of deserializing the object.
(This does not apply to records, instances of java.lang.Class, java.lang.String, java.lang.Enum...)
In your example, this means that a new instance of your SerializableSingleton is created - bypassing your private constructor and instead calling java.lang.Object.<init>() - so you won't see the "Constructor is being called" output.
Now you have two instances of an "Singleton". To restore the original singleton semantics (there only ever exists one single instance of that class), we replace the just-deserialized-instance with the canonical instance:
private Object readResolve() {
return getInstance();
}
tl;dr: Java's serialization is complicated and sometimes indistinguishable to black magic. Using java's serialization opens the door to some surprising behaviors.
As the docs say:
By implementing the readResolve method, a class can directly control
the types and instances of its own instances being deserialized. The
method is defined as follows:
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
And:
... For example, a Symbol class could be created for which only a
single instance of each symbol binding existed within a virtual
machine. The readResolve method would be implemented to determine if
that symbol was already defined and substitute the preexisting
equivalent Symbol object to maintain the identity constraint. In this
way the uniqueness of Symbol objects can be maintained across
serialization.
And:
A writeObject method to control what information is saved ...
A readObject method [..] to read the information written ...
A writeReplace method to allow a class to nominate a replacement object to be written to the stream
A readResolve method to allow a class to designate a replacement object for the object just read from the stream
To get full control of Serialization (also to serialize static and transient fields) you have to implement the Externalization interface:
The writeExternal and readExternal methods of the Externalizable
interface are implemented by a class to give the class complete
control over the format and contents of the stream for an object and
its supertypes.
So writeReplace and readResolve methods give you some more control than the ordinary (and automated) serialization mechanism, that is, replace the object before/after serialization. and it is not urgently linked to Singleton serialization, but to fulfill the proxy pattern for serialization. But as you mentioned, this mechanism is also used to implement serialization of a Singleton.
Related
I'm dealing with a contractor's code. For whatever reason he has made a series of "constants" files that are all interfaces. They look like this:
interface SomeTypeConsts {
public static class SomeSubTypeA {
public static final String CONSTANT_A = "foo";
public static final String CONSTANT_B = "bar";
}
public static class SomeSubTypeB {
public static final String CONSTANT_A = "baz";
}
}
and so forth. There are no unimplemented/abstract methods, the files just contain nested classes some arbitrary level deep, and static final Strings for the constants. I cannot modify the contractor's code at this time.
I'm writing a test framework and I need an instance of one of these constants interfaces. All of them follow the above pattern, but my method needs to support all of them and not just one in specific.
I tried instantiating the interface using Reflection like this:
clazz.newInstance() // where clazz is Class<SomeTypeConsts>
But it threw a java.lang.InstantiationException.
All of the questions here on SO say that you need to implement the interface first, then use that instance. And if I knew ahead of time which const interface it was, I could easily do SomeTypeConsts consts = new SomeTypeConsts(){};. But I haven't been able to figure out how to do this with reflection, when all I have to work with is the Class<SomeTypeConst>.
Given an interface Class reference, with no abstract methods to be overwritten/implemented, how can I instantiate an instance of it using reflection?
You could do this using a JDK proxy for the interface, but it would be entirely pointless: If all you're doing is accessing static members, all of that is resolved without reference to any actual instance of the type in question, either at compile-time (far preferable) or at runtime with some approach like enumerating the fields and filtering on the static ones.
From the language spec (emphasis mine):
This type has no instance variables, and typically declares one or more abstract methods; otherwise unrelated classes can implement the interface by providing implementations for its abstract methods. Interfaces may not be directly instantiated.
And, from the Javadoc of Class.newInstance():
[throws] InstantiationException - if this Class represents an abstract class, an interface, an array class, a primitive type, or void; or if the class has no nullary constructor; or if the instantiation fails for some other reason.
You can't instantiate an interface. You can only instantiate (non-abstract) classes which implement it.
No. You cannot do that. Interfaces by definition are not instantiable.
What you need is a mock object. Not reflection
I have been programming in Java for quite some time, but when I tried to explain what an java.lang.Object class is to a friend, I could not come up with more than a simple one-liner:
All objects in Java extend java.lang.Object implicitly
I was not quite sure why it should do so.
So, I looked upon the source code on GrepCode, hoping that I can find some clues. Now I know what a java.lang.Object is and what it does, I want to know if there was any specific reason as to why it was designed this way.
My question still prevails: why should every object extend java.lang.Object?
I would say that the reason is to have a common API for all objects in java to supports basic functionality like
synchronization - wait, notify, notifyAll
garbage collection - finalize
collection support - hashCode, equals
object cloning - clone
And every object
has a class it belongs to - getClass
can represent itself as a string, because we are
humans and can read strings - toString
I think the most important use of Object is not to provide common methods like toString() but to provide a common type that would hold all reference types.
C++ don't have an Object equivalent and people are still happy. But since Java don't have pointers and C++-like templates, Object is required to make implementations of Collections, etc. possible.
See also on discussions on reference and primitive types.
This is how the language is designed. Every object will inherit from the base class Object. This means that it's guaranteed for every object there will be certain methods, like toString(), equals(), hashCode(), etc.
I would say Design. Common/Mandatory methods which every Object should support written there and extending that class as a language specification.
You find the reasons here in Official Docs.
If we are saying this is an Object ,They must have the common methods, Which defined/decided by API.
Imagine the below methods for every class on your Own.
protected Object clone() throws CloneNotSupportedException
Creates and returns a copy of this object.
public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
protected void finalize() throws Throwable
Called by the garbage collector on an object when garbage
collection determines that there are no more references to the object
public final Class getClass()
Returns the runtime class of an object.
public int hashCode()
Returns a hash code value for the object.
public String toString()
Returns a string representation of the object.
The notify, notifyAll, and wait methods of Object all play a part in synchronizing the activities of independently running threads in a program:
public final void notify()
public final void notifyAll()
public final void wait()
public final void wait(long timeout)
public final void wait(long timeout, int nanos)
So to reduce the pain, created a common and standard API.
Every Class extends Object class implicitly so that they provide basic features which according to Java recommendation every class should have. Such as clone(), equals(), hashCode(), toString(), etc.
By implicitly, it means that if you are not extending any class then only compiler will implicitly extends Object class.But if class already extends other class then compiler will not extend Object class. For eg.
Class A{
}
Class B extends A{
}
Here compiler will implicitly add extends Object class in class A declaration.
Class A extends Object{
}
Class B extends A{
}
As class A extends Object class so it will provide basic functionality of Object class such as equals(), toString(),etc. And since Class B extends class A which implicitly extends Class Object, so class B also provides all those features.
Thus by following this approach every class objects(variables) complies to features which every Java Object should have, without going for Multiple Inheritance (a class extending more than one class) which Java doesn't allows. This approach follows Multi-Level Inheritance.
This is done so as most of the basic functions like toString() etc would be automatically inherited and to your next question this is NOT multiple inheritence it is multilevel inheritence...
In multiple inheritence single class is derived from 2 or more base class whereas in multilevel as you have said it has a base class which is itself derived from Object class
Quoting Head first Java 2nd edition:
Without a common superclass for everything in Java, thereād be no way
for the developers of Java to create classes with methods that could
take your custom types... types they never knew about when they wrote
the ArrayList class.
Which essentially explains the need of a generic predefined class type in Java, which can be used to implement the different features provided by the language.
See the docs:
The Object class, in the java.lang package, sits at the top of the
class hierarchy tree. Every class is a descendant, direct or indirect,
of the Object class. Every class you use or write inherits the
instance methods of Object. You need not use any of these methods,
but, if you choose to do so, you may need to override them with code
that is specific to your class.
The Object class simply defines the basic state that all objects must have - Like comparing it to other objects.
It's the parent class of everything. It simply provides kind of template to all the derived objects.
It's a java design decision. It puts to use the concept of inheritance and re-usabilty. This ensures that all classes have some basic methods like wait(), toString() etc.
Object class is the most super class of java programming, It has predefined methods according to types, you can use those methods. & you don't need to extends object class anymore & anywhere it's implicitly there
Every class in Java is a descendent (direct or indirect) of the Object class. The Object class defines the basic state and behavior that all objects must have, such as the ability to compare oneself to another object, to convert to a string, to wait on a condition variable, to notify other objects that a condition variable has changed, and to return the object's class.
I have:
class MyClass extends MyClass2 implements Serializable {
//...
}
In MyClass2 is a property that is not serializable. How can I serialize (and de-serialize) this object?
Correction: MyClass2 is, of course, not an interface but a class.
As someone else noted, chapter 11 of Josh Bloch's Effective Java is an indispensible resource on Java Serialization.
A couple points from that chapter pertinent to your question:
assuming you want to serialize the state of the non-serializable field in MyClass2, that field must be accessible to MyClass, either directly or through getters and setters. MyClass will have to implement custom serialization by providing readObject and writeObject methods.
the non-serializable field's Class must have an API to allow getting it's state (for writing to the object stream) and then instantiating a new instance with that state (when later reading from the object stream.)
per Item 74 of Effective Java, MyClass2 must have a no-arg constructor accessible to MyClass, otherwise it is impossible for MyClass to extend MyClass2 and implement Serializable.
I've written a quick example below illustrating this.
class MyClass extends MyClass2 implements Serializable{
public MyClass(int quantity) {
setNonSerializableProperty(new NonSerializableClass(quantity));
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
// note, here we don't need out.defaultWriteObject(); because
// MyClass has no other state to serialize
out.writeInt(super.getNonSerializableProperty().getQuantity());
}
private void readObject(java.io.ObjectInputStream in)
throws IOException {
// note, here we don't need in.defaultReadObject();
// because MyClass has no other state to deserialize
super.setNonSerializableProperty(new NonSerializableClass(in.readInt()));
}
}
/* this class must have no-arg constructor accessible to MyClass */
class MyClass2 {
/* this property must be gettable/settable by MyClass. It cannot be final, therefore. */
private NonSerializableClass nonSerializableProperty;
public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) {
this.nonSerializableProperty = nonSerializableProperty;
}
public NonSerializableClass getNonSerializableProperty() {
return nonSerializableProperty;
}
}
class NonSerializableClass{
private final int quantity;
public NonSerializableClass(int quantity){
this.quantity = quantity;
}
public int getQuantity() {
return quantity;
}
}
MyClass2 is just an interface so techinicaly it has no properties, only methods. That being said if you have instance variables that are themselves not serializeable the only way I know of to get around it is to declare those fields transient.
ex:
private transient Foo foo;
When you declare a field transient it will be ignored during the serialization and deserialization process. Keep in mind that when you deserialize an object with a transient field that field's value will always be it's default (usually null.)
Note you can also override the readResolve() method of your class in order to initialize transient fields based on other system state.
If possible, the non-serialiable parts can be set as transient
private transient SomeClass myClz;
Otherwise you can use Kryo. Kryo is a fast and efficient object graph serialization framework for Java (e.g. JAVA serialization of java.awt.Color requires 170 bytes, Kryo only 4 bytes), which can serialize also non serializable objects. Kryo can also perform automatic deep and shallow copying/cloning. This is direct copying from object to object, not object->bytes->object.
Here is an example how to use kryo
Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();
Serialized objects can be also compressed by registering exact serializer:
kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));
If you can modify MyClass2, the easiest way to address this is declare the property transient.
Depends why that member of MyClass2 isn't serializable.
If there's some good reason why MyClass2 can't be represented in a serialized form, then chances are good the same reason applies to MyClass, since it's a subclass.
It may be possible to write a custom serialized form for MyClass by implementing readObject and writeObject, in such a way that the state of the MyClass2 instance data in MyClass can be suitably recreated from the serialized data. This would be the way to go if MyClass2's API is fixed and you can't add Serializable.
But first you should figure out why MyClass2 isn't serializable, and maybe change it.
You will need to implement writeObject() and readObject() and do manual serialization/deserialization of those fields. See the javadoc page for java.io.Serializable for details. Josh Bloch's Effective Java also has some good chapters on implementing robust and secure serialization.
You can start by looking into the transient keyword, which marks fields as not part of the persistent state of an object.
Several possibilities poped out and i resume them here:
Implement writeObject() and readObject() as sk suggested
declare the property transient and it won't be serialized as first stated by hank
use XStream as stated by boris-terzic
use a Serial Proxy as stated by tom-hawtin-tackline
XStream is a great library for doing fast Java to XML serialization for any object no matter if it is Serializable or not. Even if the XML target format doesn't suit you, you can use the source code to learn how to do it.
A useful approach for serialising instances of non-serializable classes (or at least subclasses of) is known a Serial Proxy. Essentially you implement writeReplace to return an instance of a completely different serializable class which implements readResolve to return a copy of the original object. I wrote an example of serialising java.awt.BasicStroke on Usenet
How can I serialize an object that does not implement Serializable? I cannot mark it Serializable because the class is from a 3rd party library.
You can't serialise a class that doesn't implement Serializable, but you can wrap it in a class that does. To do this, you should implement readObject and writeObject on your wrapper class so you can serialise its objects in a custom way.
First, make your non-serialisable field transient.
In writeObject, first call defaultWriteObject on the stream to store all the non-transient fields, then call other methods to serialise the individual properties of your non-serialisable object.
In readObject, first call defaultReadObject on the stream to read back all the non-transient fields, then call other methods (corresponding to the ones you added to writeObject) to deserialise your non-serialisable object.
I hope this makes sense. :-)
Wrap the non-serializable class in a class of your own that implements Serializable. In your class's writeObject method, do whatever's necessary to serialize sufficient information on the non-serializable object so that your class's readObject method can reconstruct it.
Alternatively, contact the developer of the non-serializable class and tell him to fix it. :-)
You can use Kryo. It works on non serialized classes but classes needs registered aforehand.
If your class already implements the Serializable interface (required for serializing), all you must do is to declare the field you don't want to serialize with transient:
public transient String description;
If the class is not final, you can make your own class that extends it and implements Serializable. There are lots of other ways to serialize besides Java's built-in mechanism though.
I'm getting this error when I try to serialize a Method object.
java.io.NotSerializableException: java.lang.reflect.Method
Any Idea?
You can do it manually. Just serialize your class name, method name and parameter class names as strings and then recreate your Method object using a reflection mechanism during deserialization.
Class.forName(clsName).getMethod("methodName", Class.forName(param1ClsName), ....);
If you implement Externalizable interface then You can use your class as regular serializable class.
There is no way to serialize a method object in a portable way since it doesn't contain all the necessary information to restore it (for example, the bytecode).
Instead, you should serialize the name of the class, the method name and the parameter types. Then you can recreate the Method instance during deserialization.
java.lang.reflect.Method does not implement java.io.Serializable. So it can not be serialized using the build-in Java methods.
Assuming that the java.lang.reflect.Method object is a member of another class, you should mark it as transient, and recreate it using class name and method name/signature after deserialization.
You could implement an MethodInfo class for this purpose.
class SerializableClass {
private transient Method m_method; //Not serialized
private MethodInfo m_methodInfo;
public Method getMethod() {
if(m_method != null) {
//Initailize m_method, based on m_methodInfo
}
return m_method;
}
}