четверг, 29 мая 2008 г.

Java Puzzle 94: Lost in the Shuffle

Рассмотрим метод перемешивания содержимого массива. Хорош ли он? Если нет, то как его исправить?
import java.util.Random;
public class Shuffle {
private static Random rnd = new Random();
public static void shuffle(Object[] a) {
for (int i = 0; i < a.length; i++) {
swap(a, i, rnd.nextInt(a.length));
}
}
private static void swap(Object[] a, int i, int j) {
Object tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}

Aвторы доказывают, почему он не достаточно хорош, и рекомендуют использовать библиотечный класс java.utul.Collections, у которого есть метод shuffle. В принципе, достаточно изменить метод так:
  public static void shuffle(Object[] a) {
for (int i = a.length; i > 1; i--) {
swap(a, i - 1, rnd.nextInt(i));
}
}
}

Говорят, что надо читать Кнута. А я у него только второй том осилил ;)

Java Puzzle 93: Class Warfare

Это головоломка тестирует знания совместимости классов. Авторы приводят два класса. В одном определены статические поля, а второй эти поля использует. После компиляции программы авторы предлагают переопределить эти поля в первом классе и перекомпилить его, не компилируя при этом второй. Естественно, результат работы второго класса не изменится.
Это одна из особенностей языка, которые я не люблю: ссылки на константы резолвятся во время компиляции (JLS 13.1). Из-за этого большие проекты приходится перекомпилировать целиком, чтобы не наступить на грабли.

Однако в этой головоломке скрыта другая. Одна из констант в первом классе - null, а согласно JLS 15.28: null не является константой во время компиляции и ссылка на неё резолвится во время исполнения.
Обратите внимание, что enum-константы, введённые в Java 5, не являются константами времени компиляции, т.е. не надо перекомпилировать классы, использующие эти enum-константы, если они поменяются.
Для всех бы констант так!