1. 泛型
1.1 Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符?
- 泛型:参数化类型,也就是所有操作的数据类型被指定为一个参数。提供编译时类型安全检测机制,能够检测到非法类型。
- 类型擦除:Java 的泛型是伪泛型,这是因为 Java 代码编译阶段,所有的泛型信息都会被擦掉。
- 泛型使用方式:泛型类、泛型接口、泛型方法。
- 常用的通配符为: T,E,K,V,? 区别:
没有区别,知识约定好的特定类型
? 表示不确定的 Java 类型
T (type) 表示具体的一个 Java 类型
K V (key value) 分别代表 Java 键值中的 Key Value
E (element) 代表 Element - 通配符的种类
无限定通配符-Unbounded Wildcard <?> :能够装入任意类型
上限通配符-Upper Bounded Wildcard:必须是指定Number类型或指定Number类型的子类。<? extends Number>
下限通配符-Lower Bounded Wildcard:必须是 Integer 类或 Integer 类的父类—<? super Integer> - List,List,List<?>的区别 List :指定的类,可以通过实例化进行传入 List:指定的类,Object List<?>:不能进行操作。 ? car = getCar()。不合法
2. 反射:
- 什么是反射?
1)对于任意一个Class类,在“运行的时候”,都可以直接得到这个类的全部成分;这种运行时动态获取类信息以及动态调用类成分的能力叫做Java语言的反射机制。 - 反射的关键是什么?
1)反射的第一步是获取编译后的Class类对象,然后可以得到Class的全部成分。
(1):Class c1=Class.forName(“全类名”)已知类的文件名,获取类(静态方法获取,用的最多)
(2):Class c2=类名.class :已知类名,获取类(最安全)
(3):Class c3=对象.getClass() :已知类的实例对象,获取类 - 反射的作用
0)破坏封装性
1)反射获取构造器对象:用于创建类对象(如果是私有构造器,也能够打开,所以会破坏封装性)
2)反射获取成员变量对象(私有成员变量可以通过暴力打开权限):用于在某个对象中取值和赋值。
3)反射获取方法方法对象(私有方法可以通过暴力打开权限):用于在某个对象中触发方法。
4)绕过编译阶段给集合添加数据,没有泛型的约束了。 - 总结反射的作用
1)可以在运行时得到一个类的全部成分然后操作
2)可以破坏封装性(很突出)
3)可以破坏泛型的约束性(很突出)
4)更重要的用途:做Java高级框架
5)基本上主流框架都会基于反射设计一些通用的技术功能。
3. 注解
3.0 注解的作用
- Java语言中的类,构造器,方法,成员变量和参数都可以被注解进行标注
- 进行标记,然后会进行特殊的处理。
3.1 自定义注解
- 自己定义的注解,注解名称和功能自己写;
- 通过元注解注解自己注解的使用范围和生命周期,这是一定要写的。
- 然后使用反射的原理,把注解给解析了。通过反射去取注解,如果是一定的注解,那么就实现一定的功能。
3.2 元注解
注释注解的注解,主要就两类
- @Target:使用范围:约束自定义注解只能在哪些地方使用
- @Retention:申明注解的生命周期。
3.3 注解解析
- 定义:注解的解析就是判断是否存在注解,存在注解就解析出内容
- 类型
1)比如注解在成员方法上面,则现货区成员方法Methods对象,然后再拿上面的注解,实现具体的功能。 - 注解的应用实例
1)junit框架就是一个,主要用于测试书写的方法。(启动时,会被触发执行)
3.4 动态代理
- 定义:代理是被代理者没有能力或者不愿意去完成某件事,需要找个人替自己去完成。
- 关键步骤
1)必须有接口,实现类要实现接口(代理通常是基于接口实现的)
- 创建一个实现类对象,该对象为业务对象,然后再为业务对象做一个代理对象。
- 动态代理的优点
1)非常灵活,支持任意接口类型的实现类对象做代理
2)可以为被代理对象的所有方法做代理
3)可以在不改变源码的情况下,实现对方法功能的增强
4)简化了编程工作,提高了软件系统的可扩展性,同时也提高了开发的效率。(切面编程思想)
4. 异常
4.1 什么是异常,为什么要学习异常
- 什么是异常
1):异常是程序在编译或者执行的过程中可能出现的问题。注意:语法错误不属于异常体系
2):举例:数组索引越界,空指针异常,日期格式化异常 - 为什么需要学习异常
1)异常一旦出现,没有处理的话,会使得JVM虚拟机停止运行
2)研究异常和避免异常,能够使得程序更加安全和稳健。
4.2 异常的体系
- 异常属于Throwable接口,下分有两个,一个是Error,属于操作系统出现错误,不再考量范围内
- 另一个接口为Exception,有两类需要格外注意
(1):RuntimeException及其子类:编译时不报错,但是运行时报错,原因是程序员水平不行,代码写的有问题。
(2):除了RuntimeException及其子类:编译时就报错,主要目的是提醒程序员,这一块比较容易出错,需要格外注意。

4.3 运行时异常
- 概念:直接继承自RuntimeException及其子类,编译阶段不报错,运行时报错
- 举例:
(1)数组索引越界异常:ArrayIndexOutOfBoundsException
(2) 空指针异常:NullPointerException
(3)数学操作异常:ArithmeticException
(4)类型转换异常:ClassCastExcetion
(5)数字转换异常:NumberFormatException - 错误原因:自己代码编写水平有问题
4.4 编译时异常
- 概念:不是直接继承自RuntimeException及其子类,编译阶段就报错
- 举例:
(1)日志解析异常 - 错误原因:担心程序员水平不行,提醒一下,可遇而不可求
4.5 异常的默认处理机制
- 创建异常对象:默认在出现异常的地方常见一个异常对象
- 抛给调用者,抛给虚拟机:异常会从方法出现的点连续向外面抛出
- 输出异常栈:虚拟机接收到异常后,在控制台直接输出异常栈的信息数据
- 干掉程序:程序会被迫停止,后面的程序也运行不了
评价:默认的异常处理机制并不好,一旦真的出现异常,程序会立即死亡
4.6 编译时异常处理机制
4.6.1 抛出去:出现异常直接抛出去给调用者,调用者也继续抛出去:
- 核心使用方法:throws:将方法内部出现的异常抛给本方法的调用者处理
- 缺点:异常方法如果自己不处理,那么就会抛给虚拟机,使得程序死亡
- 抛出的两种途径:
//方式一:对象为方法,能抛出指定的异常
方法 throws 异常一,异常二,异常三..{
方法的内容
}
//方式二:对象为方法,能抛出所有的异常
方法 throws Exception{
方法的内容
}
4.6.2 捕获处理:出现异常自己捕获处理,不麻烦人
- 核心方法:try…catch…:
- 抛出的两种格式
//方式一:并不怎么规范```
try{
//监控可能出现异常的代码
}catch(异常类型1 变量){
//处理异常
}catch(异常类型2 变量){
//处理异常
}...
//方式二:规范格式
try{
//监控可能出现异常的代码
}catch(Exception 变量){
e.printStackTrace(); //直接打印异常栈的信息,可以捕获所有异常
}
4.6.3 两者结合,出现异常直接抛出去给调用者,调用者捕获处理。
- 前两个抛出方法问题:对于方法一,直接抛出异常,会使得程序马上进行死亡状态 ;对于方法二,会使得调用者不知道哪里出现了异常。
- 两者结合的方法
1)在方法中调用异常抛出
2)在调用者处进行捕获处理
4.7 运行时异常处理机制
一般情况是不需要处理异常的,但是可以建议在最外层调用处集中捕获处理即可。
4.8 自定义异常
5. I/O流
6. 重要知识点
6.1 反射机制详情?
6.2 Java代理模式详情
设计模式–代理模式:
- 定义:使用代理对象来代替真实对象的访问,可以在不修改原目标对象的前提下,提供额外的功能。
- 功能:扩展目标对象的功能,在方法执行前后增加功能。
- 实现方法:静态代理和动态代理
- 静态代理的步骤:
- 动态代理的步骤:
- 静态和动态代理的区别:
6.3 IO模型详情
- I/O:输入输出
1)计算机结构角度:
I/O描述了计算机系统 与外部设备之间的通信过程
2)应用程序角度:
用户进程通过向系统请求系统调用,操作系统间接访问内核空间,完成数据的交换。 - 常见的I/O模型:
同步阻塞I/O,同步非阻塞I/O,异步I/O和I/O多路复用和信号驱动I/O
1)同步阻塞I/O–BIO (Blocking I/O)
定义:应用程序发起read调用后,会一直阻塞,直到内核把数据拷贝到用户空间去。
缺点:并发程度不高,一旦数据量大,很难操作
2)同步非阻塞I/O
定义:通过轮询操作,一次次请求read调用,避免了一直阻塞。
缺点:系统调用轮询数据是否已经准备好的过程是十分消耗CPU资源。
3)I/O 多路复用模型 ----NIO (Non-blocking/New I/O)
定义:线程先发起select调用,看是否内核数据已经准备好了,用户线程再发起read调用,NIO引入有一个多路复用器,一个线程能够管理多个客户端。
优点:相比同步非阻塞,通过使用select调用,减少无效的系统调用。降低CPU压力。
4)异步I/O—AIO (Asynchronous I/O)
发起请求,直接返回,后台处理,通知回调。
5)总结:
BIO:客户端发起请求,应用程序阻塞等待,直到处理完成。
NIO:线程通过选择器可以监听多个客户端,客户端发起select调用,看是否准备就绪,然后发起请求。
AIO:客户端发起请求,直接返回,后台处理,通知回调。
6)形象的比喻
(1) BIO:同步阻塞,我去访问一个人家里(read操作),他没在家,我在门口一直等
(2) NIO: 同步非阻塞,我去访问一个人家里(read操作),发现他没在家,我先回去,然后隔一段时间就去一次。
(3) NIO 多路复用(同步非阻塞),在他家装了一个监控,发现他回家了(select操作),电话联系某一个等待的人,让他去他家(read操作)
(4) AIO:异步非阻塞,直接去他家,留下一封信,信上面交代要处理的事情,然后直接回去,主人回来后看见性处理问题,并且寄出回信。
6.4 BigDecimal 详解
-
功能:为了避免精度丢失,采用bigdecimal进行解决。
-
为什么浮点数 float 或 double 运算会有精度丢失的风险呢?
浮点数没有办法用二进制精确表示,因此存在精度丢失的风险。 -
解决办法:
直接使用 BigDecimal 来定义浮点数的值,再进行浮点数的运算操作即可。 -
BigDecimal的常用方法:
新建对象:BigDecimal a = new BigDecimal(“1.0”);
加减乘除:add;abstract; multiply; divid;
大小比较:a.compareTo(b): -1 ; 0 ; 1
保留几位小数:setScale
本文详细介绍了Java中的泛型,包括类型擦除和通配符的使用。接着探讨了反射机制,解释了如何获取和操作类的组件,并强调其在破坏封装性和破坏泛型约束性方面的应用。此外,文章还讲解了注解的定义、自定义注解、元注解以及注解解析,并提到了动态代理的概念和实现。在异常处理部分,阐述了异常的分类、默认处理机制以及如何进行编译时和运行时异常的捕获和处理。最后,简单提及了I/O流和BigDecimal在处理高精度计算时的作用。
&spm=1001.2101.3001.5002&articleId=124258221&d=1&t=3&u=49ea1046ad8a4b84b9a643fc5542bfb7)

被折叠的 条评论
为什么被折叠?



