понедельник, 5 мая 2008 г.

Java Puzzle 88: Raw Deal

Что напечатает следующая программа?
import java.util.Arrays;
import java.util.List;
public class Pair<T> {
private final T first;
private final T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public List<String> toArray() {
return Arrays.asList(
String.valueOf(this.first),
String.valueOf(this.second));
}
public static void main(String[] args) {
Pair pair = new Pair<Object>(23, "skidoo");
for (String str : pair.toArray()) {
System.out.println(str);
}
}
}

Удивлены? Я тоже. Она просто не скомпилируется. Несовместимость типов в строке:
    for (String str : pair.toArray()) {

Что происходит? Ведь метод toArray всегда возвращает список строк! Проблема в том, что локальная переменная pair использует raw type. А это означает, что все поля и методы тоже будут использовать raw types. Т.е. метод toArray в таком случае возвращает просто список List. Бороться с этим просто. Измените декларацию переменно таким образом:
    Pair<Object> pair = new Pair<Object>(23, "skidoo");

или ещё более просто:
    Pair<?> pair = new Pair<Object>(23, "skidoo");

И запомните, что тип List (raw type) отличается от List<Object> (parametrized type).

А для меня, как разработчика пакета JavaBeans, который в полный рост использует reflection, это знание ОЧЕНЬ важно. Я вышел на новый уровень понимания generics!

Java Puzzle 87: Strained Relations

Тут задачка на равенства. Отношение равенства должно быть рефлексивным (reflexive), транзитивным (transitive) и симметричным (symmetric). Это в теориии...
А в Java определяет ли оператор сравнения == отношение равенства для значений примитивных типов? Если нет, то какое из трёх свойств оно нарушает?

В головоломке 29 мы узнали, что оператор сравнения не рефлексивный, так как Double.NaN == Double.NaN возравщает false.

Головоломка 35 поможет понять, что оператор сравнения не транзитивный. При сравнении двух числовых значений сначала осуществляется приведение типов. Но аккуратнее, конвертация int или long в double может привести к потере точности. А это чревато!
public class Transitive {
public static void main(String[] args) {
long x = Long.MAX_VALUE;
double y = (double)Long.MAX_VALUE;
long z = Long.MAX_VALUE - 1;
System.out.println(x == y);
System.out.println(y == z); // surprise!
System.out.println(x == z);
}
}

Haluz

Хороший on-line квест, продолжающий традиции Samorost 1 и 2. И тоже двухсерийный...