Java QA

1. 为什么在某方法内定义一个匿名内部类,并且希望它使用外部定义的对象,那么要求此方法的参数引用要声明为final?

这是一个编译器设计的问题,如果你了解java的编译原理的话很容易理解。首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并不与外部类在同一class文件中。当外部类传的参数被内部类调用时,从java程序的角度来看是直接的调用例如:

public void dosome(final String a,final int b){  
     class Dosome{
          public void dosome(){
              System.out.println(a+b)
          }
     };  
     Dosome some=new Dosome();  
     some.dosome();  
}

从代码来看好像是那个内部类直接调用的a参数和b参数,但是实际上不是,在java编译器编译以后实际的操作代码是

class Outer$Dosome{  
    public Dosome(final String a,final int b){  
        this.Dosome$a=a;  
        this.Dosome$b=b;  
    }  
    public void dosome(){  
        System.out.println(this.Dosome$a+this.Dosome$b);  
    }  
}

从以上代码看来,内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。

这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。

2. Java参数传递

JAVA的参数传递总是传”值”,但是传值方式也分为两种方式,它们是靠传递参数的类型区分的。这两种类型分别为JAVA的基础类型和Object(对象)类型;基础类型包括boolean,byte,short,char,int,long,float,double,而Object就是对象,如数组。
此时结果的输出将是1,而且只要你的值在Main函数中没变,a的值不管怎么传都不回变,这是因为a是传值,而这个”值”是a的一个拷贝,a的值在传递后的改变只是改变了a的拷贝的内容,并没有改变真正的a的值。

public class A{                                  
     public static void main(String arg[]){    
       int[] a=new int[1];                               
       a[0]=3;                                             
       method1(a);                                       
       System.out.println(a[0]);                      
     }                                          
     public static void method1(int[] a){        
      a[0]--;                                                  
     }                                                          
}
public class A{
     public static void main(String arg[]){    
       int[] a=new int[1];                               
       a[0]=3;                                             
       method1(a);                                       
       System.out.println(a[0]);                      
     }
     public static void method1(int[] a){
       a=new int[0];
       a[0]=4;
     }
}

上边的结果将是2,下边的结果将是3(未变),原因是:在传递的参数为对象时,这个传递的”值”中放的内容实际上是对向所在的地址,上边的情况是指针定位到对象的地址后,在上面把内容给改了,所以数组的值后会改变,而下边的情况为给对象新分配了一个指针到新的地址上面去,所以所有的操作都在新的地址上面,并不会影响原来的值。注:对于String,Interger,Boolean,Double等的系统对象,它们虽然是Object,但是任何方式的传递参数的值得改变并不会影响原来的值。

1 week ago, this page was being read.

,

Subscribe to Comments