JavaSE进阶——Day08 该篇主要讲解Java中的异常、Lambda表达式、Stream流、File类、递归
回顾
logback使用步骤:
- 在当前项目下导入logback相关jar文件,并添加到项目工程资源库中
- 把logback核心配置文件,复制到当前项目工程的src目录下
- 在开发的类中,创建logback对象,使用logback中的API方法记录日志信息
logback日志级别:
trace
//追踪
debug
//调试(程序有bug,测试bug使用的)
info
//关键信息
warn
//警告
error
//错误
异常
什么是异常?
- 程序在运行过程中,发生了不正常的情况,造成程序中断向下执行
有异常了怎么办呢?
- 当前发生异常的代码位置处,有处理异常的代码,那么异常就会被处理掉,程序继续执行
- 当前发生异常的代码位置处,没有处理异常的代码(程序中没有处理异常的代码),最终异常会抛出给JVM来处理
- JVM处理异常的方式:
- 打印异常的信息(异常的类型、异常发生的位置、异常的原因)
- JVM停止
异常体系
异常处理的方式:
- 声明:throws
- 遇到异常发生了,自己不处理,交给别人处理
- 最终还是需要有一个位置使用try..catch来处理异常
- 结论:在main方法中,只能使用try..catch
- 捕获:try..catch
使用声明的方式处理异常:
1 2 3 4 5
| 修饰符号 返回值类型 方法名(参数类型 参数,...) throws 异常类1 , 异常类2 , .... { }
|
1 2 3 4
| //在定义方法时,使用声明的方式处理异常 public void method(String name) throws NullPointerException { // }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package ex;
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat;
public class ExceptionDemo2 { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); try { mothed1(sdf, "2024-04-24"); } catch (ParseException e) { System.out.println("时间格式不正确"); }
int[] arr = new int[5]; String str = null; mothed2(arr, str); }
private static void mothed1(SimpleDateFormat sdf, String strDate) throws ParseException { System.out.println(sdf.parse(strDate)); }
private static void mothed2(int[] arr, String str) throws RuntimeException { System.out.println(str.length() + arr[arr.length]); }
}
|
Java基础面试题 : throws和throw的区别
throws : 声明
throw : 抛出 (手动引发异常)
1 2
| throw new RuntimeException("参数不能为空");
|
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package ex;
public class ExceptionDemo3 { public static void main(String[] args) { String name = null; getName(name); }
private static void getName(String name) { if (name == null || "".equals(name)){ throw new RuntimeException("name不能为空", new NullPointerException("空指针异常")); } System.out.println("dadada"); } }
|
异常处理有两种:声明、捕获,在程序开发中到底怎么选择使用哪个呢?
捕获和日志代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package ex;
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner;
public class ExceptionDemo4 { private static final Logger LOGGER = LoggerFactory.getLogger("ExceptionDemo4类"); public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (true) { System.out.println("输入你的生日(年-月-日):"); String birthday = sc.nextLine(); try { mothed(birthday); System.out.println("生日: " + birthday); } catch (ParseException e) { System.out.println("开始捕获异常"); LOGGER.error(e.getMessage()); } } }
private static Date mothed(String date) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.parse(date); } }
|
Throwable类 //异常的顶层父类型
编译时异常:Exception类
运行时异常:RuntimeException类 (继承了Exception)
自定义异常:
Lambda
lambda作用:
lambda表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package lam;
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List;
public class LambdaDemo2 { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); Collections.addAll(list, 4, 6, 2, 4, 8);
Collections.sort(list, (Integer n1, Integer n2) -> { return n2 - n1; });
System.out.println(list); } }
|
例:带参和返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| //Calculator接口 package lam;
/** * @Author EthanLiu 16693226842@163.com * @Date 2024/4/26 00:23 * @Project JavaCode_SE_Advance * @Theme 代参数与返回值的接口方法 */ //函数式接口(计算器) @FunctionalInterface public interface Calculator { public abstract int calculator(int n1, int n2); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package lam;
public class CalculatorDemo { public static void main(String[] args) { addNum((int n1, int n2) -> { return n1 + n2; }); }
private static void addNum(Calculator calculator) { int res = calculator.calculator(10, 20); System.out.println(res);
} }
|
Lambda表达式的省略模式:
- 可以省略参数类型:要么全部省略,要么全部保留
- 如果参数仅有一个时,可以省略小括号
- 如果代码块中仅有一行代码,可以省略:大括号、分号、return
Stream流
stream流的作用:
Stream流的使用通常需要Lambda表达式
Stream流方法分类:
- 获取方法:获取流(创建一个流水线)
- 中间方法:在流水线进行操作(例:过滤、截取)
- 终结方法:流水线上的操作结束了,要关闭流水线
获取Stream流对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Stream 流对象 = 单列集合对象.stream();
1. 先通过keySet()或entrySet(),获取到Set集合 2. Stream 流对象 = Set集合对象.stream();
Stream 流对象 = Arrays.stream( 数组 );
Stream 流对象 = Stream.of( 同一种类型元素 ,同一种类型元素,同一种类型元素, ... );
|
代码案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| package stream_demo;
import java.util.*;
public class StreamDemo1 { public static void main(String[] args) { method1();
System.out.println(); method2();
System.out.println(); method3();
}
private static void method2() { Map<Integer, String> map = new HashMap<>(); map.put(1, "Java基础"); map.put(2, "Java进阶"); map.put(3, "MySQL"); map.put(4, "JavaWeb"); map.put(5, "Spring"); map.entrySet().stream().forEach(s -> System.out.print(s + "\t")); }
private static void method1() { List<Integer> list = new ArrayList<>(); Collections.addAll(list, 1, 3, 6, 2, 4, 7, 3); list.stream().forEach(s-> System.out.print(s + "\t")); }
private static void method3() { int[] arr = {2, 74, 342, 42, 23, 5}; Arrays.stream(arr).forEach(s -> System.out.print(s + "\t")); }
}
|
中间方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| package stream_demo;
import java.util.ArrayList; import java.util.Comparator;
public class StreamDemo2 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("张无忌"); list.add("张翠山"); list.add("张三丰"); list.add("谢广坤"); list.add("谢广坤"); list.add("赵四"); list.add("刘能"); list.add("小沈阳"); list.add("张良"); list.add("张良");
list.stream() .filter(name->name.startsWith("谢")) .forEach(-> System.out.println(s)); System.out.println(); list.stream().limit(5).forEach(s-> System.out.println(s)); System.out.println(); list.stream().skip(3).forEach(s-> System.out.println(s)); System.out.println(); list.stream().distinct().forEach(s-> System.out.println(s)); System.out.println(); list.stream().sorted().forEach(s -> System.out.println(s)); System.out.println(); list.stream() .sorted((str1, str2)-> str1.length() - str2.length()) .forEach(s -> System.out.println(s));
} }
|
终结方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package stream_demo;
import java.util.ArrayList; import java.util.function.Consumer;
public class StreamDemo4 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("张无忌"); list.add("张翠山"); list.add("张三丰"); list.add("谢广坤");
long count = list.stream().count(); System.out.println(count); } private static void method1(ArrayList<String> list) { list.stream().forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } });
System.out.println("=====================");
list.stream().forEach( (String s) -> { System.out.println(s); });
System.out.println("=====================");
list.stream().forEach( s -> { System.out.println(s); }); }
}
|
Stream流转换
Stream流收集方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package stream_demo;
import java.util.ArrayList;
public class StreamDemo5 { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) { list.add(i); }
list.stream().filter(num -> num % 2 == 0).forEach(num -> System.out.println(num));
System.out.println("=============");
System.out.println(list); } }
|
结论:在Stream流中无法直接修改集合,数组中的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| package stream_demo;
import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors;
public class StreamDemo6 { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { list.add(i); } list.add(10); list.add(10); list.add(10); list.add(10); list.add(10);
List<Integer> list2 = list.stream().filter(num -> num % 2 == 0 ).collect(Collectors.toList()); System.out.println(list2);
Set<Integer> set = list.stream().filter(num -> num % 2 == 0 ).collect(Collectors.toSet()); System.out.println(set);
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package stream_demo;
import java.util.ArrayList; import java.util.Map; import java.util.stream.Collectors;
public class StreamDemo7 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("zhangsan,23"); list.add("lisi,24"); list.add("wangwu,25");
Map<String, String> map = list.stream().filter(s -> Integer.parseInt(s.split(",")[1]) > 23).collect( Collectors.toMap( (String s) -> { return s.split(",")[0]; } , (String s) -> { return s.split(",")[1]; } ) ); System.out.println(map); } }
|
Optional类判空
1 2 3 4 5 6 7 8 9 10
| boolean res = Optional.ofNullable(对象).is对象所属类();
Optional<类> optional对象 = Optional.ofNullable(对象) if (optional对象.is对象所属类()){ .... }else{ .... }
|
File类
File类的介绍
- java.io.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 25 26 27
| package file_demo;
import java.io.File;
public class FileDemo1 { public static void main(String[] args) {
File f1 = new File("~/Desktop/abc.txt"); System.out.println(f1);
File f2 = new File("~/Desktop/aaa", "bbb.txt"); System.out.println(f2);
File f3 = new File(new File(~/Desktop/aaa"), "bbb.txt"); System.out.println(f3); } }
|
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 25 26 27
| package file_demo;
import java.io.File; import java.io.IOException;
public class FileDemo2 { public static void main(String[] args) throws IOException { File f1 = new File("~/Desktop/a.txt"); System.out.println(f1.createNewFile());
File f2 = new File("day10_demo/aaa"); System.out.println(f2.mkdir());
File f3 = new File("day10_demo/bbb/ccc"); System.out.println(f3.mkdirs()); } }
|
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 25 26 27 28 29 30
| package file_demo;
import java.io.File; import java.io.IOException;
public class FileDemo3 {
public static void main(String[] args) throws IOException { File f1 = new File("~/Desktop/a.txt"); System.out.println(f1.delete());
File f2 = new File("day10_demo/aaa"); System.out.println(f2.delete());
File f3 = new File("day10_demo/bbb"); System.out.println(f3.delete()); } }
|
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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package file_demo;
import java.io.File;
public class FileDemo4 { public static void main(String[] args) { File f1 = new File("day10_demo/aaa"); File f2 = new File("day10_demo/a.txt");
System.out.println(f1.isDirectory()); System.out.println(f2.isDirectory());
System.out.println(f1.isFile()); System.out.println(f2.isFile());
System.out.println(f1.exists());
System.out.println(f1.getAbsolutePath());
System.out.println(f1.getPath());
System.out.println(f2.getName()); } }
|
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 25 26 27 28 29
| package file_demo;
import java.io.File;
public class FileDemo5 { public static void main(String[] args) { File file = new File("day10_demo/bbb/ccc");
File[] files = file.listFiles();
for (File f : files) { System.out.println(f.getName()); } } }
|
练习 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package file_demo;
import java.io.File; import java.util.HashMap;
public class FileTest2 { public static void main(String[] args) { File file = new File("day10_demo/统计文件个数文件夹");
getFileCount(file); }
public static void getFileCount(File f) {
HashMap<String, Integer> hm = new HashMap<>();
if (f.isDirectory()) { File[] files = f.listFiles(); for (File file : files) { String fileName = file.getName(); String name = fileName.split("\\.")[1]; if (hm.containsKey(name)) { hm.put(name, hm.get(name)); } else { hm.put(name, 1); } } }
System.out.println(hm); } }
|
递归
概述
- 递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
好处
- 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
小的问题解决 , 大的问题也会逐一进行解决
注意
- 递归出口:否则会出现内存溢出
- 递归规则:需要找到与原问题相似的规模较小的问题
案例
- ```java
package com.itheima.recursion_demo;
/*
需求:用递归求5的阶乘,并把结果在控制台输出
思路:
1 定义一个方法,用于递归求阶乘,参数为一个int类型的变量
2 在方法内部判断该变量的值是否是1
是:返回1
不是:返回n*(n-1)!
3 调用方法
4 输出结果
*/
public class Demo1 {
public static void main(String[] args) {
int result = jc(5);
System.out.println(“5的阶乘是:” + result);
}
private static int jc(int n) {
if (n == 1) {
return 1;
}
return n * jc(n - 1);
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
- ```java package com.itheima.recursion_demo; import java.io.File; /* 需求 : 使用递归删除计算机中指定的文件夹 删除D盘中的aaa文件夹! */ public class Demo2 { public static void main(String[] args) { File f = new File("D:\\aaa"); deleteFiles(f); } private static void deleteFiles(File f) { File[] files = f.listFiles(); for (File file : files) { if (file.isDirectory()) { // 递归 deleteFiles(file); } else { // 删除文件 file.delete(); } } // 删除当前文件夹 f.delete(); } }
|