Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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 关于重构返回空值的代码的有趣想法问题_Java_Design Patterns_Refactoring_Null_Null Object Pattern - Fatal编程技术网

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

我很想听听你的反馈。我最近看到一些Java代码以以下方式实现:

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