意外行为与最终修饰符相关

时间:2011-07-28 18:03:46

标签: java private final modifiers

这是我的代码

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,程序都会编译并运行。

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

我无法理解为什么它适用于最终修饰符。不应该禁止A1.A12的压倒一切吗?

这是具有最终修改器的程序的输出

java alpha/A1
A11:    HelloHello

如果它只是忽略了另一个有趣的方法那么

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

对于publicprotected和包私有/默认访问方法,final确实会阻止覆盖方法。

但是,所有private方法都是“非虚拟”的,所以有效的最终方法。超类中的private方法与派生类没有区别。你没有覆盖,只是忽略了基类中的方法。

JVM所基于的第一版Java语言规范没有内部或嵌套类,因此可以专门处理private方法。该语言的后续版本围绕着JVM。

在字节码术语中,使用invokespecial而不是private调用invokevirtual方法。

不同包中的默认访问/包私有final方法也是彼此独立的。在同一个包中可以互相覆盖,final会产生影响。在不同的包中,匹配方法不会互相覆盖。