`
fredred
  • 浏览: 11227 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

创建和销毁对象(内功篇)

    博客分类:
  • Java
阅读更多

第1条:考虑用静态工厂方法替代构造函数

静态方法的好处
1. 与构造函数不同,静态工厂方法具有名字。如果以个构造函数的参数并没有确切的描述被返回的对象,那么选用适当的名字的静态工厂可以试一个类更易于使用,并且相应的客户代码更易于阅读。因为静态工厂方法自己有名字,所以他们没有构造函数那样的限制,对于给定的原型的特征,可以有不止一个静态工厂方法,如果以个类看起来需要多个构造函数,并且他们的原型特征相同,那么你应该考虑用静态工厂方法来代替其中一个或者多个构造函数,并且慎重的选择他们的名字以便明显的标示出他们的不同。
2. 与构造函数不同,他们的每次被调用的时候,不要求非要创建一个新的对象。静态工厂方法可以为重复的调用返回同一个对象。
3. 与构造函数不同,他们可以返回一个原返回类型的子类型的对象。这样我们的选择被返回对象的类型时就有了更大的灵活性。

静态方法的缺点:
1. 类如果不含有公有的或者受保护的构造函数,就不能被子类化,例如,想要子类化Collecions中的任何一个方便的实现类,是不可能的,然而这也许会因祸得福,因为它会鼓励程序员使用复合结构,而不是继承。
2. 他们与其他任何静态方法没有任何区别。在API文档中,他们不会像构造函数那样被明确标示出来,而且,静态工厂方法代表了一种对规范的背离。
静态工厂方法的量个名字已经变得很流行:
 valueOf----不太严格的讲,该方法返回的实力与他的参数具有同样的值,使用这个名字的静态工厂方法是一些非常有效的类型转换操作符。
 getInstance----返回的实例是由该方法的参数来描述的,但是不能够说与参数具有同样的值。对于singleton的情形,改方法返回唯一的实例。
总得来说,静态工厂方法和公有的构造函数都有他们各自的用途,我们需要理解他们各自的长处,避免一上来就构造函数,而不考虑静态工厂方法。因为静态工厂通常更加适合。如果你正在权衡这两种选择,又没有其他因素强烈的影响你的选择,那么你最好还是简单的使用构造函数,毕竟他们语言提供的规范。

第2条:使用私有构造函数强化singleton属性
Singleton通常被用来代表那些本质上具有唯一性的系统组件,比如视频显示或者文件系统。实现singleton有两种方法。这两种方法都要把构造函数保持似有,并且提供一个静态成员,以便允许客户能够访问该类唯一的实例。在这一种方法中,公有的静态成员是一个final域:
Public class Elvis{
Public static  final  Elvis INSTANCE=new Elvis();
Private   Elvis(){}
}

Public class Elivs{
Private static final Elvis INSTANCE=new Elvis();
Private   Elvis(){}
Public static Elvis getInstance(){
Return INSTANCE;
}
}
第一种的好处在于,组成类的成员的声明很清楚的表明了这个类的是一个singleton:公有的静态域是final的,所以该域总是包含相同的对象引用。第一种方法可能在性能上稍微领先。
第二种方法的主要好处在于,它提供了灵活性:在不改变API的前提下,允许我们改变想法,把该类做成singleton.或者不做成singleton.singleton的静态工厂方法返回该类的唯一实例,但是,它也很容易被修改,比如说,为每个调用该方法的线程返回一个唯一的实例。总言而之,如果你确信该类将永远是一个singleton,那么使用第一种方法是有意义的。如果你希望保留一点余地,那么请使用第二种方法。
对象序列化seializeble,仅仅在声明中加上implements Serializeble是不够的,为了维护唯一性,你必须也要提供一个readResolve方法,否则得话,一个序列化的对象每次反序列化得时候,都会创建一个新的实例,比如说,在我们的例子中,就会产生一个假冒的Elvis,为了防止这种情况,在Elvis类中加入下面的readRelove方法:
Private Object readResolve()throws ObejctStreamExcetion{
Return INSTANCE;
}

第3条:通过似有构造函数强化不可实例化的能力
偶尔情况下,你可能会编写出只包含静态方法和静态域的类。一些工具类就是这样,这样的类不希望被实例化,对它进行实例化没有任何意义,所以,我们只要让这个类包含单个显式的私有构造函数,则它就不可被实例化了

第4条:避免创建重复的对象
重复使用同一个对象,而不是每次需要就创建一个 功能等价的新对象,通常前者更为合适。重用方式既快速,也更为流行。如果一个对象是非可变的,那么他总是可以被重用。对于同时提供了静态工厂方法和构造函数的非可变类,你通常可以利用静态方法而不是构造函数,以避免创建重复对象。例如,静态工厂方法Boolean.valueOf(String)几乎总是优先于构造函数Boolean(String)。
不要错误的任务“创建对象的代价是昂贵的,我们应该要尽可能的避免创建对象”。相反,由于小对象的构造函数只做很少量的工作,所以,小对象的创建和回收动作是非常廉价的。
反之,通过维护自己的对象池来避免对象的创建工作并不是一个很好的做法,除非池中的对象是非常重量级的,一个正确使用对象池的典型例子就是数据库连接池。然而一般而言,维护自己的对象池会吧代码弄的很乱,增加内存占用,并且还会损害性能。JVM的垃圾回收器,其性能很容易就会超过轻量级对象池的性能。
注意,在提倡使用保护性拷贝的场合,因重用对象而肇事的代价要远远大于因创建对象而招致的代价,在要求保护性的情况下却没有实施保护性拷贝,将会导致潜在的安全漏洞;而不必要的创建对象仅仅影响程序的风格和性能。

第5条:消除过期的对象引用
垃圾回收机制很容易让人刘翔这样的印象,认为自己不再需要管理内存的事情了,实际上,这是不正确的。一般而言,只要一个类自己管理它的内存,程序员就应该警惕内存泄露的问题,一旦以个元素被释放掉,该元素中包含的任何对象引用应该要被清空。
内存泄露的另一个常见来源是缓存,一旦你把一个对象引用放入一个缓存中,他就很容易被遗忘掉,从而使得它不再游泳之后很长一段时间内仍然留在混村中,对于这个问题,,有两种可能的解决方案,如果你正巧实现这样的缓存:只要缓存之外存在某个条目的键的引用,该条目就有意义,那么你可以使用WeakHashMap来代表缓存;当缓存的条目过期之后,他们会自动删除。而更为常见的情形是,“被缓存的条目是否有意义”的周期并不很容易确定,其中的条目会在运行的过程中变得越来越没有价值。在这样的iqngkuang下,缓存应该时不时的清除掉无用的项目,这样工作可由一个后台线程来完成,或者加入新的条目的时候做清理工作。LRU算法等等。在1.4中,LinkedHashMap类,利用它的removeEldestEntry方法可以很容易实现后一种方案。

第6条:避免使用终结函数
终结函数通常是不可预测的,一般情况下是不必要的,因为运行垃圾回收是一个很低级的线程,往往很难确定垃圾回收执行的时间,所以终结函数finalizer函数的运行也存在不确定性。前往不要再finalizer函数内写关闭文件或数据库链接这类的语句,或者是必须做得事情不适合在finalizer中来完成。


0
0
分享到:
评论

相关推荐

    C#创建、销毁对象和继承

    对象的创建和销毁,以及继承,都是面向对象编程的核心概念。接下来,我们将详细探讨这些知识点。 首先,我们来讨论“使用构造方法”。构造方法是类的一个特殊方法,它的主要任务是在创建对象时初始化成员变量。在C#...

    Qt6 QML Book/动态QML/创建和销毁对象示例源码

    在本文中,我们将深入探讨Qt6中的QML技术,特别是关注如何动态地创建和销毁对象。QML是Qt框架提供的一种强大的声明式编程语言,它允许我们构建具有丰富用户界面的应用程序。Qt6版本带来了许多改进和新特性,使得QML...

    监听器:监听三个对象的创建和销毁方法

    本次工程的目标是学习监听器,掌握监听三个对象的创建和销毁方法。 三个对象:rquest,session,ServletContext 实现的接口:ServletRequestListener,HttpSessionListener,ServletContextListener 工程的大致步骤...

    【原】unity 不销毁对象的处理

    这减少了对象的频繁创建和销毁,降低了性能开销。 4. **单例模式**:单例是一种设计模式,保证一个类只有一个实例,并提供全局访问点。在Unity中,常用于管理如音频播放器、网络连接等全局服务。通过单例,对象在...

    Windows进程的创建与销毁

    除了创建和销毁进程之外,还需要了解如何控制进程中的线程行为,例如挂起和激活主线程。这可以通过`SuspendThread`和`ResumeThread`两个函数来实现。 - `SuspendThread`: 挂起一个线程。 - `ResumeThread`: 恢复一...

    JAVA创建和销毁对象的方法

    在Java编程中,创建和销毁对象是至关重要的操作,它们直接影响到程序的性能和内存管理。本文将深入探讨Java中创建对象的几种方法以及对象的销毁。 首先,我们来看看创建对象的基本方式——构造器。构造器是每个类都...

    TheadPool 线程池源码 自动管理线程的创建和销毁

    在Java、C++等编程语言中,线程池被广泛应用,用于管理线程的生命周期,避免频繁创建和销毁线程带来的开销。本文将基于提供的"ThreadPool.cpp"和"ThreadPool.h"文件,深入解析线程池的实现原理及其自动管理线程创建...

    C++源码:非模态对话框创建和销毁

    本示例中的代码着重展示了如何在VC6环境下创建和销毁非模态对话框。 首先,我们来看一下创建非模态对话框的关键步骤: 1. **定义对话框类**:在`modelessDlg.cpp`和`modelessDlg.h`文件中,定义了一个继承自`...

    易语言时钟的创建销毁

    本篇文章将详细讲解如何在易语言中创建和销毁时钟,并介绍相关函数`TimerProc`、`timeKillEvent`和`timeSetEvent`的用法。 首先,创建一个时钟意味着在易语言中设定一个定时器,这个定时器会在指定的时间间隔后触发...

    易语言API创建与销毁时钟2例

    在提供的压缩包文件"API创建与销毁时钟2例"中,应该包含两个示例代码,分别演示了如何创建和销毁时钟。通过学习这两个例子,你可以更好地理解这些API和易语言命令的实际应用。务必仔细阅读代码,理解每个部分的作用...

    c++多线程的创建挂起执行与销毁

    1. 创建一个基于对话框的应用程序。并增加如图所示控件;分别为3个进度条控件关联三个进度条类型的变量;并在对话框的初始化函数中,设定进度条的范围;为编辑框关联一个整型的变量;为12个按钮添加消息处理函数; 2...

    多线程创建于销毁实现代码

    本篇主要介绍如何在Microsoft Visual Studio 2005环境下创建、管理和销毁多线程,以及相关的实例——`MutualThread`。 1. **线程创建**: 在Windows API中,可以使用`CreateThread`函数来创建一个新的线程。该函数...

    用new创建对象和直接定义的区别

    4. **性能**:栈内存分配和回收比堆内存更快,因此直接定义的对象创建和销毁速度较快。但堆内存可以提供更大的容量。 5. **异常处理**:`new`操作可能会抛出内存不足异常,而直接定义的对象不会面临这个问题(除非...

    ATL 揭秘之“对象创建”篇

    本文将逐步揭示ATL如何创建和管理COM对象的过程。 #### 2. “对象”探讨 在深入讨论之前,我们先简要回顾一下“对象”这个概念。 **2.1 对象性质** “对象”通常具有三个核心特性:封装、继承和多态。这些特性...

    函数栈帧的创建和销毁图片

    函数栈帧的创建和销毁图片

    ACE对象生命周期管理者:一种用于控制对象创建和销毁的补充模式

    目的对象生命周期管理者模式可以被用来控制对象的整个生命周期,从对象被首次使用前创建它们到应用程序中止前完全的销毁它们。此外通过在应用启动/中止时进行对象自动的预先创建/销毁,使这个模式能够用来替代静态...

    Python 程序语言设计模式思路-并发模式:线程池模式:管理线程池,优化线程创建和销毁

    然而,线程的创建和销毁是一个开销较大的操作,频繁的线程操作可能导致系统资源的浪费和性能下降。线程池模式(Thread Pool Pattern)是一种优化线程管理的设计模式,它通过创建一个线程池来管理和复用线程,从而...

    监听session的创建到销毁

    `HttpSessionListener`可以监听Session的创建和销毁,而`HttpSessionAttributeListener`则可以监听Session属性的添加、移除和替换。 1. **创建Session监听器** 创建一个实现了`HttpSessionListener`接口的类,例如...

    c++,链队列的基本操作(创建,销毁,查找,删除,插入等)

    链队列的基本操作包括创建、销毁、查找、删除、插入等。 1. 创建链队列 创建链队列的方法是通过InitQueue_L函数来实现的,该函数将创建一个只有头结点的空队列。链队列的头结点是一个特殊的结点,它不存储任何数据...

Global site tag (gtag.js) - Google Analytics