我可以覆盖Java中的私有方法吗?

我知道我可以使用reflection来调用私有方法,并获取或设置私有变量的值,但我想覆盖一个方法。

public class SuperClass { public void printInt() { System.out.println("I am " + getClass() + ". The int is " + getInt()); } private int getInt() { return 1; } } public class SubClass extends SuperClass { public static void main(String[] args) { (new SubClass()).printInt(); } public int getInt() { return 2; } } 

我希望SubClassmain方法打印出2 ,但它打印出1 。 我听说这可以通过反思完成,但我无法弄清楚如何。 如果没有反思,有没有人知道另一种方式呢? (除了使SuperClass.getInt()受到保护,或者将printInt()方法复制并粘贴到SubClass 。)如果实际上无法覆盖私有方法,是否有办法在其上放置某种类型的触发器来调用在私有方法执行之前或之后我的子类中的方法?

私有方法不会被inheritance,也不能以任何方式覆盖。 无论谁告诉你,你都可以用反思去做,或者说谎或者谈论其他事情。

但是,您可以访问调用printInt子类的私有方法getIntprintInt所示:

 public void printInt() throws Exception { Class clazz = getClass(); System.out.println("I am " + clazz + ". The int is " + clazz.getMethod("getInt").invoke(this) ); } 

这将具有从超类’ printInt调用子类’ getInt方法的printInt 。 当然,如果子类没有声明getInt ,现在这将失败,所以你必须添加一个检查,以便能够处理不试图“覆盖”私有方法的“普通”子类:

 public void printInt() throws Exception { Class clazz = getClass(); // Use superclass method by default Method theGetInt = SuperClass.class.getDeclaredMethod("getInt"); // Look for a subclass method Class classWithGetInt = clazz; OUTER: while( classWithGetInt != SuperClass.class ){ for( Method method : classWithGetInt.getDeclaredMethods() ) if( method.getName().equals("getInt") && method.getParameterTypes().length == 0 ){ theGetInt = method; break OUTER; } // Check superclass if not found classWithGetInt = classWithGetInt.getSuperclass(); } System.out.println("I am " + classWithGetInt + ". The int is " + theGetInt.invoke(this) ); } 

您仍然需要更改超类代码才能使其工作,并且由于您必须更改超类代码,因此您应该将getInt上的访问修饰符更改为protected而不是执行reflectionhack-arounds。

您不能覆盖私有方法,因为没有其他类(包括派生类)可以告诉它存在。 它是私人的。

私有方法隐含final

在相关的说明中,子类可以声明与超类中的private字段或方法具有相同名称的字段或方法,因为从子类的角度来看,这些成员不存在。 这些成员之间没有特殊的关系。

不,你不能。 您可以构建一个看起来应该能够执行此操作的程序,使用外部类中的代码可以访问嵌套类的私有成员。 但是,私有方法实际上仍然无法被覆盖。 例:

 public class Test { public static class Superclass { private void foo() { System.out.println("Superclass.foo"); } } public static class Subclass extends Superclass { private void foo() { System.out.println("Subclass.foo"); // Looks like it shouldn't work, but does... super.foo(); } } public static void main(String[] args) throws Exception { Superclass x = new Subclass(); // Only calls Superclass.foo... x.foo(); } } 

鉴于这将是唯一可以覆盖私有方法的情况,因此不支持它并不是很大的损失。

如果您想要更改超类私有成员的行为,基本上您的设计就会被破坏。

我无法通过reflection来做到这一点,但我已经找到了通过仪器来实现这一目标的方法。 我在Dhruba Bandopadhyay的博客上建议使用ASM。 如果您有兴趣,可以查看我的代码 (这里发布的内容太多了)。

如果你真的想用reflection来做这件事,你可以:

 public class SuperClass { private final Method getInt; public SuperClass() { /** Find the appropriate method to call and cache it. **/ Method getInt = null; try { getInt = getClass().getDeclaredMethod("getInt"); } catch (NoSuchMethodException e) { try { getInt = SuperClass.class.getDeclaredMethod("getInt"); } catch (NoSuchMethodException e1) { throw new RuntimeException(e1); } } getInt.setAccessible(true); this.getInt = getInt; } public void print() { int val = 0; try { val = (Integer) getInt.invoke(this); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } System.out.println(val); } private int getInt() { return 1; } } public class SubClass extends SuperClass { public int getInt() { return 2; } public static void main(String[] args) throws Exception { new SubClass().print(); } } 

我怀疑你想以不同的方式设计你的程序,而不是采用这种方法。 它不具备性能,它肯定会让任何超越SuperClass的人感到惊讶。

请注意,如果以这种方式使用reflection,则子类的getInt()方法可以是私有的。 再次,至少提到的两个原因,采取这种方法几乎肯定是一个坏主意。 您可以通过另一种方式实现目标。 套餐保护真的不是一种选择吗?

你可以通过引用传递var – >使用java的类吗?

因为如果有可能:以上问题可以改写为:

(注意这仅用于说明目的)

VB:

function(ByRef intX as Integer)//可以显式更改值,但不能显示方法本身:P end function

更多像我猜…

不,我们不能覆盖私有方法,但有一种情况我们也可以覆盖私有方法,即内部类

 class PrivateTest { private String msg = "OuterAndInner"; private void fun() { System.out.println("Outer fun()"); } class Inner extends PrivateTest { private void fun() { System.out.println("Accessing Private Member of Outer: " + msg); } } public static void main(String args[]) { PrivateTest o = new PrivateTest(); Inner i = o.new Inner(); i.fun(); // o.fun() calls Outer's fun (No run-time polymorphism). o = i; o.fun(); } 

}

你不能覆盖私有方法,但你可以在派生类中引入/重新定义一个。喜欢:

 class Super { private void fun() { } } class Child extends Super { private void fun() { } } 

在这里,你没有覆盖Child类中的这个fun(),你正在定义一个具有相同名称的新方法,但是如果你尝试在Child类的fun()之上使用@override,那么你将得到编译时错误,因为你强迫覆盖这个有趣的()否则你只是重新定义Child类中的新fun()

您不能覆盖私有方法。

重写方法只能存在于重写方法的子类中。 如果要覆盖的方法被标记为private ,则无法覆盖它,因为子类不会inheritance标记为private的任何内容,从而切断该私有方法与子类中任何内容之间的关系,包括任何子类的方法。

“覆盖”意味着允许JVM根据您调用它的实例类型确定使用哪种方法。 多态性理论解释了使这成为可能的原因。 为了让JVM能够说“这些方法已连接,一个覆盖另一个”,JVM必须能够包含覆盖方法的子类中查看重写方法。

话虽这么说,你提供的案例中的类仍然会编译,但是这两个方法都不会基于JVM独立运行基于实例的调用来调用。 它们只是完全不同的方法,不能被JVM识别为被覆盖或覆盖。

此外,如果您使用的是NetBeans等IDE,则使用@Override注释将指示编译器您使用超类中的相同签名覆盖该方法。 如果您不这样做,您将收到一条警告,建议您进行注释。 但是,如果在以下情况下应用此批注,则会出现编译错误:

  • 超类中没有匹配签名的方法

要么

  • 您尝试覆盖的超类中的方法标记为privatefinal

有关以下摘录,请参阅官方Oracle文档https://docs.oracle.com/javase/tutorial/java/IandI/override.html

实例方法

…子类覆盖方法的能力允许类从行为“足够接近”的超类inheritance,然后根据需要修改行为….当重写方法时,您可能想要使用@覆盖注释,指示编译器您要覆盖超类中的方法。 如果由于某种原因,编译器检测到该方法在其中一个超类中不存在,那么它将生成错误。

覆盖可能非常混乱,因为它涉及JVM似乎独立地采取行动。 请记住,如果不访问超类中的方法[s](换句话说,对于标记为private的所有方法),子类不能调用或覆盖所述方法[s],因为它不能inheritance它们这样做。

仔细阅读,

私有方法不是固有的…因为它们不是inheritance的,所以它们不能被覆盖