Java:"失效"的private修饰符

论坛 期权论坛 脚本     
niminba   2021-5-23 02:55   802   0

在Java编程中,使用private关键字修饰了某个成员,只有这个成员所在的类和这个类的方法可以使用,其他的类都无法访问到这个private成员。

上面描述了private修饰符的基本职能,今天来研究一下private功能失效的情况。

Java内部类

在Java中相信很多人都用过内部类,Java允许在一个类里面定义另一个类,类里面的类就是内部类,也叫做嵌套类。一个简单的内部类实现可以如下

class OuterClass {
  class InnerClass{
  }
}

今天的问题和Java内部类相关,只涉及到部分和本文研究相关的内部类知识,具体关于Java内部类后续的文章会介绍。

第一次失效?

一个我们在编程中经常用到的场景,就是在一个内部类里面访问外部类的private成员变量或者方法,这是可以的。如下面的代码实现。

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

这是为什么呢,不是private修饰的成员只能被成员所述的类才能访问么?难道private真的失效了么?

编译器在捣鬼?

我们使用javap命令查看一下生成的两个class文件

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."<init>":()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 "<init>":()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."<init>":(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

}

咦?不对,在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

}

从给出来的注释来看,access$0返回outerClass的language属性;access$1返回outerClass的region属性。并且这两个方法都接受OuterClass的实例作为参数。这两个方法为什么生成呢,有什么作用呢?我们看一下内部类的反编译结果就知道了。

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."<init>":()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."<init>":(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/Stri
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP