Unexpected behavior by final modifier

This is my code.

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" ) ; } } 

I found that with or without the final mdifer in A1.A11, the program compiles and runs.

I can understand that without the final modifier, A1.A12 can see and thus override the fun method. This is personal, but they are in the same class, so there is no visibility.

I can’t understand why it works with the last modifier. Should you not prohibit overriding in A1.A12?

This is the result of the program working with the final modifier in place.

 java alpha/A1 A11: HelloHello 

If he simply ignored another fun method, then

  • no compiler complained about super link
  • A11 will not be output
+2
java private final modifiers
Jul 28 2018-11-18T00:
source share
2 answers

Your methods are private .

Change your visibility to protected to see the expected behavior, that is, only when the method is protected, public or by default visibility, the concept of redefinition even exists .

Doing something like this -

 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" ) ; } } 

will now throw a compile-time exception

 fun(java.lang.String) in A1.A12 cannot override fun(java.lang.String) in A1.A11; overridden method is final 
+7
Jul 28 '11 at 18:07
source share

For public , protected and private / default access methods, final really prevents method overrides.

However, all private methods are "non-virtual", so efficient final. The private method in the superclass has nothing to do with the derived class. You do not override, just ignore the method in the base class.

In the first release of the Java Language Spec, on which the JVM is based, there are no inner or nested classes, so private methods can be considered specifically. Later versions of the language are bent around the JVM.

In terms of bytecode, private methods are invoked with invokespecial instead of invokevirtual .

Priority access methods / private final package in different packages are also independent of each other. Within one package, you can override each other, and final matters. In different packages, matching methods do not override each other.

+2
Jul 28 '11 at 18:12
source share



All Articles