Java 如何从子级调用父级私有方法?

Java 如何从子级调用父级私有方法?,java,reflection,Java,Reflection,您能告诉我是否可以通过java中的反射来实现sush吗?您可以使用反射来实现,但除非有很好的理由,否则您应该首先重新考虑您的设计 下面的代码打印123,即使从A外部调用也是如此 public class A{ private int getC(){ return 0; } } public class B extends A{ public static void main(String args[]){ B = new B();

您能告诉我是否可以通过java中的反射来实现sush吗?

您可以使用反射来实现,但除非有很好的理由,否则您应该首先重新考虑您的设计

下面的代码打印123,即使从A外部调用也是如此

public class A{
    private int getC(){
        return 0;
    }
}

public class B extends A{
    public static void main(String args[]){
        B = new B();
        //here I need to invoke getC()
    }
}

您可以使用反射进行如下尝试:

public static void main(String[] args) throws Exception {
    Method m = A.class.getDeclaredMethod("getC");
    m.setAccessible(true); //bypasses the private modifier
    int i = (Integer) m.invoke(new A());
    System.out.println("i = " + i); //prints 123
}

public static class A {

    private int getC() {
        return 123;
    }
}

您应该声明getc受保护。这正是它的目的

至于反思:是的,这是可能的。不过,您必须在方法对象上调用setAccessible。这是糟糕的风格…;-)

A类{
私人文件a(){
System.out.println(“被叫方的私有”);
}
}
B类扩展了A类{
公屋空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置空置{
试一试{
System.out.println(Arrays.toString(getClass().getSuperclass().getMethods());
方法m=getClass().getSuperclass().getDeclaredMethod(“a”,新类[]{});
m、 setAccessible(true);
m、 调用(此,(对象[])null);
}捕获(例外e){
e、 printStackTrace();
}
}
}
编辑: 这是一个安静的老帖子,但增加了一些宝贵的建议

重新考虑你的设计
调用父级的私有方法,虽然可以通过反射实现,但不应该这样做。在父类上调用私有方法可能会使类处于无效状态,并可能导致意外行为。

getDeclaredMethod将只返回当前类中的私有方法,而不是继承的方法。要实现它,您需要通过getSuperclass方法导航继承图。下面是一段代码片段

class A{
    
    private void a(){
        System.out.println("private of A called");
    }
}

class B extends A{
    
    public void callAa(){
        try {
            System.out.println(Arrays.toString(getClass().getSuperclass().getMethods()));
            Method m = getClass().getSuperclass().getDeclaredMethod("a", new Class<?>[]{});
            m.setAccessible(true);
            m.invoke(this, (Object[])null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
private方法getPrivateMethod(Object currentObject)抛出NoSuchMethodException、IllegalAccessException、IllegalArgumentException、InvocationTargetException{
类currentClass=currentObject.getClass();
方法=null;
while(currentClass!=null&&method==null){
试一试{
方法=currentClass.getDeclaredMethod(“getC”);
}捕获(NoSuchMethodException nsme){
//方法不存在-请尝试超级类
currentClass=currentClass.getSuperclass();
}
}
if(方法!=null){
方法setAccessible(true);
返回法;
}否则{
抛出新的NoSuchMethodException();
}

}

请不要将父/子类比用于继承。
B
对象是
A
对象。你是你父亲吗?@aioobe
B
是继承层次结构中
a
的一个孩子。这是合法的。我仍然认为这是一个糟糕的类比,尤其是当用作“从子对象调用父对象私有方法”时。我肯定会使用“子类中的超类中的方法”。@aioobe同意这在技术上是不正确的,但我们是否可以同意,父/子类与类继承的类比是如此完善,以至于它实际上已成为超类/子类的同义词。关于面向对象编程的文献中充斥着它。我不能说我同意你的看法。我只看到那些对继承概念不熟悉的人写的,或者那些根本没有考虑过父母/孩子没有“是一种”关系这一事实的人写的。通过使用不同的(更准确的)术语,您总是可以轻松地绕过它,我认为它并不成熟。
getCMethod.invoke(null)将抛出NPE。谢谢,更正。这是针对静态方法的,我不能将getC()更改为protected,因为它位于JDK:)然后请注意,您的代码可能无法在开发中使用的JDK版本之外的其他JDK版本上工作。即使在您使用的应用程序上,如果您的应用程序使用安全管理器(如小程序)运行,也可能会失败。你肯定应该寻找另一种方法。在这里阅读:注意
m.invoke(newb())也可以工作。问题是我无法创建A的实例。A和B具有公共状态。@user1545453正如我上面所评论的,您可以使用B的实例,它也可以工作。为什么他不能调用
this.getC()
class A{
    
    private void a(){
        System.out.println("private of A called");
    }
}

class B extends A{
    
    public void callAa(){
        try {
            System.out.println(Arrays.toString(getClass().getSuperclass().getMethods()));
            Method m = getClass().getSuperclass().getDeclaredMethod("a", new Class<?>[]{});
            m.setAccessible(true);
            m.invoke(this, (Object[])null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  private Method getPrivateMethod(Object currentObject) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
  Class<?> currentClass = currentObject.getClass();
  Method method = null;
  while (currentClass != null && method == null) {
      try {
          method = currentClass.getDeclaredMethod("getC");
      } catch (NoSuchMethodException nsme) {
          // method not present - try super class
          currentClass = currentClass.getSuperclass();
      }
  }
  if (method != null) {
      method.setAccessible(true);
      return method;
  } else {
      throw new NoSuchMethodException();
  }