Запрос относительно оператора равенства (совместимые операнды) в JAVA
Я новичок в JAVA и проходил через оператор равенства. Попробовав несколько комбинаций операндов, я немного запутался в том, что именно является определением совместимых операндов для оператора равенства (==) в Java.
int x = 23;
if (x == 23.3f) { // compiler accepts it. (may be because both are primitives)
int x = 23;
Double d = new Double(23.3);
if (x == d) { // compiler accepts it. (may be compatible pair of primitive and object reference)
int x = 23;
String s = "hello";
if (x == s) // compiler throws error - incompatible operands for == operator.
Так что, как мне кажется, должно быть какое-то формальное определение совместимых операндов для оператора равенства. Пожалуйста, помогите мне прояснить это сомнение.
3 ответа
Компилятор принимает это, потому что
x
а также23.3f
имеют примитивные числовые типы. И сравнение вернетсяfalse
,Компилятор принимает это, потому что Java распаковывает
Double
Возражатьdouble
примитивно при сравнении.Компилятор не может принять это, потому что
x
является примитивным числовым типом, иs
это ссылка наString
экземпляр класса. Невозможно сравнить примитивный номер и ссылку на объект.
За
int x = 23;
if (x == 23.3f)
Если вы посмотрите на байт-код с помощью javap -v
, int
будет преобразован в float
, т.е. i2f
будет вызван, а затем они будут сравниваться как 2 значения с плавающей запятой, используя fcmpl
,
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: bipush 23
2: istore_1
3: iload_1
4: i2f // The line of interest. Converts int to float.
5: ldc #16; //float 23.3f
7: fcmpl // compare two floats
8: ifne 11
11: return
В третьем случае вы сравниваете примитив с объектом (строкой), что невозможно.
Строки - это объекты. ==
сравнивает объекты по ссылке, а не по их внутреннему значению. Все другие(int, double)
сравниваются в ==
там ссылки на объекты, поэтому в случае строки она не совпадает, поэтому для строки мы должны .equals
оператор также Java чувствителен к регистру, поэтому при сравнении строки вы должны позаботиться о Case's of strings
Оператор равенства налагает некоторые ограничения и преобразования, они довольно большие и описаны в спецификации языка https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html
- Таким образом, в первом случае "x" переводится в тип с плавающей запятой перед сравнением.
- Во втором "d" распаковывается, а "x" повышается до двойного типа перед сравнением.
- В третьем случае во время компиляции возникает ошибка, поскольку String нельзя распаковывать для сравнения с примитивным типом.
Ошибка времени компиляции также может произойти, потому что типы классов не связаны (то есть, они не одинаковы, и ни один не является подклассом другого), таким образом, приведение между ними всегда будет неудачным. Что касается сравнения типа с некоторым типом интерфейса, компилятор допускает любое сравнение, за исключением того, что одна переменная никогда не может ссылаться на значение, которое реализует интерфейс, это потому, что тип является конечным типом, а переменная конечного типа всегда содержит значение того же типа времени выполнения, что и его тип времени компиляции. Следовательно, тип переменной во время выполнения должен быть именно тем типом, который не реализует указанный интерфейс.