在构造函数中传递此变量

时间:2018-12-29 02:25:46

标签: java constructor

我遇到了一些JMS调用代码,这些代码在其构造函数内部初始化JMS会话。调用代码实现ExceptionListener接口,并将对 this 的引用传递给连接工厂对象,如下所示:

public class JmsCode implements ExceptionListener {

    private static final Logger logger = LoggerFactory.getLogger(JmsCode.class);

    public JmsCode(String url, String username, String password, String trustStorePath, char[] trustStorePassword) throws JMSException {
        ActiveMQSslConnectionFactory connectionFactory = new ActiveMQSslConnectionFactory(url);
        connectionFactory.setUserName(username);
        connectionFactory.setPassword(password);
        connectionFactory.setTrustStore(trustStorePath);
        connectionFactory.setTrustStorePassword(new String(trustStorePassword));
        connectionFactory.setExceptionListener(this);

        Connection connection = connectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    }

    @Override
    public void onException(JMSException e) {
        logger.error("Unexpected JMS exception caught", e);
    }

}

我想知道从JmsCode构造函数传递对 this 的引用是否安全,因为该对象尚未完全构建。我遇到了类似的question,让我阅读了IBM's article on not publishing this during construction。尽管我同意他们的推理,但我不确定它是否适用于这种情况,因为异常侦听器唯一要做的就是通过静态成员和最终成员进行记录。上面的代码是否安全(忽略其他人试图更改异常侦听器方法以使用对象的某些实例状态)?

3 个答案:

答案 0 :(得分:1)

这实际上是不安全的发布,并且从理论上讲,另一个对象可能会看到该对象处于不一致状态。

也就是说,尽管这不是一个好的模式(这里只是展示ExceptionListener),但构造函数的逻辑表明该类实际上是在{{ 1}}引用转义(因为它没有要构造的),因此在这种情况下,没有任何错误。

答案 1 :(得分:0)

是否安全取决于对this的引用可以在哪里逃脱 to 。如果作为此调用的结果,this可以被另一个线程读取,那么它是不安全的。

如果要确保实例完全初始化以进行安全发布 ,并且要发布实例,则构造函数不是发布它的正确位置。相反,您需要创建一个Factory对象或静态工厂方法,以安全地构造该对象,然后在将其返回给调用方之前将其发布。

答案 2 :(得分:-1)

这是完全安全的。您只是通过this引用,而不使用this范围内的任何内容。

如果.setExceptionListener(this)方法执行的不是设置者,那会出错。