Código fuente del programa ObjectCreationTest
Ver la entrada correspondiente en el siguiente enlace:
¿Se pueden crear objetos en Java sin pasar por ningún constructor?
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintStream; import java.io.Serializable; import java.lang.reflect.Constructor; /** * @see http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html * @see http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29 * * @see http://stackoverflow.com/questions/3488097/is-it-possible-to-create-an-instance-of-an-object-in-java-without-calling-the-co * @see http://www.javaspecialists.eu/archive/Issue175.html * * @see http://objenesis.googlecode.com/svn/docs/index.html */ public class ObjectCreationTest { /** Puesto por comodidad. */ private static final PrintStream OUT= System.out; //-------------------------------------------------------------------------- /** * Serializa y deserializa un objeto, devolviendo el objeto resultante * de la deserialización. * * @param aSerializable * * @return * * @throws IOException * @throws ClassNotFoundException */ public static Serializable serializeAndDeserialize(Serializable aSerializable) throws IOException, ClassNotFoundException { ByteArrayOutputStream bos= null; ObjectOutputStream oos= null; ByteArrayInputStream bis= null; ObjectInputStream ois= null; try { if (aSerializable == null) { throw new IllegalArgumentException("Cannot Serialize/Deserialize a null object."); } //Se serializa el objeto en memoria sobr e un byte[]. bos= new ByteArrayOutputStream(); oos= new ObjectOutputStream(bos); oos.writeObject(aSerializable); byte[] byte_s= bos.toByteArray(); //Se deserializa el byte[] sobre un nuevo objeto. bis= new ByteArrayInputStream(byte_s); ois= new ObjectInputStream(bis); Serializable deserialized= (Serializable) ois.readObject(); return deserialized; } finally { if (bos != null) { bos.close(); } if (oos != null) { oos.close(); } if (bis != null) { bis.close(); } if (ois != null) { ois.close(); } } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- /** * Programa de prueba. * * @param args */ public static void main(String[] args) { try { OUT.println("Start"); long antes= System.currentTimeMillis(); OUT.println("...new object..."); MySerializable normal= new MySerializable("I was created at main(...) with new."); OUT.println("...clone()..."); MySerializable cloned= (MySerializable) normal.clone(); OUT.println("...serialize and deserialize..."); MySerializable serialized= (MySerializable) serializeAndDeserialize(normal); OUT.println("...reflection..."); //In this case Class.newInstance() cannot be used because MySerializable doesn't have a zero-argument constructor. Constructor<MySerializable> constructor= MySerializable.class.getConstructor(String.class); MySerializable reflect= constructor.newInstance("I was created at main(...) with Reflection."); OUT.println(); OUT.println("...results..."); OUT.format("normal= %s%n", normal); OUT.format("cloned= %s%n", cloned); OUT.format("serialized= %s%n", serialized); OUT.format("reflect= %s%n", reflect); OUT.format("There are 4 diferent instances.%n"); OUT.println(); OUT.format("(normal == cloned)? %s%n", (normal == cloned)); OUT.format("(normal == serialized)? %s%n", (normal == cloned)); OUT.format("(cloned == serialized)? %s%n", (normal == cloned)); OUT.println(); OUT.format("MySerializable.INSTANCE_COUNT= %s%n", MySerializable.INSTANCE_COUNT); OUT.println(); OUT.format("End. %sms%n", System.currentTimeMillis()-antes); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- /** * Superclase de la clase a serializar/deserializar. */ public static class Base { //Se invoca al constructor sin argumentos al deserializar. El atributo <name> será establecido en dicho constructor. ///public static class Base implements Serializable {//No se invoca ningún constructor al deserializar. /** Sólo se puede, y se debe establecer desde un constructor/inicializador. */ final private String name; //-------------------------------------------------------------------------- public Base(String aName) { super(); OUT.format("Base(String)#Creating a %s. aName<%s>%n" , this.getClass() , aName ); this.name= aName; } //-------------------------------------------------------------------------- /** * Este es requerido si la clase no implementa Serialized pero la subclase sí. */ public Base() { this("Default constructor required for deserialization."); OUT.format("Base()#Creating a %s.%n" , this.getClass() ); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- @Override public String toString() { String str= String.format("Name<%s>." , this.name ); return str; } //-------------------------------------------------------------------------- } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- /** * Clase que se va a Serializar/Deserializar en el programa de prueba. */ public static class MySerializable extends Base implements Serializable, Cloneable { /** Recomendación de la interface java.io.Serializable */ private static final long serialVersionUID= 1L; /** Número de instancias construídas de esta clase. */ public static int INSTANCE_COUNT= 0; //-------------------------------------------------------------------------- public MySerializable(String aName) { super(aName); INSTANCE_COUNT++; OUT.format("MySerializable(String)#Creating a %s. INSTANCE_COUNT=%s%n" , this.getClass() , INSTANCE_COUNT ); } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- /** * Hay que convertir el método clone de protected a public. */ @Override public Object clone()throws CloneNotSupportedException { return super.clone(); } //-------------------------------------------------------------------------- @Override public String toString() { String str= String.format("Instance of %s with IdentityHashCode<%s> %s" , this.getClass() , System.identityHashCode(this) , super.toString() ); return str; } //-------------------------------------------------------------------------- } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- }
No hay comentarios:
Publicar un comentario