JAVA中对于需要频繁new的对象的一个优化的方法

1.前言

在实际开发中,某些情况下,我们可能需要频繁去创建一些对象(new),下面介绍一种,我从书上看到的,可以提高效率的方法。

首先,对于将会频繁创建的对象,我们要让这个类实现Cloneable接口,因为这个优化的核心,就是利用clone。

clone的最大特点就是,不会去调用任何构造方法,所以,在我看来重点应该放在构造方法中。

废话少说,先上一个简单的测试代码吧:

package util;

public class Main {

	public static void main(String[] args) {
		long beginTime = System.currentTimeMillis();

		for (int i = 0; i < 100; i++) {
			Person.getOnePerson();
		}

		long endTime = System.currentTimeMillis();
		System.out.println("采用clone的方法,一共花费的时间:" + (endTime - beginTime));

		beginTime = System.currentTimeMillis();

		for (int i = 0; i < 100; i++) {
			new Person();
		}

		endTime = System.currentTimeMillis();
		System.out.println("采用new的方法,一共花费的时间:" + (endTime - beginTime));
	}

}

class TestA {
	private String aa;

	public TestA() {
		// 模拟一下耗时操作
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public String getAa() {
		return aa;
	}

	public void setAa(String aa) {
		this.aa = aa;
	}

}

class TestB extends TestA {
	private String bb;

	public TestB() {
		// 模拟一下耗时操作
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public String getBb() {
		return bb;
	}

	public void setBb(String bb) {
		this.bb = bb;
	}

}

class Person extends TestB implements Cloneable {
	private String id;
	private String name;
	private static Person person = new Person();
	private int[] temp = null;

	// 这里理应设置为private的,但是为了在上面测试方便,这里就将其设置为public了
	// 但是,在真正开发中时,为了避免误导开发人员,应该将构造函数私有化
	public Person() {

	};

	public static Person getOnePerson() {
		try {
			return (Person) person.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 模拟有参构造方法
	public static Person getOnePersonWithInitName(String name) {
		try {
			Person tempPerson = (Person) person.clone();
			tempPerson.name = name;
			return tempPerson;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int[] getTemp() {
		return temp;
	}

	public void setTemp(int[] temp) {
		this.temp = temp;
	}

}

看一下,在我本机上的运行效果吧



可以很明显的看出,同样是循环100次,采用clone的方式要比new方式快得多得多。而且,从clone一共花费的时间,可以很轻松的看出并证实了我前面说的:“clone的最大特点就是,不会去调用任何构造方法“”。

2.简要说明

我来稍微说明一下,我上面的测试代码,为什么要这样写吧。


2.1.我之所以是创建TestA,TestB这两个看似毫无意义的类,并让TestB继承TestA,让Person继承TestB,主要是为了模拟构造函数递归调用的过程。各位应该也知道,当一个类存在继承关系时,你创建一个子类的对象时,如果在没有明确指定的情况下,子类是会隐式的去调用父类的无参构造的。假设,我们需要频繁创建的对象,是一个继承关系比较深的类的话,调用构造函数的开销不容小窥啊。


2.2.各位如果看一下我的测试代码的话,应该不难看出,我在TestA和TestB这两个类的构造函数中,都加了一个睡眠,用于模拟一些耗时操作。(当然,在实际开发中,耗时操作不一定是10毫秒,可能更高或者更低,这里主要是为了演示体现效果罢了)。如果当我们用new关键字去创建对象时,而这些对象的构造方法中,有可能会做某些事情,比如去初始化一些什么,或者准备一些什么等等。这些都是消耗不少时间的。如果一时间内,频繁创建某对象时,这些平时不显眼的消耗一叠加起来,就变得很客观了。但是,当我们使用clone的话,就可以避免这个问题。


3.个人一些看法和补充

3.1方法名字很重要

在实际开发中,我们需要的不仅仅是无参构造,还有可能是有参构造。但是,当我们屏蔽了构造函数之后,一个可以让我们获取这个类对象的方法的方法名,就显示尤为重要了:比如,我上面写到的getOnePerson()和getOnePersonWithInitName(String name)。

因为屏蔽了构造函数,上面这两个方法就充当了构造函数的角色。当名字起得不好的时候,入参的名字起得不好的时候,是很容易让别人困惑的。当

然,你说可以用注释嘛。但是,在我看来,真正好的代码,是应该具有自述性的。就是仅仅可以从方法名和入参名之间,就知道这个方法的意义和作用。虽然注释很有用,但是你要明白,注释和代码的更新,往往是不同步的啊。当代码和注释失配时,就很坑爹了!!而且,其实,让这些方法来充当构造函数时,无疑是在无形之间,增加了学习的成本。

3.2利用clone的这种创建对象的方式,和工厂模式很配哦~


  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值