论坛首页 Java企业应用论坛

讨论:单例和静态方法的深入讨论

浏览 14075 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (3)
作者 正文
   发表时间:2011-01-08   最后修改:2011-01-08
    常在论坛上看见一些有关单例模式、静态类、静态方法缺点的讨论,说得最多的无非是使用static,破坏了面向对象的多态性,建议除非确定了该对象不会被扩展,否则不要使用单例模式、静态方法等。其中,举例最多的是:辅助类可采用单例、静态方法

     确实,我在开发中,看见的基本都是如此。但我一直有点疑问,今天在这提出,希望JE上兄弟讨论下:

    辅助类使用静态方法就一定好吗?我觉得可能也会存在如下问题:

    1.如果类中属性或方法是static的,那么在该类被装载到方法区时,是要分配内存的。那如果是static的,是不是表示该类(非对象)永远不会被垃圾收集了呢?从而占用一定的内存空间,如果这样的类多的话,那JVM的可使用内存不是会很少?既然这样,又何必用静态方法呢?(我不太确定含有静态字段或方法的类是否会被垃圾收集器收集
   
    2. 问题1一出现,则会衍生出问题2来,即由于加载到方法区中的类型都保持着一个对加载该类的类加载器的引用,既然类不能被垃圾收集,从而则一定会造成其对应的类加载器也不会被垃圾收集,这样,又会出现许多类加载不能被垃圾收集,不是更占有JVM内存空间了吗?
由于Java的安全性特点,加载不同包下的类的加载器一定不会是同一个对象吧。这个我不确定)。

    基于以上问题,希望JE兄弟赏脸,讨论下。

    先贴出我的观点:辅助类采用单例或静态天方法也不一定是最完美的。使用单例、静态的目的就是为了节省JVM内存,如果一个辅助类用的概率不是特别大,难道还应该向大部分人建议那样使用单例或静态吗?不应该了吧。







   发表时间:2011-01-08  
躁动的绵羊 写道
 
    1.如果类中属性或方法是static的,那么在该类被装载到方法区时,是要分配内存的。那如果是static的,是不是表示该类(非对象)永远不会被垃圾收集了呢?从而占用一定的内存空间,如果这样的类多的话,那JVM的可使用内存不是会很少?既然这样,又何必用静态方法呢?(我不太确定含有静态字段或方法的类是否会被垃圾收集器收集


我的理解:

类一旦加载就不会被卸载,这和类是否有静态成员(字段、方法)没关系。
只有类的加载器被回收了,该加载器所加载的类才会被回收。
0 请登录后投票
   发表时间:2011-01-08  
加载一个Class占用不了多少空间的
0 请登录后投票
   发表时间:2011-01-08  
sswh 写道
躁动的绵羊 写道
 
    1.如果类中属性或方法是static的,那么在该类被装载到方法区时,是要分配内存的。那如果是static的,是不是表示该类(非对象)永远不会被垃圾收集了呢?从而占用一定的内存空间,如果这样的类多的话,那JVM的可使用内存不是会很少?既然这样,又何必用静态方法呢?(我不太确定含有静态字段或方法的类是否会被垃圾收集器收集


我的理解:

类一旦加载就不会被卸载,这和类是否有静态成员(字段、方法)没关系。
只有类的加载器被回收了,该加载器所加载的类才会被回收。


我可以很负责任的告诉你: 累是可以被卸载的,也可以被缓存的

第二个观点我保留意见。
0 请登录后投票
   发表时间:2011-01-09  
蛋疼的忧虑,从没有担心class占内存及回收的,你就算有几亿行代码吧? 能占1G内存么?
0 请登录后投票
   发表时间:2011-01-09  
大多系统的瓶颈不在这个问题上
0 请登录后投票
   发表时间:2011-01-09  
对于类的内存占用,一向不再考虑的范围内,我在学校折腾java项目时,一向不管三期二十一,把hibernate,spring的jar包不加选择扔到lib下面。与这些jar中的类相比,自己设计的几个辅助类,实在是忽略不计。
而且如果运气不好,碰上out of memery,permgen space的时候,调整一下permsize就可以了。
我觉得内存方面主要要顾及的是往内存的static区域方对象,而不是类
0 请登录后投票
   发表时间:2011-01-09   最后修改:2011-01-09
躁动的绵羊 写道
sswh 写道
躁动的绵羊 写道
 
    1.如果类中属性或方法是static的,那么在该类被装载到方法区时,是要分配内存的。那如果是static的,是不是表示该类(非对象)永远不会被垃圾收集了呢?从而占用一定的内存空间,如果这样的类多的话,那JVM的可使用内存不是会很少?既然这样,又何必用静态方法呢?(我不太确定含有静态字段或方法的类是否会被垃圾收集器收集


我的理解:

类一旦加载就不会被卸载,这和类是否有静态成员(字段、方法)没关系。
只有类的加载器被回收了,该加载器所加载的类才会被回收。


我可以很负责任的告诉你: 累是可以被卸载的,也可以被缓存的

第二个观点我保留意见。

不知道你说的类怎么卸载? 据我所知确实类加载了就不能卸载,除非加载器被回收。

使用单例、静态的目的就是为了节省JVM内存 ??
没听过这种说法,就算不用单例,同样的代码写在任何地方最终都要被加载,耗掉的内存是一样的,即便那个class被创建了多个instance,它的类的二进制文件也只有一份。所以不存在内存消耗的区别。
当然如果创建多个instance是会有内存占用区别,但是你也说有内存回收了,呵呵。这个就看值不值吧,个人不是那么在意。单例是程序要求,而不是内存性能考虑。

由于Java的安全性特点,加载不同包下的类的加载器一定不会是同一个对象吧。
普通的应用里,除jdk自带类外的其他类是会被同一个加载器加载的。
0 请登录后投票
   发表时间:2011-01-09  
被回收是肯定的
0 请登录后投票
   发表时间:2011-01-09  
yanical 写道
躁动的绵羊 写道
sswh 写道
躁动的绵羊 写道
 
    1.如果类中属性或方法是static的,那么在该类被装载到方法区时,是要分配内存的。那如果是static的,是不是表示该类(非对象)永远不会被垃圾收集了呢?从而占用一定的内存空间,如果这样的类多的话,那JVM的可使用内存不是会很少?既然这样,又何必用静态方法呢?(我不太确定含有静态字段或方法的类是否会被垃圾收集器收集


我的理解:

类一旦加载就不会被卸载,这和类是否有静态成员(字段、方法)没关系。
只有类的加载器被回收了,该加载器所加载的类才会被回收。


我可以很负责任的告诉你: 累是可以被卸载的,也可以被缓存的

第二个观点我保留意见。

不知道你说的类怎么卸载? 据我所知确实类加载了就不能卸载,除非加载器被回收。

使用单例、静态的目的就是为了节省JVM内存 ??
没听过这种说法,就算不用单例,同样的代码写在任何地方最终都要被加载,耗掉的内存是一样的,即便那个class被创建了多个instance,它的类的二进制文件也只有一份。所以不存在内存消耗的区别。
当然如果创建多个instance是会有内存占用区别,但是你也说有内存回收了,呵呵。这个就看值不值吧,个人不是那么在意。单例是程序要求,而不是内存性能考虑。

由于Java的安全性特点,加载不同包下的类的加载器一定不会是同一个对象吧。
普通的应用里,除jdk自带类外的其他类是会被同一个加载器加载的。


-------------------------------------------
我想还是存在分别的,类的延迟加载和预先加载的区别,但程序运行稳定时在维持类信息的内存消耗方面应该也是基本稳定的,与类是否单例/静态等无关
静态方法过多应该注意的是对方法堆栈的消耗
另外,servlet就是单例的,怎么能说没用呢?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics