пятница, 2 ноября 2007 г.

Java Puzzle 54: Null and Void

Что произойдет со следующей программой:
public class Null {
    public static void main(String[] args) {
        ((Null) null).hello();
    }
    private static void hello() {
        System.out.println("Hello world!");
    }
}

Сначала можно подумать, что программа сгенерирует NullPointerException. На самом деле выражение используется для вычисления класса, который содержит статический метод, а значение выражения игнорируется.

Но я бы еще больше бы постарался запутать тестируемого:
public class Null {
    public static void main(String[] args) {
        call(null);
    }
    private static void call(Null object) {
        object.hello();
    }
    private static void hello() {
        System.out.println("Hello world!");
    }
}
И совет на будущее. Не используйте ссылки на объекты для вызова статического метода - всегда указывайте имя класса, например:
Integer.toString(10)

6 комментариев:

  1. Возможно, что я не прав, но: в данном случае ограниченность синтаксиса - проблема Java. Ибо, например, в С++ вызов статического метода можно обозначить с помощью оператора разрешения видимости ::, а обращение к методу объекта - всегда . или ->.

    ОтветитьУдалить
  2. Ты как всегда прав.
    Java специально была задумана быть проще.
    Вот и ограничили синтаксис...

    А в C++ можно вызвать вызвать статический метод с использованием объекта, а не имени класса? Типа так:
    myObject->staticMethod()

    ОтветитьУдалить
  3. Можно. Поскольку тип объекта myObject известен компилятору и всегда известно, есть ли такой статический метод у классов такого типа на этапе компиляции.

    А насчет простоты Java: не думаю, чтобы она была задумана быть проще. Более того, рискну предположить, что Java не проще C++...

    ОтветитьУдалить
  4. А как себя поведет С++ в приведенной в пазле задаче, когда null приводится к некоторому типу (MyClass*), например?

    А синтаксис точно проще. Особенно, до введения Generics. В Java не надо вводить пробел при использовании вложенных templates:
    Class<Map<Object,String> >

    ОтветитьУдалить
  5. Дык эта... поведет С++ себя точно так же. Мы ж не разадресуем указатель, а только интересуемся типом, на который данный указатель может указывать.
    Поэтому, можно так:
    ((MyClass *)0)->myStaticMethod();

    ОтветитьУдалить
  6. Вот и следует отсюда, что синтаксис в Java проще. Не надо думать об объектах и ссылках, и что использовать . или ->

    ОтветитьУдалить