devolver un objeto vacío


113

¿Cuál es la forma correcta de devolver un Voidtipo, cuando no es un primitivo? P.ej. Actualmente uso null como se muestra a continuación.

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}

1
Estoy escribiendo un intérprete para un formato de archivo, usando el patrón de intérprete, pero algunas expresiones no tienen valores de retorno
Robert

2
No hay forma de crear una instancia del tipo Void, por lo que si realmente tiene que devolver algo de ese tipo, null es su única opción. Sin embargo, probablemente no necesite el valor devuelto para nada, por lo que nulo debería estar bien.
Jorn

sí, esa era mi lógica también, solo me preguntaba si había una forma más semántica
Robert

1
Lo codificaría como tu ejemplo. Ese es un buen enfoque.
David Roussel

Respuestas:


134

La clase Void es una clase de marcador de posición no desinstalable para contener una referencia al objeto Class que representa la palabra clave de Java void.

Entonces, cualquiera de los siguientes sería suficiente:

  • parametrizar con Objecty devolver new Object()onull
  • parametrizar con Voidy regresarnull
  • parametrizar con uno NullObjecttuyo

No puede hacer este método voidy cualquier otra cosa devuelve algo . Dado que ese algo se ignora, puede devolver cualquier cosa.


2
entonces, ¿cuál es la forma genéricamente correcta de lograr un tipo de retorno de vacío?
Robert

1
Si desea devolver null como vacío, debe lanzarlo en algunos casos: (Void) null
Patrick Favre

return (Void)null;
Alex R

¿Se puede (nulo) nulo diferenciarse de nulo de alguna manera?
Orangle

13

Java 8 ha introducido una nueva clase, Optional<T> , que se puede utilizar en tales casos. Para usarlo, modificaría ligeramente su código de la siguiente manera:

interface B<E>{ Optional<E> method(); }

class A implements B<Void>{

    public Optional<Void> method(){
        // do something
        return Optional.empty();
    }
}

Esto le permite asegurarse de obtener siempre un valor de retorno no nulo de su método, incluso cuando no hay nada que devolver. Eso es especialmente poderoso cuando se usa junto con herramientas que detectan cuándo se nullpuede o no se puede devolver, por ejemplo, el Eclipse @NonNully las @Nullableanotaciones.


5
Mi opinión es que esto va en la dirección equivocada. Es mejor devolver un tipo mucho más restringido que transmita el significado mucho más claro. Tener algo que devuelve un Optional<Void>es innecesario por la misma razón que usted da, siempre obtiene un Optional<Void>que está vacío y, por lo tanto, todos los demás métodos son inútiles. Esto es lo contrario de por qué debería usarse un valor opcional. Lo usa porque puede o no tener un valor. Además, el compilador no puede exigir que lo method()implemente correctamente. Esto sería un fracaso en tiempo de ejecución: return Optional.of(null).
steinybot

3

Si simplemente no necesita nada como su tipo, puede usar void. Esto se puede utilizar para implementar funciones o acciones. Entonces podrías hacer algo como esto:

interface Action<T> {
    public T execute();
}

abstract class VoidAction implements Action<Void> {
    public Void execute() {
        executeInternal();
        return null;
    }

    abstract void executeInternal();
}

O puede omitir la clase abstracta y hacer el retorno nulo en cada acción que no requiera un valor de retorno usted mismo.

Luego puede usar esas acciones como esta:

Dado un método

private static <T> T executeAction(Action<T> action) {
    return action.execute();
}

puedes llamarlo como

String result = executeAction(new Action<String>() {
    @Override
    public String execute() {
        //code here
        return "Return me!";
    }
});

o, para la acción nula (tenga en cuenta que no está asignando el resultado a nada)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});

2
¿En qué se diferencia esto de lo que ya tengo? todavía devuelve nulo, como sugerí
Robert

¿Por qué tendrías que devolver algo más? El punto que estoy tratando de hacer es que no necesita el valor de retorno, por lo que no importa lo que devuelva. Traté de aclarar eso con mi edición.
Jorn

1

Por el simple hecho de hacerlo, existe, por supuesto, la posibilidad de crear una Voidinstancia mediante la reflexión:

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something

        try {
            Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
            voidConstructor.setAccessible(true);
            return voidConstructor.newInstance();
        } catch (Exception ex) {
            // Rethrow, or return null, or whatever.
        }
    }
}

Probablemente no haga eso en producción.


0

No existe un tipo genérico que le diga al compilador que un método no devuelve nada.

Creo que la convención es usar Object cuando se hereda como parámetro de tipo

O

Propague el parámetro de tipo y luego permita que los usuarios de su clase creen una instancia usando Object y asignen el objeto a una variable escrita usando un tipo de comodín ?:

interface B<E>{ E method(); }

class A<T> implements B<T>{

    public T method(){
        // do something
        return null;
    }
}

A<?> a = new A<Object>();

1
¿Es esta la convención para configurar el tipo de retorno como anulado con genéricos? ¿No me parece muy vacío?
Robert

Creo que este es el camino a seguir. Ningún usuario de la clase A<?>podrá hacer uso del valor devuelto de method().
Christopher Oezbek
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.