Подтвердить что ты не робот

Почему java.util.Properties реализует Map <Object, Object>, а не Map <String, String>

Класс java.util.Properties предназначен для представления карты, где ключи и значения являются строками. Это связано с тем, что объекты Properties используются для чтения файлов .properties, которые являются текстовыми файлами.

Итак, почему в Java 5 они модифицировали этот класс для реализации Map<Object,Object>, а не Map<String,String>?

javadoc утверждает:

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

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

Я предполагаю, что создание Properties реализации Map<String,String> не будет полностью обратно совместимым с кодом, написанным для pre-Java 5. Если у вас есть более старый код, который привязывает non-strings к объекту Properties, тогда этот код больше не будет компилироваться с Java 5. Но... разве это не хорошо? Разве не все точки дженериков поймать такие ошибки типа во время компиляции?

4b9b3361

Ответ 1

Потому что они спешили в первые дни Java и не понимали, какими последствиями будут четыре версии позже.

С самого начала предполагалось, что общие функции должны быть частью дизайна Java, но функция была отброшена как слишком сложная и в то время не нужна. В результате много кода в стандартных библиотеках написано с предположением о не общих коллекциях. Для прототипа "Пицца" от Мартина Одерского потребовался прототип языка, чтобы показать, как их можно сделать достаточно хорошо, сохраняя при этом почти идеальную обратную совместимость с кодом Java и байт-кодом. Прототип привел к Java 5, в котором классы коллекций были модифицированы с помощью дженериков таким образом, чтобы старый код продолжал работать.

К сожалению, если они должны были ретроактивно сделать Properties наследовать от Map<String, String>, тогда предыдущий действительный код перестанет работать:

Map<Object, Object> x = new Properties()
x.put("flag", true)

Почему бы кто-нибудь это делать не по себе, но приверженность Sun к обратной совместимости в Java вышла за рамки героического в бессмысленное.

То, что сейчас ценится большинством образованных наблюдателей, заключается в том, что Properties никогда не должно унаследовать от Map вообще. Вместо этого он должен обернуться вокруг Map, отображая только те функции карты, которые имеют смысл.

С момента создания Java Мартин Одерски продолжил создание нового Scala языка, который является более чистым, наследует меньше ошибок и разбивает новые позиции в целом ряде областей. Если вы обнаружите, что Java-niggles раздражает, взгляните на него.

Ответ 2

Первоначально предполагалось, что Properties действительно расширяет Hashtable<String,String>. К сожалению, внедрение мостовых методов вызвало проблему. Properties, определяемый таким образом, заставляет javac генерировать синтетические методы. Properties должен определить, скажем, метод get, который возвращает String, но должен переопределить метод, который возвращает Object. Таким образом добавляется метод синтетического мостика.

Предположим, у вас был класс, написанный в плохие старые 1.4 дня. Вы переопределили некоторые методы в Properties. Но то, что вы еще не сделали, переопределено новыми методами. Это приводит к непреднамеренному поведению. Чтобы избежать этих мостовых методов, Properties extends Hashtable<Object,Object>. Точно так же Iterable не возвращает (только для чтения) SimpleIterable, потому что это могло бы добавить методы к реализациям Collection.

Ответ 3

Однострочный (двухстрочный без предупреждений) для создания Карты из Свойства:

@SuppressWarnings({ "unchecked", "rawtypes" })
Map<String, String> sysProps = new HashMap(System.getProperties());

Ответ 4

Обратная совместимость.

Ответ 5

Причина: Принцип подстановки Лискова и обратная совместимость. Properties extends Hashtable и, следовательно, должен принимать все сообщения, которые примет Hashtable, а это означает принятие put(Object, Object). И он должен расширять plain Hashtable вместо Hashtable<String, String>, потому что Generics были реализованы с помощью метода down-compatibe с помощью типа erasure, поэтому один раз компилятор сделал свое дело, нет никаких дженериков.