Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 作为返回参数的Void值_Java_Command_Adapter - Fatal编程技术网

Java 作为返回参数的Void值

Java 作为返回参数的Void值,java,command,adapter,Java,Command,Adapter,我有这个界面: public interface Command<T> { T execute(String... args); } 保持界面原样:这就是为什么标准库中存在Void。只要调用该命令的内容希望返回空值,就可以了 是的,null是唯一可以为Void返回的值 2017年更新 在过去的几年中,我一直避免将Void作为返回类型,除非涉及反射。我使用了一种不同的模式,我认为它更明确,并且避免了空值。也就是说,我有一个success类型,我称之为Ok,它为所有命令(如OP

我有这个界面:

public interface Command<T> {
    T execute(String... args);
}

保持界面原样:这就是为什么标准库中存在Void。只要调用该命令的内容希望返回空值,就可以了

是的,null是唯一可以为Void返回的值

2017年更新 在过去的几年中,我一直避免将
Void
作为返回类型,除非涉及反射。我使用了一种不同的模式,我认为它更明确,并且避免了空值。也就是说,我有一个success类型,我称之为
Ok
,它为所有命令(如OP)返回。这对我的团队来说非常有效,并且已经推广到其他团队中使用

public enum Ok { OK; }

public class SideEffectCommand implements Command<Ok> {
    @Override
    public Ok execute(String... args) {
        ...
        return Ok.OK; // I typically static import Ok.OK;
}
public enum Ok{Ok;}
公共类SideEffectCommand实现该命令{
@凌驾
公共Ok执行(字符串…参数){
...
return Ok.Ok;//我通常静态导入Ok.Ok;
}

在您的示例中,有趣的是参数化类型的使用

interface Command<T> {
    public T execute(T someObject);
}
接口命令{
公共T执行(T someObject);
}
在您的例子中,您只有
T
作为返回值。然而,在这种情况下使用Void是一个很好的解决方案。返回值应该是
null
,这个问题并不常见,但也不罕见……我想我在不久前看到过关于这个问题的讨论,关于不返回任何内容的可调用项


我同意其他海报上的说法,这是一个很好的解决方案,比使用Object或其他虚拟占位符要好得多。

我会坚持显式使用
Void
。在不涉及其他类的情况下,很容易看到正在发生的事情。如果您可以用
Void
覆盖
返回,那就太好了(和
Integer
int
等),但这不是优先考虑的问题。

这不是常见问题。您需要解决的问题是对界面的期望。您将非副作用界面的行为与允许副作用的界面相结合

考虑这一点:

public class CommandMonitor {

    public static void main(String[] args)  {       
        Command<?> sec = new SideEffectCommand();       
        reportResults(sec);     
    }   

    public static void reportResults(Command<?> cmd){

        final Object results = cmd.execute("arg");
        if (results != null ) {
            System.out.println(results.getClass());
        }
    }
}
因为现在有办法知道实现是否真的有对象或是空的。对于特定的情况,您肯定会知道,因为您对实现很熟悉。但是一旦您开始聚合它们,或者它们超出了您的编码范围(用作库、将来的维护等)空问题将出现

接下来,我尝试了这个:

public class SideEffectCommand implements Command<String> {

    @Override
    public String execute(String... args) {
        return "Side Effect";
    }

}

public class NoSideEffectCommand implements Command<Void>{
    @Override
    public Void execute(String... args) {
        return null;
    }   
}
public class CommandMonitor {

    public static void main(String[] args)  {       
        Command<?> sec = new SideEffectCommand();
        Command<?> nsec = new NoSideEffectCommand();

        reportResults(sec.execute("args"));
        reportResults(nsec.execute("args")); //Problem Child
    }   

    public static void reportResults(Object results){
        System.out.println(results.getClass());
    }

    public static void reportResults(Void results){
        System.out.println("Got nothing for you.");
    }
}
但这说明了问题的根源,您的客户端代码开始需要了解实现细节。接口应该在可能的情况下帮助隔离代码依赖关系。此时添加它们似乎是一种糟糕的设计

归根结底,您需要使用一种设计,该设计明确了您期望命令何时会产生副作用,并考虑如何处理一组命令,即未知命令的数组


这可能是一个例子。

在我看来很好。正如其他人所说,
Void
最初是为反射机制设计的,但现在它在泛型中经常用于描述像您这样的情况


更好的是:谷歌,在他们的GWT框架中,在他们的示例中使用了相同的想法来返回一个空回调()。我说:如果谷歌这样做了,它必须至少是好的。:)

这是一个多世界的最佳实现

// Generic interface for when a client doesn't care
// about the return value of a command.
public interface Command {
    // The interfaces themselves take a String[] rather
    // than a String... argument, because otherwise the
    // implementation of AbstractCommand<T> would be
    // more complicated.
    public void execute(String[] arguments);
}

// Interface for clients that do need to use the
// return value of a command.
public interface ValuedCommand<T> extends Command {
    public T evaluate(String[] arguments);
}

// Optional, but useful if most of your commands are ValuedCommands.
public abstract class AbstractCommand<T> implements ValuedCommand<T> {
    public void execute(String[] arguments) {
        evaluate(arguments);
    }
}

// Singleton class with utility methods.
public class Commands {
    private Commands() {} // Singleton class.

    // These are useful if you like the vararg calling style.
    public static void execute(Command cmd, String... arguments) {
        cmd.execute(arguments);
    }

    public static <T> void execute(ValuedCommand<T> cmd, String... arguments) {
        return cmd.evaluate(arguments);
    }

    // Useful if you have code that requires a ValuedCommand<?>
    // but you only have a plain Command.
    public static ValuedCommand<?> asValuedCommand(Command cmd) {
        return new VoidCommand(cmd);
    }

    private static class VoidCommand extends AbstractCommand<Void> {
        private final Command cmd;

        public VoidCommand(Command actual) {
            cmd = actual;
        }

        public Void evaluate(String[] arguments) {
            cmd.execute(arguments);
            return null;
        }
    }
}
//当客户端不关心时的通用接口
//关于命令的返回值。
公共接口命令{
//接口本身采用字符串[],而不是
//而不是字符串…参数,因为
//AbstractCommand的实现将是
//更复杂。
public void execute(字符串[]参数);
}
//为确实需要使用
//命令的返回值。
公共接口ValuedCommand extends命令{
公共T求值(字符串[]参数);
}
//可选,但如果大多数命令都是ValuedCommand,则很有用。
公共抽象类AbstractCommand实现ValuedCommand{
public void execute(字符串[]参数){
评价(论据);
}
}
//带有实用程序方法的Singleton类。
公共类命令{
private Commands(){}//Singleton类。
//如果您喜欢vararg调用样式,那么这些都很有用。
公共静态void execute(命令cmd、字符串…参数){
cmd.execute(参数);
}
公共静态void execute(ValuedCommand cmd,String…参数){
返回cmd.evaluate(参数);
}
//如果您有需要ValuedCommand的代码,则非常有用
//但你只有一个简单的命令。
公共静态值命令asValuedCommand(命令cmd){
返回新的命令(cmd);
}
私有静态类VoidCommand扩展了AbstractCommand{
私人最终命令cmd;
公共命令(实际命令){
cmd=实际值;
}
公共Void求值(字符串[]参数){
cmd.execute(参数);
返回null;
}
}
}
通过此实现,如果客户机不关心返回值,则可以使用
命令
;如果客户机需要返回特定值的命令,则可以使用
值命令


关于不直接使用
Void
的唯一原因是所有难看的
返回null;
语句,您将被迫插入这些语句。

如果没有如下界面,该怎么办

public interface Command<T> {
    T execute(String... args);
}
公共接口命令{
T执行(字符串…参数);
}
相反,你有:

public interface Command<T> {
    void execute(String... args);
    T getResult();
    bool hasResult();
}
公共接口命令{
无效执行(字符串…参数);
T getResult();
bool hasResult();
}
然后打电话的人会做:

public void doSomething(Command<?> cmd) {
    cmd.execute(args);
    if(cmd.hasResult()) {
        // ... do something with cmd.getResult() ...
    }
}
public void doSomething(命令cmd){
cmd.execute(args);
if(cmd.hasResult()){
//…使用cmd.getResult()执行某些操作。。。
}
}
如果愿意,还可以创建一个扩展命令的接口VoidCommmand

// Generic interface for when a client doesn't care
// about the return value of a command.
public interface Command {
    // The interfaces themselves take a String[] rather
    // than a String... argument, because otherwise the
    // implementation of AbstractCommand<T> would be
    // more complicated.
    public void execute(String[] arguments);
}

// Interface for clients that do need to use the
// return value of a command.
public interface ValuedCommand<T> extends Command {
    public T evaluate(String[] arguments);
}

// Optional, but useful if most of your commands are ValuedCommands.
public abstract class AbstractCommand<T> implements ValuedCommand<T> {
    public void execute(String[] arguments) {
        evaluate(arguments);
    }
}

// Singleton class with utility methods.
public class Commands {
    private Commands() {} // Singleton class.

    // These are useful if you like the vararg calling style.
    public static void execute(Command cmd, String... arguments) {
        cmd.execute(arguments);
    }

    public static <T> void execute(ValuedCommand<T> cmd, String... arguments) {
        return cmd.evaluate(arguments);
    }

    // Useful if you have code that requires a ValuedCommand<?>
    // but you only have a plain Command.
    public static ValuedCommand<?> asValuedCommand(Command cmd) {
        return new VoidCommand(cmd);
    }

    private static class VoidCommand extends AbstractCommand<Void> {
        private final Command cmd;

        public VoidCommand(Command actual) {
            cmd = actual;
        }

        public Void evaluate(String[] arguments) {
            cmd.execute(arguments);
            return null;
        }
    }
}
public interface Command<T> {
    T execute(String... args);
}
public interface Command<T> {
    void execute(String... args);
    T getResult();
    bool hasResult();
}
public void doSomething(Command<?> cmd) {
    cmd.execute(args);
    if(cmd.hasResult()) {
        // ... do something with cmd.getResult() ...
    }
}