V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
georgetso
V2EX  ›  程序员

关于单例的一个问题

  •  
  •   georgetso · 2015-02-24 13:38:50 +08:00 · 3023 次点击
    这是一个创建于 3546 天前的主题,其中的信息可能已经有所发展或是发生改变。

    public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}􏳅
    􏳅 􏳅 public static Singleton getInstance() {
    return instance; 􏳅 􏳅
    􏳅􏳅 }
    }

    上面的例子,书里解释道:
    单例在类被􏰂􏳕􏰂􏳕加载的时候实例化,这􏰼样多次加载􏰂􏳕会造成􏰅多次实例化。

    类被多次加载的意思是什么?多个线程里被加载?
    既然已经限定了 static 关键字,那 instance 应该被存储在全局和静态存储区里,不应该被多次事例化啊

    13 条回复    2015-02-25 16:18:15 +08:00
    Mirana
        1
    Mirana  
       2015-02-24 13:41:07 +08:00
    每次实例化的时候都重新执行一次把
    georgetso
        2
    georgetso  
    OP
       2015-02-24 13:48:30 +08:00
    @Mirana 实例化执行的是 Singleton() 方法。我问的是类被加载。你看错了吧
    mhycy
        3
    mhycy  
       2015-02-24 13:53:24 +08:00 via Android
    记忆中这是未定义行为,应该在get的时候判断是否为null并初始化
    Mirana
        4
    Mirana  
       2015-02-24 14:23:09 +08:00
    @georgetso 哦,ioc容器给一个类名 加载一个类的实例 应该是类的加载把
    hitsmaxft
        5
    hitsmaxft  
       2015-02-24 14:25:32 +08:00 via iPhone
    static {} 段的内容classloader在加载class的过程中被执行,多个classloader重复加载同一个class就就行多次。
    hitsmaxft
        6
    hitsmaxft  
       2015-02-24 14:27:16 +08:00 via iPhone
    @Mirana 你说的是对象实例化,static和实例无关,只和类型相关
    georgetso
        7
    georgetso  
    OP
       2015-02-25 09:49:19 +08:00
    @hitsmaxft 书中使用java作为示例。这个问题是否可能因为语言的不同出现不同的结果?例如,如果java和c++的 class loading 机制不一样的话会怎么样?
    hitsmaxft
        8
    hitsmaxft  
       2015-02-25 10:03:17 +08:00 via iPhone
    @georgetso 单例的本质是资源全局唯一。应该说这段代码是利用了java的static实现了单例。所以不同语言确实需要入乡随俗
    ob
        9
    ob  
       2015-02-25 10:45:24 +08:00
    不同的语言对内存的管理上应该都是类似,楼主提的问题,下面我说下我的理解:
    首个类和对象的区别,楼主肯定是知道的。
    那一个类,肯定是可以被创造出多个对象的,也就是被实例化多次。
    至于楼主说的static关键字,以及上面代码生成的单例。只能说在类被实例化多次的时候,用到的引用都是指向同一个对象。也就是实例化多次其实返回的是对一个对象。所以叫单例。
    georgetso
        10
    georgetso  
    OP
       2015-02-25 11:07:45 +08:00
    @ob 看了您的回答,我还是没弄明白。类被实例化的情况完全不在我的问题中。我询问的是类加载的问题。
    lip
        11
    lip  
       2015-02-25 11:26:13 +08:00   ❤️ 1
    private static Singleton instance = new Singleton();
    这个是静态的,会在classloader第一次load这个class的时候执行,而且仅在这个时候执行。
    之所以这样实现是单例,是因为一般情况下,按照java的类加载机制,一个类只会被一个classloader加载,而且仅加载一次,因此在一个jvm里面仅有这一个实例。
    文中说的多次加载会造成多次实例化是指的非一般情况下,可能有多个classloader都加载这个class,因此每个classloader加载的时候都会实例化一个实例,也就是所谓的多次实例化。非一般情况常见的是那些web容器,比如tomcat,was;eclipse的插件实现也用了一堆的classloader,都会有这种现象
    Osake
        12
    Osake  
       2015-02-25 15:29:56 +08:00
    @lip 说的应该是对的 而且如果多个classloader加载同一个class的情况时,会产生不同的class,因为jvm判断一个class是不是唯一除了通过类名外还要判断类的加载器是不是同一个,也就是说如果一个类被不同的加载器加载,那么他们的实例是不同的(互相赋值会抛出运行时异常 ClassCastException)。
    georgetso
        13
    georgetso  
    OP
       2015-02-25 16:18:15 +08:00
    @lip
    @Osake 感谢两位。java是虚拟机语言,那么 c++ 这种编译语言是否有可能出现这种情况?例如多线程之类的情况。我明白这个需要看 c++ 的编译器的实现方案,不过就大体而言,编译语言一般来讲是否会出现这种情况?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2621 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 05:28 · PVG 13:28 · LAX 21:28 · JFK 00:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.