Java中一个类的多个静态实例?
我是新来的,请不要介意你觉得这个问题很愚蠢。我在处理单例代码。我对它做了一点修改(我的问题与单例无关,是的,我删除了单实例检查)。我的问题是,尽管java中的类实例只能是一个,为什么输出中有两个静态类“实例”(见哈希)。我知道“new”关键字将给出一个新的内存地址(这就是在哈希中打印的内容),但是静态类实例不应该是一个吗?所以我得到两个哈希来打印对象实例,静态变量k具有相同的值,这很好Java中一个类的多个静态实例?,java,memory,static,Java,Memory,Static,我是新来的,请不要介意你觉得这个问题很愚蠢。我在处理单例代码。我对它做了一点修改(我的问题与单例无关,是的,我删除了单实例检查)。我的问题是,尽管java中的类实例只能是一个,为什么输出中有两个静态类“实例”(见哈希)。我知道“new”关键字将给出一个新的内存地址(这就是在哈希中打印的内容),但是静态类实例不应该是一个吗?所以我得到两个哈希来打印对象实例,静态变量k具有相同的值,这很好 public class Singleton { private static Singleton
public class Singleton {
private static Singleton instance;
static int k;
public static Singleton getInstance(){
try{
instance = new Singleton();
System.out.println(instance);
}catch(Exception e){
throw new RuntimeException("Exception occured in creating singleton instance");
}
return instance;
}
public static void main(String[] ar) {
Singleton c1=Singleton.getInstance();
c1.k=1;
Singleton c2=Singleton.getInstance();
c2.k=2;
System.out.println(c1.k);
System.out.println(c2.k);
}
}
输出:
Singleton@15db9742
Singleton@6d06d69c
2
2
你的单身汉不是这样的 每次调用getInstance都会生成一个新实例,而不是检查静态对象“instance”是否为空 这就是为什么你会得到这样的结果:
Singleton@15db9742
Singleton@6d06d69c
它清楚地显示了Singleton类的两个实例,问题是在
getInstance
方法中,您总是创建一个新的实例对象
也就是说,虽然实际实例是静态的
,即类属性,但每次调用getInstance
时都会覆盖它
要解决这个问题,您应该检查instance
是否为null
,然后才创建一个新对象
if(instance == null)
instance = new Stingleton();
return instance;
这是因为缺少只创建一次单例的保护
public static Singleton getInstance(){
try{
if(instance == null)
{
instance = new Singleton();
}
System.out.println(instance);
} catch(Exception e){
throw new RuntimeException("Exception occured in creating singleton instance");
}
return instance;
}
如果没有此保护,仍然只有一个静态实例,但此实例将被第二次覆盖。您的变量
instance
在两个对象之间共享,但当您调用instance=new Singleton()时,它指向的对象将发生更改代码>
我猜你要找的是这个
public class Singleton {
public static Singleton instance; //field is made public so we can print it from main class (just to debug)
static int k;
public static Singleton getInstance(){
try{
instance = new Singleton();
}catch(Exception e){
throw new RuntimeException("Exception occured in creating singleton instance");
}
return instance;
}
public static void main(String[] ar) {
Singleton c1=Singleton.getInstance();
c1.k=1;
Singleton c2=Singleton.getInstance();
c2.k=2;
//notice that both of the instance variables of c1 and c2 are printed
//after we've initialized all of them.
System.out.println(c1.instance);
System.out.println(c2.instance);
System.out.println(c1.k);
System.out.println(c2.k);
}
}
在这里,两个实例变量的值相同
输出
Singleton@6d06d69c
Singleton@6d06d69c
2
2
其思想是在初始化所有对象的instance
变量后打印值。最近的初始化将覆盖所有以前的初始化。如上所述,您的问题在于您没有保护您的实例化
另外,为了给@Ghislain Fourny的答案增加一点内容,确保您没有在多线程上下文中实例化2个类,请在方法getInstance中添加关键字“synchronized”
}您想问什么?您的代码不是一个单例,每次调用getInstance()
时都会生成一个新实例。static
表示只有一个变量实例。它与您创建的对象实例的数量无关;您的问题似乎是基于对Java基础知识的理解不足。您的类中只有一个静态字段,其中包含您创建的最后一个实例。您将获得两个不同的实例,因为代码就是这样做的:每次调用getInstance()
方法时创建一个新实例。它只是一个字段,可以随时(重新)分配。与非静态字段的区别在于,该字段由类拥有,而不是由该类的实例拥有。而static Singleton s=new Singleton()
是完全允许的,只要该定义在类体中,而不是在方法体中。是的!你澄清了我的疑问。但是为什么允许new创建静态实例?@Vishal这取决于需求。让我们假设在您的类中,您想知道它被初始化了多少次。在这种情况下,静态实例很方便,因为我们可以创建一个名为private static int counter=0
的字段,并在类的构造函数中递增它。由于此计数器
变量将在所有对象之间共享,因此同一变量将统计所有实例。如果我们不将其设为静态,则每次初始化一个对象时,都会创建一个新的计数器实例,它将从零开始。是的!你澄清了我的疑问。但是为什么静态被允许用new初始化呢?我的意思是,既然对象不应该在静态上下文中使用,我在这里用new Singleton()初始化“instance”;此外,Singleton.class可以直接使用。不允许使用static Singleton s=new Singleton(),这是正确的。否。我们不能使用Singleton.class
进行初始化,它表示类引用,并且不初始化对象。重点是静态变量需要一个对象来保持。这就是为什么我们使用new初始化它。不同之处在于,如果使用new
初始化static
变量,则相同的对象将在所有实例中共享,而如果不将其设为static,则所有新对象都将以null开头。@Vishal是的,这是java语言规范施加的限制。您不能在java中的任何方法中将任何字段声明为静态字段。只有类变量(字段)和方法可以是静态的。将此答案视为原因:
public static synchronized Singleton getInstance(){
try{
if(instance == null) {
instance = new Singleton();
}
System.out.println(instance);
}catch(Exception e){
throw new RuntimeException("Exception occured in creating singleton instance");
}
return instance;