为什么不为 Java 中的基元数组覆盖 .equals() 方法?
Why is the .equals() method not overriden for arrays of primitives in Java?
我目前正在从事一个项目,我想在该项目中使用与数据库进行比较的用户名和密码来实现登录机制。
我有这样的想法:
public boolean verifyUser( String username, char[] password )
{
List<char[]> dbpass = getPasswords( username );
if ( dbpass.contains( password ) )
{
overwriteWithNonsense( password );
return true;
}
overwriteWithNonsense( password );
return false;
}
当我注意到我的单元测试失败时。所以我更深入地研究了它,注意到 Object::equals
方法没有被基元数组覆盖,这解释了为什么 List::contains
会 always 评估为 false
.
我知道有一个可能的解决方法:
if ( dbpass.stream().anyMatch( pw -> Arrays.equals( pw, password ) ) )
{
overwriteWithNonsense( password );
return true;
}
我的问题是为什么设计者选择保留Object::equals
的'default implementation'?这不是比使用 Arrays.equals(array1,array2)
这样的静态实用方法实现框架更方便吗?
array
中的任何 Collection
大多是糟糕的设计。它们不应一起使用。你可能最好引入一个琐碎但需要的 class
:
public class Password{
private final char[] password;
public Password(char[] password){
this.password = password;
}
@Override
public boolean equals(Object obj){
// equals logic
}
@Override
public int hashCode(){
// hashCode logic
}
}
然后有 List<Password>
。 (我还缩短了你的 verifyUser
方法,因为它看起来有点多余):
public boolean verifyUser( String username, char[] password ){
List<Password> dbpass = getPasswords(username);
boolean contained = dbpass.contains(new Password(password));
overwriteWithNonsense(password);
return contained;
}
(关于 为什么 它没有被覆盖的其他问题主要是题外话,因为只有 java-devs 才能真正回答这个问题。)
在 Java 中,array
不是 class,但在 Java Doc section 4.3.1 中,它被视为对象。现在因为这不是 class,所以没有 equals/hashCode
.
的代码
现在,对于比较数组的解决方案,您可以使用 Arrays.equals
方法来比较两个数组:
public boolean verifyUser( String username, char[] password )
{
List<char[]> dbpass = getPasswords( username );
for(char[] arr : dbpass)
{
if ( Arrays.equals(arr,password) )
{
overwriteWithNonsense( password );
return true;
}
}
overwriteWithNonsense( password );
return false;
}
我认为没有充分的理由。通常鼓励您使用 ArrayList
作为其成熟的容器。但是,按照 AbstractList
实施 equals()
似乎只有好处。
总有 ==
来判断两个引用是否是同一个对象。
Java 数组有点不寻常,因为它们可能包含原语,但这似乎不是什么障碍。
这些数组是否相等?
Integer objects[]={Integer.valueOf(1),Integer.valueOf(1000)};
int integers[]={1,1000};
我会选择 'no' 作为最一致的。但如果不是这样,您将获得这些对象不相等的潜在令人惊讶的语义:
int ai[]={1,2,3};
long al[]={1,2,3};
也许没有人真正考虑过,改变如此基本的东西肯定会产生一些代码破解结果。
我目前正在从事一个项目,我想在该项目中使用与数据库进行比较的用户名和密码来实现登录机制。
我有这样的想法:
public boolean verifyUser( String username, char[] password )
{
List<char[]> dbpass = getPasswords( username );
if ( dbpass.contains( password ) )
{
overwriteWithNonsense( password );
return true;
}
overwriteWithNonsense( password );
return false;
}
当我注意到我的单元测试失败时。所以我更深入地研究了它,注意到 Object::equals
方法没有被基元数组覆盖,这解释了为什么 List::contains
会 always 评估为 false
.
我知道有一个可能的解决方法:
if ( dbpass.stream().anyMatch( pw -> Arrays.equals( pw, password ) ) )
{
overwriteWithNonsense( password );
return true;
}
我的问题是为什么设计者选择保留Object::equals
的'default implementation'?这不是比使用 Arrays.equals(array1,array2)
这样的静态实用方法实现框架更方便吗?
array
中的任何 Collection
大多是糟糕的设计。它们不应一起使用。你可能最好引入一个琐碎但需要的 class
:
public class Password{
private final char[] password;
public Password(char[] password){
this.password = password;
}
@Override
public boolean equals(Object obj){
// equals logic
}
@Override
public int hashCode(){
// hashCode logic
}
}
然后有 List<Password>
。 (我还缩短了你的 verifyUser
方法,因为它看起来有点多余):
public boolean verifyUser( String username, char[] password ){
List<Password> dbpass = getPasswords(username);
boolean contained = dbpass.contains(new Password(password));
overwriteWithNonsense(password);
return contained;
}
(关于 为什么 它没有被覆盖的其他问题主要是题外话,因为只有 java-devs 才能真正回答这个问题。)
在 Java 中,array
不是 class,但在 Java Doc section 4.3.1 中,它被视为对象。现在因为这不是 class,所以没有 equals/hashCode
.
现在,对于比较数组的解决方案,您可以使用 Arrays.equals
方法来比较两个数组:
public boolean verifyUser( String username, char[] password )
{
List<char[]> dbpass = getPasswords( username );
for(char[] arr : dbpass)
{
if ( Arrays.equals(arr,password) )
{
overwriteWithNonsense( password );
return true;
}
}
overwriteWithNonsense( password );
return false;
}
我认为没有充分的理由。通常鼓励您使用 ArrayList
作为其成熟的容器。但是,按照 AbstractList
实施 equals()
似乎只有好处。
总有 ==
来判断两个引用是否是同一个对象。
Java 数组有点不寻常,因为它们可能包含原语,但这似乎不是什么障碍。
这些数组是否相等?
Integer objects[]={Integer.valueOf(1),Integer.valueOf(1000)};
int integers[]={1,1000};
我会选择 'no' 作为最一致的。但如果不是这样,您将获得这些对象不相等的潜在令人惊讶的语义:
int ai[]={1,2,3};
long al[]={1,2,3};
也许没有人真正考虑过,改变如此基本的东西肯定会产生一些代码破解结果。