🙈作者简介:练习时长两年半的Java up主
🙉个人主页:程序员老茶
🙊 ps:点赞👍是免费的,却可以让写博客的作者开兴好久好久😎
📚系列专栏:Java全栈,计算机系列(火速更新中)
💭 格言:种一棵树最好的时间是十年前,其次是现在
🏡动动小手,点个关注不迷路,感谢宝子们一键三连
目录
String字符串
String是一个类,属于数据类型中的引用类型。
Java的一切使用""引起来的内容,都是这个类的实例,称为字符串对象。
字符串在定义后,值不可改变,是一个常量,实际是一个字符数组。
String类使用时注意
由此可见,如果要频繁改动String类型变量的值,会创建很多字符串对象,效率很低。
所以在频繁改动字符串时,不要使用String类。
如果要频繁改动字符串时,使用StringBuilder或StringBuffer类。
总结
在使用字符串时,字符串是对象,如果要比较其值是否相同,不能使用判断,因为判断的是内存地址。
所以在比较字符串是否相同时,要使用String类重写的equals方法进行判断。
String类中equals重写的原理大致是:
判断是否为同一个字符串,再判断是否是字符串类型,再将两个字符串转换为字节数组,逐一比较字节数组中的内容,全部一致,返回true
调用equals方法时,通常将已知非空字符串作为调用者
字符串String类中的常用方法
方法名 | 返回值 | 作用 |
---|---|---|
length() | int | 得到字符串长度 |
toLowerCase() | String | 转换为小写 |
toUpperCase() | String | 转换为大写 |
trim() | String | 去除字符串的首尾全部空格 |
isEmpty() | boolean | 判断字符串长度是否为0 |
getBytes() | byte[] | 转换为字节数组 |
toCharArray() | char[] | 转换为字符数组 |
equalsIgnoreCase(String str) | boolean | 忽略大小写比较字符串是否相同 |
equals(String str) | boolean | 判断两个字符串是否相同 |
charAt(int index) | char | 得到某个索引上的字符 |
indexOf(String str) | int | 得到某个字符串第一次出现的索引,不存在返回-1 |
lastIndexOf(String str) | int | 得到某个字符串最后一次出现的索引,不存在返回-1 |
contains(String str) | boolean | 判断是否存在某个字符串 |
startsWith(String str) | boolean | 判断是否以指定字符串开头 |
endsWith(String str) | boolean | 判断是否以指定字符串结尾 |
concat(String str) | String | 将指定字符串拼接到原字符串末尾 |
substring(int index) | String | 从索引index开始截取字符串至末尾 |
substring(int begin,int end) | String | 截取[begin,end)范围内的字符串 |
split(String regex) | String[] | 根据字符串或正则表达式切分原字符串。相当于split(regex,0) |
split(String regex,int limit) | String[] | 根据字符串或正则表达式切分原字符串,limit为正数,数组长度最大为limit;limit为0,数组长度无限制,但省略最后的空字符串;limit为负数,数组长度无限制。 |
replace(String oldStr,String newStr) | String | 将原字符串中的oldStr替换为newStr |
replaceFirst(String oldStr,String newStr) | String | 将原字符串中第一次出现的oldStr替换为newStr |
String.valueOf(参数) | String | 将参数转换为字符串。参数可以是任何数据。通常用于原始类型转换为字符串 |
String.format(String 格式,Object…obj) | String | 根据指定格式转换参数。常用与将浮点数据保留指定小数位数。\n如String.format(“%4.2f”,2.345)表示将2.345保留2位小数,整体占4位,输出为字符串格式。如果实际数字总位数大于4,原样输出,如果实际数字总位数小于4,会在最前补充空格。 |
可变字符串
String字符串对象是一个常量,在定义后,值不可改变。
如果使用String类的对象,对其频繁更新时,就会不停地创建新对象,不停引用给同一个变量。
如果要执行10000次循环重新赋值的过程,就会创建10000个字符串对象,效率很低,这是就需要使用可变字符串对象。
StringBuilder
用于表示可变字符串的一个类,是非线程安全的,在单线程环境下使用,效率更高。
StringBuffer
用于表示可变字符串的一个类,是线程安全的,在多线程环境下使用。
StringBuilder和StringBuffer中的方法都一致,只不过StringBuffer中的方法使用了synchronized关键字修饰,表示是一个同步方法,在多线程环境下不会出现问题。
这里以StringBuilder为例
构造方法
常用构造方法 | 作用 |
---|---|
StringBuilder() | 创建一个大小为16的字节数组,表示一个空白字符串。 |
StringBuilder(int capacity) | 创建一个指定大小的字节数组,表示一个空白字符串。 |
StringBuilder(String str) | 创建一个str的长度+16大小的字节数组。表示str这个字符串。 |
常用方法
常用方法 | 作用 |
---|---|
append(Object obj) | 将任意数据添加到原可变字符串末尾 |
delete(int start,int end) | 删除[start,end)范围内的字符 |
deleteCharAt(int index) | 删除index索引上的字符 |
insert(int index,Object obj) | 将obj添加到index上 |
replace(int start,int end,String str) | 将[start,end)范围内的字符替换为str |
reverse() | 反转字符串 |
注意
-
String类中的所有方法调用后,都会创建一个新的String对象,即原本的String字符串不会改变
-
StringBuilder类中的所有方法都是在操作同一个字符串对象,每次调用方法,都会让原字符串发生变化
-
StringBuilder类中没有重写equals方法,所以判断两个可变字符串对象是否相同时,如果调用equals方法,
实际调用的是Object类中未重写的方法,即==判断。所以判断可变字符串是否相同时,需要将其转换为String对象再调用equals方法。
System类
这个类中包含了一些系统相关的信息和一些方法。其中的属性和方法都是静态的。
这类不能创建对象,不是因为它是以抽象类,而是因为它的构造方法是私有的。
常用方法和属性
常用方法和属性 | |
---|---|
System.ou | 获取标准输出流对象,用于打印信息 |
System.in | 获取标准输入流对象,用于获取输入的信息 |
System.err | 获取错误输出流对象,用于打印异常信息 |
System.exit(int statues) | 终止虚拟机运行,参数0表示正常终止 |
System.currentTimeMills() | 获取从1970/1/1 0:0:0至今经过了多少毫秒。中国是UTC(+8),所以实际是从1970/1/1 8:0:0至今经过了多少毫秒。返回值为long类型。通常称为时间戳。 |
System.arraycopy(原数组,原数组的起始位置,目标数组,目标数组的起始位置,要复制的元素数量) | 将原数组中指定数量的元素复制到新数组中 |
Runtime类
Runtime类的对象,表示程序运行时对象(程序运行环境对象)。
包含了程序运行环境相关的信息。常用语获取运行环境信息(如虚拟机信息),或执行某个命令。
特点
这个类不是一个抽象类,但不能创建对象,因为它的构造方法是私有的。
这个类提供了一个静态方法getRuntime(),通过该方法,可以获取一个Runtime类的对象。
这种方式可以保证该类只能创建一个对象,是Java中的一种设计模式:单例模式。
public class Runtime{
//定义了一个私有的静态成员,创建一个当前类的对象
private static Runtime currentRuntime = new Runtime();
//将构造方法私有,无法在外创建对象
private Runtime();
//定义了一个公开的静态方法,用于获取创建的唯一的当前类的对象
public static Runtime getRuntime(){
return currentRuntime;
}
}
Date类
date日期 data数据
用于表示日期时间的类,位于java.util包下
构造方法
常用构造方法 | 说明 |
---|---|
Date() | 创建当前时间对应的日期对象 |
Date(long l) | 创建指定瞬间对应的日期对象 |
Date(int year,int month,int date) | 根据年月日创建日期对象。 |
常用方法
常用方法 | 作用 |
---|---|
getTime() | 得到Date对应对象的毫秒数 |
after(Date when) | 判断参数是否在调用日期之后 |
before(Date when) | 判断参数是否在调用日期之前 |
SimpleDateFormat类
用于格式化日期的类。
构造方法
常用构造方法 | 作用 |
---|---|
SimpleDateFormat(String pattern) | 创建一个指定日期模板的格式化日期对象 |
日期模板
特殊字符 | 作用 |
---|---|
yyyy | 年 |
MM | 月 |
dd | 日 |
hh | 12小时制 |
HH | 24小时制 |
mm | 分 |
ss | 秒 |
E | 星期 |
yyyy/MM/dd HH:mm:ss E | 2023/03/09 14:05:16 周四 |
两个字母都可以写成一个,如5月,M–5,MM–05
常用方法
常用方法 | 返回值 | 作用 |
---|---|---|
format(Date date) | String | 将Date对象按日期模板转换为字符串 |
parse(String str) | Date | 将满足日期模板的字符串转换为Date对象 |
包装类
Java是纯面向对象语言,宗旨是将一切事物视为对象处理。
但原始类型不属于对象,不满足面向对象的思想。但原始类型无需创建对象,保存在栈中,效率更高。
为了既保证效率又让原始类型也有对应的类类型,达到"万物皆对象"的理念,所以就有了包装类的概念。
包装类就是原始类型对应的类类型。
包装类常用于字符串与原始类中之间的转换。
在web应用中,从浏览器页面中获取数据提交到服务器,全部都是String类型,所以一定要使用字符串转换为原始类型的方法。
包装类 | 原始类型 |
---|---|
Byte | byte |
Short | short |
Integer | int |
Long | long |
Float | float |
Double | double |
Character | char |
Boolean | boolean |
特点
-
八个原始类型中,除了int和char,其余包装类都是将原始类型的首字母改为大写。
int对应Integer,char对应Character
-
包装类都是被final修饰的,不能被继承
-
除了Character类,其余包装类都有两个过时的构造方法,参数为对应的原始类型或字符串
Character只有一个参数为char类型的构造方法
构造方法的目的都是将原始类型的数据转换为包装类的对象
-
除了Character类,其余包装类都有静态方法"parse原始类型单词(String str)",用于将字符串转换为相应的原始类型
- 数值型的包装类parseXXX()方法,如果参数不是对应的数字,就会抛出NumberFormat异常,如"123a"或"123.4"都会报错
- boolean的包装类Boolean的parseBoolean()方法,如果参数不是"true"这个单词的四个字母,转换结果都是false
-
除了Boolean类,其余包装类都有MAX_VALUE和MIN_VALUE这两个静态属性,用于获取对应类型支持的最大最小值
-
所有包装类都重写了toString(),用于将包装类对象转换为String对象
异常
当程序没有按开发人员的意愿正常执行,中途出现错误导致程序中断,这种情况,就称为异常。
学习异常就是认识异常的种类,如何处理异常和避免异常出现。
异常的产生
异常在程序中以对象的形式存在。当代码执行过程中出现异常,虚拟机会自动创建一个异常对象,如果没有对该异常对象进行处理,就会导致程序中断,不再执行后续内容。
异常的分类
异常在程序中以对象的形式存在,就有相应的类。
所有的异常类,组成了"异常家族"。
Exception异常
-
RunTimeExcetpion运行时异常
如果一个异常类属于RunTimeExcetpion异常类的子类,称这个异常为运行时异常,可以通过编译,运行时可能抛出异常对象
常见运行时异常 说明 出现的情景 NullPointerException 空指针异常 如用空对象null调用属性或方法 IndexOutOfBoundsException 索引越界异常 如当使用某个带有索引的对象超出范围 NumberFormatException 数字格式异常 如调用包装类的parseXX()方法,如果参数不能转换 InputMismatchException 输入不匹配异常 如使用Scanner接收控制台输入时,如果输入的数据不是对应的类型 ClassCastException 对象转型异常 如Person p = (Person)Dog dog; ArithmeticException 算术运算异常 如0当分母 -
编译时异常
如果一个异常类不属于RunTimeExcetpion异常类的子类,称这个异常为编译时异常,无法通过编译,必须要处理异常后才能编译运行。
常见编译时异常 说明 出现的情景 IOException 输入输出流异常 使用流对象 FileNotFoundException 文件未找到以 方法的参数为文件对象时 SQLException 数据库相关异常 操作数据库时
处理异常
通常所说的处理异常,指的是处理Exception类的子类异常。
处理异常的目的,就是保证程序正常执行。
进程和线程
进程Process
进程就是操作系统中正在执行的程序。
一个程序就是一个执行的进程实体对象。
每个运行中的进程,都有属于它独立的内存空间,各个进程之间互不影响。
线程Thread
线程是一个进程中的执行单元,一个进程中可以有多个线程。
多个线程之间可以访问同一个进程中的资源。
每个线程都有一块独立的栈空间,这些线程所在的栈空间位于同一个进程空间中。
多线程
如果一个进程中,同时执行着多个线程,就称为多线程。
多线程可以提高程序执行效率。如多个窗口卖票,就可以加快卖票的效率。
其实每个执行的Java程序,都是多线程执行。main方法所在的线程称为主线程,还有gc线程(守护线程)在同时运行。
如工厂有很多车间,每个车间有很多流水线。
工厂就是内存,车间就是进程,每个流水线就是进程中的一个线程。
并行和并发
并行
各个进程同时执行,称为并行。
并发
多个线程同时执行,称为并发。
同步和异步
同步
所有任务排队执行,称为同步执行。
异步
在执行任务A的同时,执行任务B,称为异步执行。
Java中的线程Thread类
Java中,线程以对象的形式存在。
Thread类表示线程类。
获取线程对象
-
获取当前正在运行的线程对象
Thread thread = Thread.currentThread();
-
创建一个线程对象
常用构造方法 说明 Thread() 创建一个线程对象 Thread(String name) 创建一个指定线程名的线程对象 Thread(Runnable target) 根据Runnable对象创建线程对象 Thread(Runnable target,String name) 根据Runnable对象和指定线程名的线程对象
线程类常用方法
常用方法 | 作用 |
---|---|
getId() | 获取线程ID |
getName() | 获取线程名 |
getPriority() | 获取线程优先级,默认为5 |
getState() | 获取线程状态 |
setName(String name) | 设置线程名 |
setPriority(int i) | 设置线程优先级,范围在1~10,数字越大优先级越高,越先执行完 |
isDaemon() | 判断是否为守护线程 |
setDaemon(boolean on) | 参数为true表示设置线程为守护线程 |
start() | 让线程进入就绪状态,等待执行 |
run() | 在线程获得执行权时要执行的方法(线程要做的事情) |
Thread.sleep(long m) | 让线程休眠m毫秒后继续执行 |
Thread.currentThread() | 获取当前执行的线程对象 |
实现多线程
方式一:继承Thread类
- 1.创建一个类,继承Thread类
- 2.重写Thread类中的run()方法,该方法表示当该线程执行时要做的事情
- 3.创建自定义的线程对象后,调用start()方法,让线程就绪
线程生命周期
线程的初始化到终止的整个过程,称为线程的生命周期
新生状态
当线程对象创建成功后,进入新生状态
就绪状态
当某个线程对象调用了start()方法后,进入就绪状态。
在这个状态下,线程对象不会做任何事情,只是在等待CPU分配时间片。
运行状态
当某个线程对象得到CPU时间片(CPU执行该线程时分配的时间),进入运行状态,开始执行run()方法。
不会等待run()方法执行完毕,只会在指定的时间内尽可能地执行run()方法。
如果多线程下,某个线程对象在调用完run()方法后,就会再进入就绪状态。
阻塞状态
如果某个线程遇到了sleep()方法或wait()方法时,就会进入阻塞状态。
sleep()方法在指定时间后,会让线程重新就绪。
wait()方法只有在被调用notify()或notifyAll()方法将其唤醒后才能重新就绪。
终止状态
当某个线程的run()方法中的所有内容执行完,就会进入终止状态。
死锁的解决方式
方式一:让两个线程获取资源的顺序保持一致
如两个线程都先获取knife,再获取fork
方式二:在两个线程获取的资源A和B之前,再获取第三个资源C,对这个资源C使用synchronized进行同步
这样在某个线程获取资源C后,继续执行后续的内容,知道执行完毕,其他线程才有机会开始执行。
如在获取knife和fork之前,先获取paper对象