我不应该为了返回多个值而创建类
类永远不应该用作 C++ 结构,而只是为了对元素进行分组。
方法不应该返回非原始对象,它们应该从外部接收对象并且只修改它
对于上述任何陈述,情况绝对不是这样。数据对象很有用,事实上,将纯数据与包含繁重逻辑的类分开是一种很好的做法。
在 Java 中,最接近结构体的是 POJO(普通的旧 Java 对象),在其他语言中通常称为数据类。这些类只是一组数据。 POJO 的经验法则是它应该只包含基元、简单类型(字符串、装箱基元等)、简单容器(映射、数组、列表等)或其他 POJO 类。基本上可以轻松序列化的类。
想要将两个、三个或多个配对是很常见的n
对象在一起。有时,数据足够重要,足以保证一个全新的类别,而在其他情况下则不然。在这些情况下,程序员经常使用Pair
or Tuple
类。这是一个二元素通用元组的简单示例。
public class Tuple2<T,U>{
private final T first;
private final U second;
public Tuple2(T first, U second) {
this.first = first;
this.second = second;
}
public T getFirst() { return first; }
public U getSecond() { return second; }
}
使用元组作为方法签名一部分的类可能如下所示:
public interface Container<T> {
...
public Tuple2<Boolean, Integer> search(T key);
}
创建这样的数据类的一个缺点是,为了生活质量,我们必须实现诸如toString
, hashCode
, equals
getter、setter、构造函数等。对于每个不同大小的元组,您必须创建一个新类(Tuple2
, Tuple3
, Tuple4
, ETC)。创建所有这些方法会给我们的应用程序带来微妙的错误。由于这些原因,开发人员通常会避免创建数据类。
像 Lombok 这样的图书馆对于克服这些挑战非常有帮助。我们的定义Tuple2
,使用上面列出的所有方法,可以写为:
@Data
public class Tuple2<T,U>{
private final T first;
private final U second;
}
这也使得创建自定义响应类变得非常容易。使用自定义类可以避免泛型自动装箱,并大大提高可读性。例如:
@Data
public class SearchResult {
private final boolean found;
private final int index;
}
...
public interface Container<T> {
...
public SearchResult search(T key);
}
方法应该从外部接收对象并且只修改它
这是个坏建议。围绕不变性设计数据要好得多。从《有效的 Java》第二版,第 75 页 https://the-eye.eu/public/Books/IT%20Various/Effective%20Java%2C%202nd%20Edition.pdf
不可变对象很简单。不可变对象只能处于一种状态,即创建它时的状态。如果您确保所有构造函数都建立了类不变量,那么就可以保证这些不变量将始终保持正确,而您或使用该类的程序员无需付出任何进一步的努力。另一方面,可变对象可以具有任意复杂的状态空间。如果文档没有提供由 mutator 方法执行的状态转换的精确描述,则可靠地使用可变类可能会很困难或不可能。
不可变对象本质上是线程安全的;它们不需要同步。它们不会被同时访问它们的多个线程破坏。这无疑是实现线程安全的最简单方法。事实上,任何线程都无法观察到另一个线程对不可变对象的任何影响。所以,不可变对象可以自由共享.