2

这是我的代码

package alpha ;

class A1
{
    static class A11
    {
        private
            final // WHAT IS THE EFFECT OF THIS MODIFIER?
            void fun ( String caller )
            {
                System . out . println ( "A11:\t" + caller ) ;
            }
    }

    static class A12 extends A11
    {
        private void fun ( String caller )
        {
            super . fun ( caller + caller ) ;
        }
    }

    public static void main ( String [ ] args )
    {
        A12 a12 = new A12 ( ) ;
        a12 . fun ( "Hello" ) ;
    }
}

我发现无论有没有 A1.A11 中的最终 mdifer,程序都会编译并运行。

我可以理解,如果没有 final 修饰符,A1.A12 可以看到并因此覆盖 fun 方法。它是私有的,但它们属于同一类,因此不存在可见性问题。

我不明白为什么它与 final 修饰符一起使用。不应该禁止 A1.A12 中的覆盖吗?

这是带有最终修饰符的程序的输出

java alpha/A1
A11:    HelloHello

如果它只是忽略了其他有趣的方法,那么

  1. 编译器不会抱怨超级参考吗
  2. A11 不会在输出中
4

2 回答 2

7

您的方法是私有的。

将它们的可见性更改为受保护的以查看预期的行为,即只有当方法受到保护,公共或默认可见性时,甚至存在覆盖的概念

做这样的事情——

class A1
{
    static class A11
    {
        public
            final // WHAT IS THE EFFECT OF THIS MODIFIER?
            void fun ( String caller )
            {
                System . out . println ( "A11:\t" + caller ) ;
            }
    }

    static class A12 extends A11
    {
        public void fun ( String caller )
        {
            super . fun ( caller + caller ) ;
        }
    }

    public static void main ( String [ ] args )
    {
        A12 a12 = new A12 ( ) ;
        a12 . fun ( "Hello" ) ;
    }
}

现在将抛出编译时异常

fun(java.lang.String) in A1.A12 cannot override fun(java.lang.String) in A1.A11; overridden method is final
于 2011-07-28T18:07:47.550 回答
2

Forpublicprotectedpackage 私有/默认访问方法,final确实可以防止方法被覆盖。

但是,所有private方法都是“非虚拟的”,因此实际上是最终的。超类中的private方法对派生类没有影响。您没有覆盖,只是基类中的方法被忽略了。

JVM基于的第一版Java语言规范没有内部或嵌套类,因此private可以特殊处理方法。该语言的更高版本围绕 JVM。

在字节码术语中,private方法是用invokespecial代替 调用的invokevirtual

不同包中的默认访问/包私有final方法也相互独立。在同一个包中可以相互覆盖并final有所作为。在不同的包中,匹配方法不会相互覆盖。

于 2011-07-28T18:12:02.957 回答