通过匿名类进行封闭对象转义的参考-java
我正在阅读 Java 并发实践,下面的例子就是来自其中。我的问题是 这个引用转义是什么意思?会出现什么问题呢? 。 this 引用如何从 doSomething(e) 中转义。
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
);
}
}
这是如何解决问题
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
编辑:
我已经尝试了以下示例
public class Escape {
public Escape( Printer printer ){
printer.print(new Escaper(){
@Override
public void parentData(){
theCulprit1(Escape.this);
}
public String name = "shal";
@Override
public void theCulprit(){
System.out.println( this.name );
System.out.println( Escape.this.age );
}
});
canAccess();
}
public void canAccess(){
this.age = "25";
}
public String age = "62";
@SuppressWarnings("unused")
public static void main(String args[]){
Escape escape = new Escape(new Printer());
}
}
class Printer{
public void print(Escaper escaper){
escaper.theCulprit();
escaper.parentData();
}
}
class Escaper{
public void parentData(){
}
public void theCulprit(){
}
public void theCulprit1(Escape escape){
System.out.println(escape.age);
}
}
由于转义对象的构造不完整 该输出应 62 62
当我像这样更改我的代码时
public class Escape {
private final Escaper escaper;
private Escape( ){
escaper = new Escaper(){
@Override
public void parentData(){
theCulprit1(Escape.this);
}
public String name = "shal";
public void theCulprit(){
System.out.println( name );
System.out.println( age );
}
};
canAccess();
}
public void canAccess(){
age = "25";
}
public String age = "62";
public static Escape newInstance( Printer printer){
Escape escape = new Escape();
printer.print(escape.escaper);
return escape;
}
@SuppressWarnings("unused")
public static void main(String args[]){
Escape.newInstance(new Printer());
}
}
,它输出shal 25 25
我说得对吗? 另外,是否有任何操作重新排序,因为在第一个示例中,年龄被初始化为 62。 即使在我的第二个示例中没有将 escaper 字段设为最终值,它也能正常工作!
I am reading Java concurrency in practice and the below examples are from that. And my questions are
What do they mean by this reference escape?. What will be the problem? . How does the this reference escapes from doSomething(e).
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
);
}
}
How does this solves the problem
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
Edit :
I have tried the below examples
public class Escape {
public Escape( Printer printer ){
printer.print(new Escaper(){
@Override
public void parentData(){
theCulprit1(Escape.this);
}
public String name = "shal";
@Override
public void theCulprit(){
System.out.println( this.name );
System.out.println( Escape.this.age );
}
});
canAccess();
}
public void canAccess(){
this.age = "25";
}
public String age = "62";
@SuppressWarnings("unused")
public static void main(String args[]){
Escape escape = new Escape(new Printer());
}
}
class Printer{
public void print(Escaper escaper){
escaper.theCulprit();
escaper.parentData();
}
}
class Escaper{
public void parentData(){
}
public void theCulprit(){
}
public void theCulprit1(Escape escape){
System.out.println(escape.age);
}
}
Due to incomplete construction of the escape object
This outputs shal
62
62
Where as i changed my code like this
public class Escape {
private final Escaper escaper;
private Escape( ){
escaper = new Escaper(){
@Override
public void parentData(){
theCulprit1(Escape.this);
}
public String name = "shal";
public void theCulprit(){
System.out.println( name );
System.out.println( age );
}
};
canAccess();
}
public void canAccess(){
age = "25";
}
public String age = "62";
public static Escape newInstance( Printer printer){
Escape escape = new Escape();
printer.print(escape.escaper);
return escape;
}
@SuppressWarnings("unused")
public static void main(String args[]){
Escape.newInstance(new Printer());
}
}
Where as here.It outputs shal
25
25
Am i right ?
Also is there any re-ordering of operations, because in the first example the age got initialized to 62.
Even without making the escaper field final in my second example it works !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在第一种形式中,事件侦听器对象在构造函数内注册到事件源,因此在构造函数完成之前,它使自身(并通过关联“this”对象)可用于事件源。如果内部类对象逃逸,外部对象也会逃逸。
为什么这是一个问题?一旦注册了事件监听器,事件源就可以随时调用其方法。想象一下事件源正在使用的线程开始调用事件侦听器方法。现在甚至可以在构造函数完成之前发生这种情况。
但是,由于可见性问题,这个问题比看起来更严重。即使您将注册作为构造函数执行的“最后一个操作”,仍然有可能看到部分构造的对象或对象处于无效状态。如果没有正确的happens-before排序,根本就没有可见性保证。
声明它是最终的可以在订购之前发生(因此是第二种形式)。
In the first form, the event listener object gets registered to the event source within the constructor, and thus it makes itself (and by association the "this" object) available to the event source before the constructor completes. If the inner class object escapes, so does the outer object.
Why is this a problem? Once the event listener is registered, the event source may invoke its methods at any time. Imagine a thread that the event source is using starts invoking the event listener methods. This now can happen even before the constructor completes.
This problem is worse than it appears, however, due to visibility issues. Even if you make the registration the "last operation" that the constructor does, there is still the possibility of seeing partially constructed object or an object in an invalid state. There is simply no visibility guarantee in the absence of a proper happens-before ordering.
Declaring it final affords that happens-before ordering (thus the second form).
当你有一个非静态的内部类时,就像
内部类有一个引用外部类的隐藏字段一样,所以你可以想象它是这样的
所以无论在哪里使用内部对象,外部对象都是可引用的,并且因此它的生命周期至少和内部对象一样长。
when ever you have an inner class that is not static, like
the inner class has a hidden field that references the outer class, so you can imagine that it is like this
So whereever the inner object is used, the outer object is referenceable, and thus it's lifetime is at least as long as the inner object.