为什么所有java方法都可以隐式重写? 在C++中,我必须显式指定“虚”关键字,以使成员函数“可重写”,因为当成员函数被重写时,涉及创建虚拟表和VPoTeX的开销(因此,每个成员函数由于性能原因而隐式不可重写)。p>

为什么所有java方法都可以隐式重写? 在C++中,我必须显式指定“虚”关键字,以使成员函数“可重写”,因为当成员函数被重写时,涉及创建虚拟表和VPoTeX的开销(因此,每个成员函数由于性能原因而隐式不可重写)。p>,java,c++,virtual-functions,Java,C++,Virtual Functions,当子类提供具有相同名称和签名的单独实现时,它还允许隐藏成员函数(如果未重写) 同样的技术也在C#中使用。我想知道为什么Java拒绝了这种行为,并在默认情况下使每个方法都可以重写,并提供了在显式使用'final'关键字时禁用重写行为的功能。摘自(#34) Java中没有虚拟关键字 因为所有的非静态方法总是 使用动态绑定。在Java中 程序员不必做出决定 是否使用动态绑定。这个 C++中存在虚拟的原因就是你 可以稍微增加一点 当您调整为 性能(或者,换句话说,“如果 你不用它,你不用付钱 这通常会导

当子类提供具有相同名称和签名的单独实现时,它还允许隐藏成员函数(如果未重写)

同样的技术也在C#中使用。我想知道为什么Java拒绝了这种行为,并在默认情况下使每个方法都可以重写,并提供了在显式使用'final'关键字时禁用重写行为的功能。

摘自(#34)

Java中没有虚拟关键字 因为所有的非静态方法总是 使用动态绑定。在Java中 程序员不必做出决定 是否使用动态绑定。这个 C++中存在虚拟的原因就是你 可以稍微增加一点 当您调整为 性能(或者,换句话说,“如果 你不用它,你不用付钱 这通常会导致混乱 还有令人不快的惊喜。决赛 关键字为 效率调整–它告诉 该方法不能被编译 被覆盖,因此它可能是 静态绑定(并内联), 因此使用等价的C++ 非虚拟呼叫)。这些优化 由编译器决定


也许有点循环。

更好的问题可能是“为什么C#有非虚拟方法?”或者至少,为什么默认情况下它们不是虚拟的,并且可以选择将它们标记为非虚拟的

在C++中,有一个想法(正如布瑞恩很好地指出),如果你不想要它,你就不必为此付出代价。问题是,如果你真的想要它,这通常意味着你最终要为它付出高昂的代价。在大多数Java实现中,它们是为大量虚拟调用而显式设计的;vtable实现往往很快,几乎没有比非虚拟调用更昂贵,这意味着非虚拟函数的主要优势已经丧失。此外,JIT编译器可以在运行时内联虚拟函数。因此,出于效率原因,实际上很少有理由使用非虚拟函数

因此,这在很大程度上可以归结为最小意外的原则。它告诉我们所有方法的行为方式都是一样的,不是一半是虚拟的,一半是非虚拟的。因为我们至少需要一些虚拟的方法来实现这个多态性,所以让它们都是虚拟的是有意义的。此外,拥有两种具有相同特征的方法只会让你自食其果

多态性还规定对象本身应该控制它所做的事情。它的行为不应该取决于客户认为它是FooParent还是FooChild

编辑:所以我的断言被调用了。下一段是我的猜测,不是事实陈述

所有这些的一个有趣的副作用是Java程序员倾向于大量使用接口。由于虚拟方法优化使接口的成本基本上不存在,因此它们允许您使用列表(例如)而不是ArrayList,并在稍后的某个日期将其切换到LinkedList,只需简单的一行更改,而无需额外的惩罚

编辑:我还将收集一些资料来源。虽然不是原始来源,但它们确实来自Sun,解释了HotSpot上的一些工作原理


Java试图更接近一种更动态的语言定义,即一切都是对象,一切都是虚拟方法。它还希望避免模糊性和难以理解的构造,这是设计者认为是C++中的一个缺陷,因此没有操作符重载,并且在这种情况下,没有能力在一个类层次结构上有两个公共方法签名,这取决于引用它的变量的类型。 C#更关心子类的稳定性,并确保子类的行为是可预测的。C++关注性能。


三种不同的设计优先级,导致不同的选择。

因此Java的基本原理可能是这样的:面向对象语言的全部要点是事物可以扩展。因此,就纯设计而言,将可扩展性视为“特例”毫无意义

请记住,Java有在运行时编译的特权。所以C++编译中的一些性能参数就在窗口中出现。在C++中,如果一个类可能被重写,那么编译器必须采取额外的步骤。在Java中,它并不神秘:在任何给定的时刻,JVM都知道某个特定的方法/类是否被重写,这才是最重要的


请注意,final关键字本质上是关于程序设计,而不是优化。JVM不需要这些信息来查看类/方法是否被重写

如果问题是问java和C++/C#之间更好的方法是什么,那么它已经在另一个线程中以相反的方向进行了讨论,并且网络上有许多可用的资源

最近@Override注释的引入及其在新代码中的广泛应用表明,“为什么所有java方法都可以隐式重写?”这个问题的确切答案确实是因为设计者犯了一个错误。(他们已经修好了)


哦!!我将对此投反对票。

我会说,在Java中,虚拟方法的成本比整个虚拟机的成本低。在C++中,与C类背景相比,它的成本很高。默认情况下,没有人会决定通过指针调用所有方法作为结果o