Class.getDeclaredField: примеры (JAVA)
Class.getDeclaredField(String name): FieldОписание и сигнатура
Метод Class.getDeclaredField(String name) находится в пакете java.lang и возвращает объект java.lang.reflect.Field, соответствующий полю с указанным именем, объявленному в самом классе (не в суперклассах). Метод используется при необходимости получить доступ к метаданным поля или выполнять чтение/запись значения через рефлексию, включая приватные и пакетные поля.
Сигнатура
public Field getDeclaredField(String name) throws NoSuchFieldException, NullPointerException, SecurityException
Параметры
name- имя поля (тип:String). Значениеnullприводит кNullPointerException.
Возвращаемое значение
Объект Field, представляющий поле с заданным именем, объявленное в данном классе. Если поле не найдено, генерируется NoSuchFieldException.
Исключения и особенности безопасности
NoSuchFieldException- если поле с указанным именем отсутствует в самом классе.NullPointerException- если имя равноnull.SecurityException- при отказе проверки безопасности.- Возвращённый
Fieldпозволяет получить/установить значение, но при попытке доступа к приватному полю потребуется снять ограничения доступа черезsetAccessible(true)или использовать современные механизмыVarHandle/MethodHandles. В средах с модульной схемой (Java 9+) попытка снять доступ к полю может привести кInaccessibleObjectExceptionдля непубличных пакетов без открытий модулей.
Примеры основных сценариев
Даны простые примеры получения поля и чтения/записи его значений. В результатах показан ожидаемый вывод при выполнении.
Пример 1. Доступ к приватному полю
class Person {
private String name = "Alice";
}
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person();
java.lang.reflect.Field f = Person.class.getDeclaredField("name");
f.setAccessible(true);
System.out.println(f.get(p));
f.set(p, "Bob");
System.out.println(f.get(p));
}
}
Alice Bob
Пример 2. Поиск поля у суперкласса (поле не найдено)
class A { public int x = 1; }
class B extends A { }
public class Main {
public static void main(String[] args) {
try {
B.class.getDeclaredField("x");
} catch (Exception e) {
System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
}
}
}
NoSuchFieldException: x
Пример 3. Статическое поле и чтение через отражение
class Config { private static final int MAX = 5; }
public class Main {
public static void main(String[] args) throws Exception {
java.lang.reflect.Field f = Config.class.getDeclaredField("MAX");
f.setAccessible(true);
System.out.println(f.get(null));
}
}
5
Альтернативные подходы в Java
- Class.getField(String)
- Class.getDeclaredFields()
- java.lang.invoke.VarHandle
- MethodHandles и Lookup
Возвращает только публичное поле и включает поля суперклассов. Используется когда требуется доступ к публичным полям внешнего API без обхода видимости.
Возвращает массив всех полей, объявленных в классе. Удобно для перебора и кеширования метаданных.
Позволяет работать с памятью и полями с лучшей производительностью и поддержкой семантики памяти. В некоторых случаях предпочтительнее для высокопроизводительного кода и при необходимости атомарных операций.
Позволяют получить «ручку» на геттер/сеттер или на само поле через Lookup.unreflectGetter/unreflectSetter. Обычно быстрее и безопаснее, чем частое использование Field.setAccessible(true).
Аналоги в других языках
- PHP
ReflectionClass::getProperty возвращает ReflectionProperty; для приватных свойств можно вызвать setAccessible(true).
class C { private $v = 1; }
$r = new ReflectionClass('C');
$p = $r->getProperty('v');
$p->setAccessible(true);
$ins = new C();
echo $p->getValue($ins);
1
Нет точного аналога рефлексии полей класса как в Java. Для обычных свойств используются точечный доступ или Object.getOwnPropertyDescriptor. Приватные поля с синтаксисом #name недоступны извне.
const obj = {a: 1};
console.log(obj.a);
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
1
{ value: 1, writable: true, enumerable: true, configurable: true }
Используется getattr, доступ к __dict__ или модуль inspect. Приватные (name-mangled) атрибуты доступны по имени с манглингом.
class C:
def __init__(self):
self._x = 10
c = C()
print(getattr(c, '_x'))
10
Type.GetField(name, BindingFlags) с флагами BindingFlags.NonPublic и BindingFlags.Instance/Static - прямой аналог для получения приватного поля.
using System;
using System.Reflection;
class C { private int x = 2; }
class P { static void Main(){
var f = typeof(C).GetField("x", BindingFlags.NonPublic | BindingFlags.Instance);
var o = new C();
Console.WriteLine(f.GetValue(o));
}}
2
reflect.Type.FieldByName возвращает поле по имени, но экспортируемые (с заглавной буквы) доступны, неэкспортируемые недоступны для установки извне без небезопасных трюков.
package main
import ("fmt"; "reflect")
type T struct { a int }
func main(){
t := T{a:3}
if f, ok := reflect.TypeOf(t).FieldByName("a"); ok { fmt.Println(f.Name) }
}
a
Можно использовать рефлексию Kotlin (memberProperties) или перейти на Java-рефлексию через javaClass / ::class.java.getDeclaredField.
Типичные ошибки и их признаки
- NoSuchFieldException
Вызывается когда поле не объявлено в самом классе. Частая причина - попытка получить у подкласса поле, объявленное в суперклассе. Пример и вывод:
class A { public int x; }
class B extends A { }
public class Main { public static void main(String[] args) throws Exception {
try { B.class.getDeclaredField("x"); } catch (Exception e) { System.out.println(e); }
}}
java.lang.NoSuchFieldException: x
Происходит при передаче null в качестве имени поля.
Class<?> c = String.class;
c.getDeclaredField(null);
Exception in thread "main" java.lang.NullPointerException at java.lang.Class.getDeclaredField(Class.java:...) ...
Может возникнуть в средах с ограниченной безопасностью (SecurityManager) при попытке доступа к полю.
Возникает при попытке снять ограничения доступа через setAccessible(true) для типов в непубличных пакетах модуля без соответствующего открытия модулей. Частое решение - запуск с --add-opens или использование MethodHandles/Lookup с правами доступа.
IllegalAccessException - при попытке доступа без снятия ограничений; IllegalArgumentException - при передаче несовместимого значения в Field.set.
Изменения и влияние модульной системы
- С выходом Java 9 ввод модуляции привёл к ограничениям на рефлексивный доступ к непубличным элементам: попытки снять доступ через
setAccessible(true)могут привести кInaccessibleObjectExceptionесли модуль не открыт. - Ввёлcя API
VarHandleи расширены возможностиMethodHandles, которые во многих случаях заменяют частое использованиеField.setAccessibleи дают лучшие характеристики и безопасные способы доступа. - В новых релизах акцент смещён в сторону контролируемого рефлексивного доступа и явного открытия модулей с помощью флагов запуска или объявлений в
module-info.java.
Расширенные и редкие сценарии использования
1. Изменение final static поля (константы) - обход ограничений, не рекомендован для продакшена
class C { private static final String S = "orig"; }
public class Main {
public static void main(String[] args) throws Exception {
java.lang.reflect.Field f = C.class.getDeclaredField("S");
f.setAccessible(true);
java.lang.reflect.Field modifiers = java.lang.reflect.Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.set(null, "modified");
// чтение через рефлексию
System.out.println(f.get(null));
}
}
modified
Комментарий: в современных JVM такие изменения могут не повлиять на места, где компилятор/время компиляции встроило константу.
2. Доступ к полю суперкласса из подкласса через getSuperclass
class A { private int secret = 7; }
class B extends A { }
public class Main {
public static void main(String[] args) throws Exception {
java.lang.reflect.Field f = B.class.getSuperclass().getDeclaredField("secret");
f.setAccessible(true);
A a = new A();
System.out.println(f.getInt(a));
}
}
7
3. Кеширование Field для повышения производительности
// В реальном приложении лучше хранить Field в ConcurrentHashMap>
java.util.Map cache = new java.util.HashMap<>();
java.lang.reflect.Field f = cache.computeIfAbsent("MyClass#x", k -> {
try { return MyClass.class.getDeclaredField("x"); } catch (Exception e) { throw new RuntimeException(e); }
});
// далее использовать f.get/set
(нет вывода, демонстрация приёма)
4. Использование MethodHandles для более быстрого доступа
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandle;
class C { private int v = 2; }
public class Main {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
java.lang.reflect.Field f = C.class.getDeclaredField("v");
f.setAccessible(true);
MethodHandle getter = lookup.unreflectGetter(f);
C c = new C();
System.out.println(getter.invoke(c));
}
}
2
5. Чтение аннотаций поля и Generic-типа
class A { @Deprecated public java.util.List list; }
public class Main {
public static void main(String[] args) throws Exception {
java.lang.reflect.Field f = A.class.getDeclaredField("list");
System.out.println(java.util.Arrays.toString(f.getAnnotations()));
System.out.println(f.getGenericType());
}
}
[@java.lang.Deprecated()] java.util.List
6. Доступ к синтетическим и компиляторным полям (lambda, inner class)
// Внутренние классы могут иметь синтетические поля, например ссылка на внешний объект.
// getDeclaredFields() и getDeclaredField("this$0") иногда позволяют их обнаружить.
(в зависимости от компиляции могут появляться синтетические поля)
В продвинутых сценариях стоит учитывать модули, кеширование и предпочтение MethodHandles/VarHandle для высокопроизводительных операций.
джава Class.getDeclaredField function comments
- джава Class.getDeclaredField - аргументы и возвращаемое значение
- Функция java Class.getDeclaredField - описание
- Class.getDeclaredField - примеры
- Class.getDeclaredField - похожие методы на java
- Class.getDeclaredField на javascript, c#, python, php
- Class.getDeclaredField изменения java
- Примеры Class.getDeclaredField на джава