Java高级部分笔记总结
一、String字符串
String是一个类,属于数据类型中的引用类型,Java中一切使用“”引起来的内容,都是String类的实例,称为字符串对象。字符串在定义后,值不可改变,实际是一个字符数组。
(一)如何创建字符串对象
使用“”赋值创建
String str="abc"
(二)使用String类要注意
如果要频繁改动String类型变量的值,会创建很多字符串对象,效率很低
所以在频繁改动字符串时,不要使用String类,使用StringBuilder或Stringbuffer类。
(二)可变字符串
String字符串对象是一个常量,在定义后,值不可改变
如果使用String类的对象,对其频繁更新时,就会不停地创建新对象,不停引用给同一个变量。
(三)Stringbui和Stringbuff
StringBuilder
用于表示可变字符串的一个类,是非线程安全的,在单线程环境下使用,效率更高。
StringBuffer
用于表示可变字符串的一个类,是线程安全的,在多线程环境下使用。
StringBuilder和StringBuffer中的方法都一致,只不过StringBuffer中的方法使用了synchronized关键字修饰,表示是一个同步方法,在多线程环境下不会出现问题。
(四)可变字符串与String之间的转换
String转换为可变字符串
String str="hello";
//使用构造方法将String对象转换为StringBuilder对象
StringBuilder sb = new StringBuider(str);
可变字符串转换为String(任意类型对象转换为String)
String.valueOf(Object obj)方法
StringBuilder sb = new StringBuider("hello");
//将任意类型对象转换为String对象
String str = String.valueOf(sb);
toString()方法
StringBuilder sb = new StringBuider("hello");
//调用任意对象的toString()方法
String str = sb.toString();
拼接空字符串
```java
StringBuilder sb = new StringBuider("hello");
String str = sb+"";
```
(五)可变字符串相关面试题
比较String、StringBuilder和StringBuffer的区别
相同点:
这三个类都可以表示字符串,都提供一些操作字符串的方法。
这三个类中有相同的方法,如charAt,indexOf(等。
这三个类都是被final修饰的类,不能被继承
不同点:
String定义的字符串是一个常量,可变字符串定义的是一个变量。
String类中的方法调用后,不会改变原本字符串的值。可变字符串中的方法调用后,会改变原本字符串的值
StringBuilder是非线程安全的可变字符串类,Stringbuff是线程安全的可变字符串类,其中的方法被synchronized修饰。
(六)总结
在在使用字符串时,字符串时对象,如果要比较其值是否相同,不能使用==判断,因为==判断的是内存地址。所以在比较字符串是否相同时,要使用String类重写的equals方法进行判断。
String类中equals重写的原理大致是:
判断是否为同一个字符串,再判断是否是字符串类型,再将两个字符串转换为字节数组,逐一比较字节数组中的内容,全部一致,返回true,调用equals方法时,通常将已知非空字符串作为调用者。
在频繁操作同一个字符串时,一定使用StringBuilder或Stringbuff对象。
操作不经常改动的字符串,使用这三个;类中相应的方法处理。
二、日期类
(一)System类
这个类中包含了一些系统相关的信息和一些方法。其中的属性和方法都是静态的。
这类不能创建对象,不是因为它是以抽象类,而是因为它的构造方法是私有的。
System.currentTimeMills() 获取从1970/1/1 0:0:0至今经过了多少毫秒。中国是UTC(+8),所以实际是从1970/1/1 8:0:0至今经过了多少毫秒。返回值为long类型。通常称为时间戳。
(二)Runtime类
Runtime类的对象,表示程序运行时对象(程序运行环境对象)。
包含了程序运行环境相关的信息。常用语获取运行环境信息(如虚拟机信息),或执行某个命令。
特点
这个类不是一个抽象类,但不能创建对象,因为它的构造方法是私有的。
这个类提供了一个静态方法getRuntime(),通过该方法,可以获取一个Runtime类的对象。
这种方式可以保证该类只能创建一个对象,是Java中的一种设计模式:单例模式。
public class Runtime{
//定义了一个私有的静态成员,创建一个当前类的对象
private static Runtime currentRuntime = new Runtime();
//将构造方法私有,无法在外创建对象
private Runtime();
//定义了一个公开的静态方法,用于获取创建的唯一的当前类的对象
public static Runtime getRuntime(){
return currentRuntime;
}
}
使用
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
//如果要使用Runtime类中的方法,先通过其静态方法获取它的对象
Runtime runtime = Runtime.getRuntime();
System.out.println("当前虚拟机的空闲内存"+runtime.freeMemory() / 1024 / 1024 + "MB");//b kb MB
System.out.println("当前虚拟机的实际最大内存"+runtime.totalMemory()/ 1024 / 1024 + "MB");
System.out.println("当前虚拟机的支持的最大内存"+runtime.maxMemory()/ 1024 / 1024 + "MB");
//exec(String 指令名) 运行某个指令,返回运行的进程对象
//mspaint画图 calc计算器 notepad记事本
Process mspaint = runtime.exec("mspaint");
Thread.sleep(3000);
//销毁进程对象
mspaint.destroy();
/*runtime.exec("calc");
runtime.exec("notepad");*/
//定时关机
//runtime.exec("shutdown -s -t 600");
//runtime.exec("C:\\Program Files (x86)\\Tencent\\QQ\\Bin\\QQ.exe");
}
}
(三)Date类
date日期 data数据
用于表示日期时间的类,位于java.util包下
(四)SimpleDateFormat类
用于格式化日期的类。
日期模板 yyy/MM/dd HH:mm:ss E 2023/3/17/18:00:32 周五
特殊字符 | 作用 |
yyyy | 年 |
MM | 月 |
dd | 日 |
hh | 12小时制 |
HH | 24小时制 |
mm/ | 分/秒 |
E | 星期 |
(五)Calendar类
表示日历的类,包含了很的多日历相关的信息。
是一个抽象类,无法创建对象,可以通过静态方法getInstrance()获取Calendar类的实例。
//获取Calendar类的实例
Calendar c = Calendar.getInstance();
使用Calendar类实现万年历
package com.hqyj.dateTest;
import java.util.Calendar;
import java.util.Scanner;
public class Test2 {
public static void main(String[] args) {
//实现"万年历"
//输入年份和月份,输出
Calendar c = Calendar.getInstance();
Scanner sc = new Scanner(System.in);
System.out.println("输入年份");
int year = sc.nextInt();
System.out.println("输入月份");
int month = sc.nextInt();
//日历设置为当月1号
c.set(year, month - 1, 1);
//得到当月最大日期
int maxDate = c.getActualMaximum(Calendar.DATE);
//换行计数
int count = 0;
//输出空格
/*
* DAY_OF_WEEK 星期 空格数量
* 2 一 0
* 3 二 1
* 4 三 2
* 5 四 3
* 6 五 4
* 7 六 5
* 1 天 6
* //周天空6 其余空DAY_OF_WEEK-2
* */
System.out.println("一\t二\t三\t四\t五\t六\t日");
//获取当月1号是一周中的第几天
int week = c.get(Calendar.DAY_OF_WEEK);
//周天空6格
if (week == 1) {
System.out.print("\t\t\t\t\t\t");
//空格也需要计数
count += 6;
} else {
//其他情况空星期-2个格
for (int j = 1; j <= week - 2; j++) {
System.out.print("\t");
//空格也需要计数
count++;
}
}
//输出数字
for (int i = 1; i <= maxDate; i++) {
System.out.print(i + "\t");
//计数+1
count++;
//计数到7换行
if (count % 7 == 0) {
System.out.println();
}
}
}
}
三、异常
当程序没有按开发人员的意愿正常执行,中途出现错误导致程序中断,这种情况,就称为异常。
学习异常就是认识异常的种类,如何处理异常和避免异常出现。
(一)异常的产生
异常在程序中以对象的形式存在。当代码执行过程中出现异常,虚拟机会自动创建一个异常对象,如果没有对该异常对象进行处理,就会导致程序中断,不再执行后续内容。
(二)异常的分类
异常在程序中以对象的形式存在,就有相应的类。
所有的异常类,组成了"异常家族"。
![](https://i-blog.csdnimg.cn/blog_migrate/eead60d5e51192a411d53ed03587cad9.png)
(三)Error错误
如果出现xxxError,如StackOverFlowError,栈溢出,无法通过额外的代码解决,只能修改源代码。
(四)Exception异常
RunTimeExcetpion运行时异常
如果一个异常类属于RunTimeExcetpion异常类的子类,称这个异常为运行时异常,可以通过编译,运行时可能抛出异常对象
常见运行时异常 | 说明 | 出现的情景 |
NullPointerException | 空指针异常 | 如用空对象null调用属性或方法 |
IndexOutOfBoundsException | 索引越界异常 | 如当使用某个带有索引的对象超出范围 |
NumberFormatException | 数字格式异常 | 如调用包装类的parseXX()方法,如果参数不能转换 |
InputMismatchException | 输入不匹配异常 | 如使用Scanner接收控制台输入时,如果输入的数据不是对应的类型 |
ClassCastException | 对象转型异常 | 如Person p = (Person)Dog dog; |
ArithmeticException | 算术运算异常 | 如0当分母 |
编译时异常
如果一个异常类不属于RunTimeExcetpion异常类的子类,称这个异常为编译时异常,无法通过编译,必须要处理异常后才能编译运行。
常见编译时异常 | 说明 | 出现的情景 |
IOException | 输入输出流异常 | 使用流对象 |
FileNotFoundException | 文件未找到以 | 方法的参数为文件对象时 |
SQLException | 数据库相关异常 | 操作数据库时 |
(五)处理异常
通常所说的处理异常,指的是处理Exception类的子类异常。
处理异常的目的,就是保证程序正常执行。
方式一:try-catch-finally语句
这种方式处理异常,无论会不会抛出异常,都能让程序正常执行
try{
//可能出错的代码
}catch(异常类 异常对象){
//如果try中的代码抛出异常,异常对象属于catch中的异常类型,就会执行这里的代码
}catch(异常类 异常对象){
//如果try中的代码抛出异常,异常对象属于catch中的异常类型,就会执行这里的代码
}...{
}finally{
//无论程序是否会抛出异常,都要执行这里的代码
}
方式二:throws关键字
这种方法,可以让编译时异常通过编译。
在定义方法的时候,通过该关键字声明方法可能抛出的异常。
用法:方法的参数部分后,添加 throws 异常类型1,异常类型2....
public class Test{
//这时该方法就会有一个声明:该方法可能会抛出InterruptedException异常
public void fun() throws InterruptedException{
//sleep()方法在源码中声明了可能会抛出InterruptedException异常,
//InterruptedException异常不是RuntimeException的子类异常,必须要处理才能通过编译
//要么使用try-catch处理,要么继续声明有异常
Thread.sleep(500);
}
}
遍历集合的方式
遍历List集合
普通for循环
for(int i=0;i<集合.size();i++){
元素 变量 = 集合.get(i);
}
增强for循环
for(数据类型 变量名 : 集合){
元素 变量 = 集合.get(i);
}
forEach()方法
使用该方法遍历集合时,不要使用add或remove操作,遍历会抛出异常。
集合.forEach(obj -> {
元素 变量 = 集合.get(i);
});
迭代器
//Collection接口有一个父接口Iterable,其中有一个iterator方法用于获取迭代器对象遍历集合
//所有Collection的子实现类都能调用该方法
Iterator it = Collection集合.iterator();
//hasNext()判断是否还有下一个元素
while(it.hasNext()){
//next()方法读取该元素
元素 变量 = it.next();
}
文件类File
Java中的File类,表示本地硬盘中的文件file或文件夹directory的一个类。
通过这个类创建对象,可以读取文件信息或操作对应文件。
构造方法
常用构造方法 | 说明 |
File(String pathName) | 根据文件的完整路径创建File对象 |
File(String parent,String child) | 根据文件的父目录的路径和自身的名称创建File对象 |
File(File parent,String child) | 根据文件的父目录对应的File对象和自身的名称创建File对象 |
//使用不同构造方法表示C:\Users\Administrator\Desktop\230202.txt文件
//new File(String pathName);
File file1 = new File("C:\\Users\\Administrator\\Desktop\\230202.txt");
//new File(String parentPath,String childName);
File file2 = new File("C:\\Users\\Administrator\\Desktop", "230202.txt");
//new File(File parentFile,String childName)
File parent = new File("C:\\Users\\Administrator\\Desktop");
File file3 = new File(parent, "230202.txt");
System.out.println(file1.exists());
System.out.println(file2.exists());
System.out.println(file3.exists());
常用方法
常用方法 | 作用 |
exists() | 判断文件是否存在 |
isFile() | 判断是否为文件 |
isDirectory() | 判断是否为文件夹 |
getName() | 获取文件名 |
getPath() | 获取文件相对路径 |
getAbsolutePath() | 获取文件绝对路径 |
getParent() | 获取文件父目录路径 |
getParentFile() | 获取文件父目录对象 |
lastModified() | 获取文件最后一次修改时间 |
length() | 获取文件字节大小 |
isHidden() | 判断是否为隐藏文件 |
delete() | 删除文件或空文件夹 |
renameTo(File newFile) | 移动文件到指定文件,可重命名 |
mkdir() | 创建文件夹 |
list() | 得到文件夹中的第一层子文件名称的数组,返回String[] |
listFiles() | 得到文件夹中的第一层子文件对象的数组,返回File[] |
斐波那契数列
public class Test2 {
public static void main(String[] args) {
//兔子问题
//有一对兔子,在第三个月开始,每个月都生一公一母两只小兔子
//假设所有兔子都不死亡,第10个月一共有多少只
//1月 2月 3月 4月 5月 6月 7月 8月 9月 10月
//1 1 2 3 5 8 13 21 34 55
//斐波那契数列
System.out.println(fun(3));
System.out.println(fun(10));
}
/*
* 递归调用
* */
public static int fun(int n) {
if (n > 2) {
return fun(n - 1) + fun(n - 2);
}
return 1;
}
}
IO
I:input输入
O:output输出
流Stream
在Java中,流表示计算机硬盘与内存之间传输数据的通道
将内存中的数据存入到硬盘中,称为写write,也称为输出Output
将硬盘中的数据存入到内存中,称为读read,也称为输入Input
流的分类
Java中的流也是类,以对象的实现表示流。流有"四大家族",是所有流的父类。
字节输入流InputStream
FileInputStream、ObjectInputStream
字节输出流OutputStream
FileOutputStream、ObjectOutputStream
字符输入流Reader
FileReader、BufferedReader、InputStreamReader
字符输出流Writer
FileWriter、BufferedWriter、OutputStreamWriter
按方向分类
输入流:InputStream、Reader
读硬盘中的数据到程序中
输出流:OutputStream、Writer
将程序中的数据写到硬盘中
按数据传输类型分类
字节流:InputStream、OutputStream
读写非文本类型文件。如图片、多媒体文件
字符流:Reader、Writer
读写纯文本文件。如txt、md等
如要将硬盘中的某个txt文件中的内容读取到程序中,使用Reader
如要将硬盘中的某个图片文件中的内容读取到程序中,使用InputStream
如要将程序中的文本写入到硬盘中,保存为txt文件时,使用Writer
如要将程序中的数据写入到硬盘中,保存为非文本文件时,使用OutputStream
流的四个父类的特点
这四个父类都是在java.io包下,都是抽象类,不能直接创建其对象,使用其子类对象
这四个类都有close()方法,用于关闭流对象,释放资源
输入流(InputStream和Reader)都有read()方法,用于读取数据,输出流(OutputStream和Writer)都有write()方法
输出流(OutputStream和Writer)都有flush()方法,用于将流中的数据冲刷到硬盘中
在使用输出流对象时,一定要调用flush()或close()方法后,才能真正将数据写入到硬盘中
所有流中,以Stream结尾,都是字节流,数据以字节传输;以Reader或Writer结尾,都是字符流,数据以字符传输
读取硬盘中的数据时,读取的文件必须存在;写入数据到硬盘中时,写入的文件可以不存在,但父目录必须存在。
FileInputStream文件字节输入流
以字节的形式读取文件
构造方法
常用构造方法 | 作用 |
FileInputStream(String filePath) | 根据文件完整路径创建流对象 |
FileInputStream(File file) | 根据文件对象创建流对象 |
常用方法
常用方法 | 作用 |
read() | 读取一个字节,返回读取到的字节 |
read(byte[] bytes) | 读取指定数组大小的字节,返回读取到的字节数量 |
read(byte[] bytes,int off,int len) | 读取指定数组大小的字节,从off索引开始读取len个字节,返回读取到的字节数量 |
available() | 文件可读取的最大字节数量 |
close() | 关闭流对象 |
FileOutputStream文件字节输出流
以字节的形式写入文件
构造方法
常用构造方法 | 说明 |
FileOutputStream(String filePath) | 根据文件名创建流对象,覆盖写入 |
FileOutputStream(String filePath,boolean appen) | 根据文件名创建流对象,追加写入 |
FileOutputStream(File file) | 根据文件对象创建流对象,覆盖写入 |
FileOutputStream(File file,boolean appen) | 根据文件对象创建流对象,追加写入 |
常用方法
常用方法 | 作用 |
write(int b) | 写入一个字节 |
write(byte[] bytes) | 写入一个字节数组 |
write(byte[] bytes,int off,int len) | 写入一个字节数组,从off开始的len个字节 |
flush() | 将流中的数据冲刷到硬盘中 |
close() | 关闭流对象 |
序列化ObjectOutputStream对象字节输出流
序列化:将对象转换为文件的过程
被序列化的对象,其类必须要实现Serializable接口
这个接口是一个特殊的接口,其中没有定义任何方法,只是给类加上标记,表示该类可以被序列化
构造方法
构造方法 | 说明 |
ObjectOutputStream(OutputStream os) | 根据字节输出流对象创建 |
常用方法
常用方法 | 作用 |
writeObject(Object obj) | 将一个对象写入到本地文件 |
flush() | 冲刷数据到硬盘 |
close() | 关闭流对象 |
反序列化ObjectInputStream对象字节输入流
反序列化:将文件转换为对象的过程
构造方法
构造方法 | 说明 |
ObjectInputStream(InputStream is) | 根据字节输入流对象创建 |
常用方法
常用方法 | 作用 |
readObject() | 读取序列化后的文件,返回Object类型 |
close() | 关闭流对象 |