JAVA高级阶段技术总结
- String字符串
- System类
- RunTime类
- Date类
- SimpleDateFormat
- calendar
- 包装类
- 异常
- 数组和集合
- 集合框架(集合家族)
- Collection接口
- Map接口
- 遍历集合中元素的方式
- 泛型
- Collections集合工具类
- 集合和数组之间的转换
- 文件类File
- IO流
- 流Stream
- FileInputStream文件字节输入流(掌握)
- FileOutputStream文件字节输出流(掌握)
- 使用FileInputStream和FileOutputStream读写时的注意事项
- 使用FileInputStream和FileOutputStream实现单文件的复制
- 文件夹的复制
- FileReader文件字符输入流
- FileWriter文件字符输出流
- BufferedReader缓冲字符输入流(掌握)
- BufferedWriter缓冲字符输出流(掌握)
- ObjectOutputStream对象字节输出流(序列化)(掌握)
- ObjectInputStream对象字节输入流(反序列化)(掌握)
- 序列化和反序列化案例
- 转换流
- 网络编程
- 使用套接字对象实现两个端点(Socket和ServerSocket)之间发送文件
- 进程和线程
- 并行和并发
- 同步和异步
- Java中的线程Thread类
- 实现多线程
- 线程的生命周期
- 守护线程
- 多线程访问同一个资源
- Java高级面试题分享
String字符串
String是一个类,属于数据类型中的引用类型。
Java中一切使用""引起来的内容,都是这个类的实例,称为字符串对象。
字符串在定义后,值不可改变,是一个常量,实际是一个字符数组。
String类使用时注意
右上方案例可见,如果频繁地将一个String类型变量的值进行更改时,会创建很多字符串对象。效率
低,浪费内存空间。
所以在频繁更改字符串时,不要使用String类变量。
如何创建字符串
如果频繁地将一个String类型变量的值进行更改时,会创建很多字符串对象。效率低,浪费内存空间。
所以在频繁更改字符串时,不要使用String类变量。
字符串常用构造方法
常用构造方法 | 说明 |
---|---|
String() | 创建一个空白字符串对象。 |
String(String str) | 创建一个指定字符串的字符串对象。 |
String(char[] list) | 创建一个指定字符数组的字符串对象。 |
String(byte[] list,String charsetName) | 按指定的编码格式创建一个指定字节数组的字符串对象。 |
字符串常用方法
方法名 | 返回值 | 作用 |
---|---|---|
length() | int | 得到字符串的长度 |
toLowerCase() | String | 转换为小写 |
toUpperCase() | String | 转换为大写 |
trim() | String | 去除字符串首尾的所有空格 |
isEmpty() | boolean | 判断字符串是否为空白字符串"" |
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(字符序列) | boolean | 判断某个子字符串是否在原字符串中出现 |
concat(String str) | String | 将参数字符串拼接到原字符串末尾 |
startsWith(String str) | boolean | 判断是否以指定字符串开头 |
endsWith(String str) | boolean | 判断是否以指定字符串结尾 |
substring(int begin) | String | 从指定索引开始截取字符串至末尾 |
substring(int being,int end) | String | 截取[begin,end)区间内的字符串 |
split(String regex) | String[] | 按执行字符串或正则表达式切分原字符串。如果指定内容不再末尾,n个指定字符能得到n+1个子串;如果指定内容在末尾,n个指定字符能得到n个子串(不包含末尾的无效字符) |
replace(char oldChar,char newChar) | String | 将原字符串中的所有指定字符替换为新字符 |
String.valueOf(参数) | String | 将任意参数转换为字符串。通常用于原始类型转换为字符串。 |
String.formart(String 格式,Object… obj) | String | 根据指定格式转换参数。常用于将浮点数保留小数。如String.format(“%4.2f”,10.0/3)表示将计算的结果四舍五入保留2位小数转换为字符串;如果最终数据所占位置小于4,原样输出,大于4在最前补充空格。 |
可变字符串
StringBuilder类
用于表示可变字符串的一个类,是非线程安全的,建议在单线程环境下使用。
StringBuffer类
用于表示可变字符串的一个类,是线程安全的,建议在多线程环境下使用。
StringBuilder和StringBuffer中的方法都一致,只不过StringBuffer中的方法使用了synchoronized关键字修饰,表示是一个同步方法,在多线程环境下不会出现问题。
这里以StringBuilder为例
构造方法
常用构造方法 | 作用 |
---|---|
StringBuilder() | 创建一个大小为16的字符串数组,表示一个空白字符。类似于String str=“”; |
StringBuilder(String str) | 创建一个str长度+16的字符数组后,将str添加到其中。类似于String str=“初始值”; |
普通方法
常用方法 | 作用 |
---|---|
append(Object obj) | 将任意类型的参数添加到原可变字符串末尾 |
delete(int start,int end) | 删除[start,end)区间内的字符 |
deleteCharAt(int index) | 删除index索引上的字符 |
insert(int index,Object obj) | 在索引index上插入obj |
replace(int start,int end,String str) | 将[start,end)区间内的字符替换为str |
reverse() | 反转字符串 |
可变字符串注意事项
- 以上表格中的方法都是在直接操作同一个字符串对象,每次调用方法后,原字符串都会发生变化
- StringBuffer和StringBuilder并没有重写equals方法,所以可变字符串的值是否相同时,调用的是equals中原始的==判断。如果要判断两个可变字符串的值是否相同时,需要将其转换为String后调用equals判断
System类
这个类中包含了一些系统相关的信息和一些方法。其中的属性和方法都是静态的。
该类不能创建对象,不是因为它是一个抽象类,而是因为它的构造方法是私有的。
常用属性和方法 | |
---|---|
System.out | 获取打印输出流PrintStream对象,用于控制台打印信息。 |
System.in | 获取输入流InputStream对象,用于获取输入的信息 |
System.err | 获取打印输出流PrintStream对象,用于控制台打印异常信息。 |
System.exit(int statues) | 终止虚拟机运行,参数0表示正常终止。 |
System.currentTimeMillis() | 获取从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();
//定义了一个公共的静态方法,用于获取创建的唯一的当前类的对象
public static Runtime getRuntime() {
return currentRuntime;
}
//构造方法是私有的,不能在当前类之外创建对象
private Runtime() {
}
}
使用
package com.hqyj.test;
import java.io.IOException;
public class RuntimeTest {
public static void main(String[] args) throws IOException, InterruptedException {
//通过Runtime类的静态方法getRuntime()获取唯一的Runtime类的实例
Runtime runtime = Runtime.getRuntime();
System.out.println("当前虚拟机空闲内存" + runtime.freeMemory() / 1024 / 1024 + "MB");
System.out.println("当前虚拟机实际最大内存" + runtime.totalMemory() / 1024 / 1024 + "MB");
System.out.println("当前虚拟机支持的最大内存" + runtime.maxMemory() / 1024 / 1024 + "MB");
//exec(String 指令名)运行某个指令,返回运行的进程对象
//在指定秒后关机
// Process process = runtime.exec("shutdown -s -t 300");
//取消关机任务
// Process process = runtime.exec("shutdown -a");
//mspaint画图 calc计算器 notepad记事本
Process process = runtime.exec("mspaint");
Thread.sleep(2000);
//通过进程对象调用销毁功能,从而关闭
process.destroy();
}
}
方法调用时传值问题
package com.hqyj.test2;
public class Test {
/*
* 当方法的参数为原始类型,方法中对该参数做修改,不会影响实际参数
* */
public static void fun1(int i) {
i = 123;
System.out.println(i);
}
/*
* 当方法的参数为字符串时,方法中对字符串"重新赋值",实际是创建了一个新的字符串对象,不会影响实际参数
* */
public static void fun2(String str) {
str = "new";
System.out.println(str);
}
/*
* 如果参数为引用类型,方法中直接操作该参数,操作的就是实际参数的内存地址,会影响实际参数
* */
public static void fun3(Person p) {
p.setName("吴彦祖");
System.out.println(p.getName());
}
/*
* 如果参数为引用类型,方法中创建了一个新对象对其赋值,操作的是创建的新对象,不会影响实际参数
* */
public static void fun4(Person p) {
p = new Person();
p.setName("易烊千玺");
System.out.println(p.getName());
}
/*
* 如果参数为数组,也属于引用类型,方法中直接操作数组,操作的是实参数组,会影响实际参数
* */
public static void fun5(int[] list) {
list[0] = 123;
System.out.println(list[0]);
}
public static void fun(char[] list,Person p){
list[0]='m';//这里在直接操作实际参数,会影响实参
p = new Person();//这里创建了一个新的对象,操作的是方法中的对象,不会影响实参
p.setName("刘鑫");
}
public static void main(String[] args) {
//方法参数为原始类型,方法中对参数做修改,不会改变实际参数
int i = 0;
fun1(i);//123
System.out.println(i);//0
//方法参数为字符串,方法中对字符串重新赋值,不会改变实际参数
String str = "old";
fun2(str);//new
System.out.println(str);//old
//方法参数为引用类型,方法中对参数直接修改,会改变实际参数
Person p = new Person();
p.setName("王海");
fun3(p);
System.out.println(p.getName());
//方法参数为引用类型,方法中创建新对象后赋值给实际参数,操作的是方法中的对象,不会改变实际参数
Person p1 = new Person();
p1.setName("赵敏");
fun4(p1);
System.out.println(p1.getName());
//方法参数为数组,属于引用类型,方法中对参数直接修改,会改变实际参数
int[] list = {
0,1,2};
fun5(list);
System.out.println(list[0]);
//练习
char[] list2={
'a','b','c'};
Person p2 = new Person();
fun(list2,p2);
System.out.println(list2[0]);//m
System.out.println(p2.getName());//null
}
}
RunTime总结
参数只有是引用类型(类、数组、接口),并且方法中在直接操作该参数时,才会对实际参数造成影响。
fun3(Person p)参数为Person对象,方法中直接调用参数p的xxx方法,是在操作实际参数。
fun5(int[] list)参数为数组,方法中直接操作数组某个索引对应的元素,是在操作实际参数。
fun2(String str)和fun4(Person p)都在方法中创建了一个新的对象,是在操作方法中的参数,不影响实际参数。
public static void fun(char[] list,Person p){
list[0]='m';//这里在直接操作实际参数,会影响实参
p = new Person();//这里创建了一个新的对象,操作的是方法中的对象,不会影响实参
p.setName("刘鑫");
}
public static void main(String[] args){
char[] list={
'a','b','c'};
Person p = new Person();
fun(list,p);
System.out.println(list[0]);//方法内部直接操作数组,会影响实际参数,输出m
System.out.println(p.getName());//方法内部创建了新对象,不会影响实际参数,输出null
}
Date类
用于表示日期时间的类,位于java.util包下
构造方法
常用构造方法 | 说明 |
---|---|
Date() | 创建当前瞬间对应的日期对象 |
Date(long l) | 创建指定瞬间对应的日期对象 |
Date(int year,int month,int day) | 该构造方法已过时。创建指定年月日的日期对象(年是1900年起经过的年数,月用0-11表示1到12月) |
常用方法
常用方法 | 作用 |
---|---|
getTime() | 得到对应Date对象表示的毫秒数 |
setTime(long l) | 设置Date对象的毫秒数 |
after(Date when) | 判断调用日期对象是否在when之后 |
before(Date when) | 判断调用日期对象是否在when之前 |
SimpleDateFormat
用于格式化日期的类。
构造方法
常用构造方法 | 作用 |
---|---|
SimpleDateFormat(String pattern); | 创建一个指定日期模板的格式化日期对象 |
日期模板
特殊字符 | 作用 |
---|---|
yyyy | 年份 |
MM | 月份 |
dd | 日期 |
HH | 小时 |
mm | 分钟 |
ss | 秒 |
E | 星期 |
以上两个字母都可以写成一个,如月份5 | M:5,MM:05 |
yyyy/MM/dd HH:mm:ss E | 2022/11/24 16:24:09 星期四 |
常用方法
常用方法 | 返回值 | 作用 |
---|---|---|
format(Date date) | String | 将Date对象按日期模板转换为字符串 |
parse(String str) | Date | 将满足日期模板的字符串转换为Date对象 |
package com.hqyj.test3;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatTest {
public static void main(String[] args) throws ParseException {
//定义格式化日期类所需的时间模板
/*
* yyyy 年
* MM 月份
* dd 日期
* HH 24小时制
* hh 12小时制
* mm 分钟
* ss 秒
* E 星期
*
* 两个字母都可以写成一个,如月份MM和M
* MM 5月实际为05
* M 5月实际为5
* */
String patten = "yyyy/MM/dd HH:mm:ss E";//年/月/日 时:分:秒 星期
//创建格式化日期类对象,参数为日期模板
SimpleDateFormat sdf = new SimpleDateFormat(patten);
//创建当前日期对象
Date now = new Date();
//调用格式化日期对象的format(Date date),将Date对象转换为指定日期格式的字符串
String format = sdf.format(now);
//输出
System.out.println(format);
//parse(String str)将指定日期模板的字符串转换为Date对象
Date date = sdf.parse("2000/5/3 2:1:3 星期一");
System.out.println(date);
}
}
calendar
表示日历的类,包含了很多日历相关的信息。
是一个抽象类,无法创建对象。可以通过静态方法getInstance()获取该类的一个实例。
//获取Calendar类的对象
Calendar cal = Calendar.getInstance();
日历字段
在Calendar类中,定义了很多被final和static修饰的常量,称为日历字段,实际一个数字,用于获取指定信息
值 | 作用 |
---|---|
Calendar.YEAR | 年份 |
Calendar.MONTH | 月份(0-11表示1-12月) |
Calendar.DATE | 日期 |
Calendar.DAY_OF_WEEK | 星期(1-7表示周天到周六) |
Calendar.HOUR | 12进制小时 |
Calendar.HOUR_OF_DAY | 24进制小时 |
Calendar.MINUTE | 分钟 |
Calendar.SECOND | 秒 |
Calendar.DAY_OF_MONTH | 本月第几天 |
Calendar.DAY_OF_YEAR | 本年第几天 |
Calendar.WEEK_OF_MONTH | 本月第几周 |
Calendar.WEEK_OF_YEAR | 本年第几周 |
常用方法
常用方法 | 作用 |
---|---|
get(int field) | 根据日历字段获取对应的值 |
getTime() | 获取对应的Date对象(Calendar对象转换为Date对象) |
getMaximum(int field) | 获取指定日历字段支持的最大值,如Calendar.DATE最大31 |
getActualMaximum(int field) | 获取指定日历字段在当前日期下的实际最大值,如11月,Calendar.DATE最大30 |
set(int field,int value) | 将指定的日历字段设置为指定值 |
set(int year,int month,int date) | 同时设置日历对象的年月日 |
setTime(Date date) | 将Date对象作为参数设置日历对象的信息 |
实现万年历
package com.hqyj.homework;
import java.util.Calendar;
import java.util.Scanner;
public class Test2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入年月");
Calendar cal = Calendar.getInstance();
int year = sc.nextInt();
int month = sc.nextInt();
//设置指定年月,默认为1号
cal.set(year, month - 1, 1);
//用于换行的计数,每行7个,包括空格
int count = 0;
System.out.println("========"+year+"年"+month+"月========");
System.out.println("一\t二\t三\t四\t五\t六\t日");
//打印1号前的空格
//DAY_OF_WEEK 星期 空格数量
//2 一 0
//3 二 1
//4 三 2
//5 四 3
//6 五 4
//7 六 5
//1 日 6
//获取本月1号是所在周的第几天
int week = cal.get(Calendar.DAY_OF_WEEK);
//根据规律判断,打印空格的同时也要计数
if (week == 1) {
System.out.print("\t\t\t\t\t\t");
count += 6;
} else {
for (int i = 1; i <= week - 2; i++) {
System.out.print("\t");
count++;
}
}
//遍历当月每一天
for (int i = 1; i <= cal.getActualMaximum(Calendar.DATE); i++) {
System.out.print(i + "\t");
count++;
//隔7换行
if (count % 7 == 0) {
System.out.println();
}
}
}
}
包装类
Java是纯面向对象语言,宗旨是将一切事物视为对象处理。
但原始类型不属于对象,不满足面向对象的思想。但原始类型在使用时无需创建对象,保存在栈中,效
率高。
为了让原始类型也有对应的类类型,达到"万物皆对象"的理念,所以就有了包装类的概念。
包装类就是原始类型对应的类类型。包装类通常用于字符串与原始类型之间的转换。
在web应用中,从浏览器页面中获取到后台的数据,全部都是String类型,所以一定要使用转换为原始
类型的方法。
特点
八个原始类型中,除了int和char,其余类型的包装类,都是将首字母改为大写。int对应
Integer,char对应Character
包装类都是被final修饰的,不能被继承
除了Character类,其余包装类都有两个构造方法:参数为原始类型或String的构造方法。
Character的构造方法只有一个,参数为char类型。这些构造方法用于将原始类型或字符串转换为
包装类对象
除了Character类,其余类都有静态方法parse原始类型(String str),用于将字符串转换为相应的
原始类型
数值型的包装类的parseXXX()方法,如果参数不是对应的数字,转换时就会抛出
NumberFormat异常。如"123abc",或"123.4",在使用Integer.parseInt()时都会抛出异常
Boolean类型中的parseBoolean()方法,参数如果是"true"这四个字母,不区分大小写,都能
转换为真正boolean类型的true,只要不是"true"这个单词,转换结果都为false
除了Boolean类,其余包装类都有MAX_VALUE和MIN_VALUE这两个静态属性,用于获取对应类
型支持的最大最小值
所有包装类都重写了toString()方法,用于将包装类对象转换为String对象
异常
当程序没有按开发人员的意愿正常执行,中途出现错误导致程序中断,出现这种情况,就称为异常。
学习异常就是认识异常的种类,如何处理异常和避免异常出现。
异常的产生
异常在程序中以对象的形式存在。当代码执行过程中出现异常,虚拟机会自动创建一个异常对象,如果
没有对象该异常对象进行处理,就会导致程序中断,不再执行后续代码。
异常的分类
异常在程序中以对象的形式存在,就有相应的类。
所有的异常类,组成了一个"异常家族"。
数组和集合
数组的特点
- 数组中保存的元素都是有序的,可以通过下标快速访问
- 数组中保存的数据都是同一种类型
- 数组的长度在定义后,无法改变
- 数组无法获取其中保存的元素实际数量
集合的特点
- 能保存一组数据,可以有序可以无序
- 集合的容量可变
- 集合中可以保存不同类型的数据
- 可以获取集合中保存的元素实际数量
集合框架(集合家族)
Collection还有父接口Iterable,但Iterable接口不算严格意义上的集合的根接口。它称为迭代器,是用于遍历集合元素的一个工具接口。
所以集合的根接口为Collection接口和Map接口,位于java.util包中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ND7HiRZs-1670160759377)(F:\221001\笔记\JavaAdv04.assets\image-20221128103651452.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZURQSd7-1670160759379)(F:\221001\笔记\JavaAdv04.assets\image-20221128103904548.png)]
图上的所有实现类,都是非线程安全的,在多线程的环境下使用以上任意集合,都会产生不确定的结果。
Collection接口
该接口有两个核心子接口:List和Set。
这两个接口都可以保存一组元素,List接口保存元素时,是有序可重复的;Set接口保存元素时,是无序不重复的。
常用方法 | 返回值 | 作用 |
---|---|---|
add(Object obj) | boolean | 将元素添加到集合中 |
size() | int | 获取集合中的元素数量 |
isEmpty() | boolean | 判断集合是否为空 |
clear() | void | 清空集合 |
contains(Object obj) | boolean | 判断集合中是否存在指定元素 |
remove(Object obj) | boolean | 移除集合中的指定元素 |
toArray() | Object[] | 将集合转换为数组 |
iterator() | Iterator | 获取集合的迭代器对象,用于遍历集合 |
List接口(有序可重复)
有序集合,元素可以重复,允许保存null,可以通过索引获取对应位置上的元素。
在该接口继承Collection接口的同时,又拓展了一些操作元素的方法,如添加到指定索引、根据索引删除、获取指定索引的元素、截取子集合的方法等。
常用方法 | 返回值 | 作用 |
---|---|---|
get(int index) | Object | 根据指定索引获取对应的元素 |
set(int index,Object obj) | Object | 使用obj替换index上的元素,返回被替换的元素 |
add(int index,Object obj) | void | 将obj添加到index上 |
remove(int index) | Object | 移除指定索引的元素 |
indexOf(Object obj) | int | 得到某元素第一次出现的索引,没有返回-1 |
lastIndexOf(Object obj) | int | 得到某元素最后一次出现的索引,没有返回-1 |
subList(int from,int to) | List | 截取[from,to)区间内的元素,返回子集合 |
ArrayList实现类(掌握)
- 采用数组实现的集合
- 可以通过索引访问元素,可以改变集合大小。如果要在其中插入或删除元素时,会影响后续元素
- 该集合中保存的都是引用类型,即便保存了数组123,也保存的是Integer类型的123,而不是int类型的123
- 该集合查询效率高,中途增加和删除元素效率低