返回一个Void对象

时间:2010-03-09 11:30:16

标签: java generics return-value

Void类型不是原始类型时,返回interface B<E>{ E method(); } class A implements B<Void>{ public Void method(){ // do something return null; } } 类型的正确方法是什么?例如。我目前使用null如下。

{{1}}

6 个答案:

答案 0 :(得分:115)

  

Void类是一个不可实例化的占位符类,用于保存对表示Java关键字void的Class对象的引用。

所以以下任何一项都足够了:

  • 使用Object进行参数设置并返回new Object()null
  • 使用Void进行参数设置并返回null
  • 使用您的NullObject参数化

你不能使这个方法void,而其他任何东西都会返回某些东西。由于忽略了某些东西,你可以退货。

答案 1 :(得分:9)

Java 8引入了一个新类Optional<T>,可以在这种情况下使用。要使用它,您可以按照以下方式稍微修改代码:

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

class A implements B<Void>{

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

这使您可以确保始终从方法中获得非空返回值,即使没有任何要返回的内容也是如此。当与检测何时可以或不能返回null的工具结合使用时,这种功能特别强大,例如Eclipse @NonNull@Nullable注释。

答案 2 :(得分:3)

如果您不需要任何类型的东西,可以使用void。这可用于实现功能或操作。然后你可以做这样的事情:

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

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

    abstract void executeInternal();
}

或者您可以省略抽象类,并在每个不需要返回值的操作中返回null。

然后你可以使用这样的行为:

给出方法

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

你可以称之为

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

或者,对于void操作(请注意,您没有将结果分配给任何内容)

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

答案 3 :(得分:0)

没有泛型类型会告诉编译器方法什么都不返回。

我认为惯例是在继承为类型参数时使用Object

OR

向上传播类型参数,然后让类的用户使用Object实例化并将对象分配给使用类型 - 通配符?键入的变量:

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

class A<T> implements B<T>{

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

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

答案 4 :(得分:0)

仅出于此目的,当然可以使用反射来创建Void实例:

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

您可能不会在生产中这样做。

答案 5 :(得分:0)

如果您更改安全管理器,则可以创建 Void 的实例,如下所示:

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();
}

显然这不是那么实用或安全;但是,如果您能够更改安全管理器,它将返回一个 Void 实例。