JDK-8013357 : Javac accepts erroneous binary comparison operations
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7u40,8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-04-26
  • Updated: 2017-05-17
  • Resolved: 2013-06-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b98Fixed
Related Reports
Relates :  
Relates :  
Description
This code should not compile:

class Main {
public boolean func(Object obj) {
return obj == 0;
}
}

But javac (since JDK 7 accepts it).

The following variant:

class Main {
public boolean func(Object obj) {
return 0 == obj;
}
}

should also not compile - but note that this was accepted since JDK 5.

Relevant JLS section is 15.21. Javac seems to treat this as a reference comparison, but a reference comparison is only allowed when BOTH operands are reference types.
Comments
Change ready for push, awaiting final review.
19-06-2013

Suggested release note text: The type rules for binary comparisons in JLS Section 15.21 will now be correctly enforced by javac. Since JDK5, javac has accepted some programs with Object-primitive comparisons that are incorrectly typed according to JLS 15.21. These comparisons will now be correctly identified as type errors.
29-05-2013

CCC approved. This change will be tagged for a release note.
29-05-2013

Awaiting CCC approval
08-05-2013

A JPRT run reveals that there are int != Object comparisons in one of the test suites (DivModTest). This is almost certainly a mistake; however, it does raise an interesting point: how much code out there will be "broken" by this change?
03-05-2013

Suspect some relation to the changes made under JDK-6979683.
03-05-2013

This is caused by boxing. Javac interprets 0 == obj as equivalent to Integer.valueOf(0) == obj. More specifically, this is *not* a null pointer check, as the equivalent syntax in C++ would be. Also, current javac accepts both 0 == obj and obj == 0. It also accepts 0.0 == obj, 1 == obj, and true == obj. More generally, a primitive type can be used anywhere that a supertype of its box is expected. I would like some clarification here. Is the scope of this bug limited solely to comparisons? If so, then this suggest special rules governing boxing/unboxing for comparisons; this needs to be thought through carefully. For example, consider 1 + 2 == obj, 0.add(1) == obj, etc.
30-04-2013