Mushroom Notes Mushroom Notes
🍄首页
  • JavaSE

    • 基础篇
    • 数据结构
    • IO流
    • Stream流
    • 函数式接口
    • JUC
    • 反射
    • 网络编程
    • 设计模式
  • JavaEE

    • Servlet
    • JDBC
    • 会话技术
    • 过滤器监听器
    • 三层架构
  • JDK

    • 总览
  • JVM

    • 总览
  • 常用mate
  • CSS
  • JavaScript
  • rds 数据库

    • MySQL
    • MySQL 进阶
    • MySQL 库表规范
  • nosql 数据库

    • Redis
    • Redis 进阶
    • Redis 底层
    • MongoDB
  • Spring生态

    • Spring
    • Spring MVC
    • Spring boot
    • Spring Validation
  • Spring Cloud生态

    • Spring Cloud
    • 服务治理
    • 远程调用
    • 网关路由
    • 服务保护
    • 分布式事务
    • 消息中间件
  • 数据库

    • Mybatis
    • Mybatis Plus
    • Elasticsearch
    • Redisson
  • 通信

    • Netty
📚技术
  • 方案专题
  • 算法专题
  • BUG专题
  • 安装专题
  • 网安专题
  • 面试专题
  • 常用网站
  • 后端常用
  • 前端常用
  • 分类
  • 标签
  • 归档

kinoko

一位兴趣使然的热心码农
🍄首页
  • JavaSE

    • 基础篇
    • 数据结构
    • IO流
    • Stream流
    • 函数式接口
    • JUC
    • 反射
    • 网络编程
    • 设计模式
  • JavaEE

    • Servlet
    • JDBC
    • 会话技术
    • 过滤器监听器
    • 三层架构
  • JDK

    • 总览
  • JVM

    • 总览
  • 常用mate
  • CSS
  • JavaScript
  • rds 数据库

    • MySQL
    • MySQL 进阶
    • MySQL 库表规范
  • nosql 数据库

    • Redis
    • Redis 进阶
    • Redis 底层
    • MongoDB
  • Spring生态

    • Spring
    • Spring MVC
    • Spring boot
    • Spring Validation
  • Spring Cloud生态

    • Spring Cloud
    • 服务治理
    • 远程调用
    • 网关路由
    • 服务保护
    • 分布式事务
    • 消息中间件
  • 数据库

    • Mybatis
    • Mybatis Plus
    • Elasticsearch
    • Redisson
  • 通信

    • Netty
📚技术
  • 方案专题
  • 算法专题
  • BUG专题
  • 安装专题
  • 网安专题
  • 面试专题
  • 常用网站
  • 后端常用
  • 前端常用
  • 分类
  • 标签
  • 归档
  • JavaSE

    • 基础篇
      • 命令行
      • 标识符定义规则
      • &|与&&||的区别
      • 数组初始化方式
      • for循环
      • Debug
      • String
      • 字符串的拼接
      • StringBuilder的字符串拼接实现
      • 访问权限修饰符
      • static关键字
      • native关键字
      • 类成员变量与属性
      • 继承
      • 接口与抽象类
      • 多态
      • 工具类原理和延伸
      • 接口
      • final关键字
      • 内部类
      • 枚举类型底层
      • 常用API
        • System类
        • Object类
        • Objects类
        • Math类
        • BigDecimal类
        • SimpleDateFormat
        • Calendar日历类
        • Collections
        • File类
      • 包装类的自动装拆箱底层实现
      • 可变参数
      • 正则表达式
      • 注解
        • 自定义注解
        • 元注解
        • 注解解析
      • 单元测试
      • 异常
      • Java中两种异常的处理方式
    • 数据结构
    • IO流
    • Stream流
    • 函数式接口
    • JUC
    • 反射
    • 网络编程
    • 设计模式
  • JavaEE

  • JDK版本特性

  • JVM

  • Java
  • JavaSE
kinoko
2023-12-15
目录

基础篇

# 命令行


cmd:打开DOS命令行;在文件夹地址栏处输入cmd→在DOS命令行打开该文件夹

dir:查看当前目录下所有的内容

cls:清屏

# 标识符定义规则


  • 由数字、字母、下划线(_)、和美元符($)
  • 不能以数字开头
  • 不能是关键字
  • 区分大小写

# &|与&&||的区别


符号 作用 说明
&& 短路与 作用和&相同,但是有短路效果
|| 短路或 作用和|相同,但是有短路效果
  • 逻辑与 &,无论左边真假,右边都要执行。 短路与 &&,如果左边为真,右边执行;如果 左边为假,右边不执行。
  • 逻辑或 |,无论左边真假,右边都要执行。 短路或 ||,如果左边为假,右边执行;如果 左边为真,右边不执行。

# 数组初始化方式


分为动态初始化及静态初始化:

静态初始化:int[] arr = new int[]{1,2,3,4} int[] arr = {1,2,3,4}

动态初始化:int[] arr = new int[10]

动态初始化只能通过a[0]亦或是遍历数组进行赋值

# for循环


在嵌套循环内部使用break,只能结束内部的循环,如果要结束外部循环需要添加标识,如下:

A: for(int i=0;i<10;i++){
	for(int j=0;j<10;j++){
		break A;//此时结束的是外部的循环
	}
}
1
2
3
4
5

continue:跳过此次循环 break:结束当前循环 return:结束循环所在的当前方法

# Debug


F8:只查看main方法的执行流程 F7:可以看到自定义方法的执行流程 Alt+Shift+F7:可以看到源码的执行流程

# String


创建字符串对象的区别对比

String s1 = new String("abc"); 使用构造方法创建对象,每一次new都会申请一个新的内存空间,此时是通过地址值找这个String对象;

String s1 = "abc"; 使用“ ”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串常量池中维护,此时是在字符串常量池中找这个唯一的对象;也就是说当出现第二条String s2 = "abc";语句,这时不是新建,而是复用。

注意:JDK1.7开始字符串常量池从方法区移动到了堆内存。

有以下示例:
String s1 = "abc";
String s2 = "abc";
s1 == s2;//true

String s1 = new String("abc");
String s2 = new String("abc");
s1 == s2;//false
1
2
3
4
5
6
7
8

方法

方法名 说明
public boolean  equals(Object anObject) 比较字符串的内容,严格区分大小写
public boolean equalsIgnoreCase(String   anotherString) 比较字符串的内容,忽略大小写
public String substring(int beginIndex, int endIndex) 根据开始和结束索引进行截取,得到新的字符串(包含头,不包含尾)
public String substring(int beginIndex) 从传入的索引处截取,截取到末尾,得到新的字符串
public String replace(CharSequence target, CharSequence replacement) 使用新值,将字符串中的旧值替换,得到新的字符串
public String[] split(String regex) 根据传入的规则切割字符串,得到字符串数组
boolean startsWith(String prefix) 检查字符串是否以指定前缀开头
boolean startsWith(String prefix ,int toffset) 检查在索引开始处字符串是否以指定前缀开头
boolean endsWith(String suffix) 检查字符串是否以指定前缀结尾

注意:public boolean equals(Object anObject)这个方法只有跟字符串比较才会实现内容的比较,如果跟其他的类型是不比较的,会直接返回false。

# 字符串的拼接


String的拼接实际上会分为三步:创建StringBuilder对象,使用append方法,再调用toString方法返回拼接好的字符串;也就是说字符串的拼接,拼接一次就要创建两个新对象,即耗时又耗空间。

# StringBuilder的字符串拼接实现


StringBuilder跟String相比,StringBuilder是可变的,并且在拼接字符串的时候不会创建新的对象。其实这个说法并不准确,StringBuilder在拼接字符串时还是会开辟新的内存空间。当创建StringBuilder对象时,会创建一个容器,一个容量为16的byte数组,调用append方法会将字符串放入这个数组中。当数组满了,就会创建一个更大容量的数组,将旧数组copy过去,然后将新的字符串存入数组,从而达到字符串拼接的效果。

# 访问权限修饰符


同一个类 同一个包 不同包子类 不同包非子类
public √ √ √
Protected √ √ √
Default √ √ x
private √ x x

# static关键字


只要被静态修饰了的,在内存中都只有一份,也是最优先被加载进内存的。

static的使用场景

  • 如果某个成员变量希望被共享,则定义成静态成员,只有一份。
  • 如果该方法是以执行一个通用功能为目的,且需要共享及方便访问,既可以声明成静态方法。

注意:

  1. 静态方法只能访问静态的成员,不可以直接访问实例成员。
  2. 实例方法可以访问静态的成员,也可以访问实例成员。
  3. 静态方法中是没有this关键字

# native关键字


方法使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。这些函数的实现体在DLL中,JDK的源代码中并不包含,一般是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。

native 是用做java 和其他语言(如c++)进行协作时用的,也就是native 后的函数的实现不是用java写的
native的意思就是通知操作系统,这个函数你必须给我实现,因为我要使用。所以native关键字的函数都是操作系统实现的,java只能调用。

java是跨平台的语言,既然是跨了平台,所付出的代价就是牺牲一些对底层的控制,而java要实现对底层的控制,就要一些其他语言的帮助,这个就是native的作用了

# 类成员变量与属性


java类的成员变量和属性是一样的,这个说法并不准确,具体得看使用情境。

属性的官方定义:属性是指get或者set方法名,去掉get或者set后,把剩余的部分首字母改为小写后,即为这个类的属性。

一个类拥有自己的属性以及行为,属性即成员方法外的变量,行为即成员方法。

这种说法的成立在程序员间不约而成的一种定义规范:我们定义一个javabean默认都是将类成员私有,然后提供每一个成员变量对外的公共接口,即get和set方法。类的反射就是通过get和set方法获取成员属性的,所以我们默认将成员变量都看作为了属性,于是就有了属性即成员方法外的变量这种说法。

# 继承


定义:将多个类的相同属性和行为抽取到单独一个类中。

为什么要先执行父类构造器?

子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。

子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。

**注意:**如果父类没有无参构造,会报错,要手动在子类super.调用父类的有参构造。

子类构造器如何调用到父类构造器?

子类构造器的第一行语句默认都是:super(),不写也存在。

引用传递与值传递的区别?

首先引用传递与值传递传递的都相当于一个副本,实参和形参其实是互不相关的,但在引用传递中,形参是怎么影响实参的呢?是因为形参在拿到实参传递的地址值后,对地址值存放的数据进行了操作,所以导致实参的数据出现了变化。但要注意String 在引用传递中比较特殊。

String作为参数传递时,形参会不会影响实参的值?

String虽然是引用类型,但是不会因为形参的改变而影响实参,首先因为形参和实参是互不相关的,形参拿到的是实参传递的地址值,等于是形参和实参都指向了同一个地址,当形参指向的地址发生改变,只要方法内不return形参的地址赋值给实参,那么实参是不会受到影响的。

# 接口与抽象类


JDK8之前接口中只允许定义常量和抽象方法,JDK8后为优化版本更新带来的接口实现类维护繁琐,接口中允许定义默认方法以及静态方法(注意:静态方法必须用接口本身的接口名来调用)。也就是能够做到让接口的实现类只重写想要使用的接口方法,当实现类重写了接口方法后则使用重写的方法,否则使用接口中默认的方法实现。JDK9后接口中允许定义私有方法,只能在本类中被其他默认方法或者私有方法访问。

JDK9后接口就与抽象类的区别

接口:

  • 成员变量只能定义常量
  • 方法默认修饰符是public
  • 允许定义静态方法、默认方法
  • 不允许定义构造方法

抽象类:

  • 普通类能定义什么抽象类也能定义
  • 与普通类的区别就在于存在抽象方法

# 多态


父类 变量名 = new 子类()
1

方法的调用编译看左边,运行看右边:指的是编译左边父类的成员方法,运行调用子类与父类共有的,也就是说子类特有的方法无法调用,因为编译时加载的是父类,父类中没有子类特有的方法,所以没有加载进内存。运行看右边是指共性方法的实现根据创建的子类的不同而变。

变量的调用编译看左边,运行看左边:变量是没有多态性的

多态的优劣势

在多态形式下,右边对象可以实现组件化切换。

Animal a = new Dog();
a.run(); // 后续业务行为随对象而变,后续代码无需修改
1
2

便于扩展和维护。可以实现类与类之间的解耦。

定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,更能体现出多态的扩展性与便利。但是,多态下不能使用子类特有的功能。

弊端:无法调用子类特有方法

# 工具类原理和延伸


对于一些应用程序中都有的共性的功能,可以将这些功能进行抽取成静态方法,独立封装成工具类,以便其他方法调用。作用:一是方便逻辑调用,二是提高了代码复用。

工具类是为了方便直接用类使用,但是该类还是可以创建对象,应强制该类不能创建对象,建议将构造器私有。

# 接口


JDK8之前接口中只允许定义常量和抽象方法,JDK8后为优化版本更新带来的接口实现类维护繁琐,接口中允许定义默认方法以及静态方法。(注意:静态方法必须用接口本身的接口名来调用)。JDK9后接口中允许定义私有方法,只能在本类中被其他默认方法或者私有方法访问。

# final关键字


final 修饰的特点

修饰类:表明该类是最终类,不能被继承。
修饰方法:表明该方法是最终方法,不能被重写。
修饰变量:表明该变量是常量,表示该变量第一次赋值后,不能多次被赋值。

# 内部类


成员内部类:定义在类中方法外的内部类;字节码文件格式:外部类名$内部类名.class
局部内部类:定义在方法内的内部类;字节码文件格式:外部类名$数字(1,2,3...)内部类名.class
匿名内部类:格式: ↓ 字节码文件格式:外部类名$数字(1,2,3...).class

接口/父类 = new 接口的实现类(){
    @Override
    重写的方法;
}
--------------------------
Runable是个接口
Runable run = new Runable()#{//#是被隐藏的实现类名,也就是所谓的匿名,实现了Runable接口
	@Override
	public void running(){
		System.out.println("跑");
	}
};
run.running();
1
2
3
4
5
6
7
8
9
10
11
12
13

# 枚举类型底层


  • 枚举类本质上就是一个类,继承了Enum;
  • 枚举类定义的枚举项,其实就是用public static final 修饰了的枚举类对象,并且用了静态代码块进行初始化,也就是将成员修饰成了常量。
  • 枚举类的构造方法用private修饰,意味着我们无法实例化这个类,也就是不能创建这个类的对象,只能通过类名.成员变量的方式使用该类的成员变量。
  • 枚举是一种多例模式,有多少个枚举项就有多少例
  • 当枚举项只有一项时,这个枚举类就是单例模式
public enum Gender{
    MALE,FEMALE;
}
-------------------------------------
public final class Gender extends Enum {
    
	public static final Gender MALE;
	public static final Gender FEMALE;
    
	private Gender(String s, int i)
	{
		super(s, i);
	}
    
	static 
	{
		MALE = new Gender("MALE", 0);
		FEMALE = new Gender("FEMALE", 1);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 常用API

# System类


方法 描述
static long currentTimeMillis() 返回当前时间(以毫秒为单位)。
static void exit(int status) 终止当前运行的Java虚拟机。
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 将指定源数组中的数组从指定位置复制到目标数组的指定位置。
  • exit(0)正常退出,非0传参异常退出,主方法内所有代码运行完会默认调用该方法。
  • currentTimeMillis()用于程序耗时记录(毫秒)。从1970年1月1日,0时0分0秒开始。
  • arraycopy(源数组,源数组复制开始索引,目标数组,目标数组从哪个位置开始存放,复制的数量)很多容器的扩容方式底层都是用的这个方法。

# Object类


常用方法

方法名 说明
public String toString() 返回对象的地址值,建议所有类都重写该方法。
public boolean equals(对象) 比较对象是否相等,默认使用==比较两个对象地址。

Object类的equals()方法

Object类的equals方法底层实现也是用"=="比较的,所以默认比较的也是对象的地址值。

之所以String和集合中的Integer能直接比较值是因为重写了equals和hashcode方法,当我们需要将自定义的对象参与比较时就需要重写对象的equals和hashcode方法。

**扩展:**Object类的equals方法允许与null进行比较,但是不允许null调用equals方法,因为null没有equals方法,会报空指针异常,而Objects类中的equals方法允许两个null进行比较。

public void Demo1() {
        Student s1 = null;
        Student s2 = new Student();
        System.out.println(s2.equals(s1));
        System.out.println(Objects.equals(s1, s2));
        System.out.println(Objects.equals(s1, null));
    }

运行结果:
false
false
true
1
2
3
4
5
6
7
8
9
10
11
12

# Objects类


常用方法

方法名 说明
public String toString() 返回对象的地址值,建议所有类都重写该方法。
public boolean equals(对象) 比较对象是否相等,默认使用==比较两个对象地址。

# Math类


主要用于对数据进行处理。

常用方法

方法名 说明
public static int   abs(int a) 返回参数的绝对值
public static double ceil(double a) 向上取整
public static double floor(double a) 向下取整
public   static int round(float a) 四舍五入
public   static double pow(double a,double b) 返回a的b次幂的值

# BigDecimal类


计算机进行浮点数运算时需要将浮点数转换成二进制再进行运算,就可能会出现10/3这种除不尽的情况,所以就会导致出现精度丢失,例如:

double a = 0.1 + 0.2; //0.300000000000004
1

BigDecimal类就是用来解决数学运算的精度问题的,可以表示任意精度的数字。
当需要存储远超long精度的数字,就可以使用BigDecimal。

BigDecimal 类构造方法

构造方法 说明
BigDecimal(double val) 参数为double(不推荐)
BigDecimal(String val) 参数为String(推荐使用)

BigDecimal 类的常用方法

方法名 说明
public BigDecimal add(另一个BigDecimal对象) 加法
public BigDecimal subtract (另一个BigDecimal对象) 减法
public BigDecimal multiply (另一个BigDecimal对象) 乘法
public BigDecimal divide (另一个BigDecimal对象) 除法(除得尽的情况)
public BigDecimal divide (另一个BigDecimal对象,保留位数,RoundingMode舍入模式) 除法(除不尽的情况)

**总结:**对数据进行处理用Math,求运算精度用BigDecimal

# SimpleDateFormat


SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类。是DateFormat的子类,它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。

构造器 说明
public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认格式
public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat,使用指定的格式
方法 说明
public final String format(Date date) 将日期格式化成日期/时间字符串
public Date parse(String source) 从给定字符串的开始解析文本以生成日期

规范:
image.png
示例:
image.png

# Calendar日历类


对象创建

Calender是一个抽象类,不能直接创建对象,需要通过静态的getInstance() 方法创建子类对象。

Calender c = Calender.getInstance();//通过多态创建实例
1

Calendar类相对于Data类来说,功能更加强大,虽然获取时间可能会变得稍微繁琐一点,但是时间的设置会变得非常便利。你在系统日历中能进行的操作,基本上都可以通过这个类完成。

常用方法

方法 说明
get(int   field) 返回指定日历字段的值。
set(int   field, int value) 设置指定日历字段的值。
add(int   field, int amount) 添加或减去某个日历字段的值。(向前向后一百天)
getTime() 获取Date对象。
getTimeInMillies() 返回该日历时间的毫秒值。

**int field**字段常量 例如:**Calendar.YEAR**

字段值 含义
YEAR 年
MONTH 月(月份从0开始,0~11   表示   1月~12月)
DATE(或   DAY_OF_MONTH   ) 日
HOUR 时(12小时制)
HOUR_OF_DAY 时(24小时制)
MINUTE 分
SECOND 秒
DAY_OF_WEEK 周几(数字   1~7   表示   周日~周六)

# Collections


常用方法

方法 说明
addAll(Collection c, T... elements) 将所有指定的元素添加到指定的集合c中。
shuffle(List<?> list) 随机打乱list集合中元素的顺序。
sort(List list) 根据自然顺序对list集合的元素进行升序排序。
sort(List list, Comparator c) 根据指定的比较器,对list集合元素进行自定义排序。

**补充:**Comparator接口重写compare()方法,比较规则与compareTo()方法一致:

  • 如果返回值为负数,认为当前存入的元素是较小值,存左边。
  • 如果返回值为正数,认为当前存入的元素是较大值,存右边。
  • 如果返回值为0,认为两个元素一样,不存入集合。

# File类


常用构造方法

方法 说明
File(String pathname) 通过路径名字符串创建File对象
File(String parent, String child) 从父路径名字符串和子路径名字符串创建File对象
File(File parent, String child) 从父抽象路径名和子路径名字符串创建File对象

路径斜杠问题:\ 在字符串里要写两个 \ Windows系统支持 \ 和 / Linux只支持 /

**注意:**File对象相当于一个路径,路径可以是存在的也可以是不存在的

常用方法

方法 说明
public boolean delete() 删除文件或文件夹
public boolean createNewFile() 创建一个新的文件
public boolean mkdir() 创建一个单级文件夹
public boolean mkdirs() 推荐使用 创建一个单级或多级文件夹
public boolean isDirectory() 判断是否是文件夹
public boolean isFile() 判断是否是文件
public boolean exists() 判断是否存在
public long length() 获取文件大小,单位字节
路径
public String getAbsolutePath() 返回File对象的绝对路径
public String getName() 获取名字(路径最后一个\\右边的)
public String getParent() 获取父路径(路径最后一个\\左边的)
目录
String[] list() 获取文件夹里面的内容,以字符串的形式返回
public File[] listFiles() 获取文件夹里面的内容,以File对象的形式返回

注意:

  • delete()方法删除是不走回收站的,是直接删除,若删除的是文件夹,需清空文件夹内容才能删除
  • length()方法无法获取文件夹的大小
  • list()和listFiles()方法只有路径是文件夹的File对象才能调用,如果是文件调用listFiles()会返回null

路径

**绝对路径:**从盘符开始寻找 如:D:/Mytestfile/aaa
相对路径:不带盘符,默认从当前项目所在文件夹找 如:模块名/aaa

案例

**需求:**搜索某个文件夹中的所有java文件,如果文件夹中有文件夹也要找出来
**思路:**通过递归实现

代码:

public class Testcode {

    public static void main(String[] args) throws Exception {
        findjava(new File("D:\\Develop\\MyFileTest"));
    }

    public static void findjava(File dir){
        // 获取目录
        File[] files = dir.listFiles();
        // 遍历目录
        for (File file : files) {
            // 判断是否是文件
            if (file.isFile()){
                // 判断是否是java文件
                file.getName().endsWith(".java");
                // 打印
                System.out.println(file);
            }else {
                // 是文件夹则递归查找
                findjava(file);
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

**提示:**Windows很多操作底层也是通过递归实现的,如:删除文件夹、检索文件、计算文件夹大小

UUID.randomUUID().toString();需要文件名不重复时

# 包装类的自动装拆箱底层实现


底层其实就是调用了ValueOf(基本数据类型)和基本数据类型inValue()这两个方法

Integer integer = 10;
		int i = integer;
---------------------------------------
Integer integer = Integer.valueOf(10);
		int i = integer.intValue();
1
2
3
4
5

字符串转基本数据类型:static int parseInt(String s);

# 可变参数


格式:

修饰符 返回值类型 方法名(参数类型 ... 形参名) {

}
1
2
3

范例:

public static void getnum(int… a) {

}
----------------------------------
// 可变参数底层是数组,可以看作成
public static void getnum(int[] a){
	for(int i = 0;i < a.length;i++){//所以这个a是能作为数组遍历的
		System.out.println(a[i]);
	}		
}
1
2
3
4
5
6
7
8
9
10

调用:

sum(1);
sum(1,2);
sum(1,2,3);
1
2
3

注意

  1. 可变参数本质是数组。
  2. 一个方法只能有一个可变参数。
  3. 如果方法中有多个参数,可变参数要放到最后。

# 正则表达式


String类中支持正则表达式的方法:

方法 说明
boolean matches (String regex) 判断该字符串是否匹配指定的正则表达式。
String replaceAll (String regex, String replacement) 将该字符串中所有匹配正则表达式的内容替换成新的字符串,并返回替换后的新的字符串。
String[] split (String regex) 根据匹配规则,把字符串分割成多个子串。

范围匹配

[abc]:匹配abc中任意一个字符。 	
[a-z]:匹配小写字母a-z中的一个。
[A-Z]:匹配大写字母A-Z中的一个。
[0-9]:匹配数字0-9中的一个。 
[a-zA-Z0-9]:匹配a-z或者A-Z或者0-9之间的任意一个字符。
[a-dm-p]: 匹配a-d或m-p之间的任意一个字符。  
[^abc]:匹配除a、b、c之外的任意一个字符。
[^a-z]:匹配除小写字母外的任意一个字符。
1
2
3
4
5
6
7
8

预定义字符

“.” : 匹配一个任意字符
"\d“: 匹配一个数字字符,相当于[0-9]
"\D“: 匹配一个非数字,相当于[^0-9]
“\s“: 匹配一个空白字符 
"\S“: 匹配一个非空白字符
"\w“: 匹配一个单词字符,包括大小写字母,数字,下划线,相当于[a-zA-Z0-9_]
"\W“: 匹配一个非单词字符
---------------------
java中需要多一个\进行转义,即\\d
1
2
3
4
5
6
7
8
9

数量词(限定符)

?      0次或1次
*      0次或多次 (任意次)
+      1次或多次
{n}    重复n次
{n,}   重复n次以上 (至少n次)
{n,m}  重复n到m次(包括n和m)
1
2
3
4
5
6

逻辑匹配

&& :并且(交集)
|  :或者(并集)
1
2

括号分组

正则表达式中用小括号()来做分组,也就是括号中的内容作为一个整体。
1

示例

/*
要求:
     邮箱地址必须是6~18个字符,可使用字母,数字,下划线,需要以字母开头。
     邮箱后缀支持 @163.com 或者 @126.com 或者 @yeah.net。
*/

public class Demo1 {
    public static void main(String[] args) {
        String email = "itheima@yeah.net";
        boolean result = 
            email.matches("[a-zA-Z]\\w{5,17}@(163\\.com|126\\.com|yeah\\.net)");
        System.out.println(result);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 注解


概述

Annotation表示注解。是JDK1.5的新特性。
注解是给编译器或JVM看的,编译器或JVM可以根据注解来完成对应的功能。

**注解的主要作用:**对类进行标记。通过注解可以给类增加额外的信息。

**注:**java源码中有很多没有属性的空注解,起到标记的作用

JDK的内置注解

  • @Override:限定重写父类的方法,该注释只能用于方法
  • @Deprecated:用于表示某个程序元素(类,方法等)已过时
  • @SuppressWarnings:抑制编译器警告

# 自定义注解


自定义注解格式:

public @interface 注解名称 {
    public 属性类型 属性名();
}
1
2
3

允许存放的属性类型:基本数据类型``String``Class``注解``枚举以及以上类型的一维数组

注意:

  • 注解的属性不允许存放自定义类型。
  • 同一个位置不能放同一个注解

自定义注解的使用

public @interface MyAnno2 {
    // 属性和类中的成员变量一样,可以保存数据
    public String name();
    public double price() default 88.88; // 设置默认值
}
----------------------------------
public class Demo11 {
    @MyAnno2(name = "水浒传", price = 9.9)
    public static void main(String[] args) {
    }
}
1
2
3
4
5
6
7
8
9
10
11

注意:

  • 使用自定义注解时要保证注解每个属性都有值
  • 注解可以使用默认值
  • 当注解中只有"一个属性",并且属性名是"value",使用注解时,可以省略value属性名

# 元注解


概念:修饰注解的注解被称为元注解

注解 说明
@Target 指定注解能在哪里使用
@Retention 可以理解为保留时间(生命周期)
@Documented 添加javadoc中的描述
@Inherited 指该注解会被子类继承

使用格式

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
1
2
3
4

元注解@Target

**作用:**用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。
可使用的值定义在ElementType枚举类中,常用值如下:

  • TYPE,类,接口
  • FIELD, 成员变量
  • METHOD, 成员方法
  • PARAMETER, 方法参数
  • CONSTRUCTOR, 构造方法
  • LOCAL_VARIABLE, 局部变量

元注解@Retention

**作用:**用来标识注解的生命周期(有效范围)

可使用的值定义在RetentionPolicy枚举类中,常用值如下:

  • SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS:注解作用在源码阶段,字节码文件阶段(会存在编译后的字节码文件中),运行阶段不存在,默认值
  • RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

SOURCE(源代码) CLASS(字节码) RUNTIME(运行时)
xxx.java -> javac编译 -> xxx.class -> java运行 -> 程序运行

# 注解解析


概念:获得注解上数据的过程则称为注解解析。

与注解解析相关的接口
AnnotatedElement:该接口定义了与注解解析相关的方法

AnnotatedElement接口常用方法

方法 说明
T getAnnotation(Class annotationClass) 根据注解类型获得对应注解对象
Annotation[] getAnnotations() 获得当前对象上使用的所有注解
boolean isAnnotationPresent(Class annotationClass) 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

# 单元测试


Junit介绍

JUnit 是一个 Java 中常用的单元测试工具。
JUnit 可以很方便的对Java中的方法进行测试,提高测试效率。

**注:**JUnit是第三方的工具,需要导包

Junit常用注解(Junit 4.xxxx版本)

注解 说明
@Test 单元测试方法
@Before 在每个测试的方法前运行
@After 在每个测试的方法后运行
@BeforeClass 在所有测试的方法前运行一次
@AfterClass 在所有测试的方法后运行一次

Junit常用注解(Junit 5.xxxx版本)

注解 说明
@Test 单元测试方法
@BeforeEach 在每个测试的方法前运行
@AfterEach 在每个测试的方法后运行
@BeforeAll 在所有测试的方法前运行一次
@AfterAll 在所有测试的方法后运行一次

**@Test要求:**必须是public修饰、返回值必须是void、不能有参数

常用方法

方法 说明
void assertEquals(String,long,long) 判断是否是期望值(提示信息,期望值,实际值)

# 异常


错误:是指程序正常情况下,不应该出现的非正常情况,通过代码无法处理的;比如:电源断电了
异常:是指程序可能会出现的不正常的情况,程序员能够处理的
程序在执行过程中,出现的非正常的情况,最终会导致 JVM 的非正常停止。
注意:语法错误不算在异常体系中。

异常体系

image.png

**编译时异常:**就是在编译的时候出现的异常。
**运行时异常:**就是在运行时出现的异常。

image.png

异常的产生过程解析

  1. JVM调用main方法进入程序
  2. 执行代码发现异常
  3. 产生异常信息
  4. 检查当前代码处是否有处理异常
  5. 无则将异常传递上级,即main方法
  6. main方法也没有处理异常
  7. 传递给main方法调用者JVM
  8. JVM收到异常,打印异常信息,停止程序

异常对象的创建—throw

格式:throw new 异常类名();

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入年龄:");
        int age = sc.nextInt();
        if (age<0){
            throw new RuntimeException("年龄不能为负数");
        }else {
            System.out.println("age = " + age);
        }
    }
1
2
3
4
5
6
7
8
9
10
运行结果:

请输入年龄:-1
Exception in thread "main" java.lang.RuntimeException: 年龄不能为负数
	at Test.Testcode.main(Testcode.java:6)

1
2
3
4
5
6

# Java中两种异常的处理方式


  • throws 抛出异常,把异常抛给调用者处理(方法内即抛给方法,没有则继续向上抛,最终是抛给JVM)

格式:**修饰符返回值类型 **方法名(参数) throws 异常类名1, 异常类名2{ }

  • try_catch_finally 捕获异常,处理异常

格式:

try {
	可能出现异常的代码;
} catch (异常类名1 e) {
	处理异常的代码;
} finally {
	代码;
}
1
2
3
4
5
6
7

注意:

try_catch_finally方式catch在语法上是允许省略的,但是catch和finally不能同时省略。
这样写的话就算在try代码块中检测到了异常,也不会去捕获,一般不会这样写代码。

若try中出现异常,则try中异常语句后续代码不会执行,直接跳到对应的catch代码块。

即使在try或catch中return了,finally还是会执行。
执行流程如下:

  1. 先计算返回值,并将返回值缓存起来,等待返回
  2. 执行finally代码块
  3. 将之前存储的返回值返回

需要注意的是:
返回值的返回规则与值传递和引用传递的规则一致,返回值是在finally代码块执行前就确定了的,并且缓存了副本。如果返回的是基本数据类型,那么finally对这个变量进行再赋值也不会改变返回的值,因为这时返回的是缓存的副本。如果返回值是引用数据类型,返回的则是地址值的副本,只要finally不改变地址值对应的数据,也是不会影响返回的值。

finally代码块中不建议包含return,因为程序会在上述流程前提前退出,也就是说返回的不是try或catch的值。

如果在try或catch中停止了JVM,则finally不会执行,如:在trycatch中调用System.exit(0)

Throwable 的成员方法

方法名 说明
public String getMessage() 返回此 throwable 的详细消息字符串
public String toString() 返回此可抛出的简短描述
public void printStackTrace() 把异常的错误信息输出在控制台

重写时的异常注意事项

  • 子类重写方法throws的异常要比父类方法throws的异常相同或更少
  • 父类方法没有throws异常,子类方法只能try...catch处理
#java
上次更新: 2023/12/29 11:32:56
数据结构

数据结构→

最近更新
01
JVM 底层
09-13
02
JVM 理论
09-13
03
JVM 应用
09-13
更多文章>
Theme by Vdoing | Copyright © 2022-2024 kinoko | MIT License | 粤ICP备2024165634号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式