引用

前言

java中对象创建的方法主要包括,1,使用new关键字,2.使用clone方法,3.反射机制,4.反序列化。其中1,3都会明确的显式的调用构造函数。2是在内存上对已有对象的影印,所以不会调用构造函数。4是从文件中还原类的对象,也不会调用构造函数。本文将简要列举这些对象创建的方法,并做一些简单的分析总结。

创建对象的方法

调用构造函数

  • 代码如下所示:
public class ConstructorTest {

    public ConstructorTest() {
System.out.println("run in constructor");
} public static void main(String[] args) throws Exception {
//使用new构建对象
ConstructorTest t1 = new ConstructorTest();
System.out.println(t1); //使用反射构建对象
Class<?> clazz = Class.forName("org.editice.study.constructor.ConstructorTest");
Constructor<?> cons[] = clazz.getConstructors();
ConstructorTest t2 = (ConstructorTest) cons[0].newInstance();
System.out.println(t2);
}
}

new表达式方式

  • 直接调用函数构造器,实际上由以下两个步骤完成

      1. 创建空对象,(此时类型已经是正确的),字节码为new
      1. 调用某个版本的构造器,对应的字节码是invokespecial <init>
    • 字节码如图:

反射方式

  • 反射调用函数构造器,字节码如下图所示

不调用构造函数

  • 代码如下所示:
public class InstanceWithoutConstructorTest {

    public InstanceWithoutConstructorTest() {
System.out.println("run in constructor");
} public static void main(String[] args) throws Exception{
//allocateInstance方式
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe us = (Unsafe) f.get(null);
InstanceWithoutConstructorTest t1 = (InstanceWithoutConstructorTest) us.allocateInstance(InstanceWithoutConstructorTest.class);
System.out.println(t1); //java反序列化方式
ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
Constructor constructor = rf.newConstructorForSerialization(InstanceWithoutConstructorTest.class, Object.class.getConstructor());
InstanceWithoutConstructorTest t2 = (InstanceWithoutConstructorTest) constructor.newInstance();
System.out.println(t2);
}
}
  • 运行结果如下所示:

java反序列化方式

  • 在Sun Jdk的实现里,java层面的反射类库与JVM层面的反射实现相互配合来完成反序列化。java.io.ObjectStreamClass通过跟反射方法/构造器调用类似的机制来获取所谓的“序列化构造器”,在反序列化的时候调用这个版本的构造器。
  • 创建“序列化构造器”时要在继承链里从最具体向最抽象的方向搜索,找到第一个不可序列化的类(没有实现Serializable接口的类),并找出它的无参构造器来调用。也就是说反序列化的时候并不是完全不调用用户代码里面声明的构造器,只是不调用实现了Serializable的类而已。ps:实际上都是调用了object的无参构造器。
  • java的反序列化实际上是调用了基类的构造方法,创建对象也是两个步骤:
      1. 创建出空对象(此时类型已经是正确的了)
      1. 调用用户自定义的反序列化方法(readObject,如果有的话)或者调用默认的反序列化方法。

allocateInstance方式

  • 其实allocateInstance方式也只是反序列化方式中的一种。这里只是简单的介绍一下。

java创建对象方法列表的更多相关文章

  1. Java创建对象的几种方法

    有时候,也可能碰到这样面试题,如: Java创建对象有哪几种方法? 除了new之外,java创建对象还有哪几种方式? 本文结合例子,给出几种Java创建对象的方法,Here we go~~~~ 使用n ...

  2. JAVA 创建对象4种方法

    java创建对象的几种方式 博客分类: java   (1) 用new语句创建对象,这是最常见的创建对象的方法.(2) 运用反射手段,调用java.lang.Class或者java.lang.refl ...

  3. Java创建对象的六种方法-权当记录一下

    1 简介 Java是面向对象的编程语言,只要使用它,就需要创建对象.Java创建对象有六种方法,实际常用的不会这么多,这里权当是记录一下. 2 六种方法 (1)使用new关键字 Pumpkin p1 ...

  4. 转:最近5年133个Java面试问题列表

    最近5年133个Java面试问题列表 Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试,但是现在问题变得越来 ...

  5. 近5年133个Java面试问题列表

    Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试,但是现在问题变得越来越高级,面试官问的问题也更深入. 在我 ...

  6. 最近5年183个Java面试问题列表及答案[最全]

    Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别(String 类型和 StringBuffer 类型的主要性能区别其实在于 Stri ...

  7. 最近5年133个Java面试问题列表

    Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试,但是现在问题变得越来越高级,面试官问的问题也更深入. 在我 ...

  8. Java创建对象的过程

    Java创建对象的过程 Java是一门面向对象的编程语言,在Java程序运行过程中每时每刻都有对象被创建出来.在语言层面上,创建对象通常仅仅是一个new关键字而已,而在虚拟机中,对象的创建又是怎样一个 ...

  9. 转 最近5年183个Java面试问题列表及答案[最全]

    Java 面试随着时间的改变而改变.在过去的日子里,当你知道 String 和 StringBuilder 的区别(String 类型和 StringBuffer 类型的主要性能区别其实在于 Stri ...

随机推荐

  1. adb 配置连接

    一. adb环境安装 1.1. windown 驱动安装 1. 下载驱动(ADB Kits):http://adbshell.com/downloads 2. adb 测试 <1>. 解压 ...

  2. 使用CSDN-markdown编辑器粘贴代码块时崩溃问题解决

    原因:代码段换行符失效,所有代码一行显示 解决方法:使用Chrome浏览器即可解决(使用Microsoft Edge会出现此问题) 效果展示: # _*_ coding:utf-8 _*_ impor ...

  3. HDU1688-POJ3463-Sightseeing(求次短路的条数)

    题意 求出最短路和次短路的条数,当次短路比最短路长度小1时,输出条数之和,反之输出最短路条数. 题解  dis1[],cnt1[],dis2[],cnt2[] 分别表示最短路的长度和条数,次短路的长度 ...

  4. luogu P1232 [NOI2013]树的计数

    传送门 这题妙蛙 首先考虑构造出一个合法的树.先重新编号,把bfs序整成\(1,2,3...n\),然后bfs序就是按照从上到下从左往右的遍历顺序,所以可以考虑对bfs序分层,可以知道分层方式只会对应 ...

  5. NSString用法,object-C数组以及字符串拼接和分割

    一.介绍使用NSString创建一个字符串的代码如下: #import <Foundation/Foundation.h>int main (int argc, char *argv[]) ...

  6. 019-openstack组件使用的默认端口号

    一.OpenStack组件使用的默认端口号 openstack openstack service default ports port type keystone Identity service ...

  7. VB TreeView控件使用详解(有趣的示例)

    第一小时:学习直接用代码将数据填充到树控件中. 为什么要先学习直接用代码将数据填充到树控件中?因为这种方法是最简单的,代码也最容易理解,学习树控件,先将这个学会,已经掌握了一半,所以先不要急着想怎么将 ...

  8. hdu 3530 单调队列最值

    /** HDU 3530 单调队列的应用 题意: 给定一段序列,求出最长的一段子序列使得该子序列中最大最小只差x满足m<=x<=k. 解题思路: 建立两个单调队列分别递增和递减维护(头尾删 ...

  9. jmeter性能压测瓶颈排查-网络带宽

    问题: 有一台机器做性能压测的时候,无论开多少个线程,QPS一直压不上去,而服务器和数据库的性能指标(主要是CPU和内存)一直维持在很低的水平. 希望帮忙排查一下原因. 过去看了下进行压测的接口代码, ...

  10. pull request的使用

    在git中,不少开发者对自己的提升非常看重,github中的开源项目就是一个非常好的学习资料. github中的开源项目并不是完全正确的,而成为项目贡献者是一件值得骄傲的事情. 所以如何才能对开源项目 ...