Java SE异常、泛型、注解和反射

本文详细介绍了Java中的异常体系,包括Exception和Error的区别,Checked和Unchecked Exception的特性,以及Throwable类的方法。接着讨论了泛型的使用场景,如自定义接口、处理类和集合工具类。然后讲解了注解的本质、元注解及使用场景。最后,深入探讨了反射的优缺点、应用场景和使用步骤,包括获取Class对象和创建实例的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章只是为了复习做的记录,还会有其他的文章
一部分来自JavaGuide
大家可以关注😁😁😁😁



异常

在这里插入图片描述

Exception和Error有什么区别

Throwable是所有错误和异常的父类

  • Exception:程序本身可以处理的异常,可以通过catch来进行捕获。Exception又可以分为Checked Exception(受检异常,必须处理)和Unchecked Exception(非受检异常,可以不处理)
  • Error:Error属于程序无法处理的错误,不建议通过catch捕获。例如Java虚拟机运行错误VirtualMachineError、虚拟机内存溢出错误OutOfMemoryError、类定义错误NoClassDefFoundError等。这些错误发生时,Java虚拟机一般会选择线程终止

Checked Exception和Unchecked Exception有什么区别

Checked Exception即受检异常,Java代码在编译过程中,如果受检异常没有被处理,就没办法通过编译
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检异常。常见的受检异常有:IO相关的异常、ClassNotFoundExceptionSQLException
Unchecked Exception即非受检异常,Java代码在编译过程中,即使不处理也可以正常通过编译
RuntimeException及其子类都统称为非受检异常,常见的有

  • NullPointerException(空指针错误)
  • IllegalArgumentException(参数错误比如方法入参类型错误)
  • NumberFormatException(字符串转换为数字格式错误,IllegalArgumentException的子类)
  • ArrayIndexOutOfBoundsException(数组越界错误)
  • ClassCastException(类型转换错误)
  • ArithmeticException(算术错误)
  • SecurityException (安全错误比如权限不够)
  • UnsupportedOperationException(不支持的操作错误比如重复创建同一用户)

Throwable类的常用方法有哪些

// 返回抛出异常的详细信息
public string getMessage();
public string getLocalizedMessage();

// 返回异常发生时的简要描述
public public String toString();

// 打印异常信息到标准输出流上
public void printStackTrace();
public void printStackTrace(PrintStream s);
public void printStackTrace(PrintWriter s);

// 记录栈帧的当前状态
public synchronized Throwable fillInStackTrace();

finally中的代码一定会执行吗

不一定!

  • finally之前虚拟机被终止运行的话,finally中的代码就不会被执行
try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
    // 终止当前正在运行的Java虚拟机
    System.exit(1);
} finally {
    System.out.println("Finally");
}

输出:

Try to do something
Catch Exception -> RuntimeException

另外还有两种特殊情况finally块的代码不会被执行:

  1. 程序所在的线程死亡
  2. 关闭CPU

throw和throws的区别

位置不同

  • throws用在方法上,后面是异常类;throw用在方法内,后面是异常对象

功能不同

  • throws用来声明异常,让调用者只知道该功能可能出现的异常,可以给出预先的处理方式;throw抛出具体问题对象,执行到throw,功能就结束了,跳转到调用者,并将具体问题对象抛给调用者。就是说throw语句独立存在时,下面不要定义其他语句,因为执行不到
  • throws表示出现异常的一种可能性;throwe则是抛出了异常,执行throw则一定抛出某种异常对象
  • 两者都是消极处理异常的方式,只有抛出或者可能抛出异常,但是不会由方法去处理异常,真正处理异常使用上层调用处理

泛型

泛型是JDK 1.5之后的特性,使用泛型,可以增强代码的可读性和稳定性。
编译器会对泛型参数进行检测,并且通过泛型参数可以指定传入的对象类型。

项目中哪里用到了泛型

  • 自定义接口通用返回CommonResult<T>通过参数T可根据具体的返回类型动态的指定结果的类型
  • 定义Excel处理类ExcelUtil<T>用于动态指定Excel导出的数据类型
  • 构建集合工具类

注解

注解又称元数据,在代码中提供了一种形式化的方法。是JDK 1.5 引入的,Java定义了一天注解,共7个,3个在java.util中,4个在java.lang.annotation
注解本质是一个继承了Annotation的特殊接口
元注解有四个,元注解就是用来标志注解的注解。

  • @Retention:标志如何存储,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问

RetentionPolicy.SOURCE:注解只在源文件中,当Java文件编译成class文件的时候,注解被遗弃
RetentionPolicy.CLASS:注解保留在class文件,但JVM加载class文件时被遗弃,这是默认的生命周期
RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,JVM加载class文件之后,仍然存在

  • @Documented:标记这些注解是否包含在JavaDoc中
  • @Target:标记这个注解说明了Annotation所修饰的对象范围,Annotation可被用于packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)
public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
    TYPE_PARAMETER,
    TYPE_USE
}
  • @Inherited:标记这个注解是继承于哪个注解类的

从JDK 1.7 开始,又添加了三个额外注解

  • @SafeVarargs:在声明可变参数的构造方法时,Java编译器会报unchecked警告。使用@SafeVarargs可以忽略这些警告
  • @FunctionInterface:表明这个方法是一个函数式接口
  • @Repeatable:标识某注解可以在同一个声明上使用多次

注意:注解是不支持继承的。

反射

在Java中的反射机制是指**在运行状态中,对于任意一个类都能知道这个类所有的属性和方法了;并且对于任意一个对象,都能够调用它的任意一个方法;**这种动态获取信息以及动态调用对象方法的功能成为Java的反射机制

反射的优缺点

反射使代码更加灵活、为各种框架提供开箱即用的功能提供了便利
不过反射让我们在运行时有了分析操作类的能力的同时,也增加了安全问题,比如可以无视泛型参数的安全检查。另外反射的性能稍差

反射的应用场景

  • jdbc
  • 框架中使用的大量动态代理
  • 注解

反射使用步骤

  1. 获取想要操作的类的Class对象,是反射的核心,通过Class对象我们可以任意调用类的方法
  2. 调用Class类中的方法,即反射的使用阶段
  3. 使用反射API来操作这些信息

获取Class对象的3种方法

  • 调用某个对象的getClass()方法
Person p = new Person();
Class clazz = p.getClass();
  • 调用某个类的class属性获取该类对应的Class对象
Class clazz = Person.class;
  • 使用Class类中的forName()静态方法最安全性能最好
Class clazz = Class.forName("com.lyu.reflection.Person");

当我们获得了想要操作的类的 Class 对象后,可以通过 Class 类中的方法获取并查看该类中的方法和属性。

//获取 Person 类的 Class 对象
Class clazz=Class.forName("com.lyu.reflection.Person");

//获取 Person 类的所有方法信息
Method[] method=clazz.getDeclaredMethods();
for(Method m:method){
    System.out.println(m.toString());
}

//获取 Person 类的所有成员属性信息
Field[] field=clazz.getDeclaredFields();
for(Field f:field){
    System.out.println(f.toString());
}

//获取 Person 类的所有构造方法信息
Constructor[] constructor=clazz.getDeclaredConstructors();
for(Constructor c:constructor){
    System.out.println(c.toString());
}

创建实例对象的两种方法

  • Class对象的newInstance()
  1. 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空参构造器
  • 调用Constructor对象的newInstance()
  1. 先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建Class对象对应类的实例,通过这种方法可以选定构造方法创建实例
//获取 Person 类的 Class 对象
Class clazz=Class.forName("com.lyu.reflection.Person");
//使用.newInstane 方法创建对象
Person p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
//创建对象并设置属性
Person p1=(Person) c.newInstance("李四","男",20);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值