【问题标题】:More than one static instance of a class in Java?Java中一个类的多个静态实例?
【发布时间】:2017-02-24 08:28:51
【问题描述】:

我是新人,请不要介意你觉得这个问题很愚蠢。我弄乱了单例代码。我稍微改了一下(我的问题与单例无关,是的,我已经删除了单例检查)。我的问题是虽然 java 中的类实例只能是为什么输出中有两个静态类“实例”(参见哈希)的一个原因。我知道“new”关键字会给出一个新的内存地址(这就是在哈希中打印的内容)但不是t 静态类实例应该是一个?所以我得到了两个用于打印对象实例的哈希,静态变量 k 具有相同的值,这很好。

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() 时都会生成一个新实例。
  • static 表示只有 1 个变量实例。它与您创建多少对象实例无关。
  • Java 中没有“静态类实例”之类的东西;您的问题似乎是基于缺乏对 Java 基础知识的理解。您的类中只有一个静态字段,其中包含您创建的最后一个实例。您将获得两个不同的实例,因为这就是您的代码所做的:每次调用 getInstance() 方法时创建一个新实例。
  • 再次,这是基本的 Java。它只是一个字段,可以随时(重新)分配。与非静态字段的区别在于该字段由类拥有,而不是由该类的实例拥有。并且 static Singleton s=new Singleton() 是完全允许的,只要该定义在 class 主体中,而不是在方法主体中。

标签: java memory static


【解决方案1】:

您的变量 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 变量之后打印值。最近的初始化将覆盖所有以前的初始化。

【讨论】:

  • 是的,完全正确!你解决了我的疑问。但是为什么允许新建一个静态实例?
  • @Vishal 这取决于要求。假设在您的班级中,您想知道它被初始化了多少次。在这种情况下,静态实例会派上用场,因为我们可以创建一个名为 private static int counter = 0 的字段,然后在类的构造函数中递增它。由于这个counter 变量将在所有对象之间共享,因此同一个变量将对所有实例进行计数。如果我们不将其设为静态,则每次初始化对象时,都会创建一个 counter 的新实例,并且它将从零开始。
  • 是的,完全正确!你清除了我的疑问。但是为什么允许用 new 初始化静态?我的意思是因为对象不应该在静态上下文中使用,在这里我用 new Singleton 初始化“实例” ();而且 Singleton.class 可以直接使用。 static Singleton s=new Singleton() is not allowed 这是正确的。
  • 没有。我们不能用Singleton.class来初始化,它表示类引用,它不初始化对象。关键是静态变量需要一个对象来保持。这就是我们使用 new 初始化它的原因。不同之处在于,如果 static 变量是使用 new 初始化的,那么同一个对象将在所有实例之间共享,而如果我们不将其设为静态,那么所有新对象都将以 null 开头。
  • @Vishal 是的,这是 java 语言规范施加的限制。您不能在 java 中的任何方法中将任何字段声明为静态。只有类变量(字段)和方法可以是静态的。看到这个答案为什么:static variable in static member function in JAVA
【解决方案2】:

你的单身不是这样的..

每次调用 getInstance 时,您都会生成一个新实例,而不是检查静态对象“instance”是否为空..

这就是你得到这个的原因:

Singleton@15db9742 
Singleton@6d06d69c

清楚地显示了 Singleton 类的 2 个实例

【讨论】:

    【解决方案3】:

    如上所述,您的问题在于您没有保护您的实例化。

    还要在@Ghislain Fourny 的回答中添加更多内容,以确保您不会在多线程上下文中实例化 2 个类,将关键字“同步”添加到方法 getInstance

      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;
    

    }

    【讨论】:

      【解决方案4】:

      问题是在你的getInstance 方法中你总是创建一个新的实例对象。

      也就是说,虽然您的实际实例是 static,即一个类属性,但每次调用 getInstance 时它都会被覆盖。

      要解决这个问题,您应该检查instance 是否为null,然后才创建一个新对象。

      if(instance == null)
        instance = new Stingleton();
      
      return instance;
      

      【讨论】:

        【解决方案5】:

        这是因为缺少一个只创建一次单例的守卫。

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

        没有这个守卫,仍然只有一个静态实例,但是这个实例被第二次覆盖了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-12
          • 2014-02-03
          • 1970-01-01
          • 2015-08-13
          相关资源
          最近更新 更多