垃圾回收机制(Garbage Collection)
你可以理解我这是虚拟版的现实生活中的垃圾分类!!
垃圾回收原理及算法
-
内存管理
Java 的内存管理很大程度就是:堆中对象的管理,其中包括对象空间的分配和释放。对象空间分配:使用 new 关键字创建对象即可 对象空间的释放: 将对象赋值 null 即可。
-
垃圾回收过程
- 发现无用的对象
- 回收无用对象占用的内存空间。
简单说就像我们生活中的厨余垃圾不会在用来做饭了就需要清理掉,不然占空间!!
-
垃圾回收相关算法
- 引用计数法
堆中的每个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器加1,而当指向该对象的引用失效时(引用变为 null),引用计数器减 1,最后如果该对象的引用计算器的值为 0 时,则 Java 垃圾回收器会认为该对象是无用对象并对其进行回收。优点是算法简单,缺点是“循环引用的无用对象”无法被识别。
public class Student {
String name;
Student friend;
public static void main(String[ ] args) {
Student s1 = new Student();
Student s2 = new Student();
s1.friend = s2;
s2.friend = s1;
s1 = null;
s2 = null;
}
}
- 引用可达法(根搜索法)
程序把所有的引用关系看作一张图,从一个节点 GC ROOT 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。
通用的分代垃圾回收机制
秃头建议:可以将整个机制想象成一个五行餐厅,年轻代是刚进去的消费者坐在大厅吃饭,吃的时间太久了就给安排在包厢吃,更久的话就给安排在顶层。这部分不需要纠结做简单了解就可以。
JVM调优和Full GC
- 年老代(Tenured)被写满
- 永久代(Perm)被写满
- System.gc()被显式调用
- 上一次 GC 之后 Heap 的各域分配策略动态变化
开发中容易造成内存泄漏的操作
内存泄漏
指堆内存由于某种原因程序未释放,造成内存浪费,导致运行速度减慢甚至系统崩溃等。
秃头建议:在实际开发中,经常会造成系统的崩溃。如下这些操作我们应该注意这些使用场景。请大家学完相关内容后,回头过来温习下面的内容。不要求此处掌握相关细节。
- 创建大量无用对象
比如:大量拼接字符串时,使用了 String 而不是 StringBuilder。
- String str = "";
- for (int i = 0; i < 10000; i++) {
- str += i; //相当于产生了 10000 个 String 对象
- }
- 静态集合类的使用
像 HashMap、Vector、List 等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象也不能被释放。
- 各种连接对象(IO 流对象、数据库连接对象、网络连接对象)未关闭
IO 流对象、数据库连接对象、网络连接对象等连接对象属于物理连接,和硬盘或者网络连接,不使用的时候一定要关闭。
- 监听器的使用不当
释放对象时,没有删除相应的监听器
- 程序员无权调用垃圾回收器。
- 程序员可以调用 System.gc(),该方法只是通知 JVM,并不是运行垃圾回收器。尽量少用,会申请启动 Full GC,成本高,影响系统性能。
- Object 对象的 finalize 方法,是 Java 提供给程序员用来释放对象或资源的方法,但是尽量少用
继承
- 代码复用,更加容易实现类的扩展
- 方便建模
继承的实现
使用 extends 实现继承:
public class Test{
public static void main(String[ ] args) {
Student s = new Student("秃头",183,"Java");
s.rest();
s.study();
}
}
class Person {
String name;
int height;
public void rest(){
System.out.println("休息一会!");
}
}
class Student extends Person {
String major; //专业
public void study(){
System.out.println("在秃头,学习Java");
}
public Student(String name,int height,String major) {
//天然拥有父类的属性
this.name = name;
this.height = height;
this.major = major;
}
}
执行结果为:
休息一会!
在秃头,学习java
public class Test{public static void main(String[ ] args) {Student s = new Student( "秃头" ,183, "Java" );System. out .println(s instanceof Person);System. out .println(s instanceof Student);}}
- 父类也称作超类、基类。 子类:派生类等。
- Java 中只有单继承,没有像 C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
- Java 中类没有多继承,接口有多继承。
- 子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
- 如果定义一个类时,没有调用 extends,则它的父类是:java.lang.Object。
方法的重写
- “= =”: 方法名、形参列表相同。
- “≤”:返回值类型和声明异常类型,子类小于等于父类。
- “≥”: 访问权限,子类大于等于父类。
方法重写:
package com.itbaizhan.oop;/*** 测试方法的重写*/public class TestOverride {public static void main(String[ ] args) {Horse h = new Horse();Plane p = new Plane();h.run();h.getVehicle();p.run();}}class Vehicle { //交通工具类public void run() {System.out.println("跑....");}public Vehicle getVehicle(){System.out.println("给你一个交通工具!");return null;}}class Horse extends Vehicle { // 马也是交通工具@Overridepublic void run() {System.out.println("得得得....");}@Overridepublic Horse getVehicle() {return new Horse();}}class Plane extends Vehicle { @Overridepublic void run() {System.out.println("天上飞....");}}
final 关键字的作用:修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。final int MAX_SPEED = 120;修饰方法:该方法不可被子类重写。但是可以被重载!final void study(){}修饰类: 修饰的类不能被继承。比如:Math、String 等。final class A {}
继承和组合
public class Test{
public static void main(String[ ] args) {
Student s = new Student("秃头",183,"Java");
s.person.rest(); //s.rest();
s.study();
}
}
class Person {
String name;
int height;
public void rest(){
System.out.println("休息一会!");
}
}
class Student /*extends Person*/ {
Person person = new Person();
String major; //专业
public Student(String name,int height,String major) {
//拥有父类的对象,通过这个对象间接拥有它的属性和方法
this.person.name = name; //this.name = name;
this.person.height = height; //this.height = height;
this.person.rest();
this.major = major;
}
}
Object类详解
Object 类基本特性:
- Object 类是所有类的父类,所有的 Java 对象都拥有 Object 类的属性和方法。
- 如果在类的声明中未使用 extends,则默认继承 Object 类。
Object 类public class Person {...} //等价于:public class Person extends Object {...}
public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}
class Person {
String name;
int age;
@Override
public String toString() {
return name+",年龄:"+age;
}
}
public class Test {
public static void main(String[ ] args) {
Person p=new Person();
p.age=18;
p.name="秃头";
System.out.println("info:"+p);
Test t = new Test();
System.out.println(t);
}
}
补部分IDEA快捷键
- 类的结构视图:alt+7
- 看类的源码:ctrl+左键
- 自动生成构造器、get、set 方法、equals 等:alt+insert
- 查看错误:alt+enter
- 快捷输出常见字符串:
main public static void main(String[] args){}:sout System.out.println();soutm System.out.println(“描述:所在类中的,所在方法”);
只讲干货
#有什么错误的地方大家多多担待,欢迎大家留下意见共同努力。
#需要什么技术的内容大家也可以积极留言。
#有升本的伙伴也可留言,后序也可更新升本内容C 和数据结构。
#有需要的伙伴或有什么问题直接联留下wx或联系邮箱2821835676qq.com