Java 如何测试泛型类中的等价性?

Java 如何测试泛型类中的等价性?,java,generics,scheme,equality,Java,Generics,Scheme,Equality,知道三种不同的等价运算符:eq?,eqv?,equal?。详细情况请参阅。简而言之:eq?测试引用,eqv?测试值,equal?递归测试列表的值。我想编写一个Java泛型,它需要Scheme的equal?功能 我尝试使用Java的方法,因为我认为它可以进行值比较,因为对于引用比较,=操作符存在,并且不需要equals来进行相同的操作。但是这个假设是完全错误的,因为Java中的等于是完全不可靠的。有时进行值比较,有时进行引用比较。我们无法确定哪个类进行引用比较,哪个类进行值比较 这意味着不能在泛型

知道三种不同的等价运算符:
eq?
eqv?
equal?
。详细情况请参阅。简而言之:
eq?
测试引用,
eqv?
测试值,
equal?
递归测试列表的值。我想编写一个Java泛型,它需要Scheme的
equal?
功能

我尝试使用Java的方法,因为我认为它可以进行值比较,因为对于引用比较,
=
操作符存在,并且不需要
equals
来进行相同的操作。但是这个假设是完全错误的,因为Java中的
等于
是完全不可靠的。有时进行值比较,有时进行引用比较。我们无法确定哪个类进行引用比较,哪个类进行值比较

这意味着不能在泛型中使用
equals
,因为泛型不会对所有类型执行相同的操作。而且,也不可能以只接受实现正确值比较的类型的方式限制泛型类型

因此,问题是:如何在通用模型中进行可靠的值比较?我必须从头开始自己写吗


顺便说一句:我认为Java的同样失败并非始于。它已经从Object开始了。我认为两个对象的
等于
返回
false
是错误的。它必须返回
true
,因为如果对没有值的对象进行值比较,值不能不同,因此它们必须相同。Scheme就是这样做的,它是完全合理的:
(equal?(vector)(vector))->#t

在Scheme中,列表等价完全基于项的结构

相比之下,在Java中,相等性取决于对象的类型,并且可以在其等价性计算中使用部分或全部内部结构。同一类型的两个对象“相等”意味着什么,取决于对象类型来确定,只要满足(最明显的是,它与所有其他对象形成一个)

假设程序中使用的所有类型都有一个合理的
equals
定义,它们应该有一个“可靠”的值比较,至少在面向对象范例的意义上是这样的

回到类似的Java
equal?
实现。从问题的措辞中拼凑起来有点困难,但从上下文线索来看,这似乎也在试图对项目列表进行操作。Java类型上的方法已经实现了与Scheme的
equals?
操作直接类似的行为:

比较指定对象与此列表是否相等。返回
true
当且仅当指定的对象也是列表时,两个列表的大小相同,并且两个列表中所有对应的元素对相等。(如果
对象,则两个元素e1和e2相等。等于(e1,e2)
)换句话说,如果两个列表包含相同顺序的相同元素,则两个列表定义为相等

这个定义还意味着递归列表结构的工作方式与Scheme的
equals?
操作类似

请注意,
列表
的行为与Java的数组类型(您在问题中提到的)的行为明显不同。Java中的数组是一种相当低级的类型,不支持人们可能期望的许多典型的面向对象功能。需要特别注意的是,为了相等,数组是通过对象引用进行比较的,而不是通过数组中项的结构比较进行比较的。使用
arrays
类中的方法(例如and),可以对数组进行合理的相等性比较


顺便说一句,谈谈你的后记中关于两个裸
对象相等的问题

assert!(新对象()。等于(新对象())
从面向对象的角度来看,只有当两个裸对象是相同的引用时,它们才是相等的。首先,如上所述,对象的内部结构与其相等性之间没有直接关系,因此它们没有必要相等。从对象建模的角度来看,几乎没有上下文来说明
对象的两个不同实例表示什么,因此没有内在的概念方法来判断这两个对象在逻辑上是“相同”的



总之,假设列表中的所有类型都根据对象的类型定义了合理版本的
equals()
,Java的
list.equals()
的行为与Scheme的
equals?
操作直接类似。

您可以使用
SomeClass.getDeclaredMethod(“equals”,object.class)
检查类是否重写
对象.equals(Object)
方法。如果一个类确实重写了它,那么它很可能会进行某种形式的值比较。但是,仍然绝对不能保证它与您所寻找的类型完全相同。您也可以使用相同类型的方法(
SomeClass.getDeclaredFields()
然后
myField.setAccessible(true)
myField.get(myObject)
您还必须使用
SomeClass.getSuperclass()
并对所有超类的字段进行相同的比较),以查找两个对象的字段并递归检查它们是否具有相同的值,但这听起来有点过分。基本上欢迎使用OOP。@PaulBellora Java,欢迎使用Java。我们还有其他的结构等价性where@PaulBellora均衡接口。有些东西确实不应该在结构上进行比较。