-2

如何访问另一个包中的内部类的私有字段,该包通过使用反射(包 java.lang.reflect)扩展另一个包中的另一个内部类?

package MainPackage;
import java.lang.reflect.Field;

class PrimaryClass
{
    public static void main(String[] args)
    {
        AuxiliaryPackage.TerciaryClass.BugattiVeyron bugattiVeyron = 
            (new AuxiliaryPackage.TerciaryClass()).new BugattiVeyron(
                new MainPackage.SecondaryClass());        

        System.out.println("Name: "+ bugattiVeyron.name);
        System.out.println("Tires type: " + bugattiVeyron.tiresType);
        try
        {
            Class bugattiVeyronClass = bugattiVeyron.getClass();
            Field invisibleField1 = bugattiVeyronClass.getDeclaredField("topSpeed");
            invisibleField1.setAccessible(true);
            System.out.println(invisibleField1.get(bugattiVeyron));
            Field invisibleField2 = bugattiVeyronClass.getDeclaredField("tamperedOdometer");
            invisibleField2.setAccessible(true);
            System.out.println(invisibleField2.get(bugattiVeyron));
        }
        catch (Exception e)
        {
            /* I ALWAYS GET AN EXCEPTION !! */
            /* I need a change to be done IN the TRY block. */
            /* WHEN THE BugattiVeyron class DOES NOT EXTEND another inner class, NO EXCEPTION. */
            /* See at the end for a detail of the just mentioned case. */
            System.out.println("An exception has occurred.");
            System.err.println(e.getMessage());
            e.printStackTrace();
        }
    }
}



package MainPackage;
public class SecondaryClass
{
    public class SportsCar
    {
        /* Public fields. Accesible from any package. */
        public String name = new String();

        /* Protected fields. Accesible from the same package and subclasses in any package */
        protected String tiresType = new String();

        /* Package fields. No explicit modifier. Accessible from the same package only. */
        int topSpeed; //km per hour

        /* Private fields. Accessible from the same class only. */
        private boolean tamperedOdometer;

        /* Default constructor */
        public SportsCar()
        {
            name = "Sports car";
            tiresType = "Race";
            topSpeed = 250;
            tamperedOdometer = false;
        }

        public SportsCar(String name, String tiresType, int topSpeed, boolean tamperedOdometer)
        {
            this.name = name;
            this.tiresType = tiresType;
            this.topSpeed = topSpeed;
            this.tamperedOdometer = tamperedOdometer;
        }     
    }
}



package AuxiliaryPackage;
public class TerciaryClass
{
    public class BugattiVeyron extends MainPackage.SecondaryClass.SportsCar
    {
        /* Default constructor */
        public BugattiVeyron(MainPackage.SecondaryClass secondaryClass)
        {
            secondaryClass.super("Buggati Veyron", "Michelin Pilot Sport PS2 PAX", 431, false);
        }
    }
}

当 BugattiVeyron 类没有扩展任何东西时(在代码中进行了一些更改之后),我像这样实例化它:

AuxiliaryPackage.TerciaryClass.BugattiVeyron bugattiVeyron = (new
        AuxiliaryPackage.TerciaryClass()).new BugattiVeyron();

...并且没有例外...那么我应该在 try 块中进行哪些更改才能将事情做好?

提前致谢!!

编辑 1. 我不是故意大喊大叫的。我认为由于帖子的长度,介绍可能会丢失。我已经包含了 stackTrace。我道歉。这是我的第二个问题。

这是第一个例外(另一个类似):

java.lang.NoSuchFieldException: topSpeed
        at java.lang.Class.getDeclaredField(Unknown Source)
        at MainPackage.PrimaryClass.main(PrimaryClass.java:17)

第 17 行是:Field invisibleField1 = bugattiVeyronClass.getDeclaredField("topSpeed");

编辑 2. 我知道它看起来不像“好的编程模式”。这是关于 java.lang.reflect 限制的研究。

编辑3:答案。我要感谢所有对我友善和耐心并试图提供答案的人。最后,我从vsb得到了解决方案。因此,自从我发布问题以来,大约花了一个小时才得到答案。一个记录!自 3 月 1 日以来,我的第一个问题根本没有受到任何关注。

4

2 回答 2

0

getDeclaredField如文档中所述,为您提供Class对象引用的确切类中的字段。如果该字段未在子类中声明,则不会这样。

您可能想改用getField

要反射的场由下面的算法确定。设 C 为该对象所代表的类:

  1. 如果 C 声明了一个具有指定名称的公共字段,那就是要反映的字段。
  2. 如果在上面的步骤 1 中没有找到任何字段,则该算法递归地应用于 C 的每个直接超接口。直接超接口按照它们被声明的顺序进行搜索。
  3. 如果在上面的步骤 1 和 2 中没有找到字段,并且 C 有一个超类 S,则在 S 上递归调用此算法。如果 C 没有超类,则抛出 NoSuchFieldException。
于 2012-06-11T08:04:03.130 回答
0

此代码有效。

        Class bugattiVeyronClass = bugattiVeyron.getClass();
        Class sportsCarClass = bugattiVeyronClass.getSuperclass();
        Field invisibleField1 = sportsCarClass.getDeclaredField("topSpeed");
        Field invisibleField2 = sportsCarClass.getDeclaredField("tamperedOdometer");

BugattiVeyron 类没有这些字段,它们来自超类,必须相应访问。

您可以使用以下方法在类层次结构中查找字段:

private static Field getDeclaredFieldInHierarchy(Class<?> clazz, String fieldName) {
    if (clazz == null) {
        return null;
    }
    try {
        return clazz.getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        return getDeclaredFieldInHierarchy(clazz.getSuperclass(), fieldName);
    }
}

但请考虑另一种方法来解决您的问题。这是非常糟糕的风格,只应在绝对必要时使用。

于 2012-06-11T08:18:38.567 回答