Чтобы получить доступ к закрытым полям, вам нужно получить их из объявленных полей класса, а затем сделать их доступными:
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
РЕДАКТИРОВАТЬ : как было прокомментировано aperkins , доступ к полю, установка его как доступного и получение значения могут вызвать Exception
s, хотя единственные отмеченные исключения, о которых вам следует помнить, прокомментированы выше.
NoSuchFieldException
Будет выброшено , если вы попросили поле имени , которое не соответствует заявленной области.
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
IllegalAccessException
Будет выброшено , если поле не было доступно (например, если он является частным и не доступен через пропускает в f.setAccessible(true)
линию.
В RuntimeException
s , которые могут быть выброшены либо является SecurityException
s (если JVM - й SecurityManager
не позволит вам изменить доступность полевой в), или IllegalArgumentException
s, если вы попробуете и доступ к полю на объекте не типа класса месторождения в:
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
getDeclaredField()
не находит поля, если они определены в родительских классах - вы также должны пройти по иерархии родительского класса, вызываяgetDeclaredField()
каждое из них, пока не найдете совпадение (после которого вы можете вызватьsetAccessible(true)
) или пока не достигнетеObject
.private
. Это исключает случайный доступ.Попробуйте
FieldUtils
из apache commons-lang3:источник
Отражение - не единственный способ решить вашу проблему (то есть получить доступ к закрытой функциональности / поведению класса / компонента)
Альтернативное решение состоит в том, чтобы извлечь класс из .jar, декомпилировать его с помощью, скажем, Jode или Jad , изменить поле (или добавить метод доступа) и перекомпилировать его с исходным .jar. Затем поместите новый .class впереди
.jar
в classpath или заново вставьте его в.jar
. (утилита jar позволяет вам извлечь и снова вставить в существующий .jar)Как отмечено ниже, это решает более широкую проблему доступа / изменения частного состояния, а не просто доступа / изменения поля.
Это требует, чтобы
.jar
не быть подписанным, конечно.источник
Еще один вариант, который еще не был упомянут: используйте Groovy . Groovy позволяет вам получить доступ к частным переменным экземпляра как побочный эффект дизайна языка. Есть ли у вас добытчик для поля, вы можете просто использовать
источник
Используя Reflection в Java, вы можете получить доступ ко всем
private/public
полям и методам одного класса к другому. Но согласно документации Oracle в недостатках раздела, они рекомендовали следующее:«Поскольку отражение позволяет коду выполнять операции, которые были бы недопустимыми в неотражающем коде, такие как доступ к закрытым полям и методам, использование отражения может привести к неожиданным побочным эффектам, которые могут сделать код неработоспособным и разрушить переносимость. Рефлексивный код нарушает абстракции и, следовательно, может изменить поведение при обновлении платформы "
Вот следующие фрагменты кода, чтобы продемонстрировать основные понятия отражения
Reflection1.java
Reflection2.java
Надеюсь, это поможет.
источник
Как упоминает oxbow_lakes, вы можете использовать отражение, чтобы обойти ограничения доступа (при условии, что ваш SecurityManager позволит вам).
Тем не менее, если этот класс настолько плохо спроектирован, что заставляет вас прибегать к таким хакерским атакам, возможно, вам следует искать альтернативу. Конечно, этот маленький хакер может сэкономить вам несколько часов, но сколько это будет стоить вам в будущем?
источник
Используйте платформу Soot Java Optimization для непосредственного изменения байт-кода. http://www.sable.mcgill.ca/soot/
Сажа полностью написана на Java и работает с новыми версиями Java.
источник
Вам нужно сделать следующее:
источник
При использовании Spring ReflectionTestUtils предоставляет несколько удобных инструментов, которые помогут здесь с минимальными усилиями. Он описывается как «для использования в сценариях модульного и интеграционного тестирования» . Существует также аналогичный класс с именем ReflectionUtils, но он описан как «Предназначен только для внутреннего использования» - см. Этот ответ для интерпретации того, что это значит.
Чтобы обратиться к опубликованному примеру:
источник
ReflectionTestUtils
как в моем опыте, мне только когда-либо нужно было делать подобные вещи в тестовой ситуации.)Просто еще одно замечание об отражении: я заметил, что в некоторых особых случаях, когда несколько классов с одинаковыми именами существуют в разных пакетах, это отражение, используемое в верхнем ответе, может не выбрать правильный класс из объекта. Так что если вы знаете, что такое package.class объекта, то лучше получить доступ к значениям его частного поля следующим образом:
(Это пример класса, который не работал для меня)
источник
Вы можете использовать @JailBreak от Manifold для прямого, типобезопасного отражения Java:
@JailBreak
разблокируетfoo
локальную переменную в компиляторе для прямого доступа ко всем членам вFoo
иерархии.Точно так же вы можете использовать метод расширения jailbreak () для одноразового использования:
Через
jailbreak()
метод вы можете получить доступ к любому члену вFoo
иерархии «S.В обоих случаях компилятор разрешает доступ к полю для вас безопасно, как если бы это было открытое поле, тогда как Manifold генерирует эффективный код отражения для вас изнутри.
Узнайте больше о коллектор .
источник
Это довольно легко с инструментом XrayInterface . Просто определите отсутствующие методы получения / установки, например
и xray ваш плохо разработанный проект:
Внутренне это зависит от размышлений.
источник
Попробуйте обойти проблему для случая, класс которого вы хотите установить / получить данные, является одним из ваших собственных классов.
Просто создайте
public setter(Field f, Object value)
иpublic Object getter(Field f)
для этого. Вы можете даже сделать некоторую проверку безопасности внутри этих функций-членов. Например, для сеттера:Конечно, теперь вам нужно выяснить значение
java.lang.reflect.Field
forsString
до установки значения поля.Я использую эту технику в универсальном сопоставителе ResultSet-to-and-from-model-mapper.
источник