目录
1. Java面向对象的内存分析
Java虚拟机内存可分为栈(Stack)、堆(Heap)、方法区(Method Area)。
1.1 栈的特点
① 栈描述的时方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数和方法出入口等);
② JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际变量和局部变量等);
③ 栈属于线程私有,不能实现线程间的共享;
④ 栈的存储特性是“先进后出,后进先出”;
⑤ 栈是有系统自动分配,速度快,栈是一个练习的内存空间。
package com.ppw.test;
public class Test05 {
public static void main(String[] args) {
fun1();
}
public void fun1() {
fun2();
}
public void fun2() {
fun3();
}
public void fun3() {
}
}
上述代码中各函数的存储区如上
1.2 堆的特点
① 堆用于存储创建好的对象和数组(数组也是对象);
② JVM只有一个队,被所有线程共享;
③ 堆是一个不连续的内存空间,分配灵活,速度慢。
package com.ppw.test;
public class Test05 {
public static void main(String[] args) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
Class3 c3 = new Class3();
}
}
class Class1{
}
class Class2{
}
class Class3{
}
上述代码中各类的存储区如下,当运行结束后c1=c1的地址、c2=c2的地址、c3=c3的地址
1.3 方法区(静态区)
① JVM中只有一个方法区,被所有线程共享;
② 方法区实际上也是堆,只是用于存储类、常量相关的信息;
③ 用来存放程序中永远不变的或唯一的内容。(类信息【class对象】、静态变量、字符串常量等、被final修饰的变量)
此处缺一个多态的内存分析图
2. 构造方法
2.1 语法
①无参构造方法:public 类名(){}
public abstract class Pet {
public Pet() {
}
}
【注意】当类中无构造方法时,JVM虚拟机会为类自动生成构造方法
② 含参构造方法:public 类名(参数列表){}
public class Pet {
String nickname;
double health;
double degree;
public Pet() {
}
public Pet(String nickname, double health, double degree) {
super();
this.nickname = nickname;
this.health = health;
this.degree = degree;
}
}
【注意】自定义类的含参构造方法和自定义普通方法类似,需要有访问修饰符、方法名(类名)、参数列表(成员变量列表),但没有返回值,甚至连void也没有。当我们自定义含参的构造方法后,JVM虚拟机不会为类自动生成无参构造方法,因此需要我们手动添加。
2.2 构造方法的重载
【重载条件】构造方法重载和普通方法的重载条件一样,即:
① 参数个数不同;
② 参数个数相同,但参数位置 / 顺序不同;
③ 参数个数相同,参数类型不同,而且参数类型有包含关系,也能构成重载。具体调用见参数实际类型
例如:
public class Pet {
String nickname;
double health;
double degree;
// 参数个数不同
public Pet() {
}
public Pet(String nickname) {
super();
this.nickname = nickname;
}
// 参数顺序不同
public Pet(String nickname,double health) {
super();
this.nickname = nickname;
this.health = health ;
}
// 参数顺序不同
public Pet(String nickname,double health,double degree) {
this(String nickname,double health,double);
this.degree = degree;
}
// 参数类型不同
public Pet(double health) {
super();
this.health = health ;
}
public Pet(int health) {
super();
this.health = health ;
}
// 参数类型不同 -- byte包含于int类型
public Pet(byte health) {
super();
this.health = health ;
}
}
【构造方法的使用】
① 构造方法可以调用其他构造方法,使用this关键字,但this必须放在改构造方法的第一句,并且被调用的构造方法已经被声明;
public class Pet {
String nickname;
double health;
double degree;
// 参数个数不同
public Pet() {
}
// 参数顺序不同
public Pet(String nickname,double health) {
super();
this.nickname = nickname;
this.health = health ;
}
// 参数顺序不同
public Pet(String nickname,double health,double degree) {
this(String nickname,double health,double);
this.degree = degree;
}
}
② 构造方法可以调用类的普通方法,但类的普通方法不能调用类的构造方法
public class Pet {
String nickname;
double health;
double degree;
// 参数个数不同
public Pet() {
}
// 参数顺序不同
public Pet(String nickname,double health) {
super();
this.nickname = nickname;
this.health = health ;
// 显示pet信息
this.show(nickname, health)
}
}
3. this关键字
在上节关于构造方法的学习中,可以总结出this关键字的三种用法:
3.1 this.成员变量
this.成员变量 -- 相当于调用当前对象的成员变量
3.2 this.方法名
this.方法名 -- 相当于调用当前对象的方法
3.3 this()
this() -- 相当于调用当前对象的构造方法