我正在测试下面的代码段,我需要知道如何访问t.x或t.hello?它的范围是什么? 开发人员是否以这种方式定义变量?
public class Test{
public Test(){
System.out.print("constructor\n");
}
public static void main(String[] args) {
Test t = new Test(){
int x = 0;
//System.out.print("" + x);
void hello(){
System.out.print("inside hello\n");
}
};
}
修改
但为什么这个片段有效
Thread tr = new Thread() {
int loops = 1;
@Override
public void run() {
loops += 1;
}
};
tr.start();
答案 0 :(得分:3)
你应该区分声明和定义。
在你的情况下,你声明一个类Test
的变量,并将它分配给从Test
派生的某个类的对象(它是一个匿名类),其中包含一些额外的东西。
此定义后的代码仅显示t
类的Test
,它对x
和hello
一无所知,因为Test
没有它们。
因此,除了反射之外,在定义匿名类之后,您不能使用x
和hello
。是的,开发人员在定义中需要这些变量时会使用这些变量。
有人提到你可以在定义后立即调用方法并访问不属于Test
的变量:
int y = new Test(){
int x = 0;
//System.out.print("" + x);
void hello(){
System.out.print("inside hello\n");
}
}.x;
这可以做到,因为此时对象的类型是知道的(它是匿名类)。只要将此对象分配给Test t
,就会丢失此信息。
答案 1 :(得分:1)
您的代码会创建anonymous inner class。它(或多或少)相当于这样做:
public class Test {
// ...
private class TestAnonymousInner extends Test {
int x = 0;
//System.out.print("" + x);
void hello(){
System.out.print("inside hello\n");
}
}
public static void main(String[] args) {
Test t = new TestAnonymousInner();
// invalid:
// t.hello();
}
}
如果查看该文件的编译器输出,您会注意到一个名为Test$1.class
的文件 - 这是您定义的匿名类。
由于您存储实例的变量属于Test
类型,因此无法通过它访问这些字段。它们可以通过反射或构造函数表达式访问。例如。 the following works,虽然它不是特别有用:
new Test() {
void hello() {
System.out.println("hello()");
}
}.hello(); // should print "hello()"
Re:你的编辑。 start()
是Thread
的一种方法。变量tr
也是Thread
类型,因此您可以调用其方法。不是你在AIC中添加的方法。
答案 2 :(得分:1)
它创建了一个匿名内部类。在这种情况下它几乎没有用处。匿名类通常用于实现接口而不创建全新的类。执行此操作时,您可以根据需要添加任意数量的成员。例如:
Runnable r = new Runnable() {
int i = 0;
public void run() {
System.out.println(i++);
}
};
通过这样做,您已经为Runnable接口的实现添加了一个计数器(没有这样的字段),并且每次调用r.run();
时都会打印增量值。
使用类似模式的一个较少人为的例子:
private final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
private final AtomicInteger threadId = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "Thread #" + threadId.incrementAndGet());
}
});
这里提供了ThreadFactory的基本实现,它命名每个新的线程Thread #i
。
答案 3 :(得分:1)
如上所述,在t引用的对象之外都不能访问x和hello。问题是它们只在t的匿名类中声明。它们没有在Test中定义,也不可能将t引用转换为声明它们的类型,因为它是匿名的。
我修改了Test以使其抽象并添加一个hello的抽象声明,允许从t引用的对象外部调用它。我还修改了hello来添加x的使用。这些更改说明了访问匿名类功能的两种方法 - 通过基类或内部。
public abstract class Test {
abstract void hello();
public Test() {
System.out.print("constructor\n");
}
public static void main(String[] args) {
Test t = new Test() {
int x = 0;
// System.out.print("" + x);
void hello() {
System.out.print("inside hello\n");
System.out.print("My value of x is "+x);
}
};
t.hello();
}
}