【Java】new的过程发生了什么?看完这一篇就懂了

new的过程发生了什么?看完这一篇就懂了

Java攻城师发布于 今天 08:51

在现实世界中,找对象是一门学问,找对象不在于多而在于精

【Java】new的过程发生了什么?看完这一篇就懂了

在计算机世界中,面向对象编程的关键在于能否灵活地运用类,如何设计出一个符合需求的对象也是也是值得学习和思考的。

那么,面向对象编程到底是什么?

在面向对象编程中,肯定会涉及类和对象两个概念。类是什么?对象是什么,两者有什么关系?

接下来就一 一地来解答这些疑惑吧

【Java】new的过程发生了什么?看完这一篇就懂了

类和对象

  • 类,是指将相同属性的东西放在放在一起,类是一个模板,能够描述一类对象的状态和行为
  • 而对象,就是实际存在某个类中的一个个的个体,所以也被称为实例(instance)。
  • 对象的抽象是类,类的具体化就是对象,也就是类的实例就是对象。

在C语言中,结构体是数据的集合,它将数据捆绑在一起,使得我们可以将这些数据看作是一个整体。而对结构体中的数据 进行操作的函数就写在结构体的外部。

而在面向对象编程中,将表示事物行为的函数也放入了这个整体,就形成了对象的概念。使得这个整体既描述属性,又能描述行为。

所以,面向对象编程是一种将关注点置于对象Object本身的程序设计方法,对象的构成要素包含对象的行为及操作,以此基础进行编程。

这种方法使得程序易于复用。OOP主要使用的编程技巧有:继承、封装、多态三种。

说了这么多,是不是看晕了,没关系,继续往下看。

现实世界中的抽象

在现实生活中,可以将人看成一个类,这类称为人类(抽象类)

如果某个男孩想找一个对象(女朋友),那么所有的女孩都是这个男孩选女朋友的范围,所有的女孩就是一【类】

  • 对象

如果这个时候男孩已经找到喜欢的对象了,他的女朋友名字叫【林允儿】。那么假设这个名字是唯一的,此时名字叫【林允儿】的这个女孩就是一个对象(小声bb,其实{她是我老婆|hē hē hē hē}[狗头])

【Java】new的过程发生了什么?看完这一篇就懂了

接下来通过具体的代码来讲解一下

// FileName: Person.java

public abstract class Person {

protected int age;

protected String name;

public Person(int age,String name) {

this.age = age;

this.name = name;

}

public abstract void speak();

public abstract void sayInfo(Person person);

}

复制代码

在这里,定义了一个抽象类-人,在人的这个抽象类里面,包含了人的一些属性和行为,代表了人具有的共同属性

然后,定义了一个子类Man和子类Woman继承父类Person,里面包含了共同拥有的属性,并增加了性别sex,然后对方法进行了重写

// FileName: Man.java

public class Man extends Person {

private String sex = "man";

public Man(int age,String name) {

super(age,name);

}

@Override

public void speak() {

System.out.println("我的名字是: " + super.name + "n" + "我今年" + super.age + "岁了.");

};

@Override

public void sayInfo(Person person) {

System.out.println("我的女朋友是:" + person.name + "n" + "她今年" + person.age + "岁了.");

}

}

复制代码


// FileName: WoMan.java

public class WoMan extends Person {

private String sex = "woman";

public WoMan(int age,String name) {

super(age,name);

}

@Override

public void speak() {

System.out.println("我的名字是: " + super.name + "n" + "我今年" + super.age + "岁了.");

};

@Override

public void sayInfo(Person person) {

System.out.println("我的男朋友是:" + person.name + "n" + "她今年" + person.age + "岁了.");

}

}

复制代码

那么,他们的关系就是如下图: 【Java】new的过程发生了什么?看完这一篇就懂了

所以,一个类的基本组成为下图:【Java】new的过程发生了什么?看完这一篇就懂了

那么,我们再来编写下测试代码:

// FileName: TestPerson.java

public class TestPerson {

/**

* @param args

*/

public static void main(String[] args) {

Person codevald = new Man(21,"codevald");

Person lye = new Woman(20,"linyuer");

codevald.speak();

codevald.sayInfo(lye);

lye.speak();

lye.sayInfo(codevald);

}

}

复制代码

运行结果: 【Java】new的过程发生了什么?看完这一篇就懂了

接下来,是最有意思的部分,我们来分析下代码中new的时候发生了什么。

new操作的过程

当我们new一个对象的时候JVM首先会去找到对应的类元信息,如果找不到意味着类信息还没有被加载,所以在对象创建的时候也可能会触发类的加载操作。当类元信息被加载之后,我们就可以通过类元信息来确定对象信息和需要申请的内存大小。

对象创建的流程

1.构建对象

首先main线程会在栈中申请一个属于自己的栈空间,然后我们调用main方法的时候,会生成一个main方法的栈帧,然后执行new Man(),这里会根据Man类的元信息先确定对象的大小,然后在JVM堆里申请一块内存区域并构建对象,同时对Man对象成员变量信息 并赋予默认值(在这里会涉及多态,在内存中的分配情况有机会再解释解释)。

【Java】new的过程发生了什么?看完这一篇就懂了

2.初始化对象

这一步会执行对象内部的init方法,初始化成员变量值,即执行对象的构造方法(这里调用父类的构造方法进行赋值),构造方法执行完,此时的age = 21,name = "codevald"。

【Java】new的过程发生了什么?看完这一篇就懂了

3.引用对象

对象实例化完成之后,再把栈中的Person对象引用地址指向Man对象在堆内存中的地址

【Java】new的过程发生了什么?看完这一篇就懂了

4.继续构造、初始化,引用对象对象

这一步和上面三个步骤一样,就不详细说了 附上图

【Java】new的过程发生了什么?看完这一篇就懂了【Java】new的过程发生了什么?看完这一篇就懂了【Java】new的过程发生了什么?看完这一篇就懂了

5.调用方法

调用speak()方法的时候,会先找到Person对象(codevald)中的引用地址,找到真正的在堆内存中的Man对象,执行speak()方法,执行的时候,会调用父类中的成员变量,所以会找到堆内存中的父对象的成员变量(name和age),加载进来,进行输出

我的名字是: codevald 我今年21岁了.

【Java】new的过程发生了什么?看完这一篇就懂了

调用sayInfo()方法的时候,一样先找到对象(codevald)中的引用地址,找到真正的在堆内存中的Man对象,执行sayInfo()方法,执行的时候,会找到Person对象(linyuner)的地址,即指向堆内存中的Woman对象,找到父类里面的成员变量(name和age),进行输出

我的女朋友是:linyuer 她今年20岁了.

【Java】new的过程发生了什么?看完这一篇就懂了

下面的代码的执行过程同理,就留给小伙伴们自行去分析啦~

附上TestPerson的字节码文件,感兴趣的小伙伴可以自行查看进行分析

Compiled from "TestPerson.java"

public class person.TestPerson {

public person.TestPerson();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."<init>":()V

4: return

public static void main(java.lang.String[]);

Code:

0: new #7 // class person/Man

3: dup

4: bipush 21

6: ldc #9 // String codevald

8: invokespecial #11 // Method person/Man."<init>":(ILjava/lang/String;)V

11: astore_1

12: new #14 // class person/Woman

15: dup

16: bipush 20

18: ldc #16 // String linyuer

20: invokespecial #18 // Method person/Woman."<init>":(ILjava/lang/String;)V

23: astore_2

24: aload_1

25: invokevirtual #19 // Method person/Person.speak:()V

28: aload_1

29: aload_2

30: invokevirtual #24 // Method person/Person.sayInfo:(Lperson/Person;)V

33: aload_2

34: invokevirtual #19 // Method person/Person.speak:()V

37: aload_2

38: aload_1

39: invokevirtual #24 // Method person/Person.sayInfo:(Lperson/Person;)V

42: return

}

复制代码

学无止境,我们曾经擅长的正在被淘汰,不擅长的却是仍然存在。最基础的往往是最难的,而往往也是最重要的,平时注重基础的积累,学会去分析底层的执行过程,才是学习中最应该掌握的技能,希望这篇回答能帮到正在寻找这个问题的答案的你~

参考:《2020最新Java基础精讲视频教程和学习路线!》

链接:https://juejin.cn/post/692241...

java程序员spring后端springboot

阅读 35发布于 今天 08:51

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

avatar

Java攻城师

本人太过于丰富,无法简介

226 声望

352 粉丝

0 条评论

得票时间

avatar

Java攻城师

本人太过于丰富,无法简介

226 声望

352 粉丝

宣传栏

在现实世界中,找对象是一门学问,找对象不在于多而在于精

【Java】new的过程发生了什么?看完这一篇就懂了

在计算机世界中,面向对象编程的关键在于能否灵活地运用类,如何设计出一个符合需求的对象也是也是值得学习和思考的。

那么,面向对象编程到底是什么?

在面向对象编程中,肯定会涉及类和对象两个概念。类是什么?对象是什么,两者有什么关系?

接下来就一 一地来解答这些疑惑吧

【Java】new的过程发生了什么?看完这一篇就懂了

类和对象

  • 类,是指将相同属性的东西放在放在一起,类是一个模板,能够描述一类对象的状态和行为
  • 而对象,就是实际存在某个类中的一个个的个体,所以也被称为实例(instance)。
  • 对象的抽象是类,类的具体化就是对象,也就是类的实例就是对象。

在C语言中,结构体是数据的集合,它将数据捆绑在一起,使得我们可以将这些数据看作是一个整体。而对结构体中的数据 进行操作的函数就写在结构体的外部。

而在面向对象编程中,将表示事物行为的函数也放入了这个整体,就形成了对象的概念。使得这个整体既描述属性,又能描述行为。

所以,面向对象编程是一种将关注点置于对象Object本身的程序设计方法,对象的构成要素包含对象的行为及操作,以此基础进行编程。

这种方法使得程序易于复用。OOP主要使用的编程技巧有:继承、封装、多态三种。

说了这么多,是不是看晕了,没关系,继续往下看。

现实世界中的抽象

在现实生活中,可以将人看成一个类,这类称为人类(抽象类)

如果某个男孩想找一个对象(女朋友),那么所有的女孩都是这个男孩选女朋友的范围,所有的女孩就是一【类】

  • 对象

如果这个时候男孩已经找到喜欢的对象了,他的女朋友名字叫【林允儿】。那么假设这个名字是唯一的,此时名字叫【林允儿】的这个女孩就是一个对象(小声bb,其实{她是我老婆|hē hē hē hē}[狗头])

【Java】new的过程发生了什么?看完这一篇就懂了

接下来通过具体的代码来讲解一下

// FileName: Person.java

public abstract class Person {

protected int age;

protected String name;

public Person(int age,String name) {

this.age = age;

this.name = name;

}

public abstract void speak();

public abstract void sayInfo(Person person);

}

复制代码

在这里,定义了一个抽象类-人,在人的这个抽象类里面,包含了人的一些属性和行为,代表了人具有的共同属性

然后,定义了一个子类Man和子类Woman继承父类Person,里面包含了共同拥有的属性,并增加了性别sex,然后对方法进行了重写

// FileName: Man.java

public class Man extends Person {

private String sex = "man";

public Man(int age,String name) {

super(age,name);

}

@Override

public void speak() {

System.out.println("我的名字是: " + super.name + "n" + "我今年" + super.age + "岁了.");

};

@Override

public void sayInfo(Person person) {

System.out.println("我的女朋友是:" + person.name + "n" + "她今年" + person.age + "岁了.");

}

}

复制代码


// FileName: WoMan.java

public class WoMan extends Person {

private String sex = "woman";

public WoMan(int age,String name) {

super(age,name);

}

@Override

public void speak() {

System.out.println("我的名字是: " + super.name + "n" + "我今年" + super.age + "岁了.");

};

@Override

public void sayInfo(Person person) {

System.out.println("我的男朋友是:" + person.name + "n" + "她今年" + person.age + "岁了.");

}

}

复制代码

那么,他们的关系就是如下图: 【Java】new的过程发生了什么?看完这一篇就懂了

所以,一个类的基本组成为下图:【Java】new的过程发生了什么?看完这一篇就懂了

那么,我们再来编写下测试代码:

// FileName: TestPerson.java

public class TestPerson {

/**

* @param args

*/

public static void main(String[] args) {

Person codevald = new Man(21,"codevald");

Person lye = new Woman(20,"linyuer");

codevald.speak();

codevald.sayInfo(lye);

lye.speak();

lye.sayInfo(codevald);

}

}

复制代码

运行结果: 【Java】new的过程发生了什么?看完这一篇就懂了

接下来,是最有意思的部分,我们来分析下代码中new的时候发生了什么。

new操作的过程

当我们new一个对象的时候JVM首先会去找到对应的类元信息,如果找不到意味着类信息还没有被加载,所以在对象创建的时候也可能会触发类的加载操作。当类元信息被加载之后,我们就可以通过类元信息来确定对象信息和需要申请的内存大小。

对象创建的流程

1.构建对象

首先main线程会在栈中申请一个属于自己的栈空间,然后我们调用main方法的时候,会生成一个main方法的栈帧,然后执行new Man(),这里会根据Man类的元信息先确定对象的大小,然后在JVM堆里申请一块内存区域并构建对象,同时对Man对象成员变量信息 并赋予默认值(在这里会涉及多态,在内存中的分配情况有机会再解释解释)。

【Java】new的过程发生了什么?看完这一篇就懂了

2.初始化对象

这一步会执行对象内部的init方法,初始化成员变量值,即执行对象的构造方法(这里调用父类的构造方法进行赋值),构造方法执行完,此时的age = 21,name = "codevald"。

【Java】new的过程发生了什么?看完这一篇就懂了

3.引用对象

对象实例化完成之后,再把栈中的Person对象引用地址指向Man对象在堆内存中的地址

【Java】new的过程发生了什么?看完这一篇就懂了

4.继续构造、初始化,引用对象对象

这一步和上面三个步骤一样,就不详细说了 附上图

【Java】new的过程发生了什么?看完这一篇就懂了【Java】new的过程发生了什么?看完这一篇就懂了【Java】new的过程发生了什么?看完这一篇就懂了

5.调用方法

调用speak()方法的时候,会先找到Person对象(codevald)中的引用地址,找到真正的在堆内存中的Man对象,执行speak()方法,执行的时候,会调用父类中的成员变量,所以会找到堆内存中的父对象的成员变量(name和age),加载进来,进行输出

我的名字是: codevald 我今年21岁了.

【Java】new的过程发生了什么?看完这一篇就懂了

调用sayInfo()方法的时候,一样先找到对象(codevald)中的引用地址,找到真正的在堆内存中的Man对象,执行sayInfo()方法,执行的时候,会找到Person对象(linyuner)的地址,即指向堆内存中的Woman对象,找到父类里面的成员变量(name和age),进行输出

我的女朋友是:linyuer 她今年20岁了.

【Java】new的过程发生了什么?看完这一篇就懂了

下面的代码的执行过程同理,就留给小伙伴们自行去分析啦~

附上TestPerson的字节码文件,感兴趣的小伙伴可以自行查看进行分析

Compiled from "TestPerson.java"

public class person.TestPerson {

public person.TestPerson();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."<init>":()V

4: return

public static void main(java.lang.String[]);

Code:

0: new #7 // class person/Man

3: dup

4: bipush 21

6: ldc #9 // String codevald

8: invokespecial #11 // Method person/Man."<init>":(ILjava/lang/String;)V

11: astore_1

12: new #14 // class person/Woman

15: dup

16: bipush 20

18: ldc #16 // String linyuer

20: invokespecial #18 // Method person/Woman."<init>":(ILjava/lang/String;)V

23: astore_2

24: aload_1

25: invokevirtual #19 // Method person/Person.speak:()V

28: aload_1

29: aload_2

30: invokevirtual #24 // Method person/Person.sayInfo:(Lperson/Person;)V

33: aload_2

34: invokevirtual #19 // Method person/Person.speak:()V

37: aload_2

38: aload_1

39: invokevirtual #24 // Method person/Person.sayInfo:(Lperson/Person;)V

42: return

}

复制代码

学无止境,我们曾经擅长的正在被淘汰,不擅长的却是仍然存在。最基础的往往是最难的,而往往也是最重要的,平时注重基础的积累,学会去分析底层的执行过程,才是学习中最应该掌握的技能,希望这篇回答能帮到正在寻找这个问题的答案的你~

参考:《2020最新Java基础精讲视频教程和学习路线!》

链接:https://juejin.cn/post/692241...

以上是 【Java】new的过程发生了什么?看完这一篇就懂了 的全部内容, 来源链接: utcz.com/a/109807.html

回到顶部