restituire un oggetto Void


113

Qual è il modo corretto per restituire un Voidtipo, quando non è una primitiva? Per esempio. Attualmente uso null come di seguito.

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

class A implements B<Void>{

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

1
sto scrivendo un interprete per un formato di file, usando il modello interprete, ma alcune espressioni non hanno valori di ritorno
Robert

2
Non c'è modo di istanziare il tipo Void, quindi se devi davvero restituire qualcosa di quel tipo, null è la tua unica opzione. Tuttavia, probabilmente non è necessario il valore restituito per nulla, quindi null dovrebbe andare bene.
Jorn

sì, anche quella era la mia logica - mi chiedevo solo se ci fosse un modo più semantico
Robert

1
Lo codificherei proprio come il tuo esempio. È un ottimo approccio.
David Roussel

Risposte:


134

La classe Void è una classe segnaposto non istanziabile per contenere un riferimento all'oggetto Class che rappresenta la parola chiave Java void.

Quindi una qualsiasi delle seguenti operazioni sarebbe sufficiente:

  • parametrizzare con Objecte restituire new Object()onull
  • parametrizzazione con Voide ritornonull
  • parametrizzare con un NullObjecttuo

Non puoi creare questo metodo voide qualsiasi altra cosa restituisce qualcosa . Poiché quel qualcosa viene ignorato, puoi restituire qualsiasi cosa.


2
allora qual è il modo genericamente corretto per ottenere un tipo di vuoto di ritorno?
Robert

1
Se vuoi restituire null come void devi lanciarlo in alcuni casi: (Void) null
Patrick Favre

return (Void)null;
Alex R

(Void) null può essere differenziato in qualche modo da null?
Orangle,

13

Java 8 ha introdotto una nuova classe Optional<T>, che può essere utilizzata in questi casi. Per usarlo, modifichi leggermente il tuo codice come segue:

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

class A implements B<Void>{

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

Ciò ti consente di assicurarti di ottenere sempre un valore restituito non nullo dal tuo metodo, anche quando non c'è nulla da restituire. È particolarmente potente se utilizzato insieme a strumenti che rilevano quando nullpuò o non può essere restituito, ad esempio Eclipse @NonNulle @Nullableannotazioni.


5
La mia opinione è che questo stia andando nella direzione sbagliata. È meglio restituire un tipo molto più vincolato che trasmetta il significato in modo molto più chiaro. Avere qualcosa che restituisce un Optional<Void>non è necessario per lo stesso motivo che dai, ottieni sempre un Optional<Void>che è vuoto e quindi tutti gli altri metodi sono inutili. Questo è l'opposto del motivo per cui dovrebbe essere utilizzato un valore opzionale. Lo usi perché può o non può avere un valore. Inoltre, il compilatore non può imporre che lo method()implementa correttamente. Questo avrebbe fallito in fase di esecuzione: return Optional.of(null).
steinybot

3

Se semplicemente non hai bisogno di nulla come tipo, puoi usare void. Può essere utilizzato per implementare funzioni o azioni. Potresti quindi fare qualcosa del genere:

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

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

    abstract void executeInternal();
}

Oppure puoi omettere la classe astratta e restituire null in ogni azione che non richiede un valore di ritorno.

Puoi quindi usare quelle azioni in questo modo:

Dato un metodo

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

puoi chiamarlo come

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

oppure, per l'azione void (nota che non stai assegnando il risultato a nulla)

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

2
in che modo è diverso da quello che ho già? restituisce ancora solo null, come ho suggerito
Robert

Perché dovresti restituire qualcos'altro? Il punto che sto cercando di sottolineare è che non hai bisogno del valore restituito, quindi non importa cosa restituisci. Ho provato a chiarirlo con la mia modifica.
Jorn

1

Solo per il gusto di farlo, c'è ovviamente la possibilità di creare Voidistanze usando la riflessione:

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.
        }
    }
}

Probabilmente non lo farai in produzione.


0

Non esiste un tipo generico che dirà al compilatore che un metodo non restituisce nulla.

Credo che la convenzione sia quella di utilizzare Object quando si eredita come parametro di tipo

O

Propaga il parametro di tipo verso l'alto e quindi consenti agli utenti della tua classe di creare un'istanza utilizzando Object e assegnando l'oggetto a una variabile digitata utilizzando un carattere jolly di tipo ?:

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

class A<T> implements B<T>{

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

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

1
è questa la convenzione per impostare il tipo di ritorno su nullo con i generici - non mi sembra molto nullo?
Robert

Credo che questa sia la strada da percorrere. Qualsiasi utente della classe A<?>non sarà in grado di utilizzare il valore restituito di method().
Christopher Oezbek
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.