一.动态代理
无侵入式的给方法增加执行的内容
之后springboot的AOP底层就是使用动态代理实现的。
二.反射
利用反射创建的对象可以无视修饰符调用类里面的内容
面试相关内容:泛型擦除,修改字符串内容。
可以跟配置文件结合起来使用,把要创建的对象信息和方法写在配置文件中。
读取到什么类,就创建什么类的对象
读取到什么方法,就调用什么方法
此时当需求变更的时候不需要修改代码,只要修改配置文件即可。
注:未来我们用框架写代码时,经常把类的配置信息放在配置文件上
三.XML
类似于HTML,是另一种标记语言,简单说就是用来存放和传递信息的。
主要作为软件的配置文件,标签元素就是配置的相关内容。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itheima</groupId>
<artifactId>uuAttendance</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
<description>demo2</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
例如这个XML,文件,version标签标识目前XML的版本,encoding代表的是该XML标签使用游览器打开的时候采取的字符集,dependencies标签中存放的是当前项目所需的依赖。
XML解析技术有JAXP,JDOM,DOM4J等,并从编写好的XML中提取内容。
XML中的标签千奇百怪,我们可以用did,shema提供的API自定义可使用的标签和属性,这就叫做XML文档约束。
四.异常
异常就是代表程序出现的问题。
Java中将异常封装为类,继承体系如下。
1.异常体系
2.抛出异常throw
在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。
throw new 异常类名(参数);
3.捕获异常try-catch-finally
try catch捕获异常,try代码块中的代码是可能会出现异常的代码,如果出现异常,就直接走catch代码块中的代码处理异常,处理完异常后会执行finally中的代码。
具体例子:
public static void main(String[] args){
try {
Scanner scanner=new Scanner(System.in);
int a=scanner.nextInt();
int b=scanner.nextInt();
int cal=a/b;
System.out.println(cal);
}catch (RuntimeException runtimeException){
System.out.println(runtimeException);
}finally {
System.out.println("666");
}
}
比如上面这个,实现的是输入两个数实现除法,如果没有抛出异常程序会终止运行,如果没有try catch,程序会终止运行,这不是我们想要的,如果try--catch,如果出现异常,就直接走catch代码块中的代码处理异常,然后再执行finally中的代码。
那么为什么要捕获异常而不直接设置if条件避免异常呢? 因为我们虽然预测到了try代码块中的代码会异常,但往往引起一个异常对应的情况就千千万万,我们无法预测引起异常的所有情况,所以普通if是列举不完情况的。
比如用户输入框输入,你永远不知道用户会输入什么玩意导致异常,这时直接一个捕获异常,然后抛出异常就使得问题变得简单。
注意:不要在 finally 语句块中使用 return! 当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。
4.声明异常throws
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常或者抛出异常,不然会报错。
比较:从作用上看,throw是于运行时抛出异常,当符合设定的异常条件时,抛出异常。 而throws是声明异常,声明多个异常,声明过后使用者使用这个方法就要对方法就行捕获或继续声明异常,不然就会编译时期不能通过。
格式:throws后面跟的是异常类,可以多个,写在方法名后。
例:
(1)声明异常
public class Dog{
public void eat() throws Exception{
System.out.println("狗吃东西");;
}
}
(2)当你调用这个方法的时候要去处理异常:
public class Main {
public static void main(String[] args){
try {
Dog dog=new Dog();
dog.eat();
}catch (Exception exception){
System.out.println(exception);
}
}
}
或者继续抛出:
public class Main {
public static void main(String[] args) throws Exception{
Dog dog=new Dog();
dog.eat();
}
}
也可以声明多个异常:
import java.io.IOException;
public class Dog{
public void eat() throws IOException,RuntimeException{
System.out.println("狗吃东西");;
}
}
相应的也要处理对应的所有异常或者抛出对应的所有异常
如果只处理一个会报错:
public class Main {
public static void main(String[] args){
try {
Dog dog=new Dog();
dog.eat();
}catch (RuntimeException exception){
System.out.println(exception);
}
}
}
要全部处理或全部抛出
public class Main {
public static void main(String[] args){
try {
Dog dog=new Dog();
dog.eat();
}catch (Exception exception){
System.out.println(exception);
}
}
}
import java.io.IOException;
public class Main {
public static void main(String[] args){
try {
Dog dog=new Dog();
dog.eat();
}catch (RuntimeException runtimeException){
System.out.println(runtimeException);
}catch (IOException ioException){
System.out.println(ioException);
}
}
}
5.自定义异常类
继承其他异常
五.多线程(JUC)入门
1.什么是多线程
有了多线程,我们就可以让程序同时做多件事情。
比如一个软件要边运行边计算时间就要用到多线程。
2.并发与并行
并发:在同一时刻,有多个指令在单个CPU上交替执行。
并行:在同一时刻,有多个指令在多个CPU上同时执行。
因为并发交替的时间很短,所以从宏观来说就是同时执行。
当CPU的线程足够时,就用并行就够了,如果当要同时操作的事情数量大于CPU则一定需要用到并发。
举个例子,两个线程可以看成你有两只手,当你执行看报纸同时喝牛奶的时候,则一只手喝牛奶,一只手看报纸就够了,这就是并行。
但是当你同时执行同时看报纸,喝牛奶,吃香蕉的时候,你的另一只手就要在喝牛奶喝吃香蕉之间快速切换,喝一口牛奶,然后吃一口香蕉,再喝一口牛奶。这就是并发。
3.多线程的实现
【1】实现方式
【2】Tread中常用的成员方法