一、⭐异常⭐
1.1 异常
1.2 异常处理
1.2.1 抛出异常(throws)
在Java的方法调用中,如果一个方法中出现了异常,本方法自己不处理,默认是会抛给调用方法去处理的 此时要注意的是,如果发生的是非运行时异常,需要在方法上明确使用throws关键字声明抛出 格式 public void 方法名 throws 异常1 ,异常2 ,异常3 ..{ 方法体 throw new Exception() }
public class Demo2 {
public static void main(String[] args) throws Exception {
print();
}
public static void print() throws Exception {
new SimpleDateFormat("yyyy-MM-dd").parse("2019");
}
}
throws只抛出并不处理,使得代码能够继续编译(即继续写代码),但运行报错,上面代码运行结果如下:
1.2.2 捕获异常(try...catch)
直接在当前方法,发生异常的代码外使用try--catch--结构捕获并处理异常 异常处理后,后续的代码是可以继续执行的 格式 public void 方法名{ try{ // 方法体 }catch(异常类型1 变量){ // 处理异常 }catch(异常类型2 变量){ // 处理异常 } }
public class Demo3 {
public static void main(String[] args) {
print();
}
public static void print(){
//1.运行时异常
String srt = null;
//System.out.println("字符串长度:" + srt.length());
try {
//java代码,jdk会监控try中的代码,一旦出现指定类型的错误,会进入到catch中做容错处理
System.out.println("字符串长度:" + srt.length());
}catch (Exception e){
System.out.println("字符串为空,长度为0");
}
}
}
1.2.3 自定义异常
自定义异常 Java无法为这个世界上全部的问题都提供异常类来代表,如果以后我们自己写的代码中的某种问题, 想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了。 自定义运行时异常 1、定义一个异常类,继承RuntimeException 2、在类中提供构造函数 3、在需要抛出异常的地方使用throw关键字 抛出异常类的对象 自定义编译时异常 1、定义一个异常类,继承Exception 2、在类中提供构造函数 3、在需要抛出异常的地方使用throw关键字 抛出异常类的对象 注意 编译时异常,在编写代码的过程中必须手动处理 异常的作用 1、异常是用来查找系统bug 的关键参考信息 2、异常可以作为方法内部一种特殊的返回值,以便通知上层调用者,代码底层的执行情况
public class Demo4 {
public static void main(String[] args) {
//模拟用户登录,用户名:admin,密码123456
System.out.println(login("admin","123456"));
}
//设置登录的方法
public static String login(String username,String password) {
if (!username.equals("admin")) {
//1.用户名错误,用户登录失败
throw new LoginException("用户名错误,用户登录失败");
} else if (!password.equals("123456")) {
//2.用户密码错误,用户登录失败
throw new LoginException("用户密码错误,用户登录失败");
} else {
//3.用户登录成功,返回用户信息
return "用户登录成功,用户名" + username;
}
}
}
//自定义运行时异常类
class LoginException extends RuntimeException{
//有参构造
public LoginException(String message) {
super(message);
}
}
public class Demo5 {
public static void main(String[] args) throws LoginException2{
//模拟用户登录,用户名:admin,密码123456
System.out.println(login("admin","1023456"));
}
//设置登录的方法
public static String login(String username,String password) throws LoginException2 {
if (!username.equals("admin")) {
//1.用户名错误,用户登录失败
throw new LoginException2("用户名错误,用户登录失败");
}else if (!password.equals("123456")) {
//2.用户密码错误,用户登录失败
throw new LoginException2("用户密码错误,用户登录失败");
}else {
//3.用户登录成功,返回用户信息
return "用户登录成功,用户名" + username;
}
}
}
//自定义编译时异常类
class LoginException2 extends Exception {
public LoginException2(String message) {
super(message);
}
}
二、⭐Lambda表达式⭐
Lambda表达式 是JDK8开始新增的一种语法形式,主要用来简化匿名内部类代码的书写 Lambda格式 (被重写方法的参数列表)->{ 被重写方法的方法体; } Lambda使用前提 Lambda只能操作函数式接口(有且仅有一个抽象方法的接口,被FunctionalInterface注解修饰)(接口才有Lambda,父子关系没有)
public class Demo1 {
public static void main(String[] args) {
//匿名内部类操作接口
Person person = new Person() {
@Override
public void eat() {
System.out.println("吃饭");
}
};
person.eat();
//Lambda简化
Person person1 = () -> {
System.out.println("吃软饭");};
person1.eat();
System.out.println("===========================================");
//匿名内部类操作抽象类
Animal animal = new Animal() {
@Override
void eat() {
System.out.println("狗吃肉脯");
}
};//无法使用Lambda简化
animal.eat();
}
}
//接口
interface Person {
void eat();
}
//抽象类
abstract class Animal {
abstract void eat();
}
三、方法引用
JDK8新特性,方法引用 主要用来简化、替换Lambda表达式 方法引用分类 1、静态方法的引用 2、实例方法的引用 3、特定类型方法的引用 4、构造器引用 小提示 先写匿名内部类,发现能化再化(写的多了就热练了) 1、静态方法的引用: 某个Lambda只是调用一个静态方法,并且前后参数一致,即可使用 类名::静态方法 2、实例方法的引用: 某个Lambda只是调用一个实例方法,并且前后参数一致,即可使用 对象名::实例方法 3、特定类型方法的引用: 如果某个Lambda只是调用一个实例方法,并且前面参数列表中第一个参数作为主调,后面的参数作为入参,即可使用 类型::方法 4、构造器引用 如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用 类名::new
四、⭐常见算法⭐
4.1 冒泡排序
冒泡排序 相邻的两个元素进行比较,小的放左边大的放右边,完成升序排列 实现步骤 确定总共需要做几轮: 数组长度-1 每轮比较几次: 轮数从0计数的话, 就是数组长度-1-当前轮数 比较规则: 相邻两个元素比较,大的放在右边
4.2 选择排序
选择排序 每轮选择当前位置,开始找后面的最小值,与当前位置交换 关键点分析 确定总共需要做几轮: 数组长度-1 每次的基准位:轮数从0计数的话, 就是基准位索引敲好就是轮数 比较规则: 以每次的第一个为基准做比较,谁小谁来基准位
public class Demo2 {
public static void main(String[] args) {
int[] arr = {5, 2, 3, 1};
selectionSort(arr);
System.out.println(Arrays.toString(arr));
}
private static void selectionSort(int[] arr) {
// 控制轮数:确定总共需要做几轮: 数组长度-1
for (int i = 0; i < arr.length-1; i++) {
// 每次的基准位:轮数从0计数的话, 就是基准位索引恰好就是轮数(i+1)
for (int j = i+1; j < arr.length; j++) {
if(arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
}
4.3 折半查找(二分查找)
二分查找/折半查找 前提是数组有序 特点是每一次查找完成,会舍去一半元素 思路分析 1、定义两个指针,指向数组第一个和最后一个索引位置 2、循环查找,min小于等max则继续(三个指针可能重叠的) 3、每次循环进来,重新计算中间指针 4、判断情况1:如果mid指向的元素就是num,则返回mid 5、判断情况2:如果要查找的元素,在左半边,舍弃max重新计算 6、判断情况3:如果要查找的元素,在右半边,舍弃min重新计算 7、循环结束没有找到,则代表不存在,返回-1
public class Demo1 {
public static void main(String[] args) {
int[] arr = {10, 23, 39, 45, 59, 166, 728, 810, 999};
System.out.println("索引位置为:" + binarySearch(arr, 166));//索引位置为:5
System.out.println("索引位置为:" + binarySearch(arr, 200));//索引位置为:-1
}
//二分查找
private static int binarySearch(int[] arr, int num) {
//1.设置返回索引
int index = -1;
//2.设置开始和结束索引
int min = 0;
int max = arr.length - 1;
//3.使用while循环,条件:左侧开始索引 <= 右侧结束索引
while (min<=max){
//4.计算中间索引
int mid = (min + max)/2;
//5.使用中间索引的数据和需要查询的num比较
//5.1 数据一致,返回索引位置
if(num == arr[mid]){
index = mid;
break;
}else if(num < arr[mid]){
//5.2 数据小于中间索引的数据,舍弃右侧数据,重新计算
max = mid - 1;
}else{
//5.3 数据大于中间索引的数据,舍弃左侧数据,重新计算
min = mid + 1;
}
}
//如果min>max,则代表没有找到,返回-1
//6.循环结束,返回索引位置
return index;
}
}