Java八股学习笔记1

一、Java的垃圾回收机制

(1)垃圾收集GC(Garbage Collection)是Java语言的核心技术之一, 在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理;
(2) java提供了一个系统级的线程,即垃圾回收器线程GC线程(Java虚拟机中的守护线程)负责垃圾回收,用来对每一个分配出去的内存空间进行跟踪。java程序员不用操心;

1、垃圾回收机制(GC):通过自动垃圾回收算法对堆内存中 new出的且不再被引用的对象 进行回收

2、垃圾回收机制如何判断对象是否还有用?

  检查堆内存中空间是否充裕:

足够,则不回收
不足,通过算法检查是否有 已创建 且长时间未被引用的对象——>若长时间未被引用 且急需创建新的对象,垃圾回收机制就会将这些对象定为垃圾,会优先将这部分空间进行回收。

3、垃圾回收机制在回收任何对象之前,总会先自动调用 finalize()方法(自动调用,不由程序员调用),调用该方法可以在垃圾回收同时打印日志等操作

注:finalize可以用来清理不是new出的对象所占用的内存,可以用来清理本地对象

本地对象:指的是在Java中调用非Java代码(C/C++)时创建的对象

例题
在这里插入图片描述
当JVM空闲时,自动回收每块可能被回收的内存,GC是完全自动的,不能被强制执行。程序员最多只能用System.gc()来建议执行垃圾回收器回收内存,但是具体的回收时间,是不可知的。

当对象的引用变量被赋值为null,可能被当成垃圾,但也不是马上就会回收。

局部变量分为引用变量和基本类型变量,基本类型的变量名称和值都是存储在栈中。引用变量只存储引用在栈中,值在堆中,题目中说的是局部变量的引用,而要释放这个需要finalize()方法,这个方法即便使用了也不是一定立刻马上执行。一般局部变量都是随着方法执行结束而释放。

二、JAVA语言异常处理

指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。

• 异常指的并不是语法错误和逻辑错误。语法错了,编译不通过,不会产生字节码文件,根本不能运行。
• 代码逻辑错误,只是没有得到想要的结果,例如:求a与b的和,你写成了a-b。

Java语言中的异常处理包括声明异常、抛出异常、捕获异常和处理异常四个环节。

1、Java异常体系结构

1.Throwable
java.lang.Throwable类是Java程序执行过程中发生的异常事件对应的类的根父类
Throwable中的常用方法:
public void printStackTrace():打印异常的详细信息。
包含了异常的类型、异常的原因、异常出现的位置、在开发和调试阶段都得使用printStackTrace。
public String getMessage():获取发生异常的原因。

2.Error和Exception
Throwable可分为两类:Error和Exception。
分别对应着java.lang.Error,java.lang.Exception两个类。

Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。
例如:StackOverflowError(栈内存溢出)和OutOfMemoryError(堆内存溢出,简称OOM)。

Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,需要使用针对性的代码进行处理,使程序继续运行。否则一旦发生异常,程序也会挂掉。
例如:

  • 空指针访问
  • 试图读取不存在的文件
  • 网络连接中断
  • 数组角标越界

2、异常分类

(1) 编译时期异常(即checked异常、受检异常):在代码编译阶段,编译器就能明确警示当前代码可能发生(不是一定发生)XX异常,并明确督促程序员提前编写处理它的代码。如果程序员没有编写对应的异常处理代码,则编译器就会直接判定编译失败,从而不能生成字节码文件。通常,这类异常的发生不是由程序员的代码引起的。
例如:FileNotFoundException(文件找不到异常)。

(2) 运行时期异常(即runtime异常、unchecked异常、非受检异常):在代码编译阶段,编译器完全不做任何检查,无论该异常是否会发生,编译器都不给出任何提示。只有等代码运行起来并确实发生了XX异常,它才能被发现。通常,这类异常是由程序员的代码编写不当引起的,只要稍加判断,或者细心检查就可以避免。 java.lang.RuntimeException类及它的子类都是运行时异常。
比如:ArrayIndexOutOfBoundsException数组下标越界异常,ClassCastException类型转换异常

3、异常处理

Java的异常处理是通过5个关键字来实现的:try、catch、finally、throw、throws
在这里插入图片描述

try:检测不安全的代码块(发现异常
try块中任何一条语句发生了异常,下面的代码将不会被执行,程序将跳转到异常处理代码块中,即catch块。因此,不要随意将不相关的代码放到try块中,因为随时可能会中断执行。

cacth:用于捕获从try中抛出的异常并作出处理。(捕获异常
把抓到的类型匹配的异常捕获,保证程序能继续运行下去,catch语句必须紧跟着try语句之后,称为捕获异常,也就是异常处理函数,一个try后面可以写多个catch,分别捕获不同类型的异常,要从子类往父类的顺序写,否则有编译错误。

throw:用于抛出异常
throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异常对象。
throw用于方法体中,用来抛出一个实际的异常对象,使用throw后,
要么使用try catch捕获异常,要么使用throws声明异常
● throws用于方法声明处,用来声明该方法可能发生的异常类型,可以是
多个异常类型,用来强制调用该方法时处理这些异常
● 抽象方法也可以使用throws

throws:定义一个方法的时候可以使用throws关键字声明,表示此方法不处理异常,而交给方法调用处进行处理。
● 任何方法都可以使用throws关键字声明异常类型,包括抽象方法。
● 子类重写父类中的方法,子类方法不能声明抛出比父类类型更大的异常。
● 使用了throws的方法,调用时必须处理声明的异常,要么使用try-catch,要么继续使用throws声明。

finally
语句块是不管有没有出现异常都要执行的内容。finally该内容总是会执行的,只能有一个finally语句。

例题:
在这里插入图片描述

三、JAVA反射机制

1、是什么?

(1)Java反射机制(Java Reflection)是Java语言中一种动态(运行时)访问、检测 & 修改它本身的能力,主要作用是动态(运行时)获取类的完整结构信息 & 调用对象的方法~

更简单点的说就是Java程序在运行时(动态)通过创建一个类的反射对象,再对类进行相关操作,比如:

获取该对象的成员变量 & 赋值
调用该对象的方法(含构造方法,有参/无参)
判断该对象所属的类
PS:不过说实话,直接看比较官方的定义还是有点难理解,再来更加通俗点的说吧~

(2)一般情况下,我们使用某个类,都会知道这个类,以及要用它来做什么,可以直接通过new实例化创建对象,然后使用这个对象对类进行操作,这个就属于正射~

(3)而反射则是一开始并不知道要初始化的是什么类,无法使用new来实例化创建对象,主要是通过JDK提供的反射API来实现,在运行时才知道要操作的是什么类,并且可以获取到类的完整构造以及调用对应的方法,这就是反射~

package com.justin.java.lang;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * @program: Jdk1.8 Test
 * @description: 正射、反射简单调用示例
 * @author: JustinQin
 * @create: 2021/8/22 13:23
 * @version: v1.0.0
 **/
public class Student {
    private int id;

    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }

    public static void main(String[] args) throws Exception{
        //一、正射调用过程
        Student student = new Student();
        student.setId(1);
        System.out.println("正射调用过程Student id:" + student.getId());

        //二、反射调用过程
        Class clz = Class.forName("com.justin.java.lang.Student");
        Constructor studentConstructor = clz.getConstructor();
        Object studentObj = studentConstructor.newInstance();
        
        Method setIdMethod = clz.getMethod("setId", int.class);
        setIdMethod.invoke(studentObj, 2);
        Method getIdMethod = clz.getMethod("getId");
        System.out.println("正射调用过程Student id:" + getIdMethod.invoke(studentObj));
    }
}


上述例子反射的调用过程,可以看到获取一个类的反射对象,主要过程为:

1.获取类的Class实例对象
2.根据Class实例对象获取Constructor对象
3.再根据Constructor对象的newInstance方法获取到类的反射对象

获取到类的反射对象后,就可以对类进行操作了~ 例如,上述示例中对类的方法进行调用过程为:

1.根据Class实例对象获取到类的Method对象
2.再根据Method对象的invoke方法调用到具体类的方法

2、Java反射机制中获取Class方式

在这里插入图片描述

例题:
在这里插入图片描述
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态***。

四、重载 重写 以及 重构

1、重载(overloaded)

重载就是在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。

我们知道构造方法的名称已经由类名决定,所以构造方法只有一个名称,但如果希望以不同的方式来实例化对象,就需要使用多个构造方法来完成。由于这些构造方法都需要根据类名进行命名,为了让方法名相同而形参不同的构造方法同时存在,必须用到“方法重载”,虽然方法重载起源于构造方法,但是它也可以应用到其他方法中。

重载的规则:

(1)必须具有不同的参数列表。

(2)可以有不同的返回类型,只要参数列表不同就可以了

(3)可以有不同的访问修饰符。

(4)可以抛出不同的异常。

2、重写(override)

重写(还可以称为覆盖)就是在子类中将父类的成员方法的名称保留,重写成员方法的实现内容,更改成员方法的存储权限,或是修改成员方法的返回值类型(注意:重写父类成员方法的返回值类型是基于J2SE 5.0版本以上编译器提供的新功能)。

子类重写父类的方法还可以修改方法的返回值类型,但这只是在J2SE 5.0以上的版本中支持的新功能。示例中子类中的doIt()方法就使用了这个新功能,父类中的doIt()方法的返回值类型为Parent类,而子类中的doIt()方法的返回值类型为Children类,子类中重写了父类的doIt()方法。这种重写方式需要遵循一个原则,即重写的返回值类型必须是父类中同一方法返回值类型的子类,而Children类正是Parent类的子类。

注意:当重写父类方法时,修改方法的修饰权限只能从小的范围到大的范围改变,例如,父类中的dosomething()方法的修饰权限为protected,继承后子类中的方法doSomething()的修饰权限只能修改为public,不能修改为private。

重写的规则:

(1)参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。

(2)访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)。

(3)重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。

3、重构

重构:是重写的一种特殊方式,子类与父类的成员方法的返回值、方法名称、参数类型及个数完全相同,唯一不同的是方法实现内容,这种特殊重写方式被称为重构。

4、区分总结

重构就是单单改进代码的结构和可读性,其他方法名,返回值,参数所有都不变

重载是在同一个类中根据不同的参数定义多个同名的方法(参数数量,类型,返回值可以不同)。

重写是子类重新定义父类中的方法。子类必须与父类有相同的方法签名(方法名和参数列表必须相同,返回值可以不同),并且子类方法的访问修饰符不能比父类方法更严格。

例题:
在这里插入图片描述
ACD 重载是在同一个类中,有多个方法名相同,参数列表不同(参数个数不同,参数类型不同),与方法的返回值无关,与权限修饰符无关,B中的参数列表和题目的方法完全一样了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值