Java 使用反射获取private not primitive字段的值

Java 使用反射获取private not primitive字段的值,java,reflection,Java,Reflection,假设我们有两个不同的包。。。一个包无法访问,但我们想知道名为b的复杂字段的值 public class A { private String whatever; private B b; private static class B { final ArrayList<Z> c = new ArrayList<Z>(); private void addItem(Z z) {

假设我们有两个不同的包。。。一个包无法访问,但我们想知道名为b的复杂字段的值

public class A {
    private String  whatever;
    private B       b;

    private static class B {
         final ArrayList<Z> c   = new ArrayList<Z>();

         private void addItem(Z z) {
                this.c.add(z);
         }

         private Z getItem(int nr) {
                return this.c.get(nr);
          }
     }
}

public class Reflect extends A {
      public static void main(String[] args) throws NoSuchFieldException, SecurityException {
            Reflect ref = new Reflect();
            Class getA = ref.getClass().getSuperclass();
            Field getB = getDeclaredField("b");
            getB.setAccessible(true);
            Class bInst = getB.getClass();
            Method bMeth = bInst.getMethod("getItem", Integer.TYPE);
            Object zInst = bMeth.invoke(new Integer(123));
      }
}
公共A类{
私人字符串;
私人B,;
专用静态B类{
最终ArrayList c=新ArrayList();
专用无效附加项(Z){
本条c.增补(z);
}
私人Z getItem(内部编号){
返回此.c.get(nr);
}
}
}
公共类反射扩展了{
publicstaticvoidmain(字符串[]args)抛出NoSuchFieldException、SecurityException{
Reflect ref=新的Reflect();
类getA=ref.getClass().getSuperclass();
字段getB=getDeclaredField(“b”);
getB.setAccessible(true);
类bInst=getB.getClass();
方法bMeth=bInst.getMethod(“getItem”,Integer.TYPE);
对象zInst=bMeth.invoke(新整数(123));
}
}
如果我没有从包中获取复杂类型B,如何获取该值? 仍然获取java.lang.NoSuchMethodException:stackOver.A.getItem(int)即使我将字段gstB设置为可访问

如果我没有从包中获取复杂类型B,如何获取该值

您可以将其作为
对象
,然后使用反射进一步发现它公开的方法

Object bInst = ... // Get b through reflection
Class bClass = bInst.getClass();
Method[] bMeth = bClass.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));
如果我没有从包中获取复杂类型B,如何获取该值

您可以将其作为
对象
,然后使用反射进一步发现它公开的方法

Object bInst = ... // Get b through reflection
Class bClass = bInst.getClass();
Method[] bMeth = bClass.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));

您唯一缺少的是getField只提供公共可访问的字段

 Field getB = getA.getDeclaredField("b");
将为您提供该类的任何字段


一个较长的例子

class Main {
    public static class A {
        private String whatever;
        private B b = new B();

        private static class B {
            final ArrayList<String> c = new ArrayList<String>();

            private void addItem(String z) {
                this.c.add(z);
            }

            private String getItem(int nr) {
                return this.c.get(nr);
            }
        }
    }

    public static class Reflect extends A {
        public static void main(String... ignored) throws Exception {
            Reflect ref = new Reflect();
            Class getA = ref.getClass().getSuperclass();
            Field getB = getA.getDeclaredField("b");
            getB.setAccessible(true);
            Object b = getB.get(ref);

            Method addItem = b.getClass().getDeclaredMethod("addItem", String.class);
            addItem.setAccessible(true);
            addItem.invoke(b, "Hello");

            Method getItem = b.getClass().getDeclaredMethod("getItem", int.class);
            getItem.setAccessible(true);
            String hi = (String) getItem.invoke(b, 0);
            System.out.println(hi);
        }
    }
}

您唯一缺少的是getField只提供公共可访问的字段

 Field getB = getA.getDeclaredField("b");
将为您提供该类的任何字段


一个较长的例子

class Main {
    public static class A {
        private String whatever;
        private B b = new B();

        private static class B {
            final ArrayList<String> c = new ArrayList<String>();

            private void addItem(String z) {
                this.c.add(z);
            }

            private String getItem(int nr) {
                return this.c.get(nr);
            }
        }
    }

    public static class Reflect extends A {
        public static void main(String... ignored) throws Exception {
            Reflect ref = new Reflect();
            Class getA = ref.getClass().getSuperclass();
            Field getB = getA.getDeclaredField("b");
            getB.setAccessible(true);
            Object b = getB.get(ref);

            Method addItem = b.getClass().getDeclaredMethod("addItem", String.class);
            addItem.setAccessible(true);
            addItem.invoke(b, "Hello");

            Method getItem = b.getClass().getDeclaredMethod("getItem", int.class);
            getItem.setAccessible(true);
            String hi = (String) getItem.invoke(b, 0);
            System.out.println(hi);
        }
    }
}
使用下面的方法,比自己做要干净得多

PropertyUtils.getNestedProperty(ref, "b.propertyOfClassB");
用实际的属性名替换propertyOfClassB。

使用并使用以下方法,它比自己做要干净得多

PropertyUtils.getNestedProperty(ref, "b.propertyOfClassB");

将propertyOfClassB替换为实际的属性名。

这意味着我必须循环B以获得完整的对象。。。因此,如果我有大量复杂对象,我必须遍历所有对象…@Fendrix这是正确的:如果在编译时无法访问某个类型,则需要遍历对象,甚至可能递归对象层次结构。我想我可以以某种方式直接获取对象。。。无论如何谢谢…:)@Fendrix啊,我以为你已经找到了一个关于如何通过反射获取私有变量的链接。这是一个非常好的答案。这意味着我必须循环通过B来获得完整的对象。。。因此,如果我有大量复杂对象,我必须遍历所有对象…@Fendrix这是正确的:如果在编译时无法访问某个类型,则需要遍历对象,甚至可能递归对象层次结构。我想我可以以某种方式直接获取对象。。。无论如何谢谢…:)@Fendrix啊,我以为你已经找到了一个关于如何通过反射获取私有变量的链接。这是一个非常好的答案。这不起作用,因为B是私有的,因此它不可见。。。即使使用getB.setAccessible(true);我不知道如何访问B的方法…要访问B的实例方法,您需要一个B的实例。反射不会以任何方式改变这一事实。这不起作用,因为B是私有的,因此它不可见。。。即使使用getB.setAccessible(true);我不知道如何访问B的方法…要访问B的实例方法,您需要有一个B的实例。反射不会以任何方式改变这一事实。