为什么Jave方法不返回元组而不是对象引用(或null)? [英] Why not have Jave methods return a tuple instead of an object reference (or null)?

查看:91
本文介绍了为什么Jave方法不返回元组而不是对象引用(或null)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,Java方法如下:

Typically Java methods look like:

public <U,V> U doSomething(V aReference) {
    // Do something
}

这通常意味着方法doSomething()如果返回null 失败(无论出于何种原因)或有效的对象引用.在某些情况下 有效对象引用"本身可以是null.例如方法 如果没有键k有键,则aMap.get(k)可能返回null k ,但其对应值为null.混乱!

This typically means that the method doSomething() returns a null if it fails (for whatever reason) or a valid object reference. In some cases the "valid object reference" may itself be null. For example, the method aMap.get(k) may return null if there is no key k or if there is a key k but its corresponding value is null. Confusion!

如果您的LOC的50%不只是NullPointerException,就更不用说了 空检查.

Not to mention NullPointerExceptions if 50% of your LOC isn't just null-checking.

看起来像这样的方法有什么问题

What's wrong with methods looking like this:

public <T> ReturnTuple<T> doSomething(V aReference) {
    T anotherObjRef = getValidObjT();
    if (successful) {
        return ReturnTuple.getSuccessTuple(anotherObjRef);
    } else {
        return ReturnTuple.getFailureTuple("aReference can't be null");
    }
}

其中类ReturnTuple<T>的定义类似于:

class ReturnTuple<T> {
    private boolean success;

    // Read only if success == true
    private T returnValue;

    // Read only if success == false
    private String failureReason;

    // Private constructors, getters, setters & other convenience methods

    public static <T> ReturnTuple<T> getSuccessTuple(T retVal) {
        // This code is trivial
    }

    public static <T> ReturnTuple<T> getFailureTuple(String failureReason) {
        // This code is trivial
    }
}

然后,调用代码将如下所示:

Then the calling code will look like:

ReturnTuple<T> rt = doSomething(v);
if (rt.isSuccess()) {
    // yay!
} else {
    // boo hoo!
}

所以,我的问题是:为什么这种模式不常见?怎么了?

So, my question is: why isn't this pattern more common? What is wrong with it?

请记住,我并不是要批评这个确切的代码,而是要 对这个总体思想的批评.

Keep in mind I am not asking for a critique of this exact code, but for a critique of this general idea.

请注意:这里的重点不是让上面的代码进行编译,而只是为了 讨论一个想法.因此,请不要对代码的正确性过于痴迷:-).

Please note: the point here is not to get the code above to compile, just to discuss an idea. So please don't be too pedantic about code correctness :-).

我想我应该从一开始就添加此部分,但是后期应该更好 从来没有...

I guess I should have added this section from the beginning, but better late than never...

  • 是否希望一个方法可以一次返回两个值?还是那个回头 价值的表示可以与表示成功的能力脱钩,或者 失败?

  • Ever wished a method could return two values at once? Or that the returning of a value could be de-linked from the ability to indicate success or failure?

这还可以促进一种方法的想法,即干净整洁 独立的单元(低耦合和高内聚性):处理所有(或大部分) 在执行过程中生成的异常(不谈论异常) 如IllegalArgumentException),谨慎记录失败原因(而是 比没有捕获到的异常的丑陋堆栈痕迹),而且只会打扰 来电者提供所需的确切信息.恕我直言,这也促进 信息隐藏和封装.

This could also promote the idea of a method being a neat-and-clean self-contained unit (low coupling and high cohesion): handle all (or most) exceptions generated during it's execution (not talking about exceptions like IllegalArgumentException), discreetly log failure reasons (rather than the ugly stack trace of an uncaught exception) and only bother the caller with exactly the information required. IMHO this also promotes information-hiding and encapsulation.

尽力完成测试,但是将代码部署到客户后, 一个未捕获的异常的丑陋堆栈跟踪使一切看起来都如此 不专业.

Done your best with testing, but when the code is deployed to the customer, an uncaught exception's ugly stack trace makes it all look so unprofessional.

类似于以上几点:您可能有可能生成的代码 20种不同的例外,但您只抓到其中的5-7种.就像我们所有人 知道,客户要做最该死的事情:依靠他们来导致其他所有事情 未捕获的13-15个例外:-).当他们看到一个大 堆栈跟踪(而不是将离散的故障原因添加到日志中).

Similar to the point above: you may have code that could possibly generate 20 different exceptions but you're catching only 5-7 of those. As we all know, customers do the damndest things: rely on them to cause all the other uncaught 13-15 exceptions :-). You end up looking bad when they see a big stack trace (instead of a discrete failure reason added to the logs).

例如,这是显示堆栈跟踪到 网络应用程序中的用户与向他们展示格式正确的5xx错误页面,内容如下: 诸如:出现错误,您的请求无法完成. 管理员已收到通知,将尽快修复."等.

This is the difference (for example) between showing a stack trace to a user in a web app vs. showing them a nicely formatted 5xx error page saying something like: "There was an error and your request couldn't be completed. Admins have been notified and will fix as soon as possible." etc.

这个想法并非完全没有优点,因为Java 8提供了 可选 类(由@JBNizet指出)和Google的 Guava 库也有一个 可选 班级.这只是走了一点.

This idea isn't entirely without merit as Java 8 provides the Optional class (as pointed out by @JBNizet) and Google's Guava library also has an Optional class. This just takes that a little further.

推荐答案

这通常意味着方法doSomething()如果失败则返回null

This typically means that the method doSomething() returns a null if it fails

不,并不意味着那样.这意味着方法doSomething()有时可以合法地返回null,而不会失败. Java提供了一个强大的系统来处理故障-即异常处理.这就是API应该指示失败的方式.

No, it does not mean that. It means that the method doSomething() may sometimes legally return null, without a failure. Java provides a powerful system for handling failures - namely, exception handling. This is how the API should indicate failures.

为什么这种[返回元组]模式不更常见?怎么了?

why isn't this [return a tuple] pattern more common? What is wrong with it?

此模式的主要缺点是它使用了Java陌生的方式来报告故障.如果您的API发生故障,则引发异常.这样可以避免创建主流"情况下所需对象的数量增加两倍,并使熟悉API的人可以直观地理解您的API.

The primary thing that is wrong with this pattern is that it is using a mechanism of reporting failures in a way that is foreign to Java. If your API runs into a failure, throw an exception. This saves you from creating twice as many objects as needed in "mainstream" cases, and keeps your APIs intuitively understandable to people who learned the Java class library well.

在某些情况下,返回null可以解释两种方式-作为失败和合法的返回值.在关联容器中查找对象提供了一个很好的例子:当您提供不在映射中的键时,可能会声称这是编程错误并抛出异常(.NET类库会这样做)或声明当键如果缺少,则映射中的对应点包含默认值,即null-用Java完成的方式.在这种情况下,返回元组是完全可以接受的. Java的Map对此表示反对,每次从Map请求对象时,最有可能节省创建其他对象的时间.

There are situations when returning a null can be interpreted both ways - as a failure, and as a legitimate return value. Looking up objects in associative containers provide a good example: when you supply a key that is not in the map, one could claim that that is a programming error and throw an exception (.NET class library does that) or claim that when the key is missing, the corresponding spot in the map contains the default value, i.e. a null - the way this is done in Java. In situations like that it is entirely acceptable to return a tuple. Java's Map decided against this, most likely to save on creating additional objects every time an object is requested from a Map.

这篇关于为什么Jave方法不返回元组而不是对象引用(或null)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆