class A{ 
  private static int i; 
  //内部类
  class B
      { 
        private int k=333; 
        B(){i=8;}//修改外部类的i 
    } 
        
        
  public void f(){ 
        B bb=new B(); 
  } 
      
  public static void main(String[] args){ 
          A aa=new A(); 
          aa.f(); 
          System.out.println(i); 
          System.out.println(new A().new B().k);   //这里怎么可以直接访问内部类数据成员,这不破坏了封装了吗??
  } 

解决方案 »

  1.   

    因为你的main()在 A内部定义的,写到外部就不能访问了!
      

  2.   

    new A().new B().k============
    new A之后返回一个A的对象,A的对象当然能访问类A中的非私有性质的任何东西了。。
    B在类A中是default属性的,所以A的对象当然能够去利用它再进行构造B的对象!至于后面的.k就不用我说了吧?
      

  3.   

    服了楼主,老弄这些问题折磨人,以下是我 javap 的结果,能说明原因:测试代码:
    public class A { public static class B {
    private int i = 333;
    } public static void main(String[] args) {
    int n = 0;
    B t = new B();
    n = t.i;
    }}javap 结果:
    javap -c -private A
    Compiled from "A.java"
    public class A extends java.lang.Object{
    public A();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   returnpublic static void main(java.lang.String[]);
      Code:
       0:   iconst_0
       1:   istore_1
       2:   new             #2; //class A$B
       5:   dup
       6:   invokespecial   #3; //Method A$B."<init>":()V
       9:   astore_2
       10:  aload_2
       11:  invokestatic    #4; //Method A$B.access$000:(LA$B;)I  //调用 B 的静态方法 access$000
       14:  istore_1
       15:  return}javap -c -private A$B
    Compiled from "A.java"
    public class A$B extends java.lang.Object{
    private int i;public A$B();
      Code:
       0:   aload_0
       1:   invokespecial   #2; //Method java/lang/Object."<init>":()V
       4:   aload_0
       5:   sipush  333
       8:   putfield        #1; //Field i:I
       11:  returnstatic int access$000(A$B);  //编译器添加的静态方法,用于访问参数传入的内部类 B 对象的私有实例域 i 的值
      Code:
       0:   aload_0
       1:   getfield        #1; //Field i:I
       4:   ireturn}请注意类 A 的内部类 B,看似只有一个私有实例域 i,但实际上为了使 main 方法中能访问到 i 的值编译器又动了手脚,它给你加了个方法,使代码变成了下面这个样子:public class A { public static class B {
    private int i = 333;
    static int access$000(A$B t) { return t.i; }  //编译器加上的
    } public static void main(String[] args) {
    int n = 0;
    B t = new B();
    n = B.access$000(t);  //编译器改造后的 n = t.i;
    }}这就是“破坏封装”的原因。
      

  4.   

    javap
      是什么东东啊??
       我喜欢在基础上做到彻底理解.谢谢大家的理解
      

  5.   

    javap -c 类文件名
    可以得到class文件的字节码指令表示。