143

What is the correct way to return a Void type, when it isn't a primitive? Eg. I currently use null as below.

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

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}
Robert
  • 8,406
  • 9
  • 38
  • 57
  • 1
    i'm writing an interpreter for a file format, using the interpreter pattern, but some expressions don't have return values – Robert Mar 09 '10 at 11:36
  • 3
    There's no way to instantiate the Void type, so if you really have to return something of that type, null is your only option. However, you probably don't need the returned value for anything, so null should be fine. – Jorn Mar 09 '10 at 11:52
  • yeah, that was my logic too - just wondered if there was a more semantic way – Robert Mar 09 '10 at 11:56
  • 1
    I would code it up just like your example. That's a fine approach. – David Roussel Mar 09 '10 at 13:13

7 Answers7

165

The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.

So any of the following would suffice:

  • parameterizing with Object and returning new Object() or null
  • parameterizing with Void and returning null
  • parameterizing with a NullObject of yours

You can't make this method void, and anything else returns something. Since that something is ignored, you can return anything.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
16

Java 8 has introduced a new class, Optional<T>, that can be used in such cases. To use it, you'd modify your code slightly as follows:

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

class A implements B<Void>{

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

This allows you to ensure that you always get a non-null return value from your method, even when there isn't anything to return. That's especially powerful when used in conjunction with tools that detect when null can or can't be returned, e.g. the Eclipse @NonNull and @Nullable annotations.

Erick G. Hagstrom
  • 4,873
  • 1
  • 24
  • 38
  • 12
    My opinion is that this is going in the wrong direction. It is better to return a much more constrained type that conveys the meaning much clearer. Having something that returns an `Optional` is unnecessary for the same reason that you give, you _always_ get an `Optional` that is empty and so all the other methods are pointless. This is the opposite of why an optional value should be used. You use it because it may or may not have a value. Also the compiler cannot enforce that `method()` implements it correctly. This would fail at runtime: `return Optional.of(null)`. – steinybot Mar 09 '17 at 20:58
3

If you just don't need anything as your type, you can use void. This can be used for implementing functions, or actions. You could then do something like this:

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

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

    abstract void executeInternal();
}

Or you could omit the abstract class, and do the return null in every action that doesn't require a return value yourself.

You could then use those actions like this:

Given a method

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

you can call it like

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

or, for the void action (note that you're not assigning the result to anything)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});
Jorn
  • 20,612
  • 18
  • 79
  • 126
  • 2
    how is this different from what I already have? it still just returns null, like I suggested – Robert Mar 09 '10 at 11:51
  • Why would you have to return anything else? The point I'm trying to make is you don't need the return value, so it doesn't matter what you return. I tried to clarify that with my edit. – Jorn Mar 09 '10 at 11:58
2

Just for the sake of it, there is of course the possibility to create Void instance using reflection:

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

You probably won't do that in production.

kap
  • 1,456
  • 2
  • 19
  • 24
1

It is possible to create instances of Void if you change the security manager, so something like this:

static Void getVoid() throws SecurityException, InstantiationException,
        IllegalAccessException, InvocationTargetException {
    class BadSecurityManager extends SecurityManager {
    
        @Override
        public void checkPermission(Permission perm) { }
    
        @Override
        public void checkPackageAccess(String pkg) { }

    }
    System.setSecurityManager(badManager = new BadSecurityManager());
    Constructor<?> constructor = Void.class.getDeclaredConstructors()[0];
    if(!constructor.isAccessible()) {
        constructor.setAccessible(true);
    }
    return (Void) constructor.newInstance();
}

Obviously this is not all that practical or safe; however, it will return an instance of Void if you are able to change the security manager.

0

There is no generic type which will tell the compiler that a method returns nothing.

I believe the convention is to use Object when inheriting as a type parameter

OR

Propagate the type parameter up and then let users of your class instantiate using Object and assigning the object to a variable typed using a type-wildcard ?:

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

class A<T> implements B<T>{

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

A<?> a = new A<Object>();
Christopher Oezbek
  • 23,994
  • 6
  • 61
  • 85
  • 1
    is this the convention for setting the return type to void with generics - it doesn't look very void to me? – Robert Mar 09 '10 at 11:48
  • I believe this is the way to go. Any user of class `A>` will not be able to make any use of the returned value of `method()`. – Christopher Oezbek Mar 09 '10 at 11:56
0

I found a new way to get an instance of Void class. This is a native code where env allocates a Void object. Then the object it's returned to java code. The object exists in java code and is usable as an actual instance.

JNIEXPORT jobject JNICALL Java_main_Main_getVoid(JNIEnv *env, jobject obj){
    jclass voidclass=env->FindClass("java/lang/Void");
    return env->AllocObject(voidclass);
}
  • 2
    Your answer does not help in the context of the question. The question is about the proper usage of the Void class in Java, not about how to create an object of type Void. – Ralf Wagner Jul 19 '22 at 06:17