静态类和单例模式之间存在什么实际的区别?

两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?


当前回答

当我想要具有完整功能的类时,例如,有很多方法和变量,我使用单例;

如果我希望类中只有一个或两个方法,例如MailService类,它只有一个方法SendMail(),我使用静态类和方法。

其他回答

两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?

问题是错误的,这两种说法都是错误的。请注意:这里的静态类意味着嵌套的静态类,而不是只有静态方法的类。

我假设(即,静态类意味着嵌套的静态类,而不是只有静态成员的类),因为如果我看到最流行的Singleton实现,即DCL方式,它只不过是实例的静态声明和获取Singleton实例的静态方法。它是一个实现。那么在这种情况下,Singleton和只有静态成员的类之间有什么区别呢。尽管其他实现也是可能的,比如使用Enum。

让我纠正以下说法:

Singleton类可以具有单实例应用程序范围。嵌套的静态类可以有多个实例(请参阅下面的代码作为证明)。在这里阅读嵌套类的基础知识。没有一个类本质上是线程安全的,它必须通过编程实现线程安全。它既可以用于嵌套静态类,也可以用于Singleton。

下面是更多的神话故事(这个问题的大多数答案都给出了这些陈述,因此认为最好通过编程来证明这一点):

嵌套的静态类可以像任何其他类一样实现接口。嵌套的静态类可以扩展其他非最终类。嵌套静态类可以具有实例变量。嵌套静态类可以具有参数化构造函数。

在下面的代码中,您可以看到嵌套的静态类NestedStaticClass实现了接口,扩展了另一个类,具有实例变量和参数化构造函数。

 package com.demo.core;

    public class NestedStaticClassTest
    {
        public static void main(String[] args)
        {
            OuterClass.NestedStaticClass obj1 = new OuterClass.NestedStaticClass();
            OuterClass.NestedStaticClass obj2 = new OuterClass.NestedStaticClass();

            if(obj1 == obj2)
            {
                System.out.println("Both nested static objects are equal....");
            }
            else
            {
                System.out.println("NOT EQUAL......");
            }

            System.out.println(OuterClass.NestedStaticClass.d);

            obj1.setD(5);

            System.out.println(OuterClass.NestedStaticClass.d);

            System.out.println(obj1.sum());
        }
    }

    class OuterClass
    {
        int a =1;
        static int b = 2;

        static class NestedStaticClass extends OneClass implements Sample
        {
            int c = 3;
            static int d = 4;

            public NestedStaticClass()
            {
            }

            //Parameterized constructor
            public NestedStaticClass(int z)
            {
                c = z;
            }

            public int sum()
            {
                int sum = 0;
                sum = b + c + d + getE();
                return sum;
            }

            public static int staticSum()
            {
                int sum = 0;
                sum = b + d;
                return sum;
            }

            public int getC()
            {
                return c;
            }
            public void setC(int c)
            {
                this.c = c;
            }
            public static int getD()
            {
                return d;
            }
            public static void setD(int d)
            {
                NestedStaticClass.d = d;
            }
        }
    }

    interface Sample
    {

    }

    class OneClass
    {
        int e = 10;
        static int f = 11;

        public int getE()
        {
            return e;
        }
        public void setE(int e)
        {
            this.e = e;
        }
        public static int getF()
        {
            return f;
        }
        public static void setF(int f)
        {
            OneClass.f = f;
        }

    }

延迟加载支持接口,以便提供单独的实现能够返回派生类型(作为lazyloading和接口实现的组合)

我头脑中的不同是实现面向对象编程(Singleton/Prototype)或函数编程(Static)。

我们过于关注单例模式创建的对象数量,而我们应该关注的是最终我们持有一个对象。正如其他人已经说过的,它可以扩展,作为参数传递,但最重要的是它是状态满的。

另一方面,静态用于实现函数式编程。静态成员属于一个类。他们是无国籍的。

顺便问一下,您是否知道可以创建单例静态类:)

这是一篇好文章:http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

静态类

具有所有静态方法的类。更好的性能(静态方法在编译时绑定)无法重写方法,但可以使用方法隐藏。(Java中隐藏的方法是什么?甚至JavaDoc的解释都令人困惑)公共级动物{公共静态void foo(){System.out.println(“动物”);}}公共课猫延伸动物{public static void foo(){//隐藏Animal.foo()System.out.println(“类别”);}}

辛格尔顿

只能实例化一次的对象。方法可以被重写(为什么Java不允许重写静态方法?)比静态方法更容易模拟更善于保持状态

总之,我只使用静态类来保存util方法,而使用Singleton来处理其他所有事情。


编辑

静态类也被延迟加载。谢谢@jmoreno(静态类初始化何时发生?)静态类的方法隐藏。谢谢@MaxPeng。

静态类示例

public class Any {

    private static Any instance = new Any();

    private Singleton() {
        System.out.println("creating");
    }
}

单例模式只存在一个实例:

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
        System.out.println("creating");
        if (instance != null) {
            throw new RuntimeException("Imposible create a new instance ");
        }
    }
}