这是小小本周的第五篇,本篇将会说到失效的private修饰符

前言

在Java编程里,使用private关键字修饰了一个成员,只有成员内部可以访问,其余成员都不可访问,今天说明一下private功能失效的问题。

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

查看原因

使用javap命令查看一下生成的class文件

15:30 $ javap -c  OuterClass
Compiled from "OuterClass.java"
public class OuterClass extends java.lang.Object{
public OuterClass();Code:0:  aload_01:  invokespecial    #11; //Method java/lang/Object."<init>":()V4:  aload_05:  ldc  #13; //String en7:  putfield #15; //Field language:Ljava/lang/String;10: aload_011: ldc  #17; //String US13: putfield #19; //Field region:Ljava/lang/String;16: returnpublic static void main(java.lang.String[]);Code:0:  new  #1; //class OuterClass3:  dup4:  invokespecial    #27; //Method "<init>":()V7:  astore_18:  new  #28; //class OuterClass$InnerClass11: dup12: aload_113: dup14: invokevirtual    #30; //Method java/lang/Object.getClass:()Ljava/lang/Class;17: pop18: invokespecial    #34; //Method OuterClass$InnerClass."<init>":(LOuterClass;)V21: astore_222: aload_223: invokevirtual    #37; //Method OuterClass$InnerClass.printOuterClassPrivateFields:()V26: returnstatic java.lang.String access$0(OuterClass);Code:0:  aload_01:  getfield #15; //Field language:Ljava/lang/String;4:  areturnstatic java.lang.String access$1(OuterClass);Code:0:  aload_01:  getfield #19; //Field region:Ljava/lang/String;4:  areturn}

在这里有一个OuterClass方法,

static java.lang.String access$0(OuterClass);Code:0:  aload_01:  getfield #15; //Field language:Ljava/lang/String;4:  areturnstatic java.lang.String access$1(OuterClass);Code:0:  aload_01:  getfield #19; //Field region:Ljava/lang/String;4:  areturn}

根据注释,可以知道access1返回outerClass的region属性,并且这两个方法都接受OuterClass的实例作为参数, 对这两个方法进行反编译。

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_01:  aload_12:  putfield #10; //Field this$0:LOuterClass;5:  aload_06:  invokespecial    #12; //Method java/lang/Object."<init>":()V9:  returnpublic void printOuterClassPrivateFields();Code:0:  new  #20; //class java/lang/StringBuilder3:  dup4:  ldc  #22; //String language=6:  invokespecial    #24; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V9:  aload_010: 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_025: 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_138: getstatic    #46; //Field java/lang/System.out:Ljava/io/PrintStream;41: aload_142: invokevirtual    #52; //Method java/io/PrintStream.println:(Ljava/lang/String;)V45: return
}

下面代码调用access$0的代码,其目的是得到OuterClass的language 私有属性。

13:   invokestatic #27; //Method OuterClass.access$0:(LOuterClass;)Ljava/lang/String;

下面代码调用了access$1的代码,其目的是得到OutherClass的region 私有属性。

28:   invokestatic #39; //Method OuterClass.access$1:(LOuterClass;)Ljava/lang/String;

即,在内部类构造的时候,会有外部类的引用传递进来,并且作为内部类的一个属性,所以内部类会持有一个其外部类的应用。this$0就是内部类持有的外部类引用,通过构造方法传递引用并赋值。

final OuterClass this$0;public OuterClass$InnerClass(OuterClass);Code:0:  aload_01:  aload_12:  putfield #10; //Field this$0:LOuterClass;5:  aload_06:  invokespecial    #12; //Method java/lang/Object."<init>":()V9:  return

继续失效

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

和上面一样,使用Javap反编译一下

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_01:  aload_12:  putfield #12; //Field this$0:LAnotherOuterClass;5:  aload_06:  invokespecial    #14; //Method java/lang/Object."<init>":()V9:  aload_010: bipush   1012: putfield #17; //Field x:I15: returnstatic int access$0(AnotherOuterClass$InnerClass);Code:0:  aload_01:  getfield #17; //Field x:I4:  ireturn}

编译器自动生成了一个access$0一次来获取x的值 AnotherOuterClass.class的反编译结果

16:08 $ javap -c AnotherOuterClass
Compiled from "AnotherOuterClass.java"
public class AnotherOuterClass extends java.lang.Object{
public AnotherOuterClass();Code:0:  aload_01:  invokespecial    #8; //Method java/lang/Object."<init>":()V4:  returnpublic static void main(java.lang.String[]);Code:0:  new  #16; //class AnotherOuterClass$InnerClass3:  dup4:  new  #1; //class AnotherOuterClass7:  dup8:  invokespecial    #18; //Method "<init>":()V11: dup12: invokevirtual    #19; //Method java/lang/Object.getClass:()Ljava/lang/Class;15: pop16: invokespecial    #23; //Method AnotherOuterClass$InnerClass."<init>":(LAnotherOuterClass;)V19: astore_120: getstatic    #26; //Field java/lang/System.out:Ljava/io/PrintStream;23: new  #32; //class java/lang/StringBuilder26: dup27: ldc  #34; //String InnerClass Filed =29: invokespecial    #36; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V32: aload_133: invokestatic #39; //Method AnotherOuterClass$InnerClass.access$0:(LAnotherOuterClass$InnerClass;)I36: 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;)V45: return}

其中这句话,直接说明通过内部类的实例,获取到私有属性x的操作。

33:   invokestatic #39; //Method AnotherOuterClass$InnerClass.access$0:(LAnotherOuterClass$InnerClass;)I

在官网文档中是这样说道的,如果(内部类的)成员和构造方法设定成了私有修饰符,当且仅当其外部类访问时是允许的。

如何保证不被访问

使用的方法相当简单,使用匿名内部类的方法实现

public class PrivateToOuter {Runnable mRunnable = new Runnable(){private int x=10;@Overridepublic 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 allowedp.mRunnable.run(); // allowed}
}

小明菜市场

推荐阅读

● 知道 | 同学,你都了解关系型数据库,确定不了解一下这种数据库吗?

● 基础 | 零散的MySql基础记不住,看这一篇就够啦

● 面试 | 你说你熟悉MySql,那你就来谈谈InnoDB如何解决幻读的?

● 传记 | 我的大学三年-不以物喜,不以己悲

● 实践 | Centos 7搭建LVS+Keepalived高可用Web服务群集群

给我个好看再走好吗?

细说 | 失效的private修饰符相关推荐

  1. 通过反射获得类的构造引用无视private修饰符

    import operate327.Demo; import operate425.demo.demo1.Student;import java.lang.reflect.Constructor;/* ...

  2. java的protect_java的public,protect,缺省,private修饰符的访问权限

    (1)对于public修饰符,它具有最大的访问权限,可以访问任何一个在CLASSPATH下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. (2)对于protected修 ...

  3. Java的private修饰符

    private修饰的变量只有在本类中才能直接访问,而在其他类中无法访问,但是可以通过设置get()方法与set()方法来处理. 使用private的目的,可以对成员变量进行赋值控制. public c ...

  4. Spring @Autowired NPE:Why @Autowired Bean is null? private 修饰符!

    问题描述:Controller方法误写成了private而导致500错误的问题. 找原因,找了大半天, 也翻了Spring MVC的源码...终于,灵机一动,看到了 private : 原因分析 当某 ...

  5. 重新精读《Java 编程思想》系列之public,protected,private与无修饰符权限的区别...

    前言 相信大家在平时的工作中对于public和private的修饰权限是用的比较多的.对于protected和无修饰符用的是比较少的.我也一样,在读书的时候,又看到了这个问题,于是,在此进行总结和详细 ...

  6. 1.15 Java访问控制修饰符(public、 private、protected 和 friendly)

    在 Java 语言中提供了多个作用域修饰符,其中常用的有 public.private.protected.final.abstract.static.transient 和 volatile,这些修 ...

  7. 修饰符private和protected详解以及调用Object类Clone方法报错:clone() has protected access in java.lang.Object的原因及解决方案

    1. 访问修饰符 访问修饰符的权限范围不用多讲,通过如下一张表即可表示,但是使用起来却有很多疑问.public修饰符就不用多讲了,在哪都可以访问:无修饰符的也不用多加分析,就是同包下可以访问.接下来我 ...

  8. java中哪些可以私有化_《Java基础学习笔记》JAVA修饰符之私有化(Private)

    1,什么是private修饰符? private是权限修饰符,用于修饰类中的成员(成员变量,成员函数). private修饰后的成员只在本类中有效. /* 例: * 将age私有化以后,类以外即使建立 ...

  9. 不同修饰符的访问权限(private,缺省(默认即default),protected,public)

    People类和Test类在demo包里,PeopleChild类是People子类和Test1在demo1包里. 1.private 由上图可知private修饰符在同类中是可被调用的,没报错. 同 ...

最新文章

  1. MFC Timer定时器
  2. C语言printf与scanf函数
  3. nodejs 图片处理模块 rotate_学会Pillow再也不用PS啦——Python图像处理库Pillow入门!...
  4. Java之HashMap.values()转List时的错误和正确操作
  5. wpspbc按钮是什么意思_AC只是英文单词缩写,在科技领域常见的有三种意思
  6. vb不能插入png图片_收藏备用!!VBA操作图片【插入导出删除】
  7. iOS9使用提示框的正确实现方式(UIAlertView is deprecated)
  8. python面向对象遇见问题
  9. JavaScript数据类型之字符串型(4)
  10. python_14 多态,封装,反射
  11. 【读书笔记】《王道论坛计算机考研机试指南》第二章
  12. 竹子买车商学院,知名汽车人钟志,销售实战培训
  13. 前端开发-HTML+CSS实现京东官网左侧导航条列表
  14. android设置传感器的采集方向,Android-传感器开发-方向判断
  15. 行无疆靠谱讲述拼多多推广方法有哪些?
  16. Arduino与Matlab的串口通讯:通过光敏电阻进行人数统计,以及改进:人物方向的判断并进行加减。
  17. 云因成本高昂屡被关注,上云的价值是什么?
  18. 实现strStr()
  19. 10大PPT模板可直接套用助PM正确写好年终总结
  20. 谈谈单元测试:为什么要进行单元测试?

热门文章

  1. 批量修改TS Profile、盘符计算器小工具
  2. 使用Axis2方式发布webService实例说明
  3. unity, sceneview 中拾取球体gizmos
  4. [裴礼文数学分析中的典型问题与方法习题参考解答]4.3.14
  5. 通过Bigtop编译Hadoop组件的rpm包
  6. Pass4side CompTIA PDI+ Beta Exam PD1-001 DEMO 免费下载
  7. 程序员的算法课(9)-常见字符串算法
  8. Linux下安装ActiveMQ
  9. nodeJs 控制台打印中文显示为Unicode解决方案
  10. shell:判断某个变量是否包含字符串/变量的方法