按需初始化持有人习语的正确实现 [英] Correct implementation of initialization-on-demand holder idiom

查看:21
本文介绍了按需初始化持有人习语的正确实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个版本的Initialization-on-demand holder idiom":

I have got two versions of "Initialization-on-demand holder idiom":

  1. http://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
  2. http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh

上面的主要区别在于第一个将INSTANCE声明为private,而第二个将INSTANCE声明为public.

The major difference between above is that the first one declared INSTANCE as private, but the second one declared INSTANCE as public.

请告诉我应该使用哪个.

Please tell me which one should I use.

抱歉,我没有发现在我的应用程序中使用 privatepublic 之间的区别:

Sorry, I have not found the difference between using private and public in my application:

public class Singleton {
    private int x;
    public int getX() {
        return x;
    }

    private Singleton () {}

    private static class LazyHolder {
        //both private and public works
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

我唯一要做的就是调用类似 Singleton.getInsance().getX() 之类的东西,这样两个版本都可以工作.因此我想知道使用它们的情况.

The only thing I do is to call something like Singleton.getInsance().getX(), so both versions works. Thus I want to know the situations for using them.

推荐答案

关于单例和按需初始化的持有者习惯用法,有几件事需要解释.我们开始:

There are several things to explain about singletons and the initialization-on-demand holder idiom. Here we go:

1) 访问修饰符:

通常你不能访问另一个类中的字段和方法,如果它们是私有的.如果访问类在同一个包中,它们至少必须是包私有的(没有修饰符,它是).因此,实现它的正确方法是:

Normally you can't access fields and methods in another class if they are private. They must at least be package private (having no modifier, it is) if the accessing class is in the same package. So the correct way to implement it, would be:

public class Singleton {
    ...
    private static class LazyHolder {
        static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}

但是,JLS 6.6.1 解释:

否则,如果成员或构造函数被声明为私有,那么访问是当且仅当它出现在顶级类的主体内时才允许(第 7.6 节)包含成员或构造函数的声明.

Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

这意味着,将字段INSTANCE 声明为私有仍然允许从顶级类Singleton 内部进行访问.但是编译器必须做一些技巧来绕过私有修饰符:它插入包私有方法来获取和设置这样的字段.

That means, declaring the field INSTANCE as private still allows the access from inside the top level class Singleton. But the compiler must do some tricks to get around the private modifier: It inserts package private methods for getting and setting such a field.

其实,你在上面放哪个修饰符并不重要.如果它是公共的,除了 Singleton 之外,它仍然不能被其他类访问.但是...我认为包私有访问是最好的.公开是没有意义的.将其设为私有会强制编译器做一些技巧.将其设为私有反映了您所拥有的:从另一个类访问类成员.

In fact, it does not matter, which modifier you place on it. If it is public, it still cannot be accessed from other classes than Singleton. However ... I think the package private access is the best. Making it public does not makes sense. Making it private forces the compiler to do some tricks. Making it package private reflects what you have: Access to a class member from another class.

2) 如何实现单例:

如果你想考虑序列化,单例实现会有点困难.Joshu Bloch 在他的Effective Java"一书中写了一个关于实现单例的重要部分.最后,他得出结论,为此只使用枚举,因为 Java 枚举规范提供了与单例相关的所有特性.当然,那不再使用这个成语了.

If you ever want to consider serialization, the singleton implementation will get a bit difficult. Joshu Bloch wrote a great section in his book "Effective Java" about implementing singletons. At the end, he concluded to simply use an enum for this, as the Java enum specification provides every charecteristic that is needed in regards to singletons. Of course, that does not use the idiom anymore.

3) 考虑设计:

在大多数设计决策中,单身人士不再占有一席之地.事实上,如果你必须在你的程序中放置一个单例,它可能表明一个设计问题.请记住:单身人士为某些数据或服务提供了全局访问机制.这不是面向对象编程.

In most design decisions, singletons do not have their places anymore. In fact, it could indicate a design issue, if you must place a singleton into your program. Keep in mind: Singletons provide a global acess mechanism to some data or services. And this is not OOP.

这篇关于按需初始化持有人习语的正确实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆