In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
What is the private modifier in Java? I believe many inexperienced people don't know what to do about it. Therefore, this article summarizes the causes and solutions of the problem. Through this article, I hope you can solve this problem.
In Java programming, a member is modified with the private keyword. Only the class in which the member is located and the methods of this class can be used, and no other class can access the private member.
The basic functions of the private modifier are described above, and today let's take a look at the failure of private functionality.
Java inner class
In Java, it is believed that many people have used inner classes. Java allows you to define another class in one class, and the classes in the class are inner classes, also known as nested classes. A simple inner class implementation can be as follows
Class OuterClass {class InnerClass {}}
Today's question is related to Java inner classes, which only involves some of the inner class knowledge related to the study of this article, which will be covered in subsequent articles on Java inner classes.
* invalidation?
One of the scenarios we often use in programming is to access the private member variables or methods of the external class in an inner class, which is possible. Such as the following code implementation.
Public class OuterClass {private String language= "en"; private String region= "US"; public class InnerClass {public void printOuterClassPrivateFields () {String fields = "language=" + language + "; region=" + region; System.out.println (fields);} public static void main (String [] args) {OuterClass outer = new OuterClass (); OuterClass.InnerClass inner = outer.new InnerClass (); inner.printOuterClassPrivateFields () }}
Why, members that are not private-decorated can only be accessed by the class described by the member? Is private really ineffective?
Is the compiler messing around?
Let's use the javap command to look at the two generated class files
Decompilation result of OuterClass
15:30$ javap-c OuterClass Compiled from "OuterClass.java" public class OuterClass extends java.lang.Object {public OuterClass (); Code: 0: aload_0 1: invokespecial # 11; / / Method java/lang/Object. "": () V 4: aload_0 5: ldc # 13; / / String en 7: putfield # 15; / / Field language:Ljava/lang/String; 10: aload_0 11: ldc # 17 / / String US 13: putfield # 19; / / Field region:Ljava/lang/String; 16: return public static void main (java.lang.String []); Code: 0: new # 1; / / class OuterClass 3: dup 4: invokespecial # 27; / / Method "": () V 7: astore_1 8: new # 28; / / class OuterClass$InnerClass 11: dup 12: aload_1 13: dup 14: invokevirtual # 30 / / Method java/lang/Object.getClass: () Ljava/lang/Class; 17: pop 18: invokespecial # 34; / / Method OuterClass$InnerClass. ": (LOuterClass;) V 21: astore_2 22: aload_2 23: invokevirtual # 37; / / Method OuterClass$InnerClass.printOuterClassPrivateFields: () V 26: return static java.lang.String access$0 (OuterClass); Code: 0: aload_0 1: getfield # 15; / / Field language:Ljava/lang/String 4: areturn static java.lang.String access$1 (OuterClass); Code: 0: aload_0 1: getfield # 19; / / Field region:Ljava/lang/String; 4: areturn}
Huh? No, we don't define these two methods in OuterClass.
Static java.lang.String access$0 (OuterClass); Code: 0: aload_0 1: getfield # 15; / / Field language:Ljava/lang/String; 4: areturn static java.lang.String access$1 (OuterClass); Code: 0: aload_0 1: getfield # 19; / / Field region:Ljava/lang/String; 4: areturn}
Judging from the comments given, access$0 returns the language property of outerClass; access$1 returns the region property of outerClass. And both methods accept an instance of OuterClass as a parameter. Why are these two methods generated and what is the use of them? Let's take a look at the decompilation result of the inner class.
Decompilation result of OuterClass$InnerClass
15:37$ javap-c OuterClass\ $InnerClass Compiled from "OuterClass.java" public class OuterClass$InnerClass extends java.lang.Object {final OuterClass this$0; public OuterClass$InnerClass (OuterClass); Code: 0: aload_0 1: aload_1 2: putfield # 10; / / Field this$0:LOuterClass; 5: aload_0 6: invokespecial # 12; / / Method java/lang/Object. ": () V 9: return public void printOuterClassPrivateFields (); Code: 0: new # 20 / / class java/lang/StringBuilder 3: dup 4: ldc # 22; / / String language= 6: invokespecial # 24; / / Method java/lang/StringBuilder. ": (Ljava/lang/String;) V 9: aload_0 10: getfield # 10; / / Field this$0:LOuterClass; 13: invokestatic # 27; / / Method OuterClass.access$0: (LOuterClass;) Ljava/lang/String; 16: invokevirtual # 33 / / Method java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder; 19: ldc # 37; / / String; region= 21: invokevirtual # 33; / / Method java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder; 24: aload_0 25: getfield # 10; / / Field this$0:LOuterClass; 28: invokestatic # 39; / / Method OuterClass.access$1: (LOuterClass;) Ljava/lang/String 31: invokevirtual # 33; / / Method java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder; 34: invokevirtual # 42; / / Method java/lang/StringBuilder.toString: () Ljava/lang/String; 37: astore_1 38: getstatic # 46; / / Field java/lang/System.out:Ljava/io/PrintStream; 41: aload_1 42: invokevirtual # 52 / / Method java/io/PrintStream.println: (Ljava/lang/String;) V 45: return}
The following code invokes the code of access$0 to get the language private property of OuterClass.
13: invokestatic # 27; / / Method OuterClass.access$0: (LOuterClass;) Ljava/lang/String
The following code calls the code for access$1, which aims to get the region private property of OutherClass.
28: invokestatic # 39; / / Method OuterClass.access$1: (LOuterClass;) Ljava/lang/String
Note: when the inner class is constructed, a reference to the outer class is passed in as an attribute of the inner class, so the inner class holds a reference to its external class.
This$0 is the external class reference held by the inner class, which is passed and assigned through the constructor.
Final OuterClass this$0; public OuterClass$InnerClass (OuterClass); Code: 0: aload_0 1: aload_1 2: putfield # 10; / / Field this$0:LOuterClass; 5: aload_0 6: invokespecial # 12; / / Method java/lang/Object. ": () V 9: return
Summary
This part of the private looks invalid, but it doesn't actually fail, because when the inner class calls the private properties of the external class, its real execution is to call the static methods of the attributes generated by the compiler (that is, acess$0,access$1, etc.) to get those property values. All this is a special treatment of the compiler.
It doesn't work this time?
If the above method of writing is very common, then this method of writing is not very little contact, but it can be run.
Public class AnotherOuterClass {public static void main (String [] args) {InnerClass inner = new AnotherOuterClass () .new InnerClass (); System.out.println ("InnerClass Filed =" + inner.x);} class InnerClass {private int x = 10;}}
As above, use javap decompilation to take a look. But this time, let's take a look at the results of InnerClass.
16:03$ javap-c AnotherOuterClass\ $InnerClass Compiled from "AnotherOuterClass.java" class AnotherOuterClass$InnerClass extends java.lang.Object {final AnotherOuterClass this$0; AnotherOuterClass$InnerClass (AnotherOuterClass); Code: 0: aload_0 1: aload_1 2: putfield # 12; / / Field this$0:LAnotherOuterClass; 5: aload_0 6: invokespecial # 14; / / Method java/lang/Object. ": () V 9: aload_0 10: bipush 10 12: putfield # 17 / / Field XRV I 15: return static int access$0 (AnotherOuterClass$InnerClass); Code: 0: aload_0 1: getfield # 17; / / Field XRV I 4: ireturn}
Again, the compiler automatically generates a backdoor method access$0 that gets private properties to get the value of x at once.
Decompilation result of AnotherOuterClass.class
16:08$ javap-c AnotherOuterClass Compiled from "AnotherOuterClass.java" public class AnotherOuterClass extends java.lang.Object {public AnotherOuterClass (); Code: 0: aload_0 1: invokespecial # 8; / / Method java/lang/Object. "": () V 4: return public static void main (java.lang.String []); Code: 0: new # 16; / / class AnotherOuterClass$InnerClass 3: dup 4: new # 1 / / class AnotherOuterClass 7: dup 8: invokespecial # 18; / / Method "": () V 11: dup 12: invokevirtual # 19; / / Method java/lang/Object.getClass: () Ljava/lang/Class; 15: pop 16: invokespecial # 23; / / Method AnotherOuterClass$InnerClass. ": (LAnotherOuterClass;) V 19: astore_1 20: getstatic # 26; / / Field java/lang/System.out:Ljava/io/PrintStream 23: new # 32; / / class java/lang/StringBuilder 26: dup 27: ldc # 34; / / String InnerClass Filed = 29: invokespecial # 36; / / Method java/lang/StringBuilder. "": (Ljava/lang/String;) V 32: aload_1 33: invokestatic # 39; / / Method AnotherOuterClass$InnerClass.access$0: (LAnotherOuterClass$InnerClass;) I 36: invokevirtual # 43; / / Method java/lang/StringBuilder.append: (I) Ljava/lang/StringBuilder 39: invokevirtual # 47; / / Method java/lang/StringBuilder.toString: () Ljava/lang/String; 42: invokevirtual # 51; / / Method java/io/PrintStream.println: (Ljava/lang/String;) V 45: return}
Where this call is the operation of the external class to obtain the private attribute x through the instance of the inner class.
33: invokestatic # 39; / / Method AnotherOuterClass$InnerClass.access$0: (LAnotherOuterClass$InnerClass;) I
Let's make a summary.
There is a sentence in the official document of java.
If the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
This means that if the members and constructors of the inner class are set to private modifiers, they are allowed if and only if their external classes are accessed.
How to keep private members of internal classes from being accessed externally
I believe that after reading the above two parts, you will find that it is very difficult for private members of internal classes not to be accessed by external classes, and it is possible for the compiler to be nosy. That is to use anonymous inner classes.
Because the type of mRunnable object is Runnable, not the type of anonymous inner class (we can't get it normally), and there is no attribute x in Runanble, mRunnable.x is not allowed.
Public class PrivateToOuter {Runnable mRunnable = new Runnable () {private int xylene 10; @ Override public void run () {System.out.println (x);}}; public static void main (String [] args) {PrivateToOuter p = new PrivateToOuter (); / / System.out.println ("anonymous class private filed=" + p.mRunnable.x); / / not allowed p.mRunnable.run () / / allowed}}
In this article, private appears to be invalid, but in fact it does not, and instead uses indirect methods to get private properties when called.
Unlike C++, Java's internal classes are constructed to hold applications of external classes, which C++ won't.
After reading the above, have you mastered how the private modifier in Java works? If you want to learn more skills or want to know more about it, you are welcome to follow the industry information channel, thank you for reading!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.