老生常谈…对于大佬们根本都不用看的博客!
对于像我这种菜鸡还是得一步一步的来!如果有错误请大佬们指点指点!
创建Java对象的方法
通过 new 关键字
User user = new User();
这是最常用的创建对象方法,通过new关键字调用类的无参构造方法或有参构造方法。
通过 Class 类的 newInstance() 方法
User user = (User) Class.forName("User").newInstance();
这是通过反射调用无参构造方法来创建对象。
通过 Constructor 类的 newInstance 方法
User user = (User) User.class.getConstructors()[0].newInstance();
这是也是通过反射调用无参构造方法来创建对象。
由此可见,反射YYDS!!!
利用 Clone 方法
class User implements Cloneable{
private String name;
private Integer age;
public User() {
}
public User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
}
User user = new User();
User copyUser = user.clone();
通过 对象A.clone() 方法会创建一个和对象 A 一模一样的对象 B。clone 克隆,顾名思义就是创建一个一模一样的对象出来。(我认为多此一举,了解即可)
注意: clone()方法是Object里面的protected方法,只允许在同包和子类内部调用。
通过序列化的方式进行创建
序列化是把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。
反序列化则是把磁盘文件中的对象数据或者把网络节点上的对象数据,恢复成Java对象模型的过程。
涉及IO的操作后续会更新,了解即可!
创建对象的流程
初步了解JVM内存模型
- 栈内存 存放基本类型数据和对象的引用变量。
- 堆内存 存放创建的对象和数组。
1.JVM生成.class文件
java文件会在编译期间被初始化生成.class字节码文件。
2.类加载器加载.class文件
把class文件变成一个二进制流加载到内存中。
3.连接和初始化
- (还未被初始化)首先为静态static变量内存中分配存储空间,设立初始值。(实际上所有的初始值都为最初的默认值,除非加上了final 修饰词那么初始值就是设定的值)
- 接着对已经分配存储空间的静态变量真正赋值。(包含静态代码块等以此类推)
4.创建实例
加载完类后,对象的所需大小就可以确认了,具体创建的步骤如下:
- 先给对象分配内存并设置默认值,如果有引用对象那么会在栈内存中申请一个空间用来指向的实际对象。
- 执行初始化代码实例化,先初始化父类再初始化子类,赋予给定值。
- 对象实例化完毕后如果存在引用对象的话还需要把第一步的栈对象指向到堆内存中的实际对象,这样一个真正可用的对象才被创建出来。
总结
我理解的大概流程如图所示:
反射和new效率对比
反射和new各创建100000000个进行比较时间结果如图所示:
看来反射的速度略逊一筹!
clone()和new效率比较
同样clone()与new各创建100000000个进行比较时间结果如图所示:
看来clone()的速度也略逊一筹啊。
如果在构造函数中增加一些耗时的方法,则clone()将会超过new的方法。所以要根据实际的场景来判断速度快慢!