zoukankan      html  css  js  c++  java
  • android 内部类的优化

    developer.android.com 文档中有一篇关于性能的文章,里面提到了内部类的使用。文章建议“对于私有内部类 使用 包訪问权限取代私有权限訪问”,

    这里说的是在内部类訪问外部类的成员或方法时假设 内部类是私有的而且外部类的成员也是私有的,那么编译器就会为内部类在外部类中添加一个静态方法。

    真的是这种吗?仅仅有试一试才知道。

    我们使用一个简单的样例来測试下:

    public class One {
    
    	private int a;
    	
    	private class B{
    		
    		public int getA(){
    			return a;
    		}
    	}
    
    }

    上边的代码为One创建了一个私有的内部类B,而且B中有一个方法訪问到了 One中的私有成员 a。我们把上边的代码编译成 dex文件后导出程序的指令码与类信息。

    导出的结果例如以下:

    Processing 'one.dex'...
    Opened 'one.dex', DEX version '035'
    Class #0            -
      Class descriptor  : 'LOne$B;'
      Access flags      : 0x0000 ()
      Superclass        : 'Ljava/lang/Object;'
      Interfaces        -
      Static fields     -
      Instance fields   -
        #0              : (in LOne$B;)
          name          : 'this$0'
          type          : 'LOne;'
          access        : 0x1010 (FINAL SYNTHETIC)
      Direct methods    -
        #0              : (in LOne$B;)
          name          : '<init>'
          type          : '(LOne;)V'
          access        : 0x10002 (PRIVATE CONSTRUCTOR)
          code          -
          registers     : 2
          ins           : 2
          outs          : 1
          insns size    : 6 16-bit code units
    0001a0:                                        |[0001a0] One.B.<init>:(LOne;)V
    0001b0: 5b01 0000                              |0000: iput-object v1, v0, LOne$B;.this$0:LOne; // field@0000
    0001b4: 7010 0400 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0004
    0001ba: 0e00                                   |0005: return-void
          catches       : (none)
          positions     : 
            0x0000 line=7
          locals        : 
            0x0000 - 0x0006 reg=0 this LOne$B; 
    
      Virtual methods   -
        #0              : (in LOne$B;)
          name          : 'getA'
          type          : '()I'
          access        : 0x0001 (PUBLIC)
          code          -
          registers     : 2
          ins           : 1
          outs          : 1
          insns size    : 7 16-bit code units
    0001bc:                                        |[0001bc] One.B.getA:()I
    0001cc: 5410 0000                              |0000: iget-object v0, v1, LOne$B;.this$0:LOne; // field@0000
    0001d0: 7110 0300 0000                         |0002: invoke-static {v0}, LOne;.access$0:(LOne;)I // method@0003
    0001d6: 0a00                                   |0005: move-result v0
    0001d8: 0f00                                   |0006: return v0
          catches       : (none)
          positions     : 
            0x0000 line=10
          locals        : 
            0x0000 - 0x0007 reg=1 this LOne$B; 
    
      source_file_idx   : 10 (One.java)
    
    Class #1            -
      Class descriptor  : 'LOne;'
      Access flags      : 0x0001 (PUBLIC)
      Superclass        : 'Ljava/lang/Object;'
      Interfaces        -
      Static fields     -
      Instance fields   -
        #0              : (in LOne;)
          name          : 'a'
          type          : 'I'
          access        : 0x0002 (PRIVATE)
      Direct methods    -
        #0              : (in LOne;)
          name          : '<init>'
          type          : '()V'
          access        : 0x10001 (PUBLIC CONSTRUCTOR)
          code          -
          registers     : 1
          ins           : 1
          outs          : 1
          insns size    : 4 16-bit code units
    0001dc:                                        |[0001dc] One.<init>:()V
    0001ec: 7010 0400 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0004
    0001f2: 0e00                                   |0003: return-void
          catches       : (none)
          positions     : 
            0x0000 line=3
          locals        : 
            0x0000 - 0x0004 reg=0 this LOne; 
    
        #1              : (in LOne;)
          name          : 'access$0'
          type          : '(LOne;)I'
          access        : 0x1008 (STATIC SYNTHETIC)
          code          -
          registers     : 2
          ins           : 1
          outs          : 0
          insns size    : 3 16-bit code units
    0001f4:                                        |[0001f4] One.access$0:(LOne;)I
    000204: 5210 0100                              |0000: iget v0, v1, LOne;.a:I // field@0001
    000208: 0f00                                   |0002: return v0
          catches       : (none)
          positions     : 
            0x0000 line=5
          locals        : 
    
      Virtual methods   -
      source_file_idx   : 10 (One.java)
    

    哈看到没 One中多一个方法,而我们的源代码中是没有的。
    One.access$0:(LOne;)I

    如今我们把源代码改下

    public class One {
    
    	private int a;
    	
    	class B{
    		
    		public int getA(){
    			return a;
    		}
    	}
    
    }
    

    然后在编译,导出:

    Processing 'one.dex'...
    Opened 'one.dex', DEX version '035'
    Class #0            -
      Class descriptor  : 'LOne$B;'
      Access flags      : 0x0000 ()
      Superclass        : 'Ljava/lang/Object;'
      Interfaces        -
      Static fields     -
      Instance fields   -
        #0              : (in LOne$B;)
          name          : 'this$0'
          type          : 'LOne;'
          access        : 0x1010 (FINAL SYNTHETIC)
      Direct methods    -
        #0              : (in LOne$B;)
          name          : '<init>'
          type          : '(LOne;)V'
          access        : 0x10000 (CONSTRUCTOR)
          code          -
          registers     : 2
          ins           : 2
          outs          : 1
          insns size    : 6 16-bit code units
    0001a0:                                        |[0001a0] One.B.<init>:(LOne;)V
    0001b0: 5b01 0000                              |0000: iput-object v1, v0, LOne$B;.this$0:LOne; // field@0000
    0001b4: 7010 0400 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0004
    0001ba: 0e00                                   |0005: return-void
          catches       : (none)
          positions     : 
            0x0000 line=7
          locals        : 
            0x0000 - 0x0006 reg=0 this LOne$B; 
    
      Virtual methods   -
        #0              : (in LOne$B;)
          name          : 'getA'
          type          : '()I'
          access        : 0x0001 (PUBLIC)
          code          -
          registers     : 2
          ins           : 1
          outs          : 1
          insns size    : 7 16-bit code units
    0001bc:                                        |[0001bc] One.B.getA:()I
    0001cc: 5410 0000                              |0000: iget-object v0, v1, LOne$B;.this$0:LOne; // field@0000
    0001d0: 7110 0300 0000                         |0002: invoke-static {v0}, LOne;.access$0:(LOne;)I // method@0003
    0001d6: 0a00                                   |0005: move-result v0
    0001d8: 0f00                                   |0006: return v0
          catches       : (none)
          positions     : 
            0x0000 line=10
          locals        : 
            0x0000 - 0x0007 reg=1 this LOne$B; 
    
      source_file_idx   : 10 (One.java)
    
    Class #1            -
      Class descriptor  : 'LOne;'
      Access flags      : 0x0001 (PUBLIC)
      Superclass        : 'Ljava/lang/Object;'
      Interfaces        -
      Static fields     -
      Instance fields   -
        #0              : (in LOne;)
          name          : 'a'
          type          : 'I'
          access        : 0x0002 (PRIVATE)
      Direct methods    -
        #0              : (in LOne;)
          name          : '<init>'
          type          : '()V'
          access        : 0x10001 (PUBLIC CONSTRUCTOR)
          code          -
          registers     : 1
          ins           : 1
          outs          : 1
          insns size    : 4 16-bit code units
    0001dc:                                        |[0001dc] One.<init>:()V
    0001ec: 7010 0400 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0004
    0001f2: 0e00                                   |0003: return-void
          catches       : (none)
          positions     : 
            0x0000 line=3
          locals        : 
            0x0000 - 0x0004 reg=0 this LOne; 
    
        #1              : (in LOne;)
          name          : 'access$0'
          type          : '(LOne;)I'
          access        : 0x1008 (STATIC SYNTHETIC)
          code          -
          registers     : 2
          ins           : 1
          outs          : 0
          insns size    : 3 16-bit code units
    0001f4:                                        |[0001f4] One.access$0:(LOne;)I
    000204: 5210 0100                              |0000: iget v0, v1, LOne;.a:I // field@0001
    000208: 0f00                                   |0002: return v0
          catches       : (none)
          positions     : 
            0x0000 line=5
          locals        : 
    
      Virtual methods   -
      source_file_idx   : 10 (One.java)
    
    依旧有附加的方法
    One.access$0:(LOne;)I


    我们在改动下

    public class One {
    
    	int a;
    	
    	class B{
    		
    		public int getA(){
    			return a;
    		}
    	}
    
    }
    

    在编译 导出

    Processing 'one.dex'...
    Opened 'one.dex', DEX version '035'
    Class #0            -
      Class descriptor  : 'LOne$B;'
      Access flags      : 0x0000 ()
      Superclass        : 'Ljava/lang/Object;'
      Interfaces        -
      Static fields     -
      Instance fields   -
        #0              : (in LOne$B;)
          name          : 'this$0'
          type          : 'LOne;'
          access        : 0x1010 (FINAL SYNTHETIC)
      Direct methods    -
        #0              : (in LOne$B;)
          name          : '<init>'
          type          : '(LOne;)V'
          access        : 0x10000 (CONSTRUCTOR)
          code          -
          registers     : 2
          ins           : 2
          outs          : 1
          insns size    : 6 16-bit code units
    000184:                                        |[000184] One.B.<init>:(LOne;)V
    000194: 5b01 0000                              |0000: iput-object v1, v0, LOne$B;.this$0:LOne; // field@0000
    000198: 7010 0300 0000                         |0002: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0003
    00019e: 0e00                                   |0005: return-void
          catches       : (none)
          positions     : 
            0x0000 line=7
          locals        : 
            0x0000 - 0x0006 reg=0 this LOne$B; 
    
      Virtual methods   -
        #0              : (in LOne$B;)
          name          : 'getA'
          type          : '()I'
          access        : 0x0001 (PUBLIC)
          code          -
          registers     : 2
          ins           : 1
          outs          : 0
          insns size    : 5 16-bit code units
    0001a0:                                        |[0001a0] One.B.getA:()I
    0001b0: 5410 0000                              |0000: iget-object v0, v1, LOne$B;.this$0:LOne; // field@0000
    0001b4: 5200 0100                              |0002: iget v0, v0, LOne;.a:I // field@0001
    0001b8: 0f00                                   |0004: return v0
          catches       : (none)
          positions     : 
            0x0000 line=10
          locals        : 
            0x0000 - 0x0005 reg=1 this LOne$B; 
    
      source_file_idx   : 9 (One.java)
    
    Class #1            -
      Class descriptor  : 'LOne;'
      Access flags      : 0x0001 (PUBLIC)
      Superclass        : 'Ljava/lang/Object;'
      Interfaces        -
      Static fields     -
      Instance fields   -
        #0              : (in LOne;)
          name          : 'a'
          type          : 'I'
          access        : 0x0000 ()
      Direct methods    -
        #0              : (in LOne;)
          name          : '<init>'
          type          : '()V'
          access        : 0x10001 (PUBLIC CONSTRUCTOR)
          code          -
          registers     : 1
          ins           : 1
          outs          : 1
          insns size    : 4 16-bit code units
    0001bc:                                        |[0001bc] One.<init>:()V
    0001cc: 7010 0300 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0003
    0001d2: 0e00                                   |0003: return-void
          catches       : (none)
          positions     : 
            0x0000 line=3
          locals        : 
            0x0000 - 0x0004 reg=0 this LOne; 
    
      Virtual methods   -
      source_file_idx   : 9 (One.java)
    

    已经没有附加的方法了。

    假设外部类的成员是包訪问的,内部类是私有的相同也不会产生附加的方法。

    内部类对外部类成员的訪问是不能直接訪问私有成员的,编译器会添加额外的辅助方法,避免的方法是改动外部类的成员为包訪问,文档中也提到了这会在一定程度上破坏

    封装。


  • 相关阅读:
    通过android XML 创建图形,降低对美工的依赖
    ViewPager学习之仿微信主界面
    Linux学习日志--文件搜索命令
    蓝桥杯 历届试题 小朋友排队 【树状数组】+【逆序数】
    操作系统——IO管理
    Mac和PC在工作中管理的对比(5)
    虚拟地址空间分配
    UVA 624 CD(DP + 01背包)
    【CSS】瀑布流布局的两种方式:传统多列浮动和绝对定位布局
    外煤关注:百度收购大部分糯米股份
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4002681.html
Copyright © 2011-2022 走看看