Java: Обоснование класса Object не объявляется абстрактным

Почему класс java.lang.Object не был объявлен абстрактным?

Конечно, для того, чтобы объект был полезным, ему нужно добавить состояние или поведение, класс Object является абстракцией, и поэтому он должен быть объявлен абстрактным... , почему они решили не делать этого?

Ответ 1

Анд, я думаю, вы приближаетесь к этому - каламбур НЕ предназначен - с ненужной степенью абстракции. Я думаю, что этот (ИМХО) ненужный уровень абстракции является тем, что вызывает здесь "проблему". Возможно, вы приближаетесь к этому с математического теоретического подхода, когда многие из нас приближаются к этому с подхода "программист, пытающийся решить проблемы". Я считаю, что это различие в подходе вызывает разногласия.

Когда программисты смотрят на практичность и как на самом деле что-то внедрять, есть несколько раз, когда вам нужен какой-то полностью произвольный объект, фактический экземпляр которого абсолютно неактуальен. Он просто не может быть нулевым. Пример, который я дал в комментарии к другому сообщению, - это реализация *Set (* == Hash или Concurrent или тип выбора), который обычно делается с помощью поддержки *Map и использования Map в качестве набора. Вы часто не можете использовать null как значение Map, поэтому обычно делается попытка использовать статический экземпляр Object как значение, которое будет игнорироваться и никогда не будет использоваться. Тем не менее, требуется не-нулевое местозаполнитель.

Еще одно распространенное использование с ключевым словом synchronized, где требуется некоторая Object для синхронизации, и вы хотите, чтобы ваш элемент синхронизации был полностью закрытым, чтобы избежать тупиковой ситуации, когда разные классы непреднамеренно синхронизируются с одной и той же блокировкой. Очень распространенная идиома заключается в том, чтобы выделить private final Object для использования в классе как блокировку. Справедливости ради, что касается Java 5 и java.util.concurrent.locks.Lock и связанных дополнений, эта идиома заметно менее применима.

Исторически сложилось так, что на Java было очень полезно иметь возможность Object быть реалистичной. Вы могли бы сказать, что с небольшими изменениями в дизайне или с небольшими изменениями API это больше не понадобится. Возможно, вы правы в этом.

И да, API мог бы предоставить класс Placeholder, который расширяет Object без добавления чего-либо вообще, для использования в качестве заполнителя для целей, описанных выше. Но - если вы расширяете Object, но ничего не добавляете, каково значение в классе, отличном от того, чтобы позволить Object быть абстрактным? Математически, теоретически, возможно, можно было бы найти значение, но прагматично, какое значение он добавил бы для этого?

В программировании есть моменты, когда вам нужен объект, какой-либо объект, какой-либо конкретный объект, который не является нулевым, что можно сравнить с помощью == и/или .equals(), но вам просто не нужны никакие другие для этого объекта. Он существует только для того, чтобы служить уникальным идентификатором и в противном случае абсолютно ничего не делает. Object отлично выполняет эту роль и (IMHO) очень хорошо.

Я бы предположил, что этот является частью причины, по которой Object не был объявлен абстрактом: для него это просто не полезно.

Ответ 2

An Object полезен, даже если у него нет какого-либо состояния или поведения, характерного для него.

Одним из примеров может служить его использование в качестве общего средства защиты, используемого для синхронизации:

public class Example {
    private final Object o = new Object();

    public void doSomething() {
        synchronized (o) {
            // do possibly dangerous stuff
        }
    }
}

Хотя этот класс немного прост в своей реализации (здесь неясно, почему полезно иметь явный объект, вы можете просто объявить метод synchronized), есть несколько случаев, когда это действительно полезно.

Ответ 3

Указывает ли объект методы, которые распространяют его классы, чтобы они были полезны? Нет, и поэтому он не должен быть абстрактным.

Концепция абстрактного класса имеет четко определенное значение, которое не относится к объекту.

Ответ 4

Вы можете создать экземпляр Object для блокировок синхронизации:

Object lock = new Object();

void someMethod() {
  //safe stuff
  synchronized(lock) {
     //some code avoiding race condition
  }
}

void someOtherMethod() {
  //safe code
  synchronized(lock) {
    //some other stuff avoiding race condition
  }
}

Ответ 5

Я не уверен, что это причина, но она позволяет (или разрешает, поскольку теперь есть лучшие способы сделать это) для объекта, который будет использоваться как блокировка:

Object lock = new Object();

....


synchronized(lock)
{
}

Ответ 6

Как объект более оскорбителен, чем null?

Он делает маркер хорошего места (так же как и нуль).

Кроме того, я не думаю, что было бы хорошим дизайном сделать абстрактный объект без абстрактного метода, который должен быть включен.

Я не говорю, что нуль - лучшая вещь, поскольку нарезанный хлеб - я прочитал статью на днях "Изобретателем", обсуждая стоимость/ценность понятия null... (я даже не думаю, что null был изобретательным! Я думаю, кто-то может утверждать, что он изобрел нуль..), что возможность экземпляра объекта не хуже, чем возможность пропускать null.

Ответ 7

Вы никогда не знаете, когда захотите использовать простой объект в качестве заполнителя. Подумайте об этом как о нуле в числовой системе (и null для этого не работает, поскольку null представляет отсутствие данных).

Ответ 8

Должна быть причина для создания абстрактного класса. Один из них - запретить клиентам создавать экземпляр класса и заставлять их использовать только подклассы (по каким-либо причинам). Другое дело, если вы хотите использовать его в качестве интерфейса, предоставляя абстрактные методы, которые должны реализовывать подклассы. Вероятно, дизайнеры и Java не видели таких причин, поэтому java.lang.Object остается конкретным.

Ответ 9

Как всегда, Гува помогает: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html Материал здесь можно использовать для уничтожения экземпляров nulls/Object для "не-нулевого заполнителя" из кода.

Здесь есть полностью разделенные вопросы:

  • Почему они не сделали Object abstract?
  • Насколько катастрофа наступает после того, как они решат сделать ее абстрактной в будущей версии?

Ответ 10

Я просто добавлю еще одну причину, по которой я нашел Object полезным для самостоятельной реализации. У меня есть пул объектов, которые я создал, который имеет несколько слотов. Эти слоты могут содержать любой из множества объектов, все они наследуются от абстрактного класса. Но что я положил в пул, чтобы представить "пустой". Я мог использовать null, но для моих целей было более разумно убедиться, что в каждом слоте всегда есть какой-то объект. Я не могу создать экземпляр абстрактного класса, и я бы этого не хотел. Таким образом, я мог бы создать конкретный подкласс моего абстрактного класса для представления "не настоящий foo", но это казалось ненужным, когда использование экземпляра Object было столь же хорошо… на самом деле лучше, так как оно ясно говорит, что в слоте не имеет функциональности. Поэтому, когда я инициализирую свой пул, я делаю это, создавая Объект для назначения каждому слоту в качестве начального условия пула.