有什么可以警告我 type.equals(incompleteType) 吗?

发布于 2024-12-11 19:23:42 字数 300 浏览 0 评论 0原文

是否有任何工具可以警告我以下类型的代码:

if ( someClass.equals( someString ))

例如:

if ( myObject.getClass().equals( myClassName ))

这样的东西是合法的 Java(等于接受一个对象),但永远不会计算为 true(一个类永远不能等于一个字符串),所以几乎可以肯定是漏洞。

我检查过 Eclipse、FindBugs 和 PMD,但似乎都不支持此功能?

Is there any tool that can warn me against the following sort of code:

if ( someClass.equals( someString ))

For example:

if ( myObject.getClass().equals( myClassName ))

Such a thing is legal Java (equals takes an Object) but will never evaluate to true (a class can never equal a String) so is almost certainly a bug.

I have checked Eclipse, FindBugs and PMD but none seem to support this feature?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡水深流 2024-12-18 19:23:42

是的,IntelliJ IDEA 有这样的检查,我相信默认情况下是启用的。它标记以下内容:

Class<?> clazz = String.class;
if (clazz.equals("foo")) {
   //...
}

带有警告:

不可转换类型的对象之间的“equals()”。

可以通过“设置”->“项目设置”->“检查”来启用/禁用检查,然后在“可能的错误”下选中/取消选中不可转换类型的对象之间的“'equals()'”。

FindBugs 也应该通过 "EC: Call to equals() 比较来捕获此问题不同类型” 错误检查。正如您所知,它可以与 Eclipse 集成。

但这也不是灵丹妙药。他们无法读懂你的想法。您可以期望的最好结果是,它会支持误报而不是误报。

Yes, IntelliJ IDEA has such an inspection that I believe is enabled by default. It flags the following:

Class<?> clazz = String.class;
if (clazz.equals("foo")) {
   //...
}

With the warning:

'equals()' between objects of inconvertible types.

The inspection can be enabled/disabled through Settings->Project Settings->Inspections, then under Probable Bugs check/uncheck "'equals()' between objects of inconvertible types."

FindBugs also should catch this with the "EC: Call to equals() comparing different types" bug check. It can be integrated with Eclipse as it appears you are aware.

Neither is a silver bullet though; they can't read your mind. The best you can hope for is that it will favour false positives rather than false negatives.

も星光 2024-12-18 19:23:42

这就是 .NET 中 IEquatable 接口背后的理念:为类型提供一种机制来实现我所说的强类型相等性。还有 IEqualityComparer 接口,用于允许以单独的类型实现此逻辑。

根据这个 StackOverflow 问题(由 Jon Skeet 回答) ,通常似乎知道他在说什么),Java 中似乎没有任何等效的东西。

当然,您始终可以为自己的类型自己实现这样的事情,但对于属于 Java 基类库的类型来说,这对您没有多大好处。对于此类问题的编译时检测,最好的选择是某种分析工具(Mark Peters 指出 IntelliJ IDEA 中显然内置了一个)可以向您建议某些代码可能值得怀疑。一般来说,假设您不是一个会忽略警告的人,那么这应该足够好了。

This is the idea behind the IEquatable<T> interface in .NET: providing a mechanism for types to implement what I'll call strongly typed equality. There is also the IEqualityComparer<T> interface for allowing this logic to be implemented in a separate type.

According to this StackOverflow question (answered by Jon Skeet, who generally seems to know what he's talking about), there doesn't seem to be any equivalent in Java.

Of course, you can always implement such a thing yourself for your own types, but it won't do you much good with types that are part of Java's base class libraries. For compile-time detection of such issues, your best bet is some sort of analysis tool (Mark Peters indicates there is apparently one built in to IntelliJ IDEA) that can suggest to you that certain code might be suspect. In general, assuming you aren't one to ignore warnings, this ought to be good enough.

做个ˇ局外人 2024-12-18 19:23:42

您要检查的不一定是“问题”:equals()Object 类中声明,并以 Object 作为其对象范围。类重写此方法,并且它们的实现很可能允许不同类的对象“等于”目标对象。

我自己已经这样做过几次了,例如,如果另一个对象(比如字符串)与目标的键字段匹配,则允许一个对象“等于”另一个对象:

class MyClass {
    private String id;

    public boolean equals(Object obj) {
        // Compare as if "this" is the id field
        return id.equals(obj instanceof MyClass ? ((MyClass)obj).id : obj);
    }

    public int hashCode() {
        return id.hashCode(); // so hashCode() agrees with equals()
    }
}

这实际上非常方便,因为以下代码将按预期工作:

List<MyClass> list = new ArrayList<MyClass>();
// collection methods will work with instances:
list.contains(someInstance);
list.remove(someInstance);
list.indexOf(someInstance);
// and with keys!
// handy if you can only get the key, for example from a web url parameter
list.contains("somekey");
list.remove("somekey");
list.indexOf("somekey");

What you are checking for is not necessarily a "problem": equals() is declared in the Object class, and takes and Object as its parameter. Classes override this method, and their implementation may well allow an object of a different class to "equal" the target object.

I have done this a few times myself, for example for allowing an object to "equal" another object if the other object (say a String) matches the key field of the target:

class MyClass {
    private String id;

    public boolean equals(Object obj) {
        // Compare as if "this" is the id field
        return id.equals(obj instanceof MyClass ? ((MyClass)obj).id : obj);
    }

    public int hashCode() {
        return id.hashCode(); // so hashCode() agrees with equals()
    }
}

It's actually pretty handy, because the following code will work as desired:

List<MyClass> list = new ArrayList<MyClass>();
// collection methods will work with instances:
list.contains(someInstance);
list.remove(someInstance);
list.indexOf(someInstance);
// and with keys!
// handy if you can only get the key, for example from a web url parameter
list.contains("somekey");
list.remove("somekey");
list.indexOf("somekey");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文