public class Test {
public static void main(String... args) {
class MyInner {
private int value = 10;
}
MyInner inner = new MyInner();
System.out.println(inner.value);
}
}
public class AccessAnonymous {
private Runnable runnable; // to have instance of the class
public static void main(String[] args) throws Exception {
AccessAnonymous a = new AccessAnonymous();
a.a(); // init field
Class clazz = a.runnable.getClass();
Field field = clazz.getDeclaredField("i");
field.setAccessible(true);
int int1 = field.getInt(a.runnable);
System.out.println("int1=" + int1);
}
public void a() {
runnable = new Runnable() {
private int i = 1;
public void run() {
i = 90;
}
};
runnable.run();// change value
}
}
public class MyService {
public Result doSomething() {
Result result = new Result();
result.setToday(today();
return result;
}
// not private but package-private so it can be overridden
Date today() {
return new Date();
}
}
下面是单元测试:
public class MyServiceTest {
private Date capturedToday;
// anonymous inner class
private final MyService testSubject = new MyService() {
@Override
Date today() {
// capture the Date instance created by MyService
Date today = super.today();
MyServiceTest.this.capturedToday = today;
return today;
}
};
@Test
void myTest() {
MyResult result = testSubject.doSomething();
assertSame(capturedToday, result.getToday());
public static void main(String[] args) {
var annon = new Object() {
int field;
void method() {
System.out.println("method called with field=" + field);
}
};
annon.field = 123;
annon.method(); // prints "method called with field=123"
}
如果成员声明为static,这也有效。 如果我们声明了Object annon = new Object() { ...,我们会得到编译错误,因为Object没有任何field或method()成员。
9条答案
按热度按时间8ulbf1ek1#
匿名内部类有类型但没有名称。
可以访问未由命名超类型定义的字段。但是,一旦分配给命名类型变量,接口就会丢失。
显然,您可以从内部类本身访问这些字段。添加代码的一种方法是通过示例初始化器:
由匿名内部类表达式返回的值具有匿名类型,因此您有一次机会在类本身之外使用它:
你也可以通过一个方法来传递它,该方法的声明类似于:
lpwwtiir2#
可以使用本地类代替匿名类。你看:
但是,只能在方法体中引用
MyInner
类型。因此,在方法之外,您将无法使用未在其超类(本例中为java.lang.Object
)或接口中声明的字段/方法。qni6mghb3#
m1m5dgzv4#
在匿名类的情况下,在类引起的混乱和匿名的便利性之间也有一个折衷。复杂的类很少属于匿名类,而是命名的私有内部类。
在大多数匿名类中,我们只需要“喂养”知识,并且可以在构建时完成。在一些匿名类(例如,返回值载体)中,我们也关心一个返回值。
正如我们所知,数据成员不应该被直接访问,而应该使用getter setter。如果你发现自己在添加了很多getter和setter的情况下,你可能做错了什么,不应该使用匿名类。
lskq00tm5#
如果它实现了一个接口或扩展了一个现有类,则可以访问在接口或基类中定义的成员。
j0pj023g6#
Fooz先生是对的,除了接口只能定义常量成员。最好的方法是在接口中添加getter/setter方法,然后使用它们来获取值。但是对于每个匿名类,你必须定义那些方法(有点痛苦)。
a5g8bdjr7#
如果你想要可读的、可维护的代码,不要使用匿名类。如果你使用匿名类,并且想要可读的、可维护的代码,那么当你需要访问内部类中的元素时,不要使用匿名类。有很多方法可以做到这一点,但我请求你不要使用任何这些黑客。可读性胜过所有其他优点。
s8vozzvw8#
这个问题已经有15年的历史了,但我认为还有另一种方法可以做到这一点!
该示例涉及为MyService编写单元测试:
下面是单元测试:
在本例中,MyService在内部创建了一个Date,并将其设置在结果上。为了检查这个逻辑,我创建了一个匿名内部类,它在创建示例时捕获示例并将其存储在capturedToday字段中:
此语法允许内部类访问其外部类的字段,从而公开其值。
ubof19bj9#
如果使用
var
,则可以从声明了匿名类的块(或子块)内部访问匿名类的成员。范例:如果成员声明为
static
,这也有效。如果我们声明了
Object annon = new Object() { ...
,我们会得到编译错误,因为Object
没有任何field
或method()
成员。