对象的发布与逸出

对象的发布

“发布对象”指的是使对象能够在当前作用于之外的代码中使用

例如,将一个指向该对象的引用保存到其他代码可以访问的地方(情况一),或者在某一个非私有的方法中返回该引用(情况二),或者将引用传递到其他类的方法中(情况三)。

//情况一
public class Person(){
    private String name;
    private int age;
}

public class Record{
    Person p;
}

//情况二
public class Person(){
    private String name;
    private int age;

    public Person get(){
        return new Person();
    }
}

//情况三
public class Person(){
    private String name;
    private int age;
}

public class Record{
    private void getPersonMessage(Person p){
        .....
    }
}
对象逸出

当某个不应该发布的对象被发布时,这种情况就被称为“对象逸出”。

常见的对象逸出:

  • 内部的可变状态逸出
class UnsafeStates{
    private String[] states = {"AK","AL",...};
    public String[] getStates(){
        return states;
    }
}

如上,数组states本事私有的变量,但是以public公有的方式发布出去,导致states已经逸出了它所在的作用域,任何调用者都能修改这个数组的内容。

  • 隐式地使this引用逸出
public class ThisEscape{
    public ThisEscape(EventSource source){
        source.registerListener(
            new EventListener(){
                public void onEvent(Event e){
                    dosomething(e);
                }
            })
    }
}

实际上,这里是需要发布内部类实例,而这样的做法导致当ThisEscape发布EventListener时,也隐含地发布了ThisEscape实例本身。因为在这个内部类的实例中包含了对ThisEscape实例的隐含引用。

这样的逸出会出现什么问题呢?

public class ThisEscape{
    private int count;
    public ThisEscape(EventSource source){
        source.registerListener(
            new EventListener(){
                public void onEvent(Event e){
                    dosomething(e);
                }
            })
        //在这里count初始化为1
        count = 1;
    }
}

举个例子,如上,我们知道this逸出会导致ThisEscape也发布出去,也就是ThisEscape还没有构建完成就发布出去,也就是count=1;这一句还没执行就发布了ThisEscape对象,如果要使用count时,很有可能会出现对象不一致的状态。

那么如何解决这个问题呢?
使用工厂方法来防止this引用在构造函数过程中逸出

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;
    }
}

如此,便能保证在对象为构造完成之前,是不会发布该对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,347评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,906评论 18 399
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 12,378评论 2 17
  • 并发编程简介 上古时期的计算机没有操作系统,它们从头到尾只运行一个程序。这个程序独占计算机上所有的资源。只有当一个...
    EakonZhao阅读 4,721评论 2 6
  • 1 你怀着忐忑,又极度兴奋的心情,走进了一家公司大门。 你满脑子的疑问,我的座位在哪儿、谁领导我、我的同事是谁、中...
    闪客星球阅读 1,872评论 0 1