Java 关于重构返回空值的代码的有趣想法问题
我很想听听你的反馈。我最近看到一些Java代码以以下方式实现:Java 关于重构返回空值的代码的有趣想法问题,java,design-patterns,refactoring,null,null-object-pattern,Java,Design Patterns,Refactoring,Null,Null Object Pattern,我很想听听你的反馈。我最近看到一些Java代码以以下方式实现: Object1 SomeMethod(String key) { Object1 object1 = null; List<Object1> objectList = getAllRecordsWithKeyFromDatabase(key); if (!objectList.isEmpty()) { object1 = objectList.get(0); } r
Object1 SomeMethod(String key) {
Object1 object1 = null;
List<Object1> objectList = getAllRecordsWithKeyFromDatabase(key);
if (!objectList.isEmpty()) {
object1 = objectList.get(0);
}
return object1;
}
void AnotherMethod() {
...
Object1 object1 = SomeMethod(key);
if (object1 == null) {
// throw exception
}
// continue working
}
Object1方法(字符串键){
Object1 Object1=null;
List objectList=getAllRecordsWithKeyFromDatabase(键);
如果(!objectList.isEmpty()){
object1=objectList.get(0);
}
返回对象1;
}
void-AnotherMethod(){
...
Object1 Object1=somethod(key);
if(object1==null){
//抛出异常
}
//继续工作
}
我总是担心在没有上下文的情况下返回null。我宁愿来自某个方法的响应更加明确,并且正在考虑重构它。从SomeMethod中抛出异常可以提供一种方法。它将在上下文中出现,并发生在故障点
我想知道是否有另一种方法可以让某个方法通知另一个方法“在数据库中找不到任何东西”,而不是假设null总是等于“找不到”。我认为可以使用NullObject,但我不清楚如果找不到数据,AnotherMethod应该如何避免“继续工作”
您将如何重构代码 我不认为它有什么问题,只是我要清楚地说明,
SomeMethod
在某些情况下可以返回null
但是,如果查找null显然是一种例外情况,那么抛出异常是正确的方法。如果更改AnotherMethod
,使其声明一个选中的异常,那么该方法的用户将更清楚地了解您的意图。大概是这样的:
void AnotherMethod() throws SomethingBadHappenedException {
//snip
}
我不认为它有什么问题,只是我要清楚地说明,
SomeMethod
在某些情况下可以返回null
但是,如果查找null显然是一种例外情况,那么抛出异常是正确的方法。如果更改AnotherMethod
,使其声明一个选中的异常,那么该方法的用户将更清楚地了解您的意图。大概是这样的:
void AnotherMethod() throws SomethingBadHappenedException {
//snip
}
空对象不是全部结束。它适用于某些情况(Collections.emptyXXX()就是一个很好的例子),但有时您必须区分有和无。如果返回nothing是有效状态,那么它应该返回null
例外情况适用于例外情况,即正常情况下不应发生的事情。捕获和处理异常比检查null要困难得多。null对象并不是最终的目标。它适用于某些情况(Collections.emptyXXX()就是一个很好的例子),但有时您必须区分有和无。如果返回nothing是有效状态,那么它应该返回null
例外情况适用于例外情况,即正常情况下不应发生的事情。捕获和处理异常比检查null要困难得多。我曾经在一个项目中工作,其中查询结果是非常自然的集合。但在某些特殊情况下,集合应该是空的;集合应仅包含一个元素的其他情况 这些查询是在对象上执行的,这些对象有时需要从数据库中进行故障处理 我们最终采用的方法是将返回的结果包装成我们自己的类型(而不是ArrayList或其他类型)。举例说明:
public interface Results<T> implements Iterable<T> {
Collection<T> all();
Iterator<T> iterator();
/**
* @return one value from the result, or null if the result is empty.
*/
T ifAny();
/**
* @return one value from the result.
*/
T one() throws EmptyResultException;
/**
* @return if the result is empty, returns null,
* if the result has one value, returns the value,
* if the result has more than one value, throws.
*/
T unique() throws MultiValueResultException;
/**
* @return the value if the result has exactly one; throws otherwise
*/
T exact() throws NoExactResultException;
}
公共接口结果实现Iterable{
集合所有();
迭代器迭代器();
/**
*@从结果返回一个值,如果结果为空,则返回null。
*/
T ifAny();
/**
*@从结果中返回一个值。
*/
T one()抛出EmptyResultException;
/**
*@return如果结果为空,则返回null,
*如果结果有一个值,则返回该值,
*如果结果有多个值,则抛出。
*/
T unique()抛出多值ResultException;
/**
*@如果结果正好有一个值,则返回该值;否则抛出
*/
T exact()抛出NoExactResultException;
}
如果语义对您很重要,您可以在您的案例中使用类似的方法:
public final class Result<T> {
private static final Object NON = new Object();
private final Object _value;
public Result(T value) {
if (value == null) {
throw ...
}
_value = value;
}
public T get() {
return (_value == NON) ? null : (T) _value;
}
public T use() {
if (_value == NON) {
throw ...
}
return (T) _value;
}
}
公开期末成绩{
私有静态最终对象非=新对象();
私有最终对象_值;
公共结果(T值){
如果(值==null){
扔。。。
}
_价值=价值;
}
公共部门得不到{
返回(_值==非)?空:(T)_值;
}
公共用途{
如果(_值==非){
扔。。。
}
返回(T)_值;
}
}
请注意,Scala习惯用法使用Option具有类似的效果。这是关于这一主题的众多链接之一:我曾经参与过一个项目,其中查询结果是非常自然的集合。但在某些特殊情况下,集合应该是空的;集合应仅包含一个元素的其他情况 这些查询是在对象上执行的,这些对象有时需要从数据库中进行故障处理 我们最终采用的方法是将返回的结果包装成我们自己的类型(而不是ArrayList或其他类型)。举例说明:
public interface Results<T> implements Iterable<T> {
Collection<T> all();
Iterator<T> iterator();
/**
* @return one value from the result, or null if the result is empty.
*/
T ifAny();
/**
* @return one value from the result.
*/
T one() throws EmptyResultException;
/**
* @return if the result is empty, returns null,
* if the result has one value, returns the value,
* if the result has more than one value, throws.
*/
T unique() throws MultiValueResultException;
/**
* @return the value if the result has exactly one; throws otherwise
*/
T exact() throws NoExactResultException;
}
公共接口结果实现Iterable{
集合所有();
迭代器迭代器();
/**
*@从结果返回一个值,如果结果为空,则返回null。
*/
T ifAny();
/**
*@从结果中返回一个值。
*/
T one()抛出EmptyResultException;
/**
*@return如果结果为空,则返回null,
*如果结果有一个值,则返回该值,
*如果结果有多个值,则抛出。
*/
T unique()抛出多值ResultException;
/**
*@如果结果正好有一个值,则返回该值;否则抛出
*/
T exact()抛出NoExactResultException;
}
如果语义对您很重要,您可以在您的案例中使用类似的方法:
public final class Result<T> {
private static final Object NON = new Object();
private final Object _value;
public Result(T value) {
if (value == null) {
throw ...
}
_value = value;
}
public T get() {
return (_value == NON) ? null : (T) _value;
}
public T use() {
if (_value == NON) {
throw ...
}
return (T) _value;
}
}
public-final-cla