2

我处于以下情况:

public class SuperClass
{
        public static Object superClassStaticField;
}

public class ChildClass extends SuperClass
{
... some methods and fields
}

我有一个看起来像这样的方法:

...modifiers... void action(Class <? extends SuperClass> cls)
{
...
}

我想达到所有带有反射的元素,包括我(稍后在 ChildClass 中)初始化的超类静态字段,但看起来这里有些逻辑在反射中失败:

superClassStaticField 在超类中,所以如果我尝试使用:

cls.getClass().get[Declared]Field("superClassStaticField");

我会得到 java.lang.NoSuchFieldException

所以我必须达到超类的真相:

SuperClass.class.getDeclaredField("superClassStaticField").get(null);

会成功,但如果有多个 ChildClass 在同一个运行时工作,我的程序会发疯。我认为因为所有方法都达到了在 SuperClass 中声明的相同对象。

但是我怎样才能达到实际给定的类静态字段?

我试过:

SuperClass.class.getDeclaredField("superClassStaticField").get(cls);

但结果是一样的。

我怎样才能达到它?

编辑:我现在只想获取/设置静态字段,创建一个新实例是不安全的,(酸它有空的构造函数?并且什么都不会修改?)

4

3 回答 3

6

但是我怎样才能达到实际给定的类静态字段?

只有一个静态字段。每个子类不会有一个静态字段。听起来您需要采取不同的方法。由于我们不知道您要达到什么目标,因此我们无法为您提供太多关于该方法的建议。也许 aMap<Class, Object>是你所追求的?

于 2013-07-19T16:08:38.737 回答
1

首先,静态字段属于定义它们的实际类;它们不能通过来自子类的引用的反射来访问。也就是说,使用反射:

SuperClass.field // OK - the field is declared on SuperClass
SubClass.field // Not found - the field is not declared on SubClass

您可以通过向上爬(重复)尝试在您正在检查的类的超类上找到它来使用反射来找到该字段:

clz.getSuperclass().getField("superClassStaticField")

根据层次结构的深度,您可能必须通过多个超类。

最后,因为该字段属于超类,并且您的所有子类只有一个超类,所有子类将使用相同的超类字段。

于 2013-07-19T16:10:37.260 回答
0

我知道我的回答来得有点晚。我创建了一个可以完全做到这一点的视图方法:

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import lombok.NonNull;

public final class ReflectionExtensions
{
    public static Field[] getAllDeclaredFields(final @NonNull Class<?> cls,
        List<String> ignoreFieldNames)
    {
        Field[] declaredFields = getDeclaredFields(cls, ignoreFieldNames);
        Class<?> superClass = cls.getSuperclass();
        if (superClass != null && superClass.equals(Object.class))
        {
            return declaredFields;
        }
        List<Field> fields = new ArrayList<>(Arrays.asList(declaredFields));
        while (superClass != null
            && !(superClass.getSuperclass() != null && superClass.equals(Object.class)))
        {
            fields.addAll(Arrays.asList(getDeclaredFields(superClass, ignoreFieldNames)));
            superClass = superClass.getSuperclass();
        }
        return fields.toArray(newArrayInstance(Field.class, fields.size()));
    }
    
    public static Field[] getDeclaredFields(final @NonNull Class<?> cls,
        List<String> ignoreFieldNames) throws SecurityException
    {
        Field[] declaredFields = cls.getDeclaredFields();
        return Arrays.stream(declaredFields)
            .filter(field -> !ignoreFieldNames.contains(field.getName())).toArray(Field[]::new);
    }
    
    public static <T> T[] newArrayInstance(final @NonNull Class<T> cls, final int length)
    {
        return (T[])Array.newInstance(cls, length);
    }
    public static String[] getDefaultIgnoreFieldNames()
    {
        return new String[] { "serialVersionUID", "$jacocoData" };
    }
}

并对其进行单元测试:

import io.github.astrapi69.test.objects.Member;
import io.github.astrapi69.test.objects.Person;
import io.github.astrapi69.test.objects.PremiumMember;
import org.testng.annotations.Test;

import java.lang.reflect.Field;

import static org.testng.AssertJUnit.assertEquals;

public class ReflectionExtensionsTest
{

    @Test
    public void testGetAllDeclaredFields()
    {
        int expected;
        int actual;
        Field[] allDeclaredFields;

        allDeclaredFields = io.github.astrapi69.reflection.ReflectionExtensions.getAllDeclaredFields(
            Person.class,
            io.github.astrapi69.reflection.ReflectionExtensions.getDefaultIgnoreFieldNames());
        expected = 5;
        actual = allDeclaredFields.length;
        assertEquals(expected, actual);

        allDeclaredFields = io.github.astrapi69.reflection.ReflectionExtensions.getAllDeclaredFields(
            Member.class,
            io.github.astrapi69.reflection.ReflectionExtensions.getDefaultIgnoreFieldNames());
        expected = 7;
        actual = allDeclaredFields.length;
        assertEquals(expected, actual);

        allDeclaredFields = io.github.astrapi69.reflection.ReflectionExtensions.getAllDeclaredFields(
            PremiumMember.class,
            ReflectionExtensions.getDefaultIgnoreFieldNames());
        expected = 8;
        actual = allDeclaredFields.length;
        assertEquals(expected, actual);
    }
}
    

测试类来自测试对象存储库。

于 2022-01-03T14:58:30.910 回答