[Java] 一、对象的创建 & 销毁

*1、考虑静态工厂方法(static factory method)代替构造器?!优势?不足?

服务提供者架构:

1、服务接口(Service Interface) -- 提供者实现的;

2、提供者注册API(Provider Registration API)--系统用于注册实现,让客户端访问它们;

3、服务访问API(Service Access API)--客户端用于获取服务的实例;[它是“灵活的静态工厂”,构成了服务提供者架构的基础!]

*4、服务提供者接口(Service Provider Interface)--这些提供者负责创建其服务实现的实例

[如果没有Service Provider Interface,实现就按照类名称注册,并通过反射方式进行实例化。

对于JDBC来说,

Connection就是它的服务接口,

DriverManager.registerDriver是提供注册API,

DriverManager.get Connection是服务访问API,

Driver就是服务提供者接口]

2、遇到多个构造器参数时要考虑用构造器

*3、用私有构造器or枚举类型强化Singleton属性

4、通过私有构造器强化不可实例化的能力

5、避免创建不必要的对象

*6、消除过期的对象引用

// Can you spot the "memory leak"?
public class stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        return elements[--size];
    }

    /**
     * Ensure space for at least one more element, roughly
     * doubling the capacity each time the array needs to grow.
     */
    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2*size+1);
    }
}

BUG:“内存泄漏”,随着垃圾回收器活动的增加,或者由于内存占用的不断增加,程序性能的降低逐渐表现出来。极端情况、

会导致磁盘交换(Disk Paging),甚至导致程序报错(OutOfMemoryError)--少见!

eg:如果一个栈先是增长,再收缩,那么从栈中弹出来的对象将不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,它们也

不会被回收。因为:栈内部维护着对这些对象的过期引用(obsolete reference)--即永远也不会再被解除的引用。本例中,elements

数组的“活动部分(active portion)”之外的任何引用都是过期的。活动部分指:elements中下标小于size的那些元素。

fix bug:一旦对象引用过期,需要清空这些引用。即修改pop方法,如下;

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null; // Eliminate obsolete reference.
        return result;
    }

好处:

1、解决BUG出现的内存长期占用,降低性能;

2、如果它们以后又被错误的解除引用,程序就会抛出NullPointerException异常,而不是悄悄继续运行下去!

/**

* 1、只要是自己管理内存,程序员就应该警惕内存泄露问题;

* 2、缓存;--把对象引用放到缓存中,它就很容易被遗忘掉;

[修复:只要在缓存之外存在某个项的键的引用,该项就有意义,那么就可以用WeakHashMap代表缓存!

“缓存项的生命周期是否有意义”--不容易确定。LinkedHashMap类利用它的removeEldestEntry方法!

更加复杂的缓存,必需直接使用java.lang.ref!]

* 3、监听器 & 其他回调

[eg:如果你实现一个API,客户端在这个API中注册回调,却没有显式地取消注册,那么除非你采取某些动作,否则

它们就会聚集。确保回调立即被当作垃圾回收的最佳方法是只保存它们的弱引用(weak reference),例如,只将它们

保存成WeakHashMap中的键。]

**/

7、避免使用终结方法?(即finalizer)

“不要把终结方法当作是C++析构器的对应物!(构造器)”

C++:析构器(destructors)回收一个对象所占用的资源,是构造器所必需的对应物; --也可以回收其他的非内存资源

Java:当一个对象变得不可到达时,垃圾回收机制会回收与该对象相关联的存储空间;--用try-finally实现类似工作

----------------------------

Effective Java 

  -- Second Edition (James Gosling)

----------------------------

时间: 2024-10-08 10:19:25

[Java] 一、对象的创建 & 销毁的相关文章

JAVA String对象的创建

String对象的创建是比较特殊的,普通对象创建都是在堆中创建,String对象确不一定,下面看一段代码 [java] view plaincopy public class StringTest1 { public static void main(String[] args) throws Exception{ String a = "abc"; String b = "abc"; String c = "ab"; String d = ne

深入理解java虚拟机---对象的创建过程(八)

1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下面分步骤详细讲解 A: 虚拟机为对象分配内存方式 1. 指针碰撞: 堆内存规整时,这时就可以把其看做一半连续内存被占用,一半连续的内存空闲.所以当创建新对象时,从空闲的内存中分配空间给新对象 2.空闲列表: 堆内存是不连续的,这就需要虚拟机维护一个内存列表,用于记录当前内存是否被占用,当新创建对象时

java中对象的创建过程

举例:类A的的对象a的创建过程 1,因为构造器实质上是静态方法,当首次创建A类的对象时(即执行了A类的静态方法),或者A类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位A.class文件. 2,载入A.class文件,有关静态初始化的所有动作都被执行.因此,静态初始化只在Class对象首次加载的时候执行一次. 3,为将要创建的a对象分配足够多的存储空间. 4,执行所有出现在字段定义处的初始化动作. 5,执行构造器(如有继承,先执行基类的构造器). 原文地址:https://

java学习笔记——java中对象的创建,初始化,引用的解析

如果有一个A类. 1.例如以下表达式: A  a1 = new A(); 那么A是类,a1是引用.new A()是对象.仅仅是a1这个引用指向了new A()这个对象. 2.又如: A  a2; A代表类,a2仅仅是一个引用,仅仅是a2指向的对象为空NULL. 3.再如: a2 = a1: 它代表的是a2是一个引用,a1也是一个引用:在这个过程中a1所指向对象的地址传给了a2,使得a2.a1指向同一对象. 4.引用 如以下代码片段: int  k; // base data type A  a;

Java中 对象的创建于调用

Main方法是程序的主入口,想要用某个方法必须在main方法中调用 创建对象: 类名 对象名 = new 类名(); 使用对象访问类中的成员: 对象名.成员变量: 对象名.成员方法(); 成员变量的默认值 对象的使用格式举例 public class StudentTest_01 { public static void main(String[] args) { //创建对象格式,类名 对象名 = new 类名(); //无参数使用方法 Student s2 = new Student();

Java 对象的创建过程

类的初始化与实例化一个 Java 对象的创建过程往往包括类的初始化 和 实例化 两个阶段.Java 规范规定一个对象在可以被使用之前必须要被正确地初始化.在类初始化过程中或初始化完毕后,根据具体情况才会去对类进行实例化.在实例化一个对象时,JVM 首先会检查相关类型是否已经加载并初始化,如果没有,则 JVM 立即进行加载并调用类构造器完成类的初始化.Java 对象的创建方式一个对象在可以被使用之前必须要被正确地实例化.在 Java 程序中,有多种方法可以创建对象,最直接的一种就是使用 new 关

Effective Java 读书笔记(2创建和销毁对象)

第一章是引言,所以这里不做笔记,总结一下书中第一章的主要内容是向我们解释了这本书所做的事情:指导Java程序员如何编写出清晰.正确.可用.健壮.灵活和可维护的程序. 2.1考虑用静态工厂方法代替构造器 静态工厂方法与构造器相比有四大优势: (1)静态工厂方法有名称,具有适当名称的静态工厂方法易于使用.易于阅读: (2)不必每次在调用它们的时候都创建一个新的对象: (3)可以返回原返回类型的任何子类型的对象: (4)在创建参数化类型实例的时候,它们使代码变得更加简洁. 同时静态工厂方法也有两大缺点

effective java读书笔记1——创建和销毁对象

今天刚开始读effective java,中文版的读起来很拗口,但感觉收获很多. 另外,这本书的内容是针对Java 1.5和1.6的. 在这里整理一下第2章:创建和销毁对象 的内容. 第一条:考虑用静态工厂方法代替构造器 这一条针对的情景是要获得类的实例时.一般说来,想要获得类的实例,都是通过构造函数(书里叫做构造器). 最常见的构造函数是这样的,没有返回参数,名字和类名相同. public class A{ public A(int a){ //构造函数内容 ... } } 而所谓的静态工厂,

[ Java学习基础 ] Java对象的创建和销毁

类实例化可生成对象,实例方法就是对象方法,实例变量就是对象属性.一个对象的生命周期包括三个阶段:创建.使用和销毁. 创建对象 创建对象包括两个步骤:声明和实例化. 声明 声明对象与声明普通变量没有区别,语法格式如下: type objectName; 其中type是引用类型,即类.接口和数组.示例代码如下: String name; 该语句声明了字符串类型对象name.可以声明并不为对象分配内存空间,而只是分配一个引用. 实例化 实例化过程分为两个阶段:为对象分配内存空间和初始化对象,首先使用n