Я задавал этот вопрос Есть ли способ переопределить переменные класса в Java? Первый комментарий, набравший 36 голосов, был:
Если вы когда-нибудь увидите
protected static
, бегите.
Кто-нибудь может объяснить, почему не protected static
одобряют?
Я задавал этот вопрос Есть ли способ переопределить переменные класса в Java? Первый комментарий, набравший 36 голосов, был:
Если вы когда-нибудь увидите
protected static
, бегите.
Кто-нибудь может объяснить, почему не protected static
одобряют?
final
. Изменяемое статическое поле, разделяемое всеми классами, определенно вызывает беспокойство. Множественные классы, обновляющие статическое поле, вряд ли будут надежными или легкими для отслеживания, тем более, что присутствие любого защищенного поля или метода подразумевает, что класс предназначен для расширения классами в других пакетах, возможно, классами, не находящимися под контролем автор класса, содержащего защищенное поле.final
не означает, что поле неизменяемо. Вы всегда можете изменитьobject
ссылку, на которуюfinal
ссылается ссылочная переменная.Ответы:
Это скорее стилистическая вещь, чем прямая проблема. Это говорит о том, что вы не продумали как следует, что происходит с классом.
Подумайте, что
static
означает:Подумайте, что
protected
означает:Эти два значения не совсем взаимоисключающие, но довольно близки.
Единственный случай, когда я вижу, где вы могли бы использовать их вместе, - это если бы у вас был абстрактный класс, который был разработан для расширения, и расширяющийся класс мог бы затем изменить поведение, используя константы, определенные в оригинале. Однако такая организация, скорее всего, закончится очень запутанной и указывает на слабость в дизайне классов.
В большинстве случаев было бы лучше, чтобы константы были общедоступными, поскольку это просто делает все более чистым и позволяет людям делать подклассы более гибкими. Помимо всего прочего, во многих случаях композиция предпочтительнее наследования, в то время как абстрактные классы вызывают наследование.
Чтобы увидеть один пример того, как это может сломаться, и проиллюстрировать, что я имею в виду под переменной, не имеющей независимого существования, попробуйте этот пример кода:
Вы увидите результаты:
Попробуйте сами: https://ideone.com/KM8u8O
Класс
Test2
может получить доступ к статическому членуtest
отTest
без необходимости квалифицировать имя - но он не наследует или получить свою собственную копию. Он смотрит на тот же самый объект в памяти.источник
Rectangle
) для регулировки ширины / высоты, чтобы гарантировать, что равенство (дляSquare
) приведет к нежелательным результатам, если вы замените каждый супертип экземпляром его подтипа.Это неодобрительно, потому что это противоречиво.
Создание переменной
protected
подразумевает, что она будет использоваться внутри пакета или унаследована внутри подкласса .Создание переменной
static
делает ее членом класса, что исключает намерение наследовать ее . Остается только намерение использоваться в пакете , и у нас естьpackage-private
для этого (без модификатора).Единственная ситуация, в которой я мог найти это полезным, - это если вы объявляли класс, который должен использоваться для запуска приложения (например, JavaFX
Application#launch
, и хотели иметь возможность запускаться только из подкласса. В этом случае убедитесь, что метод такжеfinal
должен запретить скрытие . Но это не «норма» и, вероятно, было реализовано, чтобы предотвратить добавление дополнительных сложностей путем добавления нового способа запуска приложений.Чтобы увидеть уровни доступа для каждого модификатора, см. Это: Учебники по Java - Управление доступом к членам класса
источник
static
устранить намерения наследовать его. Поскольку мой подкласс в другом пакете по-прежнему требует, чтобы поле super былоprotected
для доступа, даже если оноstatic
.package-private
не могу помочьprotected static
. Но это запах кода, отсюда и « запуск ». Модификаторы доступа и наследование - это две разные темы. Да, вы не сможете получить доступ к статическому члену суперкласса, если бы он былpackage-private
. Но вы не должныstatic
в первую очередь полагаться на наследование для ссылки на поля; это признак плохого дизайна. Вы заметите, что попытки переопределенияstatic
методов не дают результатов, что является явным признаком того, что наследование не основано на классах. Если вам нужен доступ за пределами класса или пакета, он должен бытьpublic
private static
Сначала у меня есть класс с некоторыми служебными функциями, но я думаю, что кто-то может захотеть улучшить или настроить мой класс, и эти служебные функции также могут обеспечить им удобство.public
может не подходить, поскольку методы util не предназначены для пользователей экземпляров моего класса. Не могли бы вы помочь мне придумать хороший дизайн вместоprotected
? СпасибоЯ не вижу особых причин, по которым это следует осуждать. Всегда могут быть альтернативы для достижения того же поведения, и от реальной архитектуры будет зависеть, являются ли эти альтернативы «лучше», чем защищенный статический метод, или нет. Но одним из примеров, где был бы разумным защищенный статический метод, мог бы быть, по крайней мере, следующий:
(Отредактировано, чтобы разделить на отдельные пакеты, чтобы было
protected
понятнее)Получено из этого:
Другой производный класс:
protected static
Модификатор , безусловно , может быть оправдано здесь:static
, потому что они не зависят от переменных экземпляра. Они не предназначены для прямого использования в качестве полиморфных методов, а скорее являются «служебными» методами, которые предлагают реализации по умолчанию. которые являются частью более сложных вычислений и служат «строительными блоками» фактической реализации.public
, потому что это деталь реализации. И они не могут быть,private
потому что они должны вызываться расширяющимися классами. Они также не могут иметь видимость по умолчанию, потому что тогда они не будут доступны для расширяющихся классов в других пакетах.(РЕДАКТИРОВАТЬ: можно было предположить, что исходный комментарий относился только к полям , а не к методам - тогда, однако, он был слишком общим)
источник
protected final
(поскольку вы не хотите, чтобы они переопределялись), notstatic
. Тот факт, что метод не использует переменные экземпляра, не означает, что это должно бытьstatic
(хотя может ).final
, он не только проясняет, что метод не предназначен для переопределения, но и дополнительно дает понять читателю, что метод не использует переменные экземпляра. Итак, кратко: просто нет причин не делать его статичным.protected
, но не для демонстрации наследования, а для того, чтобы хранить это в одном пакете, не раскрывая его. Я думаю, что запечатанные интерфейсы станут полезными в этом случае, когда они появятся в javaprotected
означает «Наследование классов (даже в разных пакетах)» ...Статические члены не наследуются, а защищенные члены видны только подклассам (и, конечно, содержащему их классу), поэтому a
protected static
имеет такую же видимость, чтоstatic
и указывает на недоразумение со стороны кодировщика.источник
protected
не то же самое. Если вы просто скажетеstatic
, поле видно только подклассам в том же пакете.protected static
разрешает доступ внутри пакета или из подкласса . Создание статической переменной удаляет намерения наследования подклассов, оставляя единственное намерение - доступ изнутри пакета.Собственно в этом нет ничего принципиального
protected static
. Если вам действительно нужна статическая переменная или метод, видимый для пакета и всех подклассов объявленного класса, тогда сделайте этоprotected static
.Некоторые люди обычно избегают использования
protected
по разным причинам, а некоторые думают, чтоstatic
следует избегать любых не конечных переменных (я лично в некоторой степени симпатизирую последним), поэтому я предполагаю, что комбинацияprotected
иstatic
должна выглядеть плохо для тех, которые принадлежат к обеим группам.источник
Protected используется так, чтобы его можно было использовать в подклассах. Нет никакой логики в определении защищенного статического элемента при использовании в контексте конкретных классов, поскольку вы можете получить доступ к той же переменной статическим способом. Однако компилятор выдаст предупреждение для доступа к статической переменной суперкласса статическим способом.
источник
Ну, как ответило большинство людей:
protected
означает - ' package-private + видимость для подклассов - свойство / поведение НАСЛЕДУЕТ 'static
означает - « противоположность экземпляру - это свойство / поведение КЛАССА, т.е. НЕ НАСЛЕДОВАНО »Поэтому они немного противоречивы и несовместимы.
Однако недавно я подошел к варианту использования, когда имело бы смысл использовать эти два вместе. Представьте, что вы хотите создать
abstract
класс, который является родительским для неизменяемых типов и имеет набор свойств, общих для подтипов. Чтобы правильно реализовать неизменяемость и сохранить удобочитаемость, можно решить использовать шаблон Builder .А почему
protected static
? Поскольку мне нужен неабстрактный подтип,AbstactType
который реализует свой собственный неабстрактный Builder и расположен снаружи,package X
чтобы иметь возможность доступа и повторного использованияBaseBuilder
.Конечно, мы можем
BaseBuilder
обнародовать, но тогда мы приходим к другим противоречивым заявлениям:Таким образом, в обоих случаях с конструктором
protected static
иpublic
конструкторомabstract class
мы сочетаем противоречивые утверждения. Это вопрос личных предпочтений.Тем не менее, я по-прежнему предпочитаю
public
конструктор,abstract class
потому что онprotected static
кажется мне более неестественным в мире OOD и OOP!источник
Нет ничего плохого в том, чтобы иметь
protected static
. Многие упускают из виду одну вещь: вы можете захотеть написать тестовые примеры для статических методов, которые вы не хотите раскрывать в обычных обстоятельствах. Я заметил, что это особенно полезно для написания тестов для статических методов в служебных классах.источник