Java 通过匿名类

Java 通过匿名类,java,Java,我将一个接口作为匿名实现传递给另一个对象,如下所示: public interface Interface { public int convert (int a); } public static void main(String[] args) throws IOException, InterruptedException { final int[] array = {1,6,3,5,7,8,4,0,3}; Interface inter = new Int

我将一个接口作为匿名实现传递给另一个对象,如下所示:

public interface Interface {
    public int convert (int a);
}



public static void main(String[] args) throws IOException, InterruptedException {

    final int[] array = {1,6,3,5,7,8,4,0,3};
    Interface inter = new Interface() {         
        public int convert(int a) {
            int result = a;             
            for (int i = 0; i < array.length; i++) {
                a=a+array[i];
            }               
            return a;
        }
    };

    SomeObject ty = new SomeObject ();
    ty.Test(7, inter);
}

public class SomeObject {   

    public void Test(int number, Interface inter) {             
        System.out.println(inter.convert(number));
    }
}
我的问题是它是如何工作的?SomeObject如何知道数组 不会直接传递给对象(数组不是 匿名类)

  • 回答:没有;除非您将
    数组
    声明为最终值
  • 推理:它有效(如果数组是final),因为它是final,所以可以像常量一样处理,因为匿名函数知道 无法更改数组
中使用的成员变量或方法如何 匿名班?它们不是最终的

Interface inter = new Interface() {         
    public int convert(int a) {
        int result = a + someMemberVar;             
        for (int i = 0; i < array.length; i++) {
            a=a+array[i];
        }               
        return a;
    }
};
  • 答案:创建匿名类时,实例变量和方法(以及静态变量和方法)无论如何都在范围内

因为,方法局部变量是直接在方法块内声明的,它仅在方法内可见,从声明后的下一条语句开始。所谓方法局部,我指的是在方法内部声明的变量,但在可能出现在该方法中的任何其他块(例如,
,而{/*nothere*/}
)外部声明的变量

如果您看到,您的匿名类也被定义为
数组
声明之后相同方法中的本地类。这就是为什么它对类可见


您需要创建
数组
final
以便能够在匿名类中使用它的原因是局部变量仅在方法存在之前存在,但局部类的对象可能存在更长的时间(即使在方法完成之后).

您正在将有权访问数组的对象接口传递给SomeObject方法

所以SomeObject使用的对象接口与您在main上传递的对象接口相同

因为接口可以访问阵列,所以可以使用它


使用数组的不是某个对象。它是接口对象。

Java保留对内部类中使用的封闭类的所有(最终)对象的引用。如果您想知道这个技巧是如何实现的,请在测试方法中添加以下行:

System.out.println(inter.getClass().getDeclaredConstructors()[0].getParameterTypes()[0].getCanonicalName()
您的输出将是“int[]”


因此,简单编译器为内部类创建一个构造函数,并将所需的字段传递给它

这是Java作用域和可见性规则的一部分。在您当前的示例中,它被称为。基本上,块中定义的所有内容在该块中都是可见的。例如,这是有效的Java代码(方法中的任意位置):

由于您在块内定义了一个新类(如果您只是实例化它,我将无法工作),因此它会看到在同一块中声明的所有内容。Java对它的唯一限制是,您不能在第一次赋值后更改值,以避免引用“转义”其块时出现问题(多线程、寿命长于声明块等)。如果声明final方法的参数,也可以使用它们,因为它们是在同一块中定义的

所以如果你把代码改成这个

      {
          final int[] array = {1,6,3,5,7,8,4,0,3};
      }
      Object inter = new Object() 
      {           
          public void test() 
          {
              System.out.println(array);
          }
      };

它不起作用(试试看)。

编译器将最终变量视为常量,并在编译时将相应变量的值替换到匿名类中。以下线程提供了极好的详细信息:

行的目的是什么
int result=a?因此当前状态下的整个数组作为常量传递给SomeObject?只有对数组对象的引用传递给匿名类。如果声明方法更改了数组元素,匿名类将看到这一点。@Jonathan您能详细介绍一下可见性吗?这不仅仅是因为它是最终的-1(可见性解决后将删除)匿名类可以访问其封闭方法的最终变量I删除最终相关的填充可见性实际上也受到块的限制。所以它不是方法中的局部变量,而是必须在同一块中。@Stefan:谢谢。将其从“仅本地”更改为“方法本地”。
      {
          final int[] array = {1,6,3,5,7,8,4,0,3};
      }
      Object inter = new Object() 
      {           
          public void test() 
          {
              System.out.println(array);
          }
      };