引用

前言

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. Bootstrap字体图标Font-Awesome 使用教程

    转载自:https://blog.csdn.net/crper/article/details/46293295   以备记录使用.

  2. Qfile

    打开方式: void AddStudents::write_to_file(QString src){ QFile file("stu.txt"); if (!file.open( ...

  3. [多校联考2019(Round 4 T2)][51nod 1288]汽油补给(ST表+单调栈)

    [51nod 1288]汽油补给(ST表+单调栈) 题面 有(N+1)个城市,0是起点N是终点,开车从0 -> 1 - > 2...... -> N,车每走1个单位距离消耗1个单位的 ...

  4. 使用before和after双伪元素清除浮动

    使用方法: .clearfix:before,.clearfix:after { content:"."; display:table; } .clearfix:after { c ...

  5. SSM框架中数据库无法连接的问题

    首先是SSM框架中所有的配置都是没有问题的,而且项目在其他人的环境上也能正常访问数据库:那么最有可能的就是数据库版本的问题导致数据库连接不上,服务器给我的报错是: 15:37:25.902 [C3P0 ...

  6. 【论文解读】[目标检测]retinanet

    作为单阶段网络,retinanet兼具速度和精度(精度是没问题,速度我持疑问),是非常耐用的一个检测器,现在很多单阶段检测器也是以retinanet为baseline,进行各种改进,足见retinan ...

  7. jsonp跨域请求的方式

    1.jsonp一种请求方式.用于解决一个棘手的问题: 由于浏览器具有同源策略:即可以通过后台去访问其他网站,而不能通过浏览器(ajax请求)访问其他网页或域(阻止ajax请求,但是无法阻止<sc ...

  8. Spring基础08——使用p命名空间

    1.使用p命名空间 为了简化xml配置,越来越多的xml文件采用属性而非子元素配置信息,Spring从2.5版本开始引入了一个新的p命名空间,可以通过<bean>元素属性的方式配置Bean ...

  9. PAT Advanced 1058 A+B in Hogwarts (20 分)

    If you are a fan of Harry Potter, you would know the world of magic has its own currency system -- a ...

  10. Codeforces 954 dijsktra 离散化矩阵快速幂DP 前缀和二分check

    A B C D 给你一个联通图 给定S,T 要求你加一条边使得ST的最短距离不会减少 问你有多少种方法 因为N<=1000 所以N^2枚举边数 迪杰斯特拉两次 求出Sdis 和 Tdis 如果d ...