developer.android.com 文档中有一篇关于性能的文章,里面提到了内部类的使用。文章建议“对于私有内部类 使用 包访问权限代替私有权限访问”,
这里说的是在内部类访问外部类的成员或方法时如果 内部类是私有的并且外部类的成员也是私有的,那么编译器就会为内部类在外部类中增加一个静态方法。
真的是这样的吗?只有试一试才知道。
我们使用一个简单的例子来测试下:
public class One {
private int a;
private 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 : 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.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)
如果外部类的成员是包访问的,内部类是私有的同样也不会产生附加的方法。
内部类对外部类成员的访问是不能直接访问私有成员的,编译器会增加额外的辅助方法,避免的方法是修改外部类的成员为包访问,文档中也提到了这会在一定程度上破坏
封装。
原文:http://blog.csdn.net/liulipuo/article/details/26028547