Java 14记录和数组

oxosxuxt  于 2024-01-05  发布在  Java
关注(0)|答案(3)|浏览(270)

下面是一个例子:

  1. public static void main(String[] args) {
  2. record Foo(int[] ints){}
  3. var ints = new int[]{1, 2};
  4. var foo = new Foo(ints);
  5. System.out.println(foo); // Foo[ints=[I@6433a2]
  6. System.out.println(new Foo(new int[]{1,2}).equals(new Foo(new int[]{1,2}))); // false
  7. System.out.println(new Foo(ints).equals(new Foo(ints))); //true
  8. System.out.println(foo.equals(foo)); // true
  9. }

字符串
显然,似乎使用了数组的toStringequals方法(而不是静态方法,Arrays::equalsArrays::deepEqualsArray::toString)。
所以我猜Java 14 Records(JEP 359)不能很好地处理数组,相应的方法必须用IDE生成(至少在IntelliJ中,默认情况下会生成“有用”的方法,即它们使用Arrays中的静态方法)。
还是有其他解决办法?

xnifntxz

xnifntxz1#

Java数组对记录提出了一些挑战,这些挑战给设计增加了一些约束。数组是可变的,它们的相等语义(继承自Object)是通过标识,而不是内容。
你的例子的基本问题是,你希望数组上的equals()意味着内容相等,而不是引用相等。在您的示例中,包含不同数组的两个Foo记录**不同,记录的行为是正确的。问题是你只是希望相等比较是不同的。
也就是说,你可以用你想要的语义来声明一条记录,这只需要更多的工作,你可能会觉得这是太多的工作。下面是一条记录,它可以做你想要的:

  1. record Foo(String[] ss) {
  2. Foo { ss = ss.clone(); }
  3. String[] ss() { return ss.clone(); }
  4. public boolean equals(Object o) {
  5. return o instanceof Foo f && Arrays.equals(f.ss, ss);
  6. }
  7. public int hashCode() { return Objects.hash(Arrays.hashCode(ss)); }
  8. }

字符串
这是一个防御性的拷贝,在传入(在构造函数中)和传出(在访问器中)的过程中,以及调整相等语义以使用数组的内容。这支持超类java.lang.Record中所需的不变式,即“将一个记录分解为它的组件,并将组件重构为一个新记录,产生一个相等的记录”。
你可能会说“但是这太麻烦了,我想使用记录,这样我就不必输入所有的东西了。”但是,记录主要不是一个语法工具(尽管它们在语法上更令人愉快),它们是一个语义工具:记录是 * 名义元组 *。大多数情况下,紧凑语法也会产生所需的语义,但是如果你想要不同的语义,你必须做一些额外的工作。

展开查看全部
8nuwlpux

8nuwlpux2#

List< Integer >解决方法

解决办法:使用Integer对象的ListList< Integer >),而不是基元数组(int[])。
在这个例子中,我使用Java 9中添加的List.of特性示例化了一个不可修改的未指定类的列表。对于一个由数组支持的可修改列表,您也可以使用ArrayList

  1. package work.basil.example;
  2. import java.util.List;
  3. public class RecordsDemo
  4. {
  5. public static void main ( String[] args )
  6. {
  7. RecordsDemo app = new RecordsDemo();
  8. app.doIt();
  9. }
  10. private void doIt ( )
  11. {
  12. record Foo( List < Integer >integers ) {}
  13. List< Integer > integers = List.of( 1 , 2 );
  14. var foo = new Foo( integers );
  15. System.out.println( foo ); // Foo[integers=[1, 2]]
  16. System.out.println( new Foo( List.of( 1 , 2 ) ).equals( new Foo( List.of( 1 , 2 ) ) ) ); // true
  17. System.out.println( new Foo( integers ).equals( new Foo( integers ) ) ); // true
  18. System.out.println( foo.equals( foo ) ); // true
  19. }
  20. }

字符串

展开查看全部
qkf9rpyu

qkf9rpyu3#

  • 解决方法:* 创建一个IntArray类并 Package int[]
  1. record Foo(IntArray ints) {
  2. public Foo(int... ints) { this(new IntArray(ints)); }
  3. public int[] getInts() { return this.ints.get(); }
  4. }

字符串
并不完美,因为您现在必须调用foo.getInts()而不是foo.ints(),但其他一切都按照您想要的方式工作。

  1. public final class IntArray {
  2. private final int[] array;
  3. public IntArray(int[] array) {
  4. this.array = Objects.requireNonNull(array);
  5. }
  6. public int[] get() {
  7. return this.array;
  8. }
  9. @Override
  10. public int hashCode() {
  11. return Arrays.hashCode(this.array);
  12. }
  13. @Override
  14. public boolean equals(Object obj) {
  15. if (this == obj)
  16. return true;
  17. if (obj == null || getClass() != obj.getClass())
  18. return false;
  19. IntArray that = (IntArray) obj;
  20. return Arrays.equals(this.array, that.array);
  21. }
  22. @Override
  23. public String toString() {
  24. return Arrays.toString(this.array);
  25. }
  26. }

  • 输出 *
  1. Foo[ints=[1, 2]]
  2. true
  3. true
  4. true

展开查看全部

相关问题