Java中的异常
运行时异常和非运行时异常
- 运行时异常是指自己的代码写的不够好,边界情况没有处理好,能够通过编译但是运行会报错。比如空指针,数组越界
- 非运行时异常是外部环境的问题,比如要访问的文件被删除了,SQL没连上去。编译都会欧保国
throw和throws
- throw相当于一个能抛出异常的输出语句
- throws是写到方法上面的,说这个方法里面可能存着某个异常但是我不处理,留给掉用者处理。如果调用者向上一抛出的话就会给JVM处理,结果就是直接报错,程序停止运行
- 如果有一个catch啦接住这个异常的话程序还会继续运行
反射
- 在运行时,动态地获取类的信息(属性、方法、构造器等),并可以操作它们
获取Class对象的三种方法
// 方式一:通过类名.class(编译时就知道类型)Class<User>c1=User.class;// 方式二:通过对象.getClass()(运行时拿到对象才知道类型)Useruser=newUser();Class<?>c2=user.getClass();// 方式三:通过全限定类名字符串(最灵活,最常用)Class<?>c3=Class.forName("com.example.User");- 一个类在JVM里面只有同一个Class对象
Class类的API
- Field字段(操作字段的)
- Method方法(invoke来调用的)
- Constructor构造器(用来实例化的)
操作构造器来实例化
Class<?>clazz=Class.forName("com.example.User");// 获取无参构造器,创建实例Constructor<?>noArg=clazz.getDeclaredConstructor();Objectuser1=noArg.newInstance();// 获取有参构造器Constructor<?>withArg=clazz.getDeclaredConstructor(String.class,int.class);Objectuser2=withArg.newInstance("张三",25);- 只有操作构造器才能来实例化
注解
- 注解是一种给代码添加元数据(描述信息)的方式,它本身不影响代码逻辑,但可以在编译期或运行时被读取和处理
- 注解本质上就是接口
// 你写的注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAnnotation{Stringvalue();intage()default18;}- 反射编译后就是一个接口
// 注解的本质是一个继承了 java.lang.annotation.Annotation 的接口publicinterfaceMyAnnotationextendsAnnotation{Stringvalue();intage();// default 18 在编译时由框架读取处理}元注解
- @Target:注解能用到哪里
@Target({ElementType.METHOD,ElementType.FIELD})public@interfaceMyAnnotation{}- @Retention:注解能活到什么时候
源码(.java) → 字节码(.class) → JVM 加载到内存 SOURCE: ✅存在 ❌丢弃 ❌丢弃 CLASS: ✅存在 ✅存在 ❌丢弃 (默认) RUNTIME: ✅存在 ✅存在 ✅存在 (反射可用)- . @Inherited — 子类是否继承父类的注解
###自定义注解
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAnnotation{// 带默认值的属性Stringvalue()default"";// 可以有多个属性intpriority()default0;// 属性类型支持:基本类型、String、Class、枚举、注解、以上类型的数组String[]tags()default{};}- 这个String value()是指变量value的类型是String,()没有任何意义
@MyAnnotation(value="test",priority=1,tags={"a","b"})publicvoiddoSomething(){}注解的处理方式:运行时反射
// 自定义注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceRoute{Stringpath();}// 使用注解publicclassUserController{@Route(path="/user/list")publicStringlistUsers(){return"user list";}@Route(path="/user/detail")publicStringgetUserDetail(){return"user detail";}}// 运行时通过反射读取注解publicclassRouter{publicstaticvoidmain(String[]args)throwsException{Class<?>clazz=UserController.class;for(Methodmethod:clazz.getDeclaredMethods()){// 判断方法上是否有 @Route 注解if(method.isAnnotationPresent(Route.class)){Routeroute=method.getAnnotation(Route.class);// 读取注解的属性值System.out.println("路径: "+route.path());System.out.println("方法: "+method.getName());// 可以把 path → method 的映射存起来,实现路由}}}}