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 内部类的优化的更多相关文章
- Android应用性能优化(转)
人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...
- 包建强的培训课程(9):Android App性能优化
v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...
- Android代码内存优化建议-Android官方篇
转自:http://androidperformance.com/ http://developer.android.com/intl/zh-cn/training/displaying-bitmap ...
- Android开发性能优化总结(一)
安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户. 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流. ...
- fir.im Weekly - 如何进行 Android App 性能优化
关于 Android App 的优化,@anly-jun 用 3 个月完成了这一系列文章,从 性能分析工具 到 ANR .Layout .消除卡顿 到 内存优化.内存分析工具大概十五六篇,并对此做一个 ...
- Android客户端性能优化(魅族资深工程师毫无保留奉献)
本文由魅族科技有限公司资深Android开发工程师degao(嵌入式企鹅圈原创团队成员)撰写,是degao在嵌入式企鹅圈发表的第一篇原创文章,毫无保留地总结分享其在领导魅族多个项目开发中的Androi ...
- Android UI性能优化实战, 识别View中的性能问题
出自:[张鸿洋的博客]来源:http://blog.csdn.net/lmj623565791/article/details/45556391 1.概述 2015年初google发布了Android ...
- 转 iOS和android游戏纹理优化和内存优化(cocos2d-x)
iOS和android游戏纹理优化和内存优化(cocos2d-x) (未完成) 1.2d游戏最占内存的无疑是图片资源. 2.cocos2d-x不同平台读取纹理的机制不同.ios下面使用CGImage, ...
- android app性能优化大汇总(内存性能优化)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 写在最前: 本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上 ...
随机推荐
- zabbix通过snmp监控vmware vpshere5.5
https://www.iyunv.com/thread-516343-1-1.html
- MYSQL的内外连接
1.内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符).包括相等联接和自然联接. 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 stude ...
- HDU1009:FatMouse' Trade(初探贪心,wait)
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containi ...
- DP重开
颓了差不多一周后,决定重开DP 这一周,怎么说,学了学trie树,学了学二叉堆,又学了学树状数组,差不多就这样,然后和cdc一番交流后发现,学这么多有用吗?noip的范围不就是提高篇向外扩展一下,现在 ...
- 4、Flask实战第4天:自定义url转换器
url传参可以限定参数的数据类型,例如:限定user_id数据类型为int @app.route('/user/<int:user_id>') def my_list(user_id): ...
- UOJ Rounds
UOJ Test Round #1 T1:数字比大小的本质是按(长度,字典序)比大小. T2:首先发现单调性,二分答案,用堆模拟,$O(n\log^2 n)$. 第二个log已经没有什么可优化的了,但 ...
- 【动态规划】【记忆化搜索】CODEVS 1011 数的计算 2001年NOIP全国联赛普及组
设答案为f(n),我们显然可以暴力地递归求解: f(n)=f(1)+f(2)+……+f(n/2). 但是n=1000,显然会超时. 考虑状态最多可能会有n种,经过大量的重复计算,所以可以记忆下来,减少 ...
- 安网讯通签约孟强美容CRM
整形美容CRM软件是辽宁安网讯通有限公司为孟强整形医院定制开发的一套客户关系管理软件,软件专门针对整形美容行业专科门诊的需求,能满足大中小整形美容机构或或各种专科科室的日常业务需求. 主要功能包括: ...
- mormot 数据集和JSON互相转换
mormot 数据集和JSON互相转换 uses SynVirtualDataSet, mORMotMidasVCL, SynCommons; procedure TForm1.Button1Clic ...
- ajax请求不能下载文件(转载)
最近在做文件下载,后台写了个控制层,直接走进去应该就可以下载文件,各种文件图片,excel等 但是起初老是下载失败,并且弹出下面的乱码: 前台请求代码: $('#fileexcel').unbind( ...