2011-02-11 21 views
5

Es posible serializar el 'vacío' primitivo por defecto, ¿por qué el objeto 'Vacío' no se puede serializar?¿Por qué java.lang.Void no se puede serializar?

ejemplo Agregado:

El RootImplementation tendrá un error de compilación diciendo "Vacío no está dentro de su límite", ya que no se extiende Serializable. Aunque se declararía 'someMethod' con 'void' no sería problema.

public interface Root<R extends Serializable> extends Serializable { 
    R someMethod(); 
} 

public class RootImplementation implements Root<Void> { 
    public Void someMethod() { 
    return null; 
    } 
} 

+1

No hay tal cosa como un vacío primitivo. Y Void nunca tiene una instancia, y no puedo pensar en un caso de uso donde sería un campo en una clase. Pero si lo es, siempre puedes hacerlo transitorio, ya que siempre será nulo de todos modos. – Yishai

+4

¿Qué quiere decir con "es posible serializar el 'vacío' primitivo por defecto"? No hay datos para serializar ... ¿puedes dar un ejemplo de lo que quieres decir? –

+0

Agregaré un ejemplo, 2 seg. –

Respuesta

5

OK, en respuesta a su ejemplo, no si cambió el método a void no funcionaría, ya que el método debe tener un tipo de devolución (incluso si Java ahora permite tipos de devolución covariantes en métodos reemplazados). La discusión de void confunde el problema.

Lo que quiere hacer es declarar un parámetro de tipo como "simplemente devolverá nulo". Void es generalmente una buena opción para eso, pero para que Void funcione, el tipo de devolución debe ser Object. Void no puede implementar todas las interfaces en la API simplemente porque alguien quiera usarla para indicar un retorno nulo en un parámetro de tipo.

Hay tres maneras de ver su problema:

  1. Serializable es una declaración de tipo excesivamente restrictiva. Realmente deberías estar usando Object. ¿Realmente necesitas que sea Serializable?
  2. Puede declarar el parámetro tipo como Serializable y, en la práctica, devolver nulo. Esto no indica completamente que está regresando nulo cada vez, pero puede ser suficiente.
  3. Puede declarar su propia clase llamada Null que implementa Serializable, tal vez como una clase anidada estática de la interfaz raíz, y usar eso como el parámetro de tipo en este caso. Encontrará que hacer su propio objeto nulo no es poco común, incluso en el JDK estándar existe (uno privado).
+0

Gracias por la respuesta. 1. Como menciona ColinD; la mayoría simplemente tira el Serialziable del tipo genérico ya que la declaración de clase en sí misma implica no guardar objetos no serializables en la implementación. Aunque bastantes personas van a usar la interfaz y realizar implementaciones, quiero que sea lo más útil posible para no cometer un error. 2. No deseo que la extensión eventual pueda devolver nada más que void (o nulo en este caso, ya que se debe usar Void). 3. Así es como lo he hecho en este momento, aunque quería hacer la pregunta y ver si alguien tenía una mejor solución. –

+0

@Tomas Forsman, una clase que implementa serializable, no significa que se pueda serializar. Considere esto: 'private void writeObject (ObjectOutputSteam out) {throw new NotSerializableException (getClass(). GetName());}' Lo uso para asegurarme de que algunas clases extendidas nunca lleguen a la forma de serialización. – bestsss

4

el Javadoc es clara:

La clase Vacío es una clase marcador de posición crearse instancias para almacenar una referencia a la clase de objeto que representa la palabra clave Java

Debido no puedes usarlo, no necesita ser serializable (excepto cosas de reflexión).


Y a la segunda pregunta: vacío = Vacío (! Si se piensa en = en una expresión no java)

void es una palabra clave y Void una clase.

1

citar el Javadocs:

La clase Void es un marcador de posición de clase crearse instancias para almacenar una referencia al objeto de clase que representa el vacío de palabras clave de Java.

Como la clase no se puede desinstalar, no se puede deserializar. Ergo no necesita soporte de serialización.

0

Es posible serializar el primitiva 'vacío' por defecto, ¿por qué no el objeto 'vacío' se extienden Serializable?

Void no tiene ningún valor, por lo tanto, no tiene sentido serializarlo.

¿Esto no significa que void! = Void?

True, just as int! = Entero. Pero cuando serializas y deserializas dos entradas, newint == oldint (quiero decir int, no Integer !!!). Ninguna construcción así sería posible con void. Simplemente no tiene sentido serializar nada.

+0

¿Por qué el voto a favor? ¿Qué pasa? –

0

Sería útil solo si tuviera un campo de tipo Void, que realmente no tiene sentido. También necesitarías asignarle una instancia, lo que nuevamente no tiene sentido. Mientras no lo hagas, puedes serializar la instancia de la clase que contiene el campo Void. Para crear una instancia de Void, necesita usar la reflexión para usar el constructor privado.

public class VoidSerializerDemo implements Serializable { 
    private Void v; 

    public static void main(String[] args) throws Exception { 
     final VoidSerializerDemo instance = new VoidSerializerDemo(); 
     final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     final ObjectOutputStream oos = new ObjectOutputStream(baos); 
     oos.writeObject(instance); 
     System.out.println("OK: null works"); 
     final Constructor<Void> constructor = Void.class.getDeclaredConstructor(); 
     constructor.setAccessible(true); 
     instance.v = constructor.newInstance(); 
     oos.reset(); 
     System.out.println("Going to throw"); 
     oos.writeObject(instance); 
    } 
} 

Así que es extremadamente improbable que alguna vez tenga que preocuparse por la serializabilidad de Void, ¿no es así?

0

Otros han explicado por qué no tiene sentido para un tipo que nunca se puede instanciar para implementar Serializable y por qué void no es una primitiva o serializable.

Para abordar el código en su edición, creo que debería simplemente cambiar el R extends Serializable con destino a solo R. La mayoría de los tipos genéricos que son Serializable no requieren que sus parámetros de tipo sean Serializable ... simplemente afirman que si coloca algo en ellos que no es serializable, tampoco serán serializables. En general, esta es una buena práctica, ya que intentar demasiado forzar la serializabilidad a nivel de compilador puede morderlo (como puede ver aquí).

0

Void sólo se diseñó para demostrar que un método sólo puede volver null, por desgracia no hay manera de declarar el tipo nulo directamente. Para el jvm Void es solo un objeto que se extiende de clase normal y como tal no se puede usar en su lugar para otras clases o interfaces, esto hace que Void sea inútil para su ejemplo.

Debido a que su método suele devuelve nada, pero nula podría reemplazar vacío con algo como lo siguiente:

public final SerializebaleVoid extends Object implements Serializeable{ 
    private SerializeableVoid(){} 
} 

En cuanto a llamar a anular una primitiva, nula muestra la ausencia de un valor, un vacío de regresar método no hace devuelve un valor de tipo vacío en su lugar, literalmente no devuelve nada.

2

lo pondré aquí como comminity-wiki

Tú puede (de) serializar java.lang.Void b/c puede inicializar con solamente nula. A Java no le importa si una clase implementa java.io.Serializable si es null.

resultado del código

 
[email protected] 
[email protected] 

public class VoidOut implements java.io.Serializable{ 
    int x=1; 
    Void v = null; 

    public static void main(String[] args) throws Throwable{ 
     VoidOut v = new VoidOut(); 
     System.out.println(v); 
     ByteArrayOutputStream b =new ByteArrayOutputStream(256); 
     ObjectOutputStream o = new ObjectOutputStream(b); 
     o.writeObject(v); 
     o.close(); 
     ObjectInputStream in =new ObjectInputStream(new ByteArrayInputStream(b.toByteArray())); 
     System.out.println(in.readObject());   
    } 
} 
Cuestiones relacionadas