Заключительные классы на Java, которые не должны быть окончательными или наоборот?
Меня недавно задали этот вопрос в интервью:
Можете ли вы назвать любой класс API Java, который является окончательным, который не должен быть, или тот, который не является и должен быть??
Я не мог думать ни о чем. Вопрос подразумевает, что я должен знать все классы API, такие как задняя часть моей руки, которые я лично не ожидал бы, чтобы какой-либо разработчик Java знал.
Если кто-либо знает какие-либо такие классы, просьба привести примеры.
Ответы
Ответ 1
Первые примеры, которые приходят на ум, - это некоторые из нечетных подклассов Number, таких как BigDecimal
и BigInteger
, который, вероятно, должен был быть окончательным.
В частности, все их методы могут быть переопределены. Это позволяет создать сломанный BigDecimal
, например:
public class BrokenBigDecimal extends BigDecimal {
public BigDecimal add(BigDecimal augend) {
return BigDecimal.ZERO;
}
}
Это может вызвать серьезные проблемы, если вы получаете BigDecimal из ненадежного кода, например.
Перефразировать эффективную Java:
- Дизайн и документ для наследования или запрет на него
- Классы должны быть неизменными, если нет веской причины сделать их изменчивыми.
Ответ 2
java.awt.Dimension
не является окончательным или неизменным и должен был быть. Все, что возвращает размер (например, объект Window), должно создавать защитные копии, чтобы предотвратить неприятности со стороны вызывающих.
Ответ 3
На мой взгляд, ваш ответ должен был состоять в том, что вопрос вкуса, какие классы должны быть окончательными, а какие нет.
Есть веские причины сделать Integer
, Double
и String
все final
.
Есть веские причины жаловаться на это.
Тогда есть BitSet
, BitInteger
и т.д., которые можно сделать final
.
Существует несколько ситуаций, когда классы не являются final
, но они также не могут быть расширены разумно, поэтому они, вероятно, должны были быть окончательными.
Чтобы выбрать конкретный класс: BitSet
. Это не final
, но вы не можете расширять его, чтобы добавить бит shift
. Они могли бы также сделать это final
или добавить нам такую функциональность.
Ответ 4
Выскакивает класс Date
. Это изменяемый простой класс значений (по существу, обертка вокруг long
), но хорошая эвристика заключается в том, что простые классы значений должны быть неизменными. Обратите внимание также на его многочисленные устаревшие методы: больше доказательств того, что дизайн был взломан. Изменчивость Date
является источником ошибок, требующих дисциплинированного оборонительного копирования.
Ответ 5
тот, который не является и должен быть
Большинство конечных классов в Java разработаны так, чтобы они учитывали соображения безопасности, в целом относительно мало конечных. Например, java.util.String
является окончательным по этой причине. Так много других.
Некоторые классы w/private c-tor объявляются окончательными (Math, StrictMath), но в этом случае это не имеет значения.
В принципе, если нет проблем с безопасностью, мне все равно, является ли класс окончательным, но вы всегда можете использовать непубличный c-tor w/some factory, что фактически ограничивает возможность подкласса. Обычно это мой предпочтительный способ, поскольку он позволяет пакетно-приватное подклассу.
Вкратце: я не могу думать о конечном классе, которого не должно быть, однако есть некоторые, которые могли бы быть. Например, java.lang.Thread
может быть окончательным, возможно, не нужно защищать против злонамеренных clone()
.
Ответ 6
Проверьте класс String, который является окончательным и, вероятно, должен был быть вашим ответом в интервью.
Проверьте документы.
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html