只讲干货!!java勇士们别问我行不行,不行也是你不行!不努力是打算去java炒面嘛?今天拿下 “垃圾回收机制_继承_Object大类基本特性”!尽量保持每天一更!一定动手操作起来,脑子记住了手不一定

垃圾回收机制(Garbage Collection)

        Java 引入了垃圾回收机制,令 C++程序员最头疼的内存管理问题迎刃而解。Java 程序员可以将更多的精力放到业务逻辑上而不是内存管理工作上,大大的提高了开发效率。
        
        你可以理解我这是虚拟版的现实生活中的垃圾分类!!

垃圾回收原理及算法

  • 内存管理

                Java 的内存管理很大程度就是:堆中对象的管理,其中包括对象空间的分配和释放。对象空间分配:使用 new 关键字创建对象即可 对象空间的释放: 将对象赋值 null 即可。
  • 垃圾回收过程

任何一种垃圾回收算法一般要做两件基本事情:
  1. 发现无用的对象
  2. 回收无用对象占用的内存空间。
        垃圾回收机制保证可以将“无用的对象”进行回收。
        无用的对象指的就是没有任何变量引用该对象。Java 的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。

        简单说就像我们生活中的厨余垃圾不会在用来做饭了就需要清理掉,不然占空间!!

  • 垃圾回收相关算法

  • 引用计数法
        堆中的每个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器加1,而当指向该对象的引用失效时(引用变为 null),引用计数器减 1,最后如果该对象的引用计算器的值为 0 时,则 Java 垃圾回收器会认为该对象是无用对象并对其进行回收。优点是算法简单,缺点是“循环引用的无用对象”无法被识别。

        循环引用演示:
        代码中,s1 和 s2 互相引用对方,导致他们引用计数不为 0,但是实际已经无用,但无法被
识别。
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 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。

通用的分代垃圾回收机制

        分代垃圾回收机制,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。我们将对象分为三种状态:年轻代、年老代、永久代。同时,将处于不同状态的对象放到堆中不同的区域
1. 年轻代
        所有新生成的对象首先都是放在 Eden 区。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是 Minor GC,每次 Minor GC 会清理年轻代的内存,算法采用效率较高的复制算法,频繁的操作,但是会浪费内存空间。当“年轻代”区域存放满对象后,就将对象存放到年老代区域。
2. 年老代
        在年轻代中经历了 N(默认 15)次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。年老代对象越来越多,我们就需要启动 Major GC 和 Full GC(全量回收),来一次大扫除,全面清理年轻代区域和年老代区域。
3. 永久代
        用于存放静态文件,如 Java 类、方法等。持久代对垃圾回收没有显著影响。JDK7以前就是“方法区”的一种实现。JDK8 以后已经没有“永久代”了,使用 metaspace元数据空间和堆替代。
秃头建议:
        可以将整个机制想象成一个五行餐厅,年轻代是刚进去的消费者坐在大厅吃饭,吃的时间太久了就给安排在包厢吃,更久的话就给安排在顶层。这部分不需要纠结做简单了解就可以。

·Minor GC:
        用于清理年轻代区域。Eden 区满了就会触发一次 Minor GC。清理无用对象,将有用对象复制到“Survivor1”、“Survivor2”区中。
·Major GC:
        用于清理老年代区域。
·Full GC:
        用于清理年轻代、年老代区域。 成本较高,会对系统性能产生影响。

JVM调优和Full GC

        在对 JVM 调优的过程中,很大一部分工作就是对于 Full GC 的调节。有如下原因可能导致 Full GC:
  1. 年老代(Tenured)被写满
  2. 永久代(Perm)被写满
  3. System.gc()被显式调用
  4. 上一次 GC 之后 Heap 的各域分配策略动态变化

开发中容易造成内存泄漏的操作

内存泄漏

指堆内存由于某种原因程序未释放,造成内存浪费,导致运行速度减慢甚至系统崩溃等。
秃头建议:
        在实际开发中,经常会造成系统的崩溃。如下这些操作我们应该注意这些使用场景。请大家学完相关内容后,回头过来温习下面的内容。不要求此处掌握相关细节。
        如下四种情况时最容易造成内存泄露的场景,请大家开发时一定注意:
  • 创建大量无用对象

        比如:大量拼接字符串时,使用了 String 而不是 StringBuilder。

  • String str = "";
  • for (int i = 0; i < 10000; i++) {
  • str += i; //相当于产生了 10000 个 String 对象
  • }
  • 静态集合类的使用
        像 HashMap、Vector、List 等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象也不能被释放。
  • 各种连接对象(IO 流对象、数据库连接对象、网络连接对象)未关闭
        IO 流对象、数据库连接对象、网络连接对象等连接对象属于物理连接,和硬盘或者网络连接,不使用的时候一定要关闭。
  • 监听器的使用不当
        释放对象时,没有删除相应的监听器
其他要点!!
  1. 程序员无权调用垃圾回收器。
  2. 程序员可以调用 System.gc(),该方法只是通知 JVM,并不是运行垃圾回收器。尽量少用,会申请启动 Full GC,成本高,影响系统性能。
  3. Object 对象的 finalize 方法,是 Java 提供给程序员用来释放对象或资源的方法,但是尽量少用

继承

        继承是面向对象编程的三大特征之一。继承让我们更加容易实现类的扩展。实现代码的重用,不用再重新发明轮子(don’t reinvent wheels)。
继承有两个主要作用:
  1. 代码复用,更加容易实现类的扩展
  2. 方便建模

继承的实现

        extends 的意思是“扩展”。子类是父类的扩展。现实世界中的继承无处不在

        上图中,哺乳动物继承了动物。意味着,动物的特性,哺乳动物都有;在我们编程中,如果新定义一个Student类,发现已经有 Person类包含了我们需要的属性和方法,那么 Student类只需要继承 Person 类即可拥有 Person 类的属性和方法。

使用 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

instanceof 运算符:
        instanceof 是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回 true;否则,返回 false。比如:
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);
        }
}
        两条语句都是ture  这段是上面那段的后序!!

继承使用要点:
  1. 父类也称作超类、基类。 子类:派生类等。
  2. Java 中只有单继承,没有像 C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
  3. Java 中类没有多继承,接口有多继承。
  4. 子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
  5. 如果定义一个类时,没有调用 extends,则它的父类是:java.lang.Object。

方法的重写

        子类重写父类的方法,可以用自身行为替换父类行为。重写是实现多态的必要条件。
方法重写需要符合下面的三个要点:
  1. “= =”: 方法名、形参列表相同。
  2. “≤”:返回值类型和声明异常类型,子类小于等于父类。
  3. “≥”: 访问权限,子类大于等于父类。

方法重写:

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 { // 马也是交通工具
@Override
public void run() {
        System.out.println("得得得....");
}
@Override
public Horse getVehicle() {
                return new Horse();
        }
}
class Plane extends Vehicle { @Override
public void run() {
                System.out.println("天上飞....");
        }
}
final 关键字
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 类的所有特性!!
Object 类基本特性:
  1. Object 类是所有类的父类,所有的 Java 对象都拥有 Object 类的属性和方法。
  2. 如果在类的声明中未使用 extends,则默认继承 Object 类。
Object 类
public class Person {
        ...
} //等价于:
public class Person extends Object {
        ...
}
toString 方法:
        Object 类中定义有 public String toString()方法,其返回值是 String 类型。Object类中 toString 方法的源码为:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
        根据如上源码得知,默认会返回“类名+@+16 进制的 hashcode”。在打印输出或者用 字符串连接对象时,会自动调用该对象的 toString()方法
重写toString方法:
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快捷键

        IDEA 快捷键和相关操作:
  1. 类的结构视图:alt+7
  2. 看类的源码:ctrl+左键
  3. 自动生成构造器、get、set 方法、equals 等:alt+insert
  4. 查看错误:alt+enter
  5. 快捷输出常见字符串:
        main          public static void main(String[] args){}:
        sout           System.out.println();
        soutm        System.out.println(“描述:所在类中的,所在方法”);
         有部分内容会在后序继续补齐的!!!  感谢大家的支持!!尽量做到每天一更!

只讲干货

#有什么错误的地方大家多多担待,欢迎大家留下意见共同努力。


#需要什么技术的内容大家也可以积极留言。


#有升本的伙伴也可留言,后序也可更新升本内容C 和数据结构。


#有需要的伙伴或有什么问题直接联留下wx或联系邮箱2821835676qq.com

  • 32
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值