文章目录
前言
这里是本人学习JavaSE进阶的学习总结,记录一下。
一、static、继承、权限修饰符
1.静态(static)
1.1.静态成员变量
1.1.1.应用场景
多个对象需要共享同一个数据
1.1.2.定义格式
public static 数据类型 变量名;
public static String country;//国籍
1.1.3.使用格式
类名.属性名 【推荐】
Chinese.country = "中国";
对象名.属性名
Chinese c1 = new Chinese();
c1.country;
1.2.静态方法
1.2.1.概念
由static修饰的方法
public static void staticMethod(){
System.out.println("静态方法");
}
1.2.2.使用场景
如果方法中没有使用到成员变量,就可以使用静态方法,不用创建对象,直接调用
1.2.3.使用格式
类名.方法名() 【推荐】
MethodDemo01.staticMethod();
对象名.方法名()
MethodDemo01 d1 = new MethodDemo01();
d1.method();
1.2.4.注意事项
静态只能调用静态的成员
非静态的方法可以调用静态和非静态的成员
1.3.工具类
步骤
- 私有构造方法
- 方法有static修饰
public class CodeUtils { //验证码的工具类
private CodeUtils(){
}
//需要把构造方法是有
public static String getCode(int length){
//生成是6个数字 0 ~ 9
Random r = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int a = r.nextInt(10);
sb.append(a);
}
String code = sb.toString();
// System.out.println("生成的验证码为:" + code);
return code;
}
public static void method(){
getCode(10);
}
}
2.继承
2.1.继承的作用
如果多个类有共同的属性和行为,我们就可以抽取这些共性数据到一个类中 【父类】
2.2.继承的格式
public class 子类 extends 父类{}
2.3.继承的特点
- Java是单继承,不支持多继承
- Java支持多层继承
- 私有数据可以被继承到子类中,但是不能使用
- 构造方法不能被继承
2.4.继承之后成员变量的访问
访问的时候,根据就近原则去访问,先从方法找,找不到就从当前类中去找,如果还是找不到就从父类中找,如果还是找不到就出错。
this.变量
本类中的成员变量
super.变量
父类中的成员变量
2.5.继承之后成员方法的访问
访问的时候,根据就近原则去访问,先从当前类中去找方法,如果还是找不到就从父类中找,如果还是找不到就出错
this.方法名()
本类中方法
super.方法名()
父类的方法
2.6.继承之后构造方法的访问
注意:子类的构造方法,默认第一行去调用父类的构造方法,super();
super(…) 调用父类的有参构造
this() 调用本类的无参构造
this(…) 调用本类中的有参构造
3.权限修饰符
二、final、抽象类、接口
三、多态、Object类、内部类、枚举
四、常用API、正则表达式
五、数据结构、List集合、泛型和可变参数
1.集合体系
1.1.单列集合 Collection接口
1.1.1.List接口
特点
- 有序(存和取顺序一样)
- 可重复
- 有索引
常用实现类
- ArrayList
查询快,增删慢 - LinkedList
查询慢,增删快
常用方法
1.1.2.Set接口
特点
- 无序
- 不重复
- 无索引
常用实现类
- HashSet
- TreeSet
1.2.双列集合Map接口
下章了解
2.数据结构
2.1.栈
2.2.队列
2.3.数组
2.4.链表
2.5.树
2.5.1.二叉树
2.5.2.平衡二叉树
2.5.3.二叉查找树
2.5.4.红黑树
3.ArrayList的底层
执行:ArrayList list = new ArrayList<>();
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
执行:ArrayList list = new ArrayList<>(20);
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
如果已经超过初始元素个数,就要扩容
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
4.可变参数
4.1.使用场景
参数的个数不确定时,设计为可变参数
4.2.格式
数据类型 … 变量
getSum(1,2,3,4);
//方法参数类型是int,参数的数量可以是任意的
//可变参数本质就是数组
public static int getSum(int... arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
4.3.注意
- 可变参只能有一个
- 可变参只能放到最后
5.泛型
5.1.泛型类
5.1.1.定义格式
修饰符 class 类名<泛型标记> { }
/*
<类型标记> 代表某一种数据类型,比如:
<T> T可以当做某种数据类型,可以出现数据类型的地方,就可以使用T去代替
*/
//创建对象的时候确定泛型的类型
public class Box<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class Test {
public static void main(String[] args) {
Box<String> b1 = new Box<>();
b1.setValue("hello");
String v1 = b1.getValue();
Box<Integer> b2 = new Box<>();
b2.setValue(12);
Integer v2 = b2.getValue();
}
}
5.1.2.泛型类的作用
- 泛型类在创建对象时确定泛型的真实类型。
- 类中引用到泛型的地方都会替换成具体类型。
5.2.泛型接口
5.2.1.定义格式
修饰符 interface 接口名<泛型标记> { }
//泛型接口
//实现接口时,确定泛型的类型
public interface MyList<E> {
void add(E e);
}
使用1
public class MyArrayList implements MyList<Double>{
@Override
public void add(Double s) {
System.out.println("添加 " + s);
}
}
MyArrayList list = new MyArrayList();
list.add(11.0);
使用2
public class MyArrayList2<T> implements MyList<T>{
@Override
public void add(T t) {
System.out.println("添加 " + t);
}
}
MyArrayList2<String> list2 = new MyArrayList2<>();
list2.add("hello");
5.2.2.泛型接口的作用
- 实现类实现接口时确定泛型。
- 接口中引用泛型的地方会替换成具体类型。
5.3.泛型方法
修饰符 <泛型标记> 返回值类型 方法名(类型 变量名) { }
5.3.1.定义格式
//定义方法,打印任意类型数组 [11, 22, 33, 44]
//泛型方法,泛型值必须是引用数据类型
public static <T> void printArray(T[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
} else {
System.out.print(arr[i] + ", ");
}
}
System.out.println("]");
}
Integer[] arr = {11, 22, 33, 44};
printArray(arr);
5.3.2.泛型方法的作用
- 调用方法,传参时确定泛型类型。
- 方法中引用泛型的地方会替换成具体类型。
5.4.泛型通配符
<?> 通配符
//当使用泛型的时候,无法确定泛型的具体类型时,可以使用通配符 ? 来表示某一种类型。
//<?> 通配符 什么类型都可以匹配,范围太大
public static void play(ArrayList<?> list){
}
类型通配符上下限
//<? extends Car> 通配的类型必须是Car 或者 Car的子类
public static void play(ArrayList<? extends Car> list){
}
//<? super Car> 通配的类型必须是Car 或者 Car的父类
public static void play(ArrayList<? super Car> list){
}
六、Set集合、迭代器、Collections工具类
1.Set集合
2.迭代器
1.1.Iterator迭代器
- JDK中提供了一个Iterator接口,称为迭代器,可以实现单列集合元素的遍历。
- Collection接口中提供了iterator()方法,可以获取迭代器对象。
1.2.迭代器的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avb79999-1662555367774)(image/迭代器方法.png)]
1.3.迭代器原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LLSiq2cM-1662555367775)(image/迭代器原理.png)]
1.4.并发修改异常
产生原因:
当使用迭代器或者增强for循环遍历集合时,在迭代过程中调用集合类自身的remove或者add等方法改变集合的元素个数时,就会产生ConcurrentModificationException,即并发修改异常。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mVYmV57w-1662555367776)(image/并发修改异常.png)]
解决方法
- 使用普通for循环遍历元素,在循环中使用集合自带的add或remove方法增删元素即可。
- 如果使用迭代器遍历集合,在迭代过程中如果需要删除元素,可以使用迭代器自带的remove方法
//使用迭代器,找出偶数元素并删除
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()){
Integer a = itr.next(); //迭代器遍历
if(a%2==0){
//list.remove(a);//集合删除数据 ConcurrentModificationException
itr.remove();
}
}
1.5.增强for循环
它是JDK5之后出现的,其内部原理是一个Iterator迭代器。
数组和Collection集合都可以使用增强for循环。
作用:简化迭代器遍历的语法。
3.Collections工具类
七、Map、图书管理系统、算法
1.Collection(单列集合)
1.1.List
1.1.1.特点
有索引,有顺序,可重复
1.2.Set
2.Map
八、异常、多线程基础
1.异常
2.多线程
九、多线程高级、Lambda、Stream流
十、File、IO流
1.File类
1.1.概念
java.io.File类可以表示文件和文件夹,主要用于文件和文件夹的创建、查找和删除等操作。
1.2.File类的构造方法
文件夹
File file1 = new File("E:\\MyTest");
System.out.println(file1);
文件
File file2 = new File("E:\\MyTest\\文件夹说明.txt");
System.out.println(file2);
从父路径名字符串和子路径名字符串创建新的 File实例。
File file3 = new File("E:\\MyTest","文件夹说明.txt");
System.out.println(file3);
从父抽象路径名和子路径名字符串创建新的 File实例。
File file4 = new File(file1,"文件夹说明.txt");
System.out.println(file4);
1.3.File类的创建功能
创建文件
File f1 = new File("E:\\MyTest\\b.doc");
System.out.println("f1.createNewFile() = " + f1.createNewFile());
创建单级文件夹
File f2 = new File("E:\\MyTest\\aaa");
System.out.println("f2.mkdir() = " + f2.mkdir());
创建多级文件夹
File f3 = new File("E:\\MyTest\\aa\\bb\\cc");
System.out.println("f3.mkdirs() = " + f3.mkdirs());
注意
Windows中文件名不区分大小写。
Java中路径斜杠支持\ 或者 // 或者 / 写法。
1.4.相对路径和绝对路径
绝对路径:从盘符开始
File file1 = new File(“D:\\itheima\\a.txt”);
相对路径:IDEA中是相对当前工程下的路径。(也就是工程路径可以省略)
File file2 = new File(“a.txt”);
如果想把a.txt创建在当前模块目录下,可以使用以下相对路径写法:
File file3 = new File(“模块名\\a.txt”);
1.5.File类删除功能
boolean delete() 删除该File对象表示的文件或文件夹。
File f = new File("study_day10\\abc\\ab.txt");
System.out.println(f.delete());
注意:
- 删除不走回收站
- 如果删除的是文件,直接删除。
- 如果删除的是文件夹,文件夹如果不为空,则无法删除。
1.6.File类获取和判断功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aaDJVQag-1662555367776)(image/File类获取和判断功能.png)]
1.7.File遍历文件夹
File[] listFiles(): 遍历文件夹中的内容,封装成File数组。
private static void findAllJava(File dir) {
File[] files = dir.listFiles();
for (File file : files) {
if(file.isFile()){
if(file.getName().endsWith(".java")){
System.out.println(file);
}
}else {
findAllJava(file);
}
}
}
2.递归
2.1.递归概述
递归指的是方法中调用方法本身的现象,递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出。
//需求:递归求1-n的和
private static int getSum(int n) {
if(n == 1){
return 1;
}
return n + getSum(n-1);
}
2.2.递归解决问题的思路
分治思想,就是**“分而治之”,把一个问题转化为若干个与原问题相似的规模较小的问题来求解。
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算**。
递归解决问题要找到两个内容:
- **递归出口:**否则会出现内存溢出
- **递归规则:**与原问题相似的规模较小的问题
3.IO流
3.1.IO流的概念
- I表示 Intput,输入。
- O表示 Output,输出。
3.2.IO流的作用
- **输入流:**读取文件中已经存在的数据到程序中。
- **输出流:**将内存数据写到文件中,实现数据永久化存储。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jJp2mmQQ-1662555367776)(image/IO流概念.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmeHDfXM-1662555367777)(image/IO流概念2.png)]
4.字节流
4.1.字节概念
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
4.2.FileOutputStream
4.2.1.FileOutputStream构造方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QqnVvKIL-1662555367777)(image/FileOutputStream构造方法.png)]
4.2.2.写入一个字节数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JW1pJBG9-1662555367777)(image/一次一字节.png)]
public class WriteDemo1 {
public static void main(String[] args) throws IOException {
//1.创建IO流
FileOutputStream fos = new FileOutputStream("study_day10\\abc\\a.txt");
//2.写数据
fos.write(97);
fos.write(98);
//3.关闭流
fos.close();
}
}
4.2.3.写入多个字节数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9vk4uxan-1662555367778)(image/写入多个数据.png)]
public class WriteDemo2 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("study_day10\\abc\\a.txt");
byte[] arr = {97, 98, 99, 100};
//void write(byte[] b):将byte数组写入流中
fos.write(arr);
fos.close();
}
}
public class WriteDemo3 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("study_day10\\abc\\a.txt");
byte[] arr = {97, 98, 99, 100};
//void write(byte[] b, int off, int len) :将byte数组的一部分写入流中
fos.write(arr,0,2);
fos.close();
}
}
4.2.4.数据追加续写和换行
数据追加
创建FileOutputStream对象 FileOutputStream(String name) :每次都会创建新的文件 FileOutputStream (String name, boolean append):如果append的值为true,表示在以前的文件上追加数据,不会创建新的文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xjgM0zBp-1662555367778)(image/数据追加.png)]
FileOutputStream fos = new FileOutputStream("study_day10\\abc\\a.txt",true);
换行符
windows:\r\n
linux:\n
mac:\r
public class WriteDemo4 {
public static void main(String[] args) throws IOException {
// 如果文件存在会先删除文件(暴力)
//FileOutputStream fos = new FileOutputStream("study_day10\\abc\\a.txt");
// 第二个参数设置为true,可以追加写数据,不会删除以前的文件
FileOutputStream fos = new FileOutputStream("study_day10\\abc\\a.txt",true);
fos.write(97);
//换行
fos.write("\r\n".getBytes());
fos.write(98);
fos.close();
}
}
4.3.FileInputStream
4.3.1.FileInputStream构造方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m5AeGErF-1662555367779)(image/FileInputStream构造方法.png)]
4.3.2.读取一个字节数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rPjTTiuE-1662555367780)(image/读取一个字节数据.png)]
public class ReadDemo1 {
public static void main(String[] args) throws IOException {
// 1.创建IO流
FileInputStream fis = new FileInputStream("study_day10\\abc\\a.txt");
// 定义一个变量保存读取到的数据
int b = fis.read();
System.out.println((char) b);
// 3.关闭
fis.close();
}
}
4.3.3.读取多个字节数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89UHifRu-1662555367780)(image/读取多个字节数据.png)]
public class ReadDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("study_day10\\abc\\a.txt");
byte[] arr = new byte[1024];
int len;
while ((len = fis.read(arr)) != -1){
System.out.print(new String(arr,0,len));
}
fis.close();
}
}
4.3.4.String和byte的相互转换
byte数组转为String:
String(byte[] bytes)
String(byte[] bytes, int offset, int length)
String转为byte数组:
byte[] getBytes()
public class StringDemo1 {
public static void main(String[] args) {
//String转为byte数组 getBytes
String s = "hello";
byte[] array = s.getBytes();
System.out.println(Arrays.toString(array));
//UTF-8编码中,一个中文是3个字节
String ss = "黑马";
byte[] bytes = ss.getBytes();
System.out.println(Arrays.toString(bytes)); //[-23, -69, -111, -23, -87, -84]
//byte数组转为String
//String(byte[] bytes)
byte[] arr = {65, 66, 67,68,69};
String s2 = new String(arr);
System.out.println(s2);
//String(byte[] bytes, int offset, int length)
String s1 = new String(arr, 0, 3);
System.out.println(s1);
}
}
4.3.5.字节流实现复制文件
public class CopyDemo {
public static void main(String[] args) throws IOException {
//1.创建字节输入流,用于读取文件到程序。
FileInputStream fis = new FileInputStream("study_day10\\abc\\test.jpg");
//2.创建字节输出流,用于写出文件到磁盘。
FileOutputStream fos = new FileOutputStream("E:\\MyTest\\aa\\test.jpg");
byte[] arr = new byte[1024];
int len;
//3.循环读写数据。
while ((len = fis.read(arr)) != -1){
fos.write(arr,0,len);
}
//4.关闭流。
fis.close();
fos.close();
}
}
4.4.6.字节流读取中文的乱码问题
因为一个中文都是多个字节,用字节流每次只能读其中的一部分,一个中文的字节可能被拆成多次读取,所以就会出现乱码问题。
public class Demo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("study_day10\\abc\\a.txt");
byte[] b = new byte[2];
int len;
while ((len = fis.read(b)) != -1){
System.out.println(new String(b,0,len));
}
fis.close();
}
}
5.字符流
5.1.字符流的引入
因为字节流一次读一个字节,而不管GBK还是UTF-8,一个中文都是多个字节,用字节流每次只能读其中的一部分,所以就会出现乱码问题。为解决中文读取的乱码问题,可以使用字符流。
5.2.FileReader
5.2.1.FileReader构造方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nGGe1qCa-1662555367781)(image/FileReader构造方法.png)]
5.2.2.读取一个字符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OPqPoBUw-1662555367781)(image/读取一个字符.png)]
public class FileReaderDemo1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("study_day10\\abc\\a.txt");
//定义变量保存读取的字符
int ch;
// int read()读一个字符
while ((ch = fr.read()) != -1){
System.out.print((char)ch);
}
fr.close();
}
}
5.2.3.读一个字符数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fUkOmHCe-1662555367781)(image/读取一个字符数组.png)]
public class FileReaderDemo2 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("study_day10\\abc\\a.txt");
// 定义数组保存读取的内容
char[] chs = new char[1024];
// 定义变量保存读取的数量
int len;
while ((len = fr.read(chs)) != -1){
System.out.print(new String(chs,0,len));
}
fr.close();
}
}
5.3.FileWriter
5.3.1.FileWriter构造方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a144Xwej-1662555367782)(image/FileWriter构造方法.png)]
5.3.2.写入操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uFf78acn-1662555367782)(image/字符写入API.png)]
FileWriter写数据的方法:
void write(int c) 写一个字符到流中
void write(char[] cbuf) 写入一个字符数组到流中
void write(char[] cbuf, int off, int len) 写入字符数组的一部分到流中
void write(String str) 写一个字符串到流中
void write(String str, int off, int len) 写一个字符串的一部分到流中
public class WriterDemo1 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("study_day10\\abc\\a.txt");
// 写一个字符到流中
fw.write(97);
//刷新缓冲区, flush后可以再写数据。
fw.flush();
fw.close();
}
}
5.3.3.flush和close的区别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bc3vhiyA-1662555367782)(image/flush和close的区别.png)]
**注意:**使用FileWrite写完数据后,记得要刷新或者关闭流,否则数据不会进入文件。
十一、IO流、装饰者模式
1.缓冲流
2.转换流
3.对象流
4.打印流
5.属性集
总结
代码写的越急,程序跑得越慢。—— Roy Carlson