我正在做大学项目 我需要从课堂上获得所有领域。甚至私人和继承。我试图获取所有声明的字段,然后转换为超类并重复。 我的代码片段:
private void listAllFields(Object obj) {
List<Field> fieldList = new ArrayList<Field>();
while (obj != null) {
fieldList.addAll(Arrays.asList(obj.getClass().getDeclaredFields()));
obj = obj.getClass().getSuperclass().cast(obj);
}
// rest of code
但它不起作用。在施法后tmpObj
仍然是同一个类(不是超类)
我将不胜感激任何帮助如何解决铸造问题,或如何以不同的方式检索这些字段。
问题不是获取对字段的访问权限,而是获取字段的名称!
我这样管理:
private void listAllFields(Object obj) {
List<Field> fieldList = new ArrayList<Field>();
Class tmpClass = obj.getClass();
while (tmpClass != null) {
fieldList.addAll(Arrays.asList(tmpClass .getDeclaredFields()));
tmpClass = tmpClass .getSuperclass();
}
// rest of code
答案 0 :(得分:76)
obj = obj.getClass().getSuperclass().cast(obj);
此行不符合您的预期。转换Object
实际上并没有改变它,它只是告诉编译器将其视为其他东西。
E.g。您可以将List
投射到Collection
,但它仍然是List
。
但是,通过超类循环访问字段可以正常工作而不需要转换:
Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
// do something with current's fields
current = current.getSuperclass();
}
顺便说一句,如果您可以访问Spring Framework,那么有一种方便的方法可以循环遍历类和所有超类的字段:
ReflectionUtils.doWithFields(baseClass, FieldCallback)
(另见我之前的答案:Access to private inherited fields via reflection in Java)
答案 1 :(得分:31)
getDeclaredFields()
为您提供该课程的所有字段,包括private
个字段。
getFields()
为您提供该类及其超类的所有public
个字段。
如果您需要超级课程的private
/ protected
种方法,则必须重复拨打getSuperclass()
,然后拨打getDeclaredFields()
超类对象。
答案 2 :(得分:8)
这是我用来获取对象的所有字段的方法
private <T> List<Field> getFields(T t) {
List<Field> fields = new ArrayList<>();
Class clazz = t.getClass();
while (clazz != Object.class) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
return fields;
}
答案 3 :(得分:3)
试试这些
How do I read a private field in Java?
Is it possible in Java to access private fields via reflection
Field.setAccessible(true)是您必须做的才能通过反射
进行访问import java.lang.reflect.Field;
class B
{
private int i = 5;
}
public class A extends B
{
public static void main(String[] args) throws Exception
{
A a = new A();
Field[] fs = a.getClass().getSuperclass().getDeclaredFields();
for (Field field : fs)
{
field.setAccessible(true);
System.out.println( field.get( a ) );
}
}
}
答案 4 :(得分:1)
要获取超类字段,请使用getSuperclass()
。从那里你可以获得超类的领域。
答案 5 :(得分:1)
是的,可以使用Reflection。
在您的代码集Field.setAccessible(true);
继续学习这个概念,但不要这样做: - )
答案 6 :(得分:1)
ClassName obj = new ClassName();
Field field = ClassName.class.getDeclaredField ("name of the field");
field.setAccessible (true);
DataType value = (DataType) field.get (obj);
在提取值之前,必须使用setAccessible为true。有时JVM不允许提取私有变量,它可能会给出Security Exception。
答案 7 :(得分:1)
答案 8 :(得分:1)
此解决方案使用Java 8流,对于那些在Java中学习函数式编程的人非常有用。它按照其他答案迭代getSuperclass和getDeclaredFields,但它以功能方式完成。
以下行将打印在SomeClass或其任何超类上找到的每个字段名称的名称。
allFieldsFor(SomeClass.class).map(Field::getName).forEach(System.out::println);
以下是逐步执行超类以创建字段流的代码。
private Stream<Field> allFieldsFor( Class c ) {
return walkInheritanceTreeFor(c).flatMap( k -> Arrays.stream(k.getDeclaredFields()) );
}
private Stream<Class> walkInheritanceTreeFor( Class c ) {
return iterate( c, k -> Optional.ofNullable(k.getSuperclass()) );
}
以下方法是从Streams.iterate建模的,但Streams.iterate旨在创建无限流。当从fetchNextFunction返回Optional.none()时,此版本已被修改为结束。
private <T> Stream<T> iterate( T seed, Function<T,Optional<T>> fetchNextFunction ) {
Objects.requireNonNull(fetchNextFunction);
Iterator<T> iterator = new Iterator<T>() {
private Optional<T> t = Optional.ofNullable(seed);
public boolean hasNext() {
return t.isPresent();
}
public T next() {
T v = t.get();
t = fetchNextFunction.apply(v);
return v;
}
};
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize( iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE),
false
);
}
答案 9 :(得分:0)
这里是解决方案
//我的对象
Student student =new Student();
Field[] field2=student.getClass().getSuperclass().getDeclaredFields();
Field[] field1=student.getClass().getDeclaredFields();
Field [] all_Fields=new Field[field1.length+field2.length];
//Joining field 1 and two
System.arraycopy(field2, 0, all_Fields, 0, field2.length);
System.arraycopy(field1, 0, all_Fields, field2.length, field1.length);
//Printing all fields
for(Field i:all_Fields)
{
System.out.println(i);
}
///如果要从多个SuperClass中获取字段,则可以使用以下代码进行迭代:
Class clazz = Student.class;
while (clazz != null) {
clazz= clazz.getSuperclass();
}