Почему java.lang. Объект не абстрактен? [дубликат]

127
задан Community 23 May 2017 в 11:47
поделиться

14 ответов

Множество крупных проектов используют некоторые Objective-C + +. Например, Camino, Chromium и Firefox представляют собой существенные проекты с открытым исходным кодом, включающие Objective-C + +.

-121--4648481-

Без дизайнеров java.lang.Object говорить нам, мы должны основывать наши ответы на мнении. Есть несколько вопросов, которые можно задать, которые могут помочь прояснить.

Выиграет ли какой-либо из методов Объекта от абстрактности?

Можно ли утверждать, что некоторые из методов выиграют от этого. Возьмем, например, hashCode () и equals () , вероятно, было бы гораздо меньше разочарования вокруг сложностей этих двух, если бы они оба были сделаны абстрактными. Это потребовало бы от разработчиков выяснить, как они должны их внедрять, что делает их более очевидными (см. Эффективная Java). Однако я больше придерживаюсь мнения, что hashCode () , равны () и clone () принадлежат отдельным абстракциям (т.е. интерфейсам). Другие методы, wait () , notify () , finalize () и т.д. достаточно сложны и/или являются собственными, поэтому лучше всего, чтобы они уже были реализованы, и не выиграют от абстрагирования.

Поэтому я полагаю, что ответ будет нет, ни один из методов Объекта не выиграет от абстрактности.

Будет ли преимуществом пометить класс Object как абстрактный?

При условии, что все методы реализованы, единственным эффектом маркировки объекта как абстрактного является невозможность его построения (т.е. new Object () является ошибкой компиляции). Будет ли это полезно? Я придерживаюсь мнения, что термин «объект» сам по себе абстрактен (можете ли вы найти вокруг себя что-нибудь, что можно полностью описать как «объект»?), так что он бы вписывался в объектно-ориентированную парадигму. Однако это на пуристской стороне. Можно утверждать, что принуждение разработчиков выбирать название для любого конкретного подкласса, даже пустого, приведет к коду, который лучше выразит их намерение. Думаю,чтобы быть полностью правильным с точки зрения парадигмы, Объект должен быть отмечен абстрактным , но когда дело доходит до него, нет реальной выгоды, это вопрос предпочтения дизайна (прагматизм против чистоты).

Является ли практика использования простого объекта для синхронизации достаточно веской причиной для того, чтобы он был конкретным?

Во многих других ответах говорится о построении простого объекта для использования в операции synchronized () . Хотя это, возможно, была распространенная и общепринятая практика, я не думаю, что это была бы достаточно хорошая причина, чтобы предотвратить абстрактность объекта, если бы проектировщики хотели, чтобы это было. В других ответах упоминалось, как мы должны объявлять один пустой подкласс Объекта в любое время, когда мы хотим синхронизироваться с определенным объектом, но это не выдерживает - пустой подкласс мог быть предоставлен в SDK ( java.lang.Lock или какой-либо другой), который можно было построить в любое время, когда мы хотели синхронизировать. Это принесло бы дополнительную пользу, создав более сильное заявление о намерениях.

Есть ли какие-либо другие факторы, которые могли бы быть неблагоприятно затронуты, делая Объект абстрактным?

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

  • Производительность
  • Безопасность
  • Простота реализации СПМ

Могут ли быть другие причины?

Упоминалось, что это может быть в отношении размышлений. Однако отражение было введено после проектирования объекта. Так что влияет это на рефлексию или нет - это не причина. То же самое для дженериков.

Есть также незабываемый момент, что java.lang.Object был разработан людьми: они, возможно, ошиблись, они, возможно, не рассмотрели вопрос. Нет языка без изъянов, и это может быть одним из них, но если это так, то вряд ли большим. И я могу смело сказать, без отсутствия стремлений, что я вряд ли буду участвовать в том , чтобы намереваться ключевой части такой широко используемой технологии, особенно той, которая длится 15 (?) лет и все еще остается сильной, поэтому это не следует считать критикой.

Сказав это, я сделал бы его абстрактным; -p

Резюме
В основном, насколько я вижу, ответ на оба вопроса «Почему java.lang.Object concept?» или (если это было так) «Почему java.lang.Object abstract?»... почему бы и нет.

65
ответ дан 24 November 2019 в 00:48
поделиться

причины, почему объект должен быть конкретным.

  1. Отражение
    См. Объект. GetClass ()

  2. Общее использование (Pre Java 5)

  3. Сравнение / выход
    см. Object.ToString (), объект. Equals (), Object.hashCode () и т. Д.

  4. Синхронизация
    см. Object.Wait (), Object.notify () и т. Д.

Несмотря на то, что пару областей были заменены / устарены, по-прежнему было необходимость в бетоном родительском классе предоставлять эти функции каждому классу Java.

Класс объекта используется в отражении, поэтому код может вызывать методы в экземплярах неопределенного типа, i.e. 'Object.Class.getDeclaredMethods ()'. Если объект должен был быть абстрактным, то код, который хотел принять участие, должен будет реализовать все абстрактные методы до того, как клиентский код может использовать отражение на них.

Согласно Солнцу, Абстрактный класс - это класс, который объявлен абстрактным - это может или не может включать в себя абстрактные методы. Абстрактные классы не могут быть созданы, но они могут быть подклассаны. Это также означает, что вы не можете вызывать методы или получать доступ к публичным полям абстрактного класса.

Пример абстрактного корневого класса:

abstract public class AbstractBaseClass
{
    public Class clazz;

    public AbstractBaseClass(Class clazz)
   {
       super();
       this.clazz = clazz;
   }
}

Ребенок нашего абстрактногоBaSeclass:

public class ReflectedClass extends AbstractBaseClass  
{
    public ReflectedClass() 
    {
       super(this);
    }

    public static void main(String[] args)  
    {
        ReflectedClass me = new ReflectedClass();
    }
}

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

   public ReflectedClass()
   {
       super(ReflectedClass.class);
   }  

, но это только работает, потому что отражениеКласс имеет родительский («объект»), который представляет собой 1) бетон и 2) имеет поле для хранения типа для своих детей.

Пример, более типичный для отражения, будет находиться в нестатическом элементе функции:

public void foo()
{
    Class localClass = AbstractBaseClass.clazz;  
}

это не удается, если вы не измените поле «Clazz», чтобы быть статичным. Для класса область объекта это не будет работать, потому что он должен быть специфичным. Это не имеет смысла для объекта иметь место статического класса.

Теперь я попробовал следующие изменения, и это работает, но немного вводит в заблуждение. Это все еще требует, чтобы базовый класс был продлен на работу.

public void genericPrint(AbstractBaseClass c)
{
    Class localClass = c.clazz;
    System.out.println("Class is: " + localClass);
}

public static void main(String[] args)
{
    ReflectedClass me = new ReflectedClass();
    ReflectedClass meTwo = new ReflectedClass();

    me.genericPrint(meTwo);
}

До-Java5 Generics (вроде с массивами) было бы невозможно было бы невозможно

Object[] array = new Object[100];
array[0] = me;
array[1] = meTwo;

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

-4
ответ дан 24 November 2019 в 00:48
поделиться

Время от времени вам нужен простой объект, который не имеет своего собственного состояния. Хотя такие объекты кажутся бесполезными с первого взгляда, у них все еще есть утилита, поскольку у каждого из них отличается идентичность . TNIS полезен в нескольких сценариях, наиболее важным из которых блокируется: вы хотите координировать два потока. В Java вы делаете это, используя объект, который будет использоваться в качестве блокировки. Объект не должен иметь никакого состояния, его простое существование достаточно, чтобы он стал блокировкой:

class MyThread extends Thread {
   private Object lock;
   public MyThread(Object l) { lock = l; }

   public void run() { 

      doSomething();
      synchronized(lock) {
          doSomethingElse();
      } 
   }
}

Object lock = new Object();
new MyThread(lock).start();
new MyThread(lock).start();

в этом примере мы использовали блокировку для предотвращения одновременного выполнения двух потоков DOSOMETTELLECTELSE ()

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

Придя, чтобы подумать об этом, вот двойной вопрос к вашему: Предположим, что объект был абстрактным, он определит любые абстрактные методы? Я думаю, что ответ - это . В таких обстоятельствах не так много ценности для определения класса в виде абстрактных.

5
ответ дан 24 November 2019 в 00:48
поделиться

Это также означает, что его можно создать в массиве. В до-1,5 дня это позволит вам иметь общие структуры данных. Это все еще может быть верно на некоторых платформах (я думаю, J2me, но я не уверен)

0
ответ дан 24 November 2019 в 00:48
поделиться

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

1
ответ дан 24 November 2019 в 00:48
поделиться

Я думаю, что все ответы до сих пор забывают то, что было похоже на Java 1.0. В Java 1.0 вы не могли сделать анонимный класс, поэтому, если вы просто хотели, чтобы объект для какой-то цели (синхронизация или нулевой заполнитель) вам придется пойти объявить класс для этой цели, а затем целую кучу кода Эти дополнительные классы для этой цели. Гораздо более прямо вперед, чтобы просто позволить прямую атмосферу объекта.

Конечно, если вы разработали Java сегодня, вы можете сказать, что каждый должен делать:

 Object NULL_OBJECT = new Object(){};

, но это не было вариантом в 1.0.

1
ответ дан 24 November 2019 в 00:48
поделиться

Я не понимаю, почему большинству, кажется, верит, что делает полностью функциональный класс, который реализует все его методы в использовании, абстрактный, будет хорошей идеей.
Я бы предпочел спросить, почему это абстракция? Это делает что-то не должно? Это не хватает некоторой функциональности, которую он должен иметь? Оба эти вопросы можно ответить No, это полностью рабочий класс самостоятельно, что делает его абстрактным, просто ведет к людям, осуществляющим пустые классы.

public class UseableObject extends AbstractObject{}

USEBARYOBJECT наследует от абстрактного объекта и удивления, он может быть реализован, он не добавляет никаких функций, и его единственная причина для существа - разрешить доступ к методам, выставленным объектом.
Также я должен не согласиться с использованием в «плохой» синхронизации. Использование частных объектов для синхронизации доступа является безопаснее, чем использование синхронизации (этого) и безопаснее, а также проще в использовании, чем классы блокировки от Java Util одновременно.

5
ответ дан 24 November 2019 в 00:48
поделиться

Я подозреваю, что короткий ответ заключается в том, что классы коллекций потеряли информацию о потерянности в течение нескольких дней до дженериков Java. Если коллекция не является универсальным, то он должен вернуть конкретный объект (и быть удрученным во время выполнения до того, какой тип его был ранее).

Поскольку изготовление бетонного класса в абстрактный класс нарушит бинарную совместимость (как отметил UpdRead), урок бетона объекта был сохранен. Я хотел бы отметить, что ни в коем случае не было создано для единственной цели синхронизации; Манекенные классы работают так же хорошо.

Ошибка дизайна не включает в себя дженерики с самого начала. Множество дизайнерской критики направлена ​​на это решение и его последствия. [О, и правило подтипона массива.]

-6
ответ дан 24 November 2019 в 00:48
поделиться

Как дополнительное примечание, не соблазнится использовать метод Object.finalize (), который работает при объекте GC'D, так как у вас нет контроля, когда объект собирается.

-121--2467921-

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

-9
ответ дан 24 November 2019 в 00:48
поделиться
-

Я думаю, что это, вероятно, должно было быть объявлено абстрактным, но как только это будет сделано и выпустить, это очень трудно отменить, не вызывая большую боль - см. Язык Java Spec 13.4.1:

«Если у класса, который не был абстрактным, не изменен, чтобы быть объявленным абстрактным, затем предъявляемые двоичными дворами, которые пытаются создать новые экземпляры этого класса, будут бросать либо инстанцироватьЭрр по времени ссылки, либо (если используется рефлексивный метод). Таким образом, такое изменение не рекомендуется для широко распространенных классов ».

7
ответ дан 24 November 2019 в 00:48
поделиться

Мне кажется, что здесь есть простой вопрос практичности. Создание класса абстрактное убрать способность программиста что-то делать что-то, а именно, чтобы создать его. Вы ничего не можете сделать с абстрактным классом, который вы не можете сделать с бетонным классом. (Ну, вы можете объявить абстрактные функции в нем, но в этом случае нам не нужно иметь абстрактные функции.) Итак, сделав его бетоном, вы делаете его более гибким.

Конечно, если был какой-то активный вред, который был сделан, сделав его бетон, что «гибкость» будет недостатком. Но я не могу думать о каком-либо действите, сделанном объектом мгновенным. («Мгновенно» слово? Что бы ни на что.) Мы могли бы обсудить, является ли какой-либо данное использование, что кто-то сделан из экземпляра необработанного объекта, является хорошей идеей. Но даже если бы вы могли убедить меня, что каждое использование, которое я когда-либо видел из необработанного объекта, был плохим идеей, что еще не докажет, что там не может быть хорошего использования. Так что, если это ничего не повредит, и это может помочь, даже если мы не можем думать о том, как оно на самом деле поможет в данный момент, зачем его запретить?

2
ответ дан 24 November 2019 в 00:48
поделиться

Я могу подумать о нескольких случаях, когда экземпляры объекта полезны:

  • Блокировка и синхронизация, как вы и другие комментарии. Это, вероятно, кодовый запах, но я видел экземпляры объектов, используемые так все время.
  • Как нулевые объекты , потому что равны , всегда возвращают ложь, за исключением самого экземпляра.
  • В тестовом коде, особенно при тестировании классов сбора. Иногда легче заполнить коллекцию или массив с пустыми предметами, а не NULL S.
  • как базовый экземпляр для анонимных классов. Например:
    Объект O = новый объект () {... Code здесь ...}
11
ответ дан 24 November 2019 в 00:48
поделиться

Обычные экземпляры Java.lang.Object обычно используются в сценариях блокировки / синхронизации, и это принято практика.

Также - какова была причина для этого быть абстрактным? Потому что он не полностью функционален сам по себе, как экземпляр? Может ли это действительно с некоторыми абстрактными членами? Не думай так. Таким образом, аргумент для того, чтобы сделать его абстрактным в первую очередь несуществуют. Так что это нет.

Возьмите классическую иерархию животных, где у вас есть абстрактный класс животных , рассуждения, позволяющие сделать животное . Аннотация Аннотация, потому что экземпляр животного фактически является «недействительным» Недостаток отсутствия лучшего слова животного (даже если все его методы обеспечивают базовую реализацию). С объектом , то есть просто не тот случай. Нет подавляющего случая, чтобы сделать его абстрактным в первую очередь.

24
ответ дан 24 November 2019 в 00:48
поделиться

Из всего, что я прочитал, кажется, что Объект не обязательно должен быть конкретным , а на самом деле должен был быть абстрактным .

Мало того, что он не должен быть конкретным, так еще и после некоторого прочтения я убежден, что Объект не, будучи абстрактным, противоречит базовой модели наследования - мы не должны допускать абстрактных подклассов конкретного класса, так как подклассы должны только добавлять функциональность.
Очевидно, что это не так в Java, где мы имеем абстрактные подклассы Object.

10
ответ дан 24 November 2019 в 00:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: