14.Java 构造方法详解/垃圾回收机制/JVM调优简述/内存泄露

构造方法

  1. 构造器也叫构造方法(constructor),用于对象的创建以及初始化。

构造方法详解(需要掌握)

  1. 通过 new 关键字调用。
  2. 构造器虽然有返回值,但是不能自定义返回值类型(返回值类型是本类),不能在构造器里使用 return 返回某个值。
  3. 如果我们没有定义构造器,则编译器会自动定义一个无参的构造器。如果已定义,则编译器不会自动添加。
  4. 构造器的方法名必须和类名一致。

代码示例:构造方法的使用

// 定义一个 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)创建一个对象分为四步:

  1. 分配对象空间,并将对象成员变量初始化为 0 或空。
  2. 执行属性值的显示初始化。
  3. 执行构造方法。
  4. 返回对象的地址给相关的变量。

构造方法重载(与方法重载一样)

注意点:

  1. 构造方法会经常重载。因为会经常调用构造方法来创建对象之类的。
  2. 如果构造方法中的形参名和属性名相同时,需要使用 this 关键字来区分属性和形参。
  3. 形如下方代码示例: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修炼手册");
    }
}

垃圾回收机制

内存管理

  1. Java 的内存管理很大程度指的是对象的管理,包括对象空间的分配与释放。
  2. 对象空间的分配:使用 new 关键字创建对象即可。
  3. 对象空间的释放:将对象赋值为 null,垃圾回收期负责回收所有 “不可达” 对象的内存空间。

垃圾回收过程

任何一种垃圾回收算法都要做两件基本事情:

  1. 发现无用的对象。
  2. 回收无用对象占用的内存空间。
    垃圾回收机制可以保证将 “无用的对象” 进行回收。无用对象指的是没有任何变量引用该对象。
    Java 垃圾回收机器通过相关算法发现无用对象,并进行清楚和整理。

垃圾回收算法

  1. 引用计数法
  2. 引用可达法(根搜索算法)
  3. …………

分代垃圾回收机制算法(通用)

分代垃圾回收机制,基于一个事实:

  1. 不同对象的生命周期是不一样的。
  2. 不同生命周期的对象可以采用不同的回收算法,以提高效率。
  3. 将对象分为三种状态:年轻代、年老代、持久代。
  4. 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

用于清理年轻代、年老代区域,成本较高,会对性能产生影响。

垃圾回收详细过程

  1. 新创建的对象绝大部分都存储在 Eden 中。
  2. 当 Eden 区满了(达到一定比例)不能再新创建对象,就会触发垃圾回收(GC),将无用对象清理掉, 然后将剩余对象复制到 Survivor 区中,如上截图的 Survivor1 区,同时清空 Eden 区。
  3. 当 Eden 区再次满了以后,会将 Survivor1 中不能清空的对象放到另一个 Survivor 区中,如 Survivor2。
  4. 重复多次(默认15次),Survivor 区中没有被清理掉的对象,就会被复制到老年(Old/Tenured) 区中。
  5. 当 Old 区满了,就会触发一次完整性的垃圾回收(Full GC),之前的年轻代垃圾回收称为 Minor GC。

JVM 调优和 Full GC

在对 JVM 进行调优时,很大一部分工作是对 Full GC 进行调节。
下方的情况可能会导致 Full GC:

  1. 年老代(Tenured)被写满。
  2. 持久代(Perm)被写满。
  3. System.gc() 被显式调用(程序遇到了并不会去马上调用,写这个语句只是建议程序去启动 Full GC,最终啥时候调用还得取决于垃圾回收机制,这个操作并不是调用 Full GC)
  4. 上一次 GC(回收) 以后 heap 堆的各域分配策略动态变化。

开发中容易造成内存泄露的操作(先简单了解)

posted @ 2021-11-04 07:53  阿jun  阅读(101)  评论(0)    收藏  举报