2015-05-21 7 views
12

Я пытаюсь понять, почему java.util.Properties был реализован таким образом. Он имеет два интерфейса: getProperty/setProperty, который принимает только строки, а put/get принимает любой объект в качестве значения. Эти два интерфейса кажутся перекрывающимися, поэтому строка, добавленная с помощью put(), может быть получена с помощью getProperty().Ввод объектов в java.util.Properties

Кажется, что есть некоторые проблемы с этим странным гибридным интерфейсом. Помещение объекта, который переопределяет свойство строки, имеет побочный эффект очистки строкового значения, создавая нуль как результат getProperty. Добавление целого числа или какого-либо другого значения, которое имеет простой перевод строк, может быть неправильно понято как значение реального свойства (но в качестве свойства оно всегда равно нулю).

Мой вопрос: есть ли реальная, практическая причина для этого? Как я подозреваю?

+0

Я не могу создать резервную копию, но я уверен, что проблема связана с обратной совместимостью. 'Свойства' расширяет' Hashtable', который является старым классом из-под дженериков; это означает, что если у вас есть «Свойства», вы могли бы вызвать в него значение 'property.put (whatthing, whateverElse)'. Когда появились дженерики, люди Java хотели сохранить совместимость кода обратно, а это означало, что он расширяет «Hashtable ». – yshavit

+0

'Свойства' является подклассом' Hashtable', без переопределения 'get' /' put', следовательно, поведение. 'getProperty' /' setProperty' - это типизированные версии 'get' /' put'. Это вопрос истории, а не скрытие get/put. –

ответ

10

Joshua Bloch упоминает об этом в явном Effective Java

[из главы 4] В случае Properties, конструкторы Подразумевается, что только строки допускается в качестве ключей и значений, но прямой доступ к базовой Hashtable позволяет этот инвариант должен быть нарушен. Как только этот инвариант нарушен, более невозможно использовать другие части API свойств (load и store). К тому времени, когда эта проблема была обнаружена, было слишком поздно исправлять ее, потому что клиенты зависели от использования ключей и значений nonstring.

Этот текст находится в контексте использования композиции над наследованием. Он в основном использует это как пример того, когда композицию следует использовать вместо наследования. Если Properties обернул a Map вместо того, чтобы расширять один, он мог бы принудительно использовать инвариантное значение String в качестве ключей и значений.

Итак, ответ: это был недосмотр.

+1

Выбор этого ответа, потому что он объясняет, почему он был реализован таким образом, больше, чем просто «не использовать другие методы». В качестве дополнительной заметки API-интерфейс java mail использует это для создания настраиваемой фабрики SSL-сокетов. О, я, отношения любви и ненависти, которые у нас есть. –

2

Официальные Документации говорит

Поскольку свойства наследует от Hashtable, надетой и методы putAll могут быть применены к объекту Свойства. Их использование сильно обескуражено, поскольку они позволяют вызывающему абоненту вставлять записи, ключи или значения которых не являются строками. Вместо этого следует использовать метод setProperty. Если метод store или save вызывается в «скомпрометированном» объекте «Свойства», который содержит не-String-ключ или значение, вызов завершится с ошибкой. Точно так же вызов метода propertyNames или list завершится неудачно, если он вызван в «скомпрометированный» объект «Свойства», который содержит нестроковый ключ.

http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html

5

Доступ к put и get является результатом Properties является продолжением Hashtable, и два метода не должна быть использован (но не может быть скрыта от реализации из-за их общий доступ в суперкласса).

Javadocs имеет хорошую записку о том, почему вы не должны использовать эти методы, а вместо этого только использовать строки:

Properties Поскольку унаследованы от Hashtable, то put и putAll методы могут быть применены к Properties объект. Их использование сильно обескуражено, поскольку они позволяют вызывающему абоненту вставлять записи, ключи или значения которых не являются Strings. Вместо этого следует использовать метод setProperty. Если метод или save вызывается на «скомпрометированном» объекте Properties, который содержит ключ или значение не String, вызов завершится с ошибкой. Аналогично, вызов метода propertyNames или list завершится с ошибкой, если он вызван на «скомпрометированный» объект Properties, который содержит ключ не String.

Как @yshavit отмечает, что было бы больше смысла для Properties продлить Hashtable<String, String> чем Hashtable двух объектов, но это, вероятно, принято решение сохранить обратную совместимость, как и любые программы, используя get/put с любым Такие переменные не были бы разбиты.

+0

Но это не касается важной части вопроса, поэтому методы get/put работают над 'Object' вместо' String'.То есть, почему он не расширяет 'Hashtable '? (В моем комментарии выше, я сильно подозреваю, что это для обратной совместимости, но у меня нет конкретных доказательств.) – yshavit

+0

@yshavit Хорошее примечание; Я согласен, что это почти определенно для обратной совместимости, и я добавил такую ​​заметку в ответ. – Vulcan

0

От Java Docs

Поскольку свойства наследует от Hashtable, надетого и методов putAll может быть применен к объекту Свойства.Их использование сильно обескуражено, поскольку они позволяют вызывающему абоненту вставлять записи, ключи которых или значения не являются строками. Вместо этого следует использовать метод setProperty. Если метод сохранения или сохранения вызывается на «скомпрометированном» объекте свойств , который содержит не-Строковый ключ или значение, вызов завершится с ошибкой. Аналогично, вызов метода propertyNames или list завершится неудачно, если вызывается в «скомпрометированном» объекте «Свойства», который содержит нестроковый ключ .

0

Properties расширяет Hashtable, так что вы можете использовать Properties в любом месте вы можете использовать Hashtable.

Класс Hashtable - это функции, которые производятся от get() и put().

0

put(key, value)get(key) и являются остатки сомнительного решения, чтобы иметь Properties продлить Hashtable обратно в тот же день. Такое поведение не может быть изменено, так как оно нарушит совместимость в обратном направлении, но любая половина руководства по достойному стилю, включая собственно документацию API, будет рекомендовать никогда не использовать эти методы.

0

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

Смежные вопросы