Java 为什么可以';我不能直接访问singleton实例吗?

Java 为什么可以';我不能直接访问singleton实例吗?,java,singleton,Java,Singleton,例如: 公共类单例{ 私有静态最终单例实例=新单例(); //私有构造函数抑制 //默认公共构造函数 私有单态(){}; 公共静态单例getInstance(){ 返回实例; } } 为什么我不能将实例设置为public,并通过Singleton.INSTANCE访问它?它会导致什么?从技术上讲,您可以这样做,但在本代码中,它不会产生任何影响-它的行为将是相同的 我们通常使用getter的原因是: 一个好习惯——人们会惊讶地看到您直接访问变量 灵活性—如果在调用getter的代码中有100个

例如:

公共类单例{
私有静态最终单例实例=新单例();
//私有构造函数抑制
//默认公共构造函数
私有单态(){};
公共静态单例getInstance(){
返回实例;
}
}

为什么我不能将
实例设置为public,并通过
Singleton.INSTANCE
访问它?它会导致什么?

从技术上讲,您可以这样做,但在本代码中,它不会产生任何影响-它的行为将是相同的

我们通常使用getter的原因是:

  • 一个好习惯——人们会惊讶地看到您直接访问变量
  • 灵活性—如果在调用getter的代码中有100个位置,那么很容易更改方法行为(比如每次都返回
    new Singleton()
    ,而不是访问静态变量)。如果这一百个地方直接访问变量,就不那么容易了

从技术上讲,您可以将
Singleton.INSTANCE
公开,因为它是
最终版
。但是,从API用户的角度来看,
Singleton.INSTANCE
在不查看
Singleton
类的内容的情况下是最终的,这一点并不明显,用户可能会尝试从其他类重新分配
Singleton.INSTANCE


使
Singleton.INSTANCE
只能通过
Singleton.getInstance()访问
使每个人都清楚地认识到,不可能重新分配变量。

因为封装实例是一种良好的做法,以避免使用锅炉板代码,在这种情况下,您需要使用静态块来初始化对象,如果在需要时初始化对象(延迟加载),效果会更好可能对内存使用有好处。

因为您尝试访问的实例变量是私有的。使用getInstance()方法,因为它是公共的。这将阻止您更改
getInstance()
的实现,以将单例的实例化推迟到第一次需要时(如果您选择的话)。将访问封装在方法中使将来的更改更容易。@gnanajeyam95您读过这个问题了吗?OP知道它是
私有的
,并询问将其更改为
公共的
是否会引起任何问题。从本质上讲,将其设置为
公共的
。与没有setter方法相比,
最终的
如何不那么明显?查看
Singleton.getInstance()
与查看
Singleton.INSTANCE
关于能够更改实例的可能性没有什么区别。@Andreas这不太明显,因为它需要读取
Singleton
类的内容,除非您有一个高级IDE。这不是有点牵强吗?使用
Singleton.getInstance()
时,由于getter/setter模式,用户可能认为可以使用
Singleton.setInstance(instance)
方法对其进行更改。如果他们尝试了,他们会发现
setInstance
不存在。这与tring赋值给
Singleton.INSTANCE
,然后发现编译器拒绝了,因为字段是
final
@NathanielJones,但它还需要读取Singleton类的内容,以确定没有setter方法。有了IDE,两者都很容易检查,因此同样明显。在没有IDE的情况下,定位字段并检查
final
修饰符既简单又快速,因为一旦找到字段(通常在开头),就可以停止扫描仪。检测是否缺少setter方法需要扫描整个源文件,因此检查字段是否为final肯定比检查setter方法是否存在更明显(更容易、更快)。@NathanielJones另外,如果字段不是
final
,即使它是
private
,也可以通过setter方法以外的代码进行更改,这意味着您需要扫描源文件中的所有代码,而不仅仅是方法签名,因此即使是IDE也无法加快速度。
final
字段总是比缺少setter方法更明显。