经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
Java类实例化原理
来源:cnblogs  作者:那股泥石流  时间:2018/11/6 10:22:22  对本文有异议

Java对象的创建过程包括 类初始化(JVM类加载机制类实例化两个阶段。

一、Java对象创建时机

(1)使用new关键字创建对象

(2)反射创建对象

  使用Class类的newInstance方法

    Student student2 = (Student)Class.forName("Student类全限定名").newInstance();

  使用Constructor类的newInstance方法

    Constructor<Student> constructor = Student.class.getConstructor(Integer.class);

    Student stu3 = constructor.newInstance(123);

 (3)使用Clone方法创建对象(实现Cloneable接口)

  无论何时我们调用一个对象的clone方法,JVM都会帮我们创建一个新的、一样的对象,特别需要说明的是,用clone方法创建对象的过程中并不会调用任何构造函数。

(4)使用(反)序列化机制创建对象(实现Serializable接口)

  当我们反序列化一个对象时,JVM会给我们创建一个单独的对象,在此过程中,JVM并不会调用任何构造函数。

二. Java 对象的创建过程

当一个对象被创建时,虚拟机就会为其分配内存来存放对象自己的实例变量及其从父类继承过来的实例变量(即使这些从超类继承过来的实例变量有可能被隐藏也会被分配空间)。

在为这些实例变量分配内存的同时,这些实例变量也会被赋予默认值(零值)。

 

主要涉及三种执行对象初始化的结构,分别是 实例变量初始化、实例代码块初始化、构造函数初始化

编译器构造类的构造函数<init>()(按顺序执行):

  父类构造器

  实例变量初始化和实例代码块初始化相关代码

  本身构造函数

1、实例变量初始化和实例代码块初始化按照编程顺序来执行,不允许顺序靠前的实例代码块访问其后面定义的实例变量,但是可以赋值。

  1. // 编译错误:代码块不可以访问其后定义的实例变量
  2. public class InstanceInitializer {
  3. {
  4. j = i;
  5. }
  6. private int i = 1;
  7. private int j;
  8. }
  9. // 没问题:代码块可以赋值其后定义的实例变量
  10. public class InstanceInitializer {
  11. {
  12. j = 1;
  13. }
  14. private int i = 1;
  15. private int j;
  16. }

2、每一个Java中的对象都至少会有一个构造函数,如果我们没有显式定义构造函数,那么它将会有一个默认无参的构造函数。

  Java强制要求所有对象(Object是Java的顶层对象,没有超类)构造函数的第一条语句必须是超类构造函数的调用语句或者是类中定义的其他的构造函数(super()/this()必须在第一句,且不能同时出现)。如果我们既没有调用其他的构造函数,也没有显式调用超类的构造函数,那么编译器会为我们自动生成一个对超类构造函数的调用

3、实例化一个类的对象的过程是一个典型的递归过程。

  首先实例化Object类,再依次对以下各类进行实例化,直到完成对目标类的实例化。

三、综合实例

  1. // 父类
  2. class Foo {
  3. int i = 1;
  4. Foo() {
  5. System.out.println(i);// -----------(1)
  6. int x = getValue();
  7. System.out.println(x);// -----------(2)
  8. }
  9. {
  10. i = 2;
  11. }
  12. protected int getValue() {
  13. return i;
  14. }
  15. }
  16. // 子类
  17. class Bar extends Foo {
  18. int j = 1;
  19. Bar() {
  20. j = 2;
  21. }
  22. {
  23. j = 3;
  24. }
  25. @Override
  26. protected int getValue() {
  27. return j;
  28. }
  29. }
  30. public class ConstructorExample {
  31. public static void main(String... args) {
  32. Bar bar = new Bar();
  33. System.out.println(bar.getValue());// -----------(3)
  34. }
  35. }
  36. /*
  37. * Output: 2 0 2
  38. */
  39.  
  40. //Foo类构造函数的等价变换:
  41. Foo() {
  42. i = 1;
  43. i = 2;
  44. System.out.println(i);
  45. int x = getValue();// 在执行Foo的构造函数的过程中,由于Bar重载了Foo中的getValue方法,所以其调用的是Bar的getValue方法
  46. System.out.println(x);
  47. }
  48. //Bar类构造函数的等价变换
  49. Bar() {
  50. Foo();
  51. j = 1;
  52. j = 3;
  53. j = 2
  54. }

 

 

参考资料:

深入理解Java对象的创建过程:类的初始化与实例化

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号