数组内存分析 面向对象 类和对象 创建对象的内存分析 成员变量 局部变量
尤其内存分析这块,很多人都不重视认为这种东西有什么用,代码会敲不就得了。然而底层原理还是挺重要的,先不说面试会不会提问,弄懂这些对以后代码的学习会有更深刻的理解和感悟。下面的内存分析都是根据老师的教案和结合自己的理解写的。Day05
jvm内存的划分
jvm在执行中会在电脑的内存划分几块区域:栈内存 堆内存 方法区 本地方法区
-
栈内存:基本类型的变量和对象的引用变量,方法中的局部变量都在栈内存中,
是执行方法的区域,方法的运行都在栈内存中运行。每当方法被调用时都会创建一个栈祯,方法进入栈内存被称为进栈,出去时称为出栈
-
堆内存:储存所有new出来的对象和数组,都是引用数据类型,里面的东西每个都有地址值
-
方法区:储存字节码文件(.class)包含方法的信息,常量,静态变量等基本唯一不变的数据
-
本地方法区:用来存储执行的方法
-
程序计数器:用于控制程序的执行流程,决定要执行程序中的哪些代码,字节码解析器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
数组的内存分析
package Chating;
public class Shuzu {
public static void main(String[] args) {
int[] arr = new int[3];//动态初始化数组
arr[0]=2;
arr[1]=6;
arr[2]=8;
}
}
- 将创建对象所属的.class(Shuzu.class)文件加载到方法区,形成.class字节码对象
- main方法进栈执行
- 在栈内存创建整数数组类型的引用(int[] arr),用于储存堆内存中申请的对象的地址(ox886)
- 在堆内存中开辟空间,给数组(new int[3])分配空间,并赋予初始值,这里基本数据类型的初始值为0,之后才被赋值各自的数据
- 将堆内存中数组的内存地址(ox886)赋值给栈内存的对象的引用变量(arr)
- 变量(arr)储存的是数组内存的地址,不是具体的数值。
两个数组的内存分析
package Chating;
public class Shuzu {
public static void main(String[] args) {
int[] arr = new int[3];//动态初始化数组
arr[0]=2;
arr[1]=6;
arr[2]=8;
int[] arr2 = new int[3];
arr2[0]=233;
arr2[1]=996;
arr2[2]=666;
}
}
数组名赋值
两个变量指向一个数组··
两个数组名存储一样的地址,指向了同一块空间
数组名中存储的是地址,所以数组名就相当于指向堆内存中某块内存,这种现象就是内存的引用··`
package Chating;
public class Shuzu {
public static void main(String[] args) {
int[] arr = new int[3];//动态初始化数组
arr[0]=2;
arr[1]=6;
arr[2]=8;
int[] arr2 = arr;
arr2[0]=233;
arr2[1]=996;
arr2[2]=666;
}
}
面向对象
一种编程思路
-
面向对象:解决问题时强调是谁来解决这个问题,把构成的问题事务分解成各个对象,让对象来解决问题
-
面向过程:解决问题时强调的是解决问题的基本步骤和解决方式,可以用函数设计解决的方式,再调用它一步步出来解决就行,更强调的是解决方法,编程思想,自顶向下,不断分解
举例
修电脑 :面向过程:预估问题 拆电脑 修电路 重装电脑 测试运行
面向对象:找个师傅 谈工钱 让他去修
面向对象的好处
- 更符合人类的生活习惯,处理问题找对象,找工具,而不是自己找方法解决
- 复杂的问题简单化
- 从执行者变成了指挥者
面向对象的特征
- 封装
- 继承
- 多态
类和对象
类:具有相同属性的对象称为类,是个抽象的概念。例如 人 车 运动员 就属于类**** ****可以看成一个模板,定义他所包涵全体对象的公共特征和功能
对象:是实际具体存在的事物。例如 张三 李四;大众 雪佛兰 ;罗纳尔多 马拉多纳;这些就是对象 对象一般都由属性+方法(行为)组成
属性:用来描述具体某个对象的特征。比如张三 身高178cm,体重72kg.这里身高体重就是属性
定义类和对象
类的定义:
对象依赖于类,没有类就没有对象
修饰符 class 类名{
属性:其实就是之前学的变量,成员变量,对象的属性
属性的格式:
数据类型1 变量名1;
数据类型2 变量名2;
行为:对象行为,对象方法
public 返回值类型 方法名(参数列表){
方法体;
return 数据;
}
}
对象创建的格式:
类名 对象名 = new 类名();
对象的使用
调用属性:对象名.属性名;(访问属性中的值)
对象名.属性名 = 值 (赋值操作)
调用方法:对象名.方法名
package Chating;
public class Shuzu {
public static void main(String[] args) {
Person p = new Person();//创建对象 类名 对象名 = new 类名();
p.name = "萨拉赫";//调用属性 对象名.属性名 = 值
p.age = 27;
p.sleep();//调用方法 对象名.方法名
p.run("马内");
System.out.println(p.name);
System.out.println(p.age);
}
}
class Person{//修饰符 class 类名{}
//属性 成员变量
String name;
int age;
//行为 成员方法
public void run(String str) {
System.out.println(str + "在跑步");
}
public void sleep() {
System.out.println("去睡觉");
}
}
创建对象的内存分析
package Chating;
public class Shuzu {
public static void main(String[] args) {
Person p = new Person();
p.name = "马内";
p.age = 26;
p.run();
Person p2 = new Person();
p.name = "萨拉赫";
p.age = 28;
p.run();
}
}
class Person{
String name;//成员变量 定义在代码块或方法中,或者方法声明上的变量
int age;
//成员方法
public void run() {
System.out.println("在跑步");
}
}
-
将创建对象所属的.class(Shuzu.class/Person.class)文件加载到方法区,形成.class字节码对象
-
main方法进栈执行
-
在栈内存创建Person类型的引用(Person p/Person p2),用于储存堆内存中申请的对象的地址(0x445/0x659)
-
在堆内存中开辟空间,给成员变量(String name/int age)分配空间,并赋予初始值,字符类型初始值为null,整数类型为0,之后再被赋值(马内 萨拉赫)
-
将堆内存中的内存地址(0x445/0x659)赋值给栈内存的对象的引用变量(p/p2)
注意:
(1) 第一次使用某个类型时,会把该类型的字节码文件加载到方法区,第二次使用的时候就不会再加载了
(2) 在堆内存中创建的对象,内部空间会有一份该类字节码文件的在方法区的地址
(3) 每个对象在调用方法的时候,该方法会有一个地址,指向该对象在堆内存中的地址,堆内存中的地址指向方法区中成员方法的地址
(4) 每次使用new,都会创建一个新的对象,都会申请新的空间
两个引用指向同一个对象的内存图解
成员变量和局部变量
成员变量:在类中方法外
局部变量:定义在代码块或方法中,或者方法声明上的变量
相同点:
都是用来存储数据
不同点:
1.代码书写位置:
局部变量:定义在方法中
成员变量:定义在类中
2.内存位置不同:
局部变量:属于方法,方法运行时进栈,所以局部变量就在栈内存
成员变量:属于对象,对象在堆内存中,所以成员变量在堆内存中
3.初始化的不同:
局部变量:没有初始化是不能使用的
成员变量:有初始值,系统会自动申请空间初始化
4.生命周期的不同:
局部变量:属于方法,所以方法调用它诞生,方法结束它消失
成员变量:随着对象的创建而创建,对象消失它消失
注意:对象的销毁需要借助于垃圾回收机制,栈内存只存储了引用,就算引用销毁了,这个对象也不一定立即销毁,对象只能通过垃圾回收机制销毁
举例:
package Chating;
public class Shuzu {
public static void main(String[] args) {
Person p = new Person();
p.run();
}
}
class Person{
String name;//成员变量 定义在代码块或方法中,或者方法声明上的变量
int age;
//成员方法
public void run() {
int a = 10;//局部变量 定义在类中方法外
System.out.println("跑步了"+a+"圈");
}
}