java是一种面向对象语言,所以我们在写代码过程中会创建很多对象,那java创建的对象到底有多少种呢?其中每种的差别又有哪些呢?请允许我慢慢道来
1.使用new关键字
这是最常见也是使用最多的一种。
Test test = new Test();// 无参构造函数
如果我们想要在创建对象的时候,初始化其一些属性,那么就可以使用有参构造函数
Test test = new Test(name);
但有时候我们会遇到这种情况情况
编译提示错误,提示信息告诉我们,这个类的构造函数是private(私有的),外部无法使用,那么此时也不要担心,在我们设计这个类的时候,我们需要清楚的知道这个类的作用目的,以便我们更好的设计它的使用范围,隐藏一个类new方式创建对象的时候,一定会提供其他方法给你创建对象。例如我们最常见的单例模式(暂时不详细讲解单例模式)
那么在使用了new后,到底发生了什么呢?
2.使用反射的方式创建对象
当我们有一定的基础过后,我们就会发现,在某些情况下,new的方式并不适合解决问题,我们需要一个动态的方式来随心所欲的创建对象。
2.1 Class.forName("包名.类名")
Test test = (Test) Class.forName("com.xxx.Test").newInstance();
为什么通过一个类的名字就可以得到它的对象呢?
我们知道java是一个需要先编译在运行的语言,在编译期间,jvm会将每一个class记录,保存一份class的元数据,当我们通过Class.forName方法就可以调取到该类型的元数据,从而来得到这个类型的Class,进而可以通过newInstance()方法,初始化该类,得到实例对象。
有使用过jdbc的同学应该都知道Class.forName("com.mysql.jdbc.Driver");
sun公司在针对java连接数据的开发上只预留了接口和JDBC规范,其具体实现交个各个厂商按照规范自己来完成,想要java可以连接到你的数据库那你就自己写个包吧。
在Class.forName过程中,JVM就会查找到该指定类,且在JDBC规范中明确要求实现的类必须向DriverManager注册自己
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
}
在这个过程中已经初始化该类了,只需要调用Class.forName("xxx")就行了不需要再newInstance();
2.2 Test.class.newInstance();
此种方法与2.1基本一致,只不过其Class是通过类名.class得来的
2.3 Constructor<Test> constructor = Test.class.getConstructor();
Test test = constructor.newInstance();
先通过Class获得其构造器,再调用newInstance()方法
查看Class.newInstance()源码
其实Class调用newInstance内部还是先得到Constructor对象,再调用其newInsance方法。
3.使用clone方法
该类应先实现接口Cloneable,在调用clone()方法
观察代码及输出结果发现,该方法创建的对象只是浅拷贝对象,新的对象在堆中开辟新的内存块,但是其内部属性都是引用克隆对象的属性,当我们改变第一个对象的属性时其克隆对象属性也随之改变,所以其只是浅复制。
4. 使用序列化再反序列化得到其的深拷贝复制对象
通过运行结果可以发现,其所有属性都是独立的,不会互相影响,所以该方式为深拷贝
但是该方式创建对象代价太大,一般不建议使用。
关于深拷贝的方案还有其他可行方案,比如new创建新对象,并将其属性一一复制,但该方案需要一个类型实现一次,还可以使用第三方jar来实现,就不一一说明了。
以上就是关于Java创建对象的几种方式,还有其他方式,但用到的机会不大,就不做说明了。