内部类的私有字段,它使用反射扩展另一个包中的另一个内部类(包java.lang.reflect)?

时间:2012-06-11 07:42:12

标签: java reflection packages inner-classes

如何通过使用反射(包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日以来,我的第一个问题一直没有受到任何关注。

2 个答案:

答案 0 :(得分:0)

getDeclaredField为您提供Class对象引用的确切类别中的字段as stated in the docs。如果字段在子类中不是声明,那么你就不会这样了。

您可能希望改为使用getField

  

要反映的字段由以下算法确定。设C为该对象表示的类:

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

答案 1 :(得分: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);
    }
}

但请考虑另一种解决问题的方法。它的风格非常糟糕,只有在绝对必要时才能使用。