1)访问非私有(private)变量
代码:
class A{
public static int psi=-5; //类变量
static int si=-1; //类变量(包)
private static int ptsi=5; //类变量(私有)
protected static int prsi = 1100; //类变量(保护)
public int pi = 100; //实例变量
int i = 1001; //实例变量(包)
private int pti = 1002; //实例变量(私有)
protected int pri = 1003; //实例变量(保护)
}
class B{
public static void main(String[] args){
A a = new A();
System.out.println( a.psi );
System.out.println( a.si );
System.out.println( a.prsi );
System.out.println("--------------------------");
System.out.println(A.psi );
System.out.println(A.si );
System.out.println(A.prsi );
System.out.println("---------------------------");
System.out.println(a.pi );
System.out.println( a.prsi );
}
}
编译后:生成B.class和A.class两个文件,B.class反编译的结果如下:
class B
{
B()
{
}
public static void main(String args[])
{
A a = new A();
A _tmp = a;
System.out.println(A.psi);
A _tmp1 = a;
System.out.println(A.si);
A _tmp2 = a;
System.out.println(A.prsi);
System.out.println("--------------------------");
System.out.println(A.psi);
System.out.println(A.si);
System.out.println(A.prsi);
System.out.println("---------------------------");
System.out.println(a.pi);
A _tmp3 = a;
System.out.println(A.prsi);
}
}
结论:
在B中,通过类访问静态变量和通过实例访问变量,增加了几个类型转换!
2)访问私有变量
代码:
public class A {
public static int psiA= 10; //类变量
static int siA=110; //类变量(包)
private static int ptsiA=1110; //类变量(私有)
protected static int prsiA = 11100; //类变量(保护)
public int piA = 1000; //实例变量
int iA = 1001; //实例变量(包)
private int ptiA = 1002; //实例变量(私有)
protected int priA = 1003; //实例变量(保护)
//内部类(静态成员类)
public static class INB{
public INB(){
}
public static int psiB=20; //类变量
static int siB=220; //类变量(包)
private static int ptsiB=2220; //类变量(私有)
protected static int prsiB = 22220; //类变量(保护)
public void output(){
A tmp = new A();
System.out.println("CLASS A");
System.out.println( A.psiA ); //访问包含类A的类变量(public)
System.out.println( tmp.siA ); //package
System.out.println( tmp.ptsiA); //private
System.out.println( A.ptsiA=9 );
//System.out.println( tmp.ptsiA=10 ); //在内部类里 实例可以对所有类变量赋值 在对私有类变量赋值时 导致反编译器出错
System.out.println( tmp.ptiA =-4); //访问类A的私有实例变量 并赋值
System.out.println( tmp.priA =6 );
}
public static void main(String[] args ){
INB t1 = new INB();
t1.output();
}
}
public static void main(String[] args ){
INB b = new INB();
b.output();
System.out.println(INB.ptsiB );
}
}
编译后:
生成2个文件A.class 和 A$B.class。A.class文件反编译结果:
public class A
{
public static class INB
{
public void output()
{
A a = new A();
System.out.println("CLASS A:");
System.out.println(A.psiA);
A _tmp = a;
System.out.println(A.siA);
System.out.println(A.ptsiA);
System.out.println(A.ptsiA = 9);
System.out.println(a.ptiA = -4);
System.out.println(a.priA = 6);
}
public static void main(String args[])
{
INB inb = new INB();
inb.output();
}
public static int psiB = 20;
static int siB = 220;
private static int ptsiB = 2220;
protected static int prsiB = 22220;
public INB()
{
}
}
A$INB.class反编译的结果:
public A()
{
piA = 1000;
iA = 1001;
ptiA = 1002;
priA = 1003;
}
public static void main(String args[])
{
INB inb = new INB();
inb.output();
System.out.println(INB.ptsiB);
}
public static int psiA = 10;
static int siA = 110;
private static int ptsiA = 1110;
protected static int prsiA = 11100;
public int piA;
int iA;
private int ptiA;
protected int priA;
public static INB m = new INB();
}
public static class A$INB
{
public void output()
{
A a = new A();
System.out.println("CLASS A:");
System.out.println(A.psiA);
A _tmp = a;
System.out.println(A.siA); //通过实例访问类变量,自动转换成了类访问
System.out.println(a.access$000()); //通过实例对包含类A的私有类变量访问
System.out.println(A.access$002(9)); //直接对包含类A的私有类变量赋值
System.out.println(A.access$102(a, -4)); //对私有实例变量赋值 自动生成了类方法进行访问
System.out.println(a.priA = 6); //对保护实例变量赋值
}
public static void main(String args[])
{
A$INB a$inb = new A$INB();
a$inb.output();
}
public A$INB()
{
}
}
结论:
1.对私有变量的访问,编译器自动产生非私有的访问方法(类方法或实例方法),并且把访问私有成员的表达式转换成这些方法的表达式!
2.acess$XXXX方法由编译系统生成,后面两位数字应该代表操作类型,前面的数字代表私有变量编号
3.在程序中,无论是类方法还是实例方法,你都不能创建acess$XXXX() (XXXX为数字)的方法!
4.程序中被注解掉的System.out.println( tmp.ptsiA=10 )可以编译通过,但是反编译的时候居然使反编译程序出错了,所以%^&*()