Являются ли экземпляры класса неизменными? - PullRequest
0 голосов
/ 29 августа 2018

Мне было интересно, являются ли Class экземплярами неизменными. Объявленные имена методов не предполагают, что состояние экземпляра изменяется при их вызове, но я не нашел явной гарантии для javadoc.

Сценарий: мне нужно хранить уникальные имена классов в Set. В идеале, я хотел бы заполнить набор Class экземплярами, чтобы избежать ненужных вызовов на Class.forName(), когда мне нужно получить доступ к классу через отражение. Однако предпочтительно использовать неизменяемые объекты в качестве ключей наборов. Поэтому мне было интересно, смогу ли я использовать Class экземпляры сразу.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Поскольку я не совсем согласен с другим ответом, я решил написать этот,
Классы не являются неизменяемыми, но они уникальны - для одного класса может существовать только один экземпляр объекта Class.

НО класс не определен по его имени, поскольку классы могут быть из разных загрузчиков классов, и разные загрузчики классов могут иметь классы с одинаковыми именами - но это будут разные классы, вы получите ClassCastException, если вы передадите несколько Объект между кодом обрабатывается двумя различными загрузчиками классов, если этот тип объекта будет существовать в обоих из них (как отдельный, не наследуемый).

Экземпляры класса все еще можно безопасно использовать в Set, так как они используют реализацию по умолчанию hashset / equals, так что только одинаковые экземпляры Class будут считаться равными.

Но чтобы решить, следует ли вам использовать String или Class, вам нужно знать, как именно должно работать ваше приложение, как я уже говорил, между разными загрузчиками классов может существовать несколько классов с одинаковым именем.

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

0 голосов
/ 29 августа 2018

Во-первых, общая часть Class<?> здесь на самом деле не имеет значения. Конечно, нет необработанных типов, поэтому Class<?> лучше, чем Class, но для вашего вопроса подстановочный знак не имеет значения.

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

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

Что не может произойти, если такие объекты класса еще где-то используются на карте.

С другой стороны: Class.forName() не должен быть слишком дорогим для уже загруженных классов. И когда в игру вступают такие вещи, как сериализация, люди, например, предлагают использовать String вместо объектов Class (см. здесь ).

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

Заключительное примечание: по мере того, как выкладываются интересные комментарии, существуют определенные способы изменения объектов класса в определенной степени. Но все эти действия определенно "вне нормы". Поэтому: теоретически вы можете предпочесть Strings объектам Class, но практически, в «обычных» приложениях, использование Class тоже должно работать нормально.

...