异常-代理-泛型

异常体系

Exception 和 Error的区别

Exception 和 Error 都继承于 Throwable,在 Java 中,只有 Throwable 类型的对象才能被 throw 或者 catch,它是异常处理机制的基本组成类型。

Exception 和 Error 体现了 Java 对不同异常情况的分类。

  • Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应的处理。
  • Error 是指在正常情况下,不大可能出现的情况,绝大部分 Error 都会使程序处于非正常、不可恢复的状态。既然是非正常,所以不便于也不需要捕获,常见的 OutOfMemoryError 就是 Error 的子类。

Exception 又分为 checked Exception 和 unchecked Exception。

checked Exception 在代码里必须显式的进行捕获,这是编译器检查的一部分。

unchecked Exception 也就是运行时异常,类似空指针异常、数组越界等,通常是可以避免的逻辑错误,具体根据需求来判断是否需要捕获,并不会在编译器强制要求

return问题答案

catch块和finally块中的代码都执行了,但是finally块中的返回值覆盖了catch中的return值

try,catch,finally中可以同时都出现return,一旦return写在最后,要么在try,catch,finally都不写return,要么在try中写return,才能通过编译。需要特别注意的是,基本数据类型(就不再强行用内存解释了),简单点记忆就是基本数据类型返回值是“覆盖”,引用类型是“叠加”

https://juejin.im/post/5a9cec866fb9a028d042ef47//陷阱

一般情况下finally块中的代码是一定会被执行,除非JVM停止工作

缺点

影响性能
程序进入catch里,非常耗资源

Try/with/resources

return,break,continue

return的功能是结束一个方法

continue的功能和break有点类似,区别是continue只是中止本次循环,接着开始下一次循环

break则是完全中止整个循环

答案是否定的,也就是不会打印输出这句话。

​不论try块是正常结束,还是中途非正常退出,也就是发生各种异常,finally块确实都会执行。然而在这个程序中,程序中try块中增加了System.exit(0);来退出程序,try语句根本就没有结束其执行过程,System.exit(0);将停止当前线程和所有其他当场死亡的线程。finally块并不能让已经停止的线程继续执行

代理

Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题

其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理

解耦合

静态代理

优点
解耦合、隐藏实现
缺点

  • 代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复
  • 代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了

动态代理

动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象

通过InvocationHandler代理不同类型的对象,如果我们把对外的接口都通过动态代理来实现,那么所有的函数调用最终都会经过invoke函数的转发,因此我们就可以在这里做一些自己想做的操作,比如日志系统、事务、拦截器、权限控制等。这也就是AOP(面向切面编程)的基本原理

        InvocationHandler handler = new ProxyHandler(hello);
        HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
        proxyHello.sayHello();
        
        public class ProxyHandler implements InvocationHandler{
    private Object object;
    public ProxyHandler(Object object){
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before invoke "  + method.getName());
        method.invoke(object, args);
        System.out.println("After invoke " + method.getName());
        return null;
    }
}

动态代理的实现方式,AOP的实现方式

  1. JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
  2. CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
  3. 区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类

泛型

简单的说,意义和作用有:
  类型的参数化,就是可以把类型像方法的参数那样传递。这一点意义非凡。
  泛型使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常。
  
  Java 语言中引入泛型是一个较大的功能增强
  消除强制类型转换
  类型安全
  
泛型中的类型擦除是什么
https://www.cnblogs.com/the-wang/p/10234727.html

https://www.cnblogs.com/coprince/p/8603492.html

https://www.jianshu.com/p/986f732ed2f1

JVM 是如何实现泛型的?

Java 中的泛型不过是一个语法糖,在编译时还会将实际类型给擦除掉,不过会新增一个 checkcast 指令来做编译时检查,如果类型不匹配就抛出 ClassCastException。

不过呢,字节码中仍然存在泛型参数的信息,如方法声明里的 T foo(T),以及方法签名 Signature 中的 “(TT;)TT”,这些信息可以通过反射 Api getGenericXxx 拿到。

除此之外,需要注意的是,泛型结合数组会有一些容易忽视的问题。数组是协变且具体化的,数组会在运行时才知道并检查它们的元素类型约束,可能出现编译时正常但运行时抛出 ArrayStoreException,所以尽可能的使用列表,这就是 Effective Java 中推荐的列表优先于数组的建议。这在我们看集合源码时也能发现的到,比如 ArrayList,它里面存数据是一个 Object[],而不是 E[],只不过在取的时候进行了强转。还有就是利用通配符来提升 API 的灵活性,简而言之即 PECS 原则,上取下存。典型的案例即 Collections.copy 方法了:

Collections.copy(List<? super T> dest, List<? extends T> src);

泛型
https://blog.csdn.net/weixin_44339238/article/details/104970464

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值