domingo, 26 de mayo de 2013

Source Code: ObjectCreationTest

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