我将一个接口作为匿名实现传递给另一个像这样的对象:
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
如何知道未直接传递给对象的数组(数组不是匿名类的成员)。
更新
(抱歉迟到了)
匿名类中使用的成员变量或方法方法呢?他们不是最终的
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;
}
};
答案 0 :(得分:2)
我的问题是如何运作的? SomeObject如何知道数组 它不直接传递给对象(数组不是 匿名课程。)
array
为最终版。如何使用成员变量或方法中使用的方法 匿名课?他们不是最终的
答案 1 :(得分:2)
因为,方法局部变量直接在方法块中声明,所以它只在方法中可见,从声明后的下一个语句开始。通过方法本地,我指的是在方法内声明但在该方法中可能出现的任何其他块(例如while { /* not here */ }
)之外的变量。
如果你看到,你的匿名类在array
声明后也被定义为同一方法中的本地类。这就是为什么课堂上可以看到它。
你需要让array
final
能够在匿名类中使用它的原因是局部变量只存在于方法存在之前但是本地类的对象可能活得更久(即使在方法完成后)。
答案 2 :(得分:1)
这是Java的范围和可见性规则的一部分。在您当前的示例中,它称为Closure。基本上,块中定义的所有内容都在该块内可见。例如,这是有效的Java代码(方法中的任何位置):
{
final int i = 5;
// do somthing with i
}
// cant refernce i here
{
final int i = 6;
// do somthing with i
}
// cant refernce i here
由于你在块中定义了一个新类(如果你只是实例化它我不会工作)它会看到在同一个块中声明的所有内容。 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);
}
};
它不起作用(试试)。
答案 3 :(得分:0)
您正在将对数组具有访问权限的对象接口传递给SomeObject方法。
所以SomeObject正在使用你在main上传递的相同对象接口。
由于Interface可以访问该阵列,因此可以使用它。
不是SomeObject正在使用该数组。它是Interface对象。
答案 4 :(得分:0)
Java保留对内部类中使用的封闭类的所有(最终)对象的引用。如果你想知道这个技巧是如何使用maid,请将以下行添加到Test方法:
System.out.println(inter.getClass().getDeclaredConstructors()[0].getParameterTypes()[0].getCanonicalName()
你的输出将是“int []”
因此,编译器简单地为内部类创建一个构造函数并将其传递给它所需的字段
答案 5 :(得分:0)
编译器将最终变量视为常量,并在编译时将相应变量的值替换为匿名类。以下主题提供了很好的细节:
Cannot refer to a non-final variable inside an inner class defined in a different method