14.Java 构造方法详解/垃圾回收机制/JVM调优简述/内存泄露
构造方法
- 构造器也叫构造方法(constructor),用于对象的创建以及初始化。
构造方法详解(需要掌握)
- 通过 new 关键字调用。
- 构造器虽然有返回值,但是不能自定义返回值类型(返回值类型是本类),不能在构造器里使用 return 返回某个值。
- 如果我们没有定义构造器,则编译器会自动定义一个无参的构造器。如果已定义,则编译器不会自动添加。
- 构造器的方法名必须和类名一致。
代码示例:构造方法的使用
// 定义一个 Point 类
class Point{
double x,y;
// 这里会默认返回成员变量x,y的结果。自定义构造方法。构造方法名称和类名必须保持一致。会默认返回成员变量的结果
public Point(double _x,double _y){
x = _x;
y = _y;
}
// 定义类方法:计算两点之间的距离
// 这里的 Point p 定义的 p 对象是属于 getDistance() 方法,跟 main() 方法中的 p 对象是两个不同的
public double getDistance(Point p){
// 定义返回值为计算结果
return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
}
}
public class TestCon {
public static void main(String[] args) {
// 定义构造方法的类对象:根据实际情况传对应参数
// 这里的 Point p 定义的 p 对象是属于 main() 方法。跟 getDistance() 方法中的 p 对象是两个不同的
Point p = new Point(3.0,4.0);
// 定义一个初始位置
Point orgin = new Point(0.0,0.0);
// 输出运算结果:将 orgin 传到 getDistance() 方法中进行计算,最后打印出来
System.out.println(p.getDistance(orgin)); // 输出结果为 5
}
}
注意点
问题(1):对象的创建完全是由构造方法实现的吗?
并不是,构造方法是创建 Java 对象的重要途径,通过 new 关键字调用构造器时,构造器也确实返回了该类对象,但这个对象并不是完全由构造器负责创建的。
问题(2)创建一个对象分为四步:
- 分配对象空间,并将对象成员变量初始化为 0 或空。
- 执行属性值的显示初始化。
- 执行构造方法。
- 返回对象的地址给相关的变量。
构造方法重载(与方法重载一样)
注意点:
- 构造方法会经常重载。因为会经常调用构造方法来创建对象之类的。
- 如果构造方法中的形参名和属性名相同时,需要使用 this 关键字来区分属性和形参。
- 形如下方代码示例:this.id 表示属性 id,id 表示形参 id
代码示例:构造方法重载
public class TestUser {
int id; // id
String name; // 用户名
String pwd; // 密码
// 定义无参构造方法
public TestUser(){
}
// 构造方法的重载
public TestUser(int id,String name){
// super():编译器执行构造方法的时候,无论是否写 super(),都会默认先执行 super(),没有会自动添加。
this.id = id; // this 表示创建好的对象
this.name = name;
// 输出传入的实参值。利用 printf() 进行字符串打印输出
System.out.printf("%s,%s%n",id,name);
}
// 构造方法的重载
public TestUser(int id,String name,String pwd){
this.id = id;
this.name = name;
this.pwd = pwd;
// 输出传入的实参值。利用 printf() 进行字符串打印输出
System.out.printf("%s,%s,%s%n",id,name,pwd);
}
public static void main(String[] args) {
TestUser user1 = new TestUser();
TestUser user2 = new TestUser(23,"阿jun");
TestUser user3 = new TestUser(23,"微信公众号","阿jun修炼手册");
}
}
垃圾回收机制
内存管理
- Java 的内存管理很大程度指的是对象的管理,包括对象空间的分配与释放。
- 对象空间的分配:使用 new 关键字创建对象即可。
- 对象空间的释放:将对象赋值为 null,垃圾回收期负责回收所有 “不可达” 对象的内存空间。
垃圾回收过程
任何一种垃圾回收算法都要做两件基本事情:
- 发现无用的对象。
- 回收无用对象占用的内存空间。
垃圾回收机制可以保证将 “无用的对象” 进行回收。无用对象指的是没有任何变量引用该对象。
Java 垃圾回收机器通过相关算法发现无用对象,并进行清楚和整理。
垃圾回收算法
- 引用计数法
- 引用可达法(根搜索算法)
- …………
分代垃圾回收机制算法(通用)
分代垃圾回收机制,基于一个事实:
- 不同对象的生命周期是不一样的。
- 不同生命周期的对象可以采用不同的回收算法,以提高效率。
- 将对象分为三种状态:年轻代、年老代、持久代。
- JVM 虚拟机将堆内存划分为 Eden、Survivor、Tenured/Old 空间
- 年轻代:
所有新生成的对象都是放在 Eden 区中。
年轻代的目标是尽量收集掉那些生命周期短的对象,对应是 Minor GC,
每次 Minor GC 会清理年轻代的内存,算法采用效率较高的复制算法,频繁操作,但有点浪费内存空间。
当 “年轻代” 区域放满对象以后,就会将对象放到年老代区域。
- 年老代:
在年轻代中执行了 N 次(默认15次)垃圾回收以后仍然存活的对象,就会被放到年老代中。
年老代中存放的一般都是声明周期较长的对象。
年老代对象越多,就需要启动 Major GC 和 Full GC(全量回收) 来进行一次大清理,全面清理年轻代和年老代两个区域。
- 持久代
持久代用来存放静态文件,如 Java 类,方法等。
持久代对于垃圾回收没有显著影响。
堆内存划分细节
- Minor GC
用于清理年轻代区域,当 Eden 区满了以后就会触发一次 Minor GC.
清理无用对象,将有用对象复制到 "Survivor1"、"Survivor2" 区中(这两个区大小空间相同,同一时刻 Survivor1 和 Survivor2 只有一个在用,另一个为空)。
- Major GC
用于清理年老代区域。
- Full GC
用于清理年轻代、年老代区域,成本较高,会对性能产生影响。
垃圾回收详细过程
- 新创建的对象绝大部分都存储在 Eden 中。
- 当 Eden 区满了(达到一定比例)不能再新创建对象,就会触发垃圾回收(GC),将无用对象清理掉, 然后将剩余对象复制到 Survivor 区中,如上截图的 Survivor1 区,同时清空 Eden 区。
- 当 Eden 区再次满了以后,会将 Survivor1 中不能清空的对象放到另一个 Survivor 区中,如 Survivor2。
- 重复多次(默认15次),Survivor 区中没有被清理掉的对象,就会被复制到老年(Old/Tenured) 区中。
- 当 Old 区满了,就会触发一次完整性的垃圾回收(Full GC),之前的年轻代垃圾回收称为 Minor GC。
JVM 调优和 Full GC
在对 JVM 进行调优时,很大一部分工作是对 Full GC 进行调节。
下方的情况可能会导致 Full GC:
- 年老代(Tenured)被写满。
- 持久代(Perm)被写满。
- System.gc() 被显式调用(程序遇到了并不会去马上调用,写这个语句只是建议程序去启动 Full GC,最终啥时候调用还得取决于垃圾回收机制,这个操作并不是调用 Full GC)
- 上一次 GC(回收) 以后 heap 堆的各域分配策略动态变化。
开发中容易造成内存泄露的操作(先简单了解)
偷偷向银河要了一把碎星✨只等你闭上眼睛撒入你的梦中。

浙公网安备 33010602011771号