Java Study Notes_Design in 2023(Day01~Day14)

文章目录

  • Day01:Java入门
    • 1.1 Java的技术体系
    • 1.2 Java快速入门
      • 1.2.1 JDK、JRE与JVM
      • 1.2.2 JDK环境变量配置
    • 1.3 Java基础语法
      • 1.3.1 注释
      • 1.3.2 字面量
      • 1.3.3 JAVA关键字
      • 1.3.4 标志符
      • 1.3.5 变量
  • Day02: 数据类型、运算符
    • 2.1 数据的表示详解
      • 2.1.1二进制
    • 2.2 数据的表示
      • 2.2.1 进制转换
      • 2.2.3 字符在计算机中的存储原理
    • 2.2 数据类型
    • 2.3 类型转换
      • 2.3.1 自动类型转换
      • 2.3.2 强制类型转换
    • 2.4 运算符
      • 2.4.1 算术运算符
      • 2.4.2 自增自减运算符
      • 2.4.3 赋值运算符
      • 2.4.4 关系运算符
      • 2.4.5 逻辑运算符
      • 2.4.6 三元运算符
      • 2.4.7 运算优先级
    • 2.5 案例技术:获取用户键盘输入的数据
  • Day03: 程序流程控制
    • 3.1 选择结构
      • 3.1.1 if单选择结构
      • 3.1.2 if双选择结构
      • 3.1.3 多单选择结构
      • 3.1.4 嵌套if结构
      • 3.1.5 switch多选择结构
      • 3.1.6 jdk7新特性
    • 3.2 循环结构
      • 3.2.1 while循环
      • 3.2.2 do...while循环
      • 3.2.3 For循环
      • 3.2.4 增强for循环
    • 3.3 练习
      • 3.3.1 练习1:计算0到100间的奇数和偶数的和
      • 3.3.2 练习2:用while或for循环输出1~1000间能被5整除的数,并且每行输出3个
      • 3.3.3 练习3:输出9X9乘法表
    • 3.4 break和continue关键字
    • 3.5 随机数
      • 3.5.1 产生一个随机数
      • 3.5.2 猜数字小游戏
  • Day04: Java数组
    • 4.1 认识数组
    • 4.2 数组的定义和访问
      • 4.2.1静态初始化
      • 4.2.2 数组的动态初始化
    • 4.3 内存分析
    • 4.4 数组在计算机中的执行原理
    • 4.5 多个变量指向同一个数组的问题
    • 4.6 数组练习
      • 4.6.1 数组求最值
      • 4.6.2 数组存取用户数据进行随机排名
      • 4.6.3 冒泡排序
      • 4.6.4 数组元素反转
    • 4.7 Debug调试
  • Day05: 方法
    • 5.1 方法概述
    • 5.2 方法的定义
    • 5.3 方法在计算机中的执行原理
      • 5.3.1 有返回值的方法,内存分析
      • 5.3.2 无返回值的方法,内存分析
    • 5.4 方法参数的传递机制
      • 5.4.1 方法参数传递是基本类型数据,内存执行原理
      • 5.4.2 参数是引用类型,实际上也是值传递,只不过参数传递存储的地址值
      • 5.4.3 方法参数传递案例1
    • 5.5 方法重载
      • 5.5.1 方法重载案例一
      • 5.5.2 方法重载案例二
    • 5.6 return单独使用
  • Day06: Java编程案例思维训练
    • 6.1 完成买飞机票的案例
    • 6.2 完成生成随机验证码
  • Day07:Java面向对象基础
    • 7.1 对象在计算机中的执行原理
    • 7.2 类和对象的一些注意事项
    • 7.3 this关键字
    • 7.4 构造器
    • 7.5 封装性
    • 7.6 实体JavaBean
      • 7.6.1 实体类案例一
      • 7.6.2 面向对象综合案例
    • 7.7 成员变量和局部变量的区别
  • Day08: Java常用API
    • 8.1 String类
    • 8.2 ArrayList类
  • Day09: Java基础项目(ATM系统)
  • Day10:面向对象高级
    • 10.1 "static" 关键字
      • 10.1.1 static修饰成员变量
      • 10.1.2 内存原理
      • 10.1.3 static修饰成员方法
      • 10.1.4 内存分析
      • 10.1.5 static的注意事项
    • 10.2 代码块(匿名、静态)
    • 10.2 单例设计模式
      • 10.2.1 单例设计模式之饿汉式
      • 10.2.2 单例设计模式之懒汉式
      • 10.2.3 懒汉式与饿汉式区别
  • Day11: 面向对象高级二
    • 11.1 多态
    • 11.2 多态优点
      • 11.2.1 案例一
    • 11.3 final关键字
      • 11.3.1 案例一
      • 11.3.2 案例二
      • 11.3.3 案例二
    • 11.4 抽象类
      • 11.4.1 案例一
      • 11.4.2 案例二
      • 11.4.3 案例三
    • 11.5 设计模式——模板方法模式
      • 11.6 接口
        • 11.6.1 案例一
        • 11.6.2 案例二
  • Day12: 面向对象高级三
    • 12.1 内部类
      • 12.1.1 成员内部类
      • 12.2.2 静态内部类
      • 12.2.3 局部内部类
      • 12.2.4 匿名内部类
    • 12.3 枚举
    • 12.4 泛型
    • 12.5 常用API
      • 12.5.1 Object类
      • 12.5.2 基本类型包装类
  • Day13: 常用API
    • 13.1 StringBuilder与StringBuffer类
    • 13.2 Math类
    • 13.3 System类
    • 13.4 Runtime类
    • 13.5 BigDecimal类
    • 13.6 Date类
    • 13.7 SimpleDateFormat类
    • 13.8 Calendar类
    • 13.9 JDK8日期、时间、日期时间
      • 13.9.1 LocalDate类
      • 13.9.2 LocalTime类
      • 13.9.3 LocalDateTime类
    • 13.10 JDK8日期(时区)
    • 13.11 JDK8日期(Instant类)
    • 13.12 JDK8日期(格式化器DateTimeFormater)
    • 13.13 JDK8日期(Period类和Duration类)
    • 13.14 Arrays类
      • 13.14 .1 Arrays基本使用
      • 13.14.2 Arrays操作对象数组实现排序
  • Day14: 算法和数据结构
    • 14.1 Lambda表达式
    • 14.2 JDK8新特性(方法引用)
    • 14.3 常见算法
      • 14.3.1 冒泡排序
      • 14.3.2 选择排序
      • 14.3.3 查找算法
    • 14.4 正则表达式

Day01:Java入门

1.1 Java的技术体系

  • Java SE(Java Standard Edition):叫做标准版,它是后面两个版本的基础,也就是学习后面两个版本必须先学习JavaSE。
  • Java EE(Java Enterprise Edition): 叫做企业版,它是为企业级应用开发提供的一套解决方案。
  • Java ME(Java Micro Edition):叫做小型版,它为开发移动设备的应用提供了一套解决方案。

1.2 Java快速入门

1.2.1 JDK、JRE与JVM

在这里插入图片描述
1. jdk包含 JRE(Java Runtime Enviroment):意思是Java的运行环境;它是由JVM和核心类库组成的;如果你不是开发人员,只需要在电脑上安装JRE就可以运行Java程序。
2. jvm(java虚拟机):JDK最核心的组成部分是JVM(Java Virtual Machine),它是Java虚拟机,真正运行Java程序的地方。
3.JDK、JRE的关系用一句话总结就是:用JDK开发程序,交给JRE运行
4. java既是编译型(C、C++)也是解释型(javascript)语言

1.2.2 JDK环境变量配置

1.2.2.1 首先找到此电脑,右键点击属性,可以按照下面的界面;点击【高级系统设置】,再点击【环境变量】
在这里插入图片描述
1.2.2.2 找到JDK的bin目录,复制一下
1.2.2.3 将JDK的bin目录粘贴在Path环境变量后面
在这里插入图片描述
1.2.2.4.在CMD输入javac -version 看提示信息是否显示你安装JDK的版本号

在这里插入图片描述

1.3 Java基础语法

1.3.1 注释

1.单行注释:
	//后面根解释文字
2.多行注释
    /*
    这里写注释文字
    可以写多行
    */
3.文档注释
    /**
    这里写文档注释
    也可以写多行,文档注释可以利用JDK的工具生成帮助文档
    */

1.3.2 字面量

字面量数据程序中书写格式
Java Study Notes_Design in 2023(Day01~Day14)_第1张图片

1.3.3 JAVA关键字

abstract assert boolean break byte
case catch char class const
continue default do double else
enum extends final finally float
for goto if implements import
instanceof int interface long native
new package private protected public
return strictfp short static super
switch synchronized this throw throws
transient try void volatile while

1.3.4 标志符

在这里插入图片描述

1.3.5 变量

变量是用来记录程序中的数据的。其本质上是内存中的一块区域,你可以把这块区域理解成一个小盒子。
Java Study Notes_Design in 2023(Day01~Day14)_第2张图片

注意:
变量的类型只有引用数据类(数组、类接口、枚举、注解)型和基本数据类型byte,short,int,long,float,double,char,boolean)两种。

Day02: 数据类型、运算符

2.1 数据的表示详解

2.1.1二进制

数据在计算机中都是以二进制表示的

2.2 数据的表示

数据的表示形式除了二进制(逢2进1),八进制(逢8进1)、还有十进制(逢10进1)、十六进制(逢10进1)等

2.2.1 进制转换

2.2.2.1.1 普通方法
a.二进制是如何表示十进制的2呢?

              1
           +  1
 --------------------------------
              10     

这里两个1相加,结果为2,由于二进制满2进1,所以最终结果10
b.那么二进制是如何表示十进制的3呢?

我们已经知道二进制10表示十进制的2,那么二进制10+1就表示十进制的3啊!

       10
     +  1
    -------
       11
  十进制的3对应的二进制是11

2.2.2.1.2除2取余法

6/2 余数
6/2 3 0
3/2 1 1
1/2 0 1

然后把余数反转:6对应的二进制是110

2.2.3 字符在计算机中的存储原理

ASCII编码表中字符编码的规律:
1.字符0对应48,后面的1,2,3,4…9 对应的十进制整数依次往后顺延
2.字符a对应97,后面的b,c,d,e…z 对应的十进制整数依次往后顺延
3.字符A对应65,后面的B,C,D,E…Z 对应的十进制整数依次往后顺延
在这里插入图片描述

2.2 数据类型

在这里插入图片描述

2.3 类型转换

在这里插入图片描述

2.3.1 自动类型转换

```public class Demo03 {
    public static void main(String[] args) {
        int i = 128;
        //byte b = (byte) i; //内存溢出
        double b = i;

        //强制转换 (类型)变量名 高到低
        //自动转换 低到高

        System.out.println(i);
        System.out.println(b);

        /*
        注意点
        1.不能对布尔值转换
        2.不能把对象类型转换为不相干的类型
        3.在把高容量转换到低容量时强制转换
        4.转换的时候可能存在内存溢出,或者精度问题

         */
        System.out.println("=====================");
        System.out.println((int)23.7); //23
        System.out.println((int)-45.89f); //-45

        System.out.println("=====================");
        char c = 'a';
        int d = c+1;
        System.out.println(d);
        System.out.println((char)d);
    }
}
输出
128
128.0
=====================
23
-45
=====================
98
b

2.3.2 强制类型转换

package com.sesameseed.type;

public class TypeConversionDemo3 {
    public static void main(String[] args) {

        //目标:强制类型转换
        int a =20;
        byte b = (byte)a;
        System.out.println(b);

        int i = 1500;
        byte j = (byte)i;
        System.out.println(j); //数据溢出

        float f1 = 12.5656F;
        int i1 = (int)f1;
        System.out.println(i1);
    }
}

print:
20
-36
12

2.4 运算符

  • 基本算术运算符
  • 自增自减运算符
  • 赋值运算符
  • 关系运算符
  • 逻辑运算符
  • 三元运算符

2.4.1 算术运算符

Java Study Notes_Design in 2023(Day01~Day14)_第3张图片

2.4.2 自增自减运算符

++i:先做加法运算,再做自加
i++:先做自加,再做加法运算

package operator;

public class Demo04 {
    public static void main(String[] args) {
        //++ -- 自增,自减 一元运算符
        int a= 3;

        int b = a++;  //执行完这行代码后,先给b赋值,再自增
        // a = a+1
        System.out.println(a);

        // a = a+1;
        int c = ++a; //执行完这行代码前,先自增,再给b赋值

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);

        //幂运算 2*3 2*2*2 = 8 很多运算用工具类来操作!
        double pow = Math.pow(2,3);
        System.out.println(pow);
    }
}
输出
4
5
3
5
8.0

2.4.3 赋值运算符

Java Study Notes_Design in 2023(Day01~Day14)_第4张图片

2.4.4 关系运算符

Java Study Notes_Design in 2023(Day01~Day14)_第5张图片

2.4.5 逻辑运算符

Java Study Notes_Design in 2023(Day01~Day14)_第6张图片

2.4.6 三元运算符

```java
package operator;

//三元运算符
public class Demo08 {
    public static void main(String[] args) {
        // x ? y : z
        //如果x == true,则结果为y,否则为z

        int score = 80;
        String type = score < 60 ?"不及格":"及格";
        // if
        System.out.println(type);
    }
}
输出
及格

2.4.7 运算优先级

Java Study Notes_Design in 2023(Day01~Day14)_第7张图片

&&运算比||运算的优先级高,所以&&和||同时存在时,是先算&&再算||;

2.5 案例技术:获取用户键盘输入的数据

package com.sesameseed.scanner;

import java.util.Scanner;

public class ScannerDemo1 {
    public static void main(String[] args) {
        //TODO:Scanner是键盘扫描器对象(你就把它理解成一个东西),这个东西有录入的功能
        //sc是给这个东西取的自定义名字
        Scanner sc = new Scanner(System.in);

        System.out.println("请输入您的年龄:");
        //sc这个东西有键盘录入整数的功能,这个功能的名字叫nextInt()
        //.表示表示调用的意思
        int age = sc.nextInt();
        System.out.println("您的年龄是:"+ age);

        System.out.println("请输入您的名字");

        //sc这个东西还有键盘录入字符串的功能,这个功能的名字叫next
        String name = sc.next();
        System.out.println(name + "欢迎进入系统");
    }
}

Day03: 程序流程控制

3.1 选择结构

在这里插入图片描述

3.1.1 if单选择结构

在这里插入图片描述

package com.jiao.struct;


import java.util.Scanner;

public class IfDemo01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入一个内容:");
        String s = scanner.nextLine();


        //equals:判断字符串是否相等
        if (s.equals("Hello")){
            System.out.println(s);
        }
        System.out.println("End");
        scanner.close();
    }
}

输出
请输入一个内容:
Hello
Hello
End

3.1.2 if双选择结构

在这里插入图片描述

package com.jiao.struct;


import java.util.Scanner;

public class IfDemo02 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入成绩:");
        int score = scanner.nextInt();
        if (score > 60){
            System.out.println("及格");
        }else{
            System.out.println("不及格");
        }


        scanner.close();
    }
}
输出
请输入成绩:
50
不及格

3.1.3 多单选择结构

在这里插入图片描述

package com.jiao.struct;


import java.util.Scanner;

public class IfDemo03 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入成绩:");
        int score = scanner.nextInt();
        if (score == 100){
            System.out.println("满分");
        }else if(score < 100 && score >= 90){
            System.out.println("A");
        }else if(score < 90 && score >= 80){
            System.out.println("B");
        }else if(score < 80 && score >= 60){
            System.out.println("C");
        }else if(score < 60 && score >= 0){
            System.out.println("不及格");
        }else{
            System.out.println("输入成绩不合法");
        }

        scanner.close();

    }
}
输出
请输入成绩:
80
B

3.1.4 嵌套if结构

在这里插入图片描述

3.1.5 switch多选择结构

在这里插入图片描述

package com.jiao.struct;
    //case穿透
    //switch 匹配一个具体的值
public class SwitchDemo01 {
    public static void main(String[] args) {

        char grade = 'B';
        switch (grade){
            case'A':
                System.out.println("优秀");
                break; //可选,如果没有则会发生case穿透现象,即会输出下边的语句结果
            case'B':
                System.out.println("良好");
                break; //可选,如果没有则会发生case穿透现象,即会输出下边的语句结果
            case'C':
                System.out.println("及格");
                break; //可选,如果没有则会发生case穿透现象,即会输出下边的语句结果
            case'D':
                System.out.println("再接再厉");
                break; //可选,如果没有则会发生case穿透现象,即会输出下边的语句结果
            default:
                System.out.println("未知等级");

        }
    }
}
输出
良好

3.1.6 jdk7新特性

package com.jiao.struct;

public class SwitchDemo02 {
    public static void main(String[] args) {
        String name = "李明";

        switch (name){
            case "张三":
                System.out.println("张三");
                break;
            case "李明":
                System.out.println("李明");
                break;
                default:
                System.out.println("输入不合法");
        }

    }
}
输出
李明

3.2 循环结构

在这里插入图片描述

3.2.1 while循环

在这里插入图片描述

package com.jiao.struct;

public class WhileDemo01 {
    public static void main(String[] args) {

        //输出1~100

        int i = 0;
        while (i < 100){
            i++;
            System.out.println(i);
        }
    }
}
输出
1
2
、、、
100
package com.jiao.struct;

public class WhileDemo02 {
    public static void main(String[] args) {
        //死循环
        while (true){
            //等待客户连接
            //定时检查
        }
    }
}

计算1+2+3+…+100 = ?

package com.jiao.struct;

public class WhileDemo03 {
    public static void main(String[] args) {
        //计算1+2+3+...+100 = ?

        int i = 0;
        int sum = 0;
        while (i <= 100){
            sum = sum + i;
            i++;
        }
        System.out.println(sum);
    }
}
输出
5050

3.2.2 do…while循环

在这里插入图片描述

package com.jiao.struct;

public class DoWhileDemo01 {
    public static void main(String[] args) {
        int i = 0;
        int sum = 0;

        do{
            sum = sum + i;
            i++;
        }while (i <= 100);
        System.out.println(sum);
    }

}
输出
5050
package com.jiao.struct;

public class DoWhileDemo02 {
    public static void main(String[] args) {
        int a = 0;
        while (a < 0){
            System.out.println(a);
            a++;
        }
        System.out.println("================");
        do {
            System.out.println(a);
            a++;
        }while (a < 0);
    }
}
输出
0

3.2.3 For循环

在这里插入图片描述

package com.jiao.struct;

public class ForDemo01 {
    public static void main(String[] args) {
        int a = 1; //初始化条件
        while (a <= 100) { //条件判断
            System.out.println(a); //循环体
            a += 2; //迭代
            }
        System.out.println("while循环结束");

        //初始化值、条件判断、迭代
        for (int i = 1;i <= 100;i++){
            System.out.println(i);
        }
        //100.for 快捷生成 for (int i = 0; i < 100; i++)
        
        System.out.println("for循环结束");
    }
}

3.2.4 增强for循环

在这里插入图片描述

package com.jiao.struct;

public class ForDemo05 {
    public static void main(String[] args) {
        int[] numbers = {10,20,30,40,50}; //定义了一个数组

        for (int i = 0;i < 5;i++) {
            System.out.println(numbers[i]);
        }
        System.out.println("=============");
        //遍历数组元素
        for (int x:numbers){ //把number赋值给int
            System.out.println(x);
        }
    }
}
输出
10
20
30
40
50
=============
10
20
30
40
50

3.3 练习

3.3.1 练习1:计算0到100间的奇数和偶数的和

package com.jiao.struct;

public class ForDemo02 {
    public static void main(String[] args) {
        //练习1:计算0到100间的奇数和偶数的和

        int oddSum = 0;
        int evenSum = 0;

        for (int i = 0; i <= 100; i++) {
            if (i % 2 != 0){
                oddSum += i;
            }else {
                evenSum += i;
            }
        }
        System.out.println("奇数的和"+oddSum);
        System.out.println("偶数的和"+evenSum);
    }
}
输出
奇数的和2500
偶数的和2550

3.3.2 练习2:用while或for循环输出1~1000间能被5整除的数,并且每行输出3个

package com.jiao.struct;

public class ForDemo03 {
    public static void main(String[] args) {
        //练习2:用while或for循环输出1~1000间能被5整除的数,并且每行输出3个
        for (int i = 0; i <= 1000; i++) {
            if(i % 5 == 0){
                System.out.print(i+"\t");
            }
            if(i % (5*3) == 0){
                //System.out.println(); 也可以实现
                System.out.println("\n");
            }

        }
        //println 输出完会换行
        //print 输出完不会换行
    }
}

输出
0	

5	10	15	

20	25	30	

35	40	45	

50	55	60	

、、、

3.3.3 练习3:输出9X9乘法表

package com.jiao.struct;

public class ForDemo04 {
    //练习3:输出9X9乘法表
    public static void main(String[] args) {
        //1.首先打印第一列
        //2.把固定的1再用一个人循环包起来
        //3.去掉重复项 i <= j
        //4.调整样式
        
        for (int j = 1; j <= 9; j++) {
            for (int i = 1; i <= j; i++) {
            System.out.print(j + "*" + i + "=" + (j * i) + "\t");
            }
            System.out.println();
        }

    }
}

3.4 break和continue关键字

break作用跳出并结束当前所在循环的执行
continue作用结束本次循环,进入下一次循环
在这里插入图片描述

package com.jiao.struct;

public class BreakDemo01 {
    public static void main(String[] args) {
        int i = 0;
        while (i < 100){
            i++;
            System.out.println(i);
            if(i == 30){
                break;
            }
        }
        System.out.println("123");
    }
}
输出
1
2
3
...
30
123
package com.jiao.struct;

public class ContinueDemo01 {
    public static void main(String[] args) {
        int i = 0;
        while (i < 100){
            i++;
            if (i % 10 == 0){
                System.out.println();
                continue;
            }
            System.out.print(i);
        }
    }
}
输出
123456789
111213141516171819
212223242526272829
313233343536373839
414243444546474849
515253545556575859
616263646566676869
717273747576777879
818283848586878889
919293949596979899
package com.jiao.struct;

public class Labe1Demo {
    public static void main(String[] args) {
        //打印101~150之间的所有质数
        //质数是指在大于1的自然数中,除了1和它本身以外不再有其他因素的自然数

        int count = 0;
        //不建议使用
        outer:for (int i = 101; i < 150; i++) {
            for (int j = 2; j < i/2; j++) {
                if (i % j == 0){
                    continue outer;
                }

            }
            System.out.println(i+"");
        }

    }
}
输出
101 103 107 109 113 127 131 137 139 149
package com.jiao.struct;

import javax.xml.transform.Source;

public class TextDemo01 {
    //打印5行的三角形
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) {
            for (int j = 5; j >=  i; j--) {
                System.out.print(" ");
            }
            for (int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            for (int j = 1; j < i; j++) {
                System.out.print("*");

            }
            System.out.println();
        }
    }
}
输出
     *
    ***
   *****
  *******
 *********

3.5 随机数

3.5.1 产生一个随机数

package com.sesameseed.random;

import java.util.Random;

public class RandomDemo {
    public static void main(String[] args) {
        // 2、创建一个Random对象,用于生成随机数。
        Random r1 = new Random();
        for (int i = 1;i <= 20;i++) {
            int data = r1.nextInt(10);
            System.out.println(data);
        }
        System.out.println("=======0~10的随机数=========");
        for (int i = 1;i <= 20;i++) {
            // 3、调用Random提供的功能:nextInt得到随机数。
            int data2 = r1.nextInt(10) + 1;
            System.out.println(data2);
        }

        System.out.println("=======0~20的随机数=========");
        for (int i = 1;i <= 20;i++) {
            int data2 = r1.nextInt(10) + 11;
            System.out.println(data2);
        }
    }
}

3.5.2 猜数字小游戏

package com.sesameseed.random;

import java.util.Random;
import java.util.Scanner;

public class RandomTest {
    public static void main(String[] args) {
        // 1、随机产生一个1-100之间的数据,做为中奖号码。
        Random r = new Random();
        int lukyNum = r.nextInt(100) + 1;

        // 2、定义一个死循环,让用户不断的猜测数据
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请输入您猜测的数据");
            int guessNum = sc.nextInt();
            if (guessNum > lukyNum){
                System.out.println("猜大了");
            } else if (guessNum < lukyNum){
                System.out.println("猜小了");
            } else {
                System.out.println("成功");
                break;
            }
            sc.close(); //凡是属于IO(输入、输出)流的类如果不关闭会一直占用资源
        }
    }
}

Day04: Java数组

数组就是一个容器,用来存同种类型的数据的
比如:要存储 “牛二“,“西门“,“全蛋“ 这些数据。
String[] names = {"牛二", "西门", "全蛋"};

4.1 认识数组

数组就是一个容器,用来存一批同种类型的数据的。

int[] array = {20,10,80,60,90};
//比如:想要存储 20,10,80,60,90 这些数据。 我们可以把代码写成这样

4.2 数组的定义和访问

4.2.1静态初始化

语法简化格式:数据类型[ ] 变量名 = {元素1,元素2,元素3};

//定义数组,用来存储多个年龄
int[] ages = {12, 24, 36}

4.2.2 数组的动态初始化

格式如下:
int[] arr = new int[3]; //数据类型[] 数组名 = new 数据类型[长度];

注意:
使用动态初始化定义数组时,根据元素类型不同,默认值也有所不同。
在这里插入图片描述
数组动态初始化案例

package com.sesameseed.array;

public class ArrayDemo4 {
    public static void main(String[] args) {
        //TODO 动态初始化数组
        //1.数据类型[] 数组名 = new 数据类型[长度]
        int[] ages = new int[3];
        System.out.println(ages[0]);
        System.out.println(ages[1]);
        System.out.println(ages[2]);

        ages[0]  = 11;
        ages[1]  = 22;
        ages[0]  = 33;

        System.out.println(ages[0]);
        System.out.println(ages[1]);
        System.out.println(ages[2]);

        System.out.println("=====其他数据类型元素默认值=====");
        char[] ch1 = new  char[3]; //char的默认值0
        System.out.println((int) ch1[0]);
        System.out.println((int) ch1[1]);
        System.out.println((int) ch1[2]);

        double[] d1 = new double[3]; //double的默认值0
        System.out.println((int) d1[0]);
        System.out.println((int) d1[1]);
        System.out.println((int) d1[2]);

        String[] s1 = new String[3]; //String的默认值null
        System.out.println(s1[0]);
        System.out.println(s1[1]);
        System.out.println(s1[2]);

        boolean[] b1 = new boolean[3]; //boolean的默认值false
        System.out.println(b1[0]);
        System.out.println(b1[1]);
        System.out.println(b1[2]);

    }
}

4.3 内存分析

在这里插入图片描述

在这里插入图片描述
注意:

基本数据类型储存的是变量引用数据(如:string)类型储存的是地址(Unicode编码表)

4.4 数组在计算机中的执行原理

Java Study Notes_Design in 2023(Day01~Day14)_第8张图片
注意:

  • a是一个变量,在栈内存中,a变量中存储的数据就是10这个
  • arr也是一个变量,在栈中,存储的是数组对象在堆内存中的地址值

4.5 多个变量指向同一个数组的问题

public class ArrayDemo2 {
    public static void main(String[] args) {
        // 目标:认识多个变量指向同一个数组对象的形式,并掌握其注意事项。
        int[] arr1 = {11, 22, 33};

        // 把int类型的数组变量arr1赋值给int类型的数组变量arr2
        int[] arr2 = arr1;

        System.out.println(arr1);
        System.out.println(arr2);

        arr2[1] = 99;
        System.out.println(arr1[1]);

        arr2 = null; // 拿到的数组变量中存储的值是null
        System.out.println(arr2);

        //System.out.println(arr2[0]);
        //System.out.println(arr2.length);
    }
}

关注这一段代码Java Study Notes_Design in 2023(Day01~Day14)_第9张图片
Java Study Notes_Design in 2023(Day01~Day14)_第10张图片
Java Study Notes_Design in 2023(Day01~Day14)_第11张图片

4.6 数组练习

4.6.1 数组求最值

package com.sesameseed.TestDemo;

public class TestDemo1 {
    public static void main(String[] args) {
//        TODO 定义一个int类型数组,求数组中元素的最大值,并打印最大值
        int[] faceScores = {15, 9000, 10000, 20000, 9500, -5};

        // 2、定义一个变量用于最终记住最大值
        int max1 = faceScores[0];

        // 3、从数组的第二个位置开始遍历。
        for (int i = 1; i < faceScores.length; i++) {
            // i = 1  2  3  4  5
            // 判断一下当前遍历的这个数据,是否大于最大值变量max存储的数据,
            //如果大于,当前遍历的数据需要赋值给max
            if (faceScores[i] >max1){
                max1 = faceScores[i];
            }
        }
        System.out.println("最大值" + max1);
    }
}

4.6.2 数组存取用户数据进行随机排名

package com.sesameseed.TestDemo;

import java.util.Random;
import java.util.Scanner;

public class TestDemo5 {
    public static void main(String[] args) {
        //TODO 随机排名
        // 1、定义一个动态初始化的数组用于存储5名员工的工号
        int[] codes = new int[5];

        // 2、提示用户录入5名员工的工号。
        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < codes.length; i++) {
            System.out.println("请你输入当前第" + (i + 1) + "员工编号");
            int code = sc.nextInt();
            codes[i] = code;
        }

        // 3、打乱数组中的元素顺序。
        // [12, 33, 54, 26, 8]
        //  i       index
        Random r = new Random();
        for (int i = 0; i < codes.length; i++) {
            // codes[i]
            // 每遍历到一个数据,都随机一个数组索引范围内的值。
            //然后让当前遍历的数据与该索引位置处的值交换。
            int index = r.nextInt(codes.length);
            // 定义一个临时变量记住index位置处的值
            int temp = codes[index];
            // 把i位置处的值赋值给index位置处
            codes[index] = codes[i];
            // 把index位置原来的值赋值给i位置处
            codes[i] = temp;
        }

        // 4、遍历数组中的工号输出即可
        for (int i = 0; i < codes.length; i++) {
            System.out.print(codes[i] + " ");
        }
    }
}

4.6.3 冒泡排序

package com.sesameseed.TestDemo;

import java.util.Arrays;

public class TestDemo2 {
    public static void main(String[] args) {
        int[] a = {1,54,5,8,99,58};

        int[] sort = sort(a); //调用完我们自己写的排序方法以后,返回一个排序后的数组

        System.out.println(Arrays.toString(sort));


    }

    //冒泡排序
    //1、比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
    //2、每一次比较,都会产生出一个最大,或者最小的数字
    //3、下一轮这可以少一排序
    //4、依次循环直到结束
    public static int[] sort(int[] array) {
        //临时变量
        int temp ;


        //外层循环,判断我们这个要走多少次
        for (int i = 0; i < array.length-1; i++) {
            //内层循环,比较判断两个数,如果第一个数比第二个数大,则交换位置
            for (int j = 0; j < array.length-1-i; j++) {
                if (array[j+1] > array[j]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
        }
        return array;
    }
}

4.6.4 数组元素反转

package com.sesameseed.TestDemo;

public class TestDemo3 {
    public static void main(String[] args) {
        //TODO 数组元素反转

        int[] arr1 = {10, 20, 30, 5, 3};
        for (int i = 0, j = arr1.length - 1; i < j; i++, j--) {
            // 1、定义一个临时变量记住后一个位置处的值
            int temp = arr1[j];
            // 2、把前一个位置处的值赋值给后一个位置了
            arr1[j] = arr1[i];
            // 3、把临时变量中记住的后一个位置处的值赋值给前一个位置处
            arr1[i] = temp;
        }

        // 3、遍历数组中的每个数据,看是否反转成功了
        for (int i = 0; i < arr1.length; i++) {
            System.out.print(arr1[i] + " ");
        }
    }
}

4.7 Debug调试

第一步:打断点,如下图的红色小圆点
第二步:右键Debug方式启动程序
启动后,代码会停留在打断点的这一行
第三步:点击箭头按钮,一行一行往下执行

Day05: 方法

方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用。

5.1 方法概述

Java Study Notes_Design in 2023(Day01~Day14)_第12张图片

package com.sesameseed.method;

public class MethonDemo1 {
    public static void main(String[] args) {
        //TODO 掌握定义方法的完整格式

        //调用方法
        int rs = sum(10,20);
        System.out.println("和是:" + rs);
    }
    //定义方法
    public  static int sum(int a ,int b){
        int c = a + b;
        return c;
    }
}

5.2 方法的定义

Java Study Notes_Design in 2023(Day01~Day14)_第13张图片在这里插入图片描述

5.3 方法在计算机中的执行原理

5.3.1 有返回值的方法,内存分析

package com.sesameseed.method;

public class TestDemo1 {

    //TODO 有返回值,可以直接调用
    public static void main(String[] args) {
        int count1 = paperCount(0.1,8848000);
        System.out.println(count1);

    }
    public static int paperCount(double paperWidth,double mountainHeig){
        int count = 0;
        while (paperWidth < mountainHeig){
            paperWidth *= 2;
            count++;
        }
        return  count;
    }
}

在这里插入图片描述

5.3.2 无返回值的方法,内存分析

package com.sesameseed.method;

public class TestDemo2 {
    //TODO 无返回值语法格式,不能调用,在方法中要打印输出
    public static void main(String[] args) {
        paperCount(0.1,8848000);


    }
    public static void paperCount(double paperWidth,double mountainHeig){
        int count = 0;
        while (paperWidth < mountainHeig){
            paperWidth *= 2;
            count++;
        }
        System.out.println(count);
    }
}

在这里插入图片描述

5.4 方法参数的传递机制

5.4.1 方法参数传递是基本类型数据,内存执行原理

Java Study Notes_Design in 2023(Day01~Day14)_第14张图片

Java的参数传递机制都是:值传递,传递的是实参存储的值的副本。

5.4.2 参数是引用类型,实际上也是值传递,只不过参数传递存储的地址值

Java Study Notes_Design in 2023(Day01~Day14)_第15张图片
总结一下:

基本类型和引用类型的参数在传递的时候有什么不同?
都是值传递

  • 基本类型的参数传递存储的数据值。
  • 引用类型的参数传递存储的地址值。

5.4.3 方法参数传递案例1

public class MethodTest3 {
    public static void main(String[] args) {
        // 目标:完成打印int类型的数组内容。
        int[] arr = {10, 30, 50, 70};
        printArray(arr);

        int[] arr2 = null;
        printArray(arr2);

        int[] arr3 = {};
        printArray(arr3);
    }

    /*
    	参数:int[] arr表示要被打印元素的数组,需要调用者传递
    */
    public static void printArray(int[] arr){
        if(arr == null){
            System.out.println(arr); // null
            return; // 跳出当前方法
        }

        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("]");
    }
}

5.5 方法重载

重载指:一个类中,出现多个相同方法名,但它们的形参列表不同叫方法重载

5.5.1 方法重载案例一

package com.jiao.method;

public class Demo02 {
    public static void main(String[] args) {
        int max = max(10, 20);
        System.out.println(max);

    }

    //比大小
    public static int max(int num1,int num2){

        int result = -1;
        if (num1 == num2){
            System.out.println("num1 == num2");
            return 0; //终止方法
        }
        if (num1 > num2){
            result = num1;
        }else {
            result = num2;
        }
        return result;
    }
    public static double max(double num1,double num2){

        double result = -1;
        if (num1 == num2){
            System.out.println("num1 == num2");
            return 0; //终止方法
        }
        if (num1 > num2){
            result = num1;
        }else {
            result = num2;
        }
        return result;
    }
}


5.5.2 方法重载案例二

package com.sesameseed.parameter;

public class MethodOverDemo1 {
    public static void main(String[] args) {
        //方法重载
        fire();
        fire("岛国2");
        fire("米国",999);
    }
    public static void fire(){
        fire("岛国");
    }
    public static void fire(String country){
        fire(country,1);

    }
    public static void fire(String country,int number){
        System.out.println("发射了" + number + "枚武器给" + country);
        //发射了1枚武器给岛国
        //发射了1枚武器给岛国2
        //发射了999枚武器给米国
    }
}

5.6 return单独使用

return跳出当前方法

package com.sesameseed.returndemo;

public class ReturnDemo1 {
    public static void main(String[] args) {
    //TODO return跳出当前方法
        System.out.println("开始");
        chu(10,0);
        System.out.println("结束");
    }
    public static void chu(int a, int b){
        if (b == 0){
            System.out.println("您的数据有误,不执行");
            return; // 直接跳出并结束当前chu方法的执行
        }
        int c = a / b;
        System.out.println("除法结果是:" + c);
    }
}
//开始
//您的数据有误,不执行
//结束

Day06: Java编程案例思维训练

6.1 完成买飞机票的案例

package com.sesameseed.testdemo;

import java.util.Scanner;

public class Test1 {
    public static void main(String[] args) {
        // TODO:完成买飞机票的案例。
        System.out.println("获取实付价:");
        Scanner sc = new Scanner(System.in);
        int price = sc.nextInt();

        System.out.println("获取月份:");
        Scanner sc2 = new Scanner(System.in);
        int month = sc2.nextInt();

        System.out.println("获取舱机类型:");
        Scanner sc3 = new Scanner(System.in);
        String type = sc3.nextLine();
//        switch (type){
//            case "1":
//                System.out.println("经济舱");
//        } 通过switch对应数字实现对经济头等舱的选择

        double fanalP = calculate(price,month,type);
        //double fanalP= calculate(1000,12,"头等舱");
        System.out.println("最终优惠价:" + fanalP);
    }
    public static double calculate(double price,int month,String type){
        if (month >= 5 && month <= 10){
            switch (type){
                case "头等舱":
                    price *= 0.9;
                    break;
                case "经济舱":
                    price *= 0.85;
                    break;
            }
        }else {
            switch (type){
                case "头等舱":
                    price *= 0.7;
                    break;
                case "经济舱":
                    price *= 0.65;
                    break;
            }
        }
        return price;
    }
}

6.2 完成生成随机验证码

package com.sesameseed.testdemo;

import java.util.Random;

public class Test2 {
    public static void main(String[] args) {
        //TODO 目标:完成生成随机验证码。
        System.out.println(getCode(3));
    }
    public static String getCode(int n){
        String getcode = "";
        Random r = new Random();
        for (int i = 0; i <= n; i++) {
            int num = r.nextInt(3);
            switch (num){
                case 0:
                    getcode += r.nextInt(10);
                    break;
                case 1:
                    char ch1 = (char)(r.nextInt(26) + 65);
                    getcode += ch1;
                    break;
                case 2:
                    char ch2 = (char) (r.nextInt(26)+97);
                    getcode += ch2;
                    break;
            }
        }
        return getcode;
    }
}

Day07:Java面向对象基础

对象实质上是一种特殊的数据结构,一句话总结,对象其实就是一张数据表,表当中记录什么数据,对象就处理什么数据。
Java Study Notes_Design in 2023(Day01~Day14)_第16张图片

7.1 对象在计算机中的执行原理

Java Study Notes_Design in 2023(Day01~Day14)_第17张图片
说明:

  • Student s1表示的是在栈内存中,创建了一个Student类型的变量,变量名为s1
  • new Student()会在堆内存中创建一个对象,而对象中包含学生的属性名和属性值
  • 同时系统会为这个Student对象分配一个地址值0x4f3f5b24
  • 接着把对象的地址赋值给栈内存中的变量s1,通过s1记录的地址就可以找到这个对象
  • 当执行s1.name=“播妞”时,其实就是通过s1找到对象的地址,再通过对象找到对象的name属性,再给对象的name属性赋值为播妞;

7.2 类和对象的一些注意事项

Java Study Notes_Design in 2023(Day01~Day14)_第18张图片

7.3 this关键字

哪一个对象调用方法方法中的this就是哪一个对象
Java Study Notes_Design in 2023(Day01~Day14)_第19张图片

7.4 构造器

什么是构造器?

构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相同**。

构造器的特点?
new 对象就是在执行构造方法 !!!

在创建对象时,会调用构造器。也就是说 new Student()就是在执行构造器,当构造器执行完了,也就意味着对象创建成功。
当执行new Student("播仔",99)创建对象时,就是在执行有参数构造器,当有参数构造器执行完,就意味着对象创建完毕了。

7.5 封装性

封装,就是用类设计对象处理某一个事物的数据时,把要处理的数据,处理数据的方法,设计到一个对象中。
合理隐藏、合理暴露

7.6 实体JavaBean

需要满足下面的要求
在这里插入图片描述

实体(JavaBean)类特点
1、实体(JavaBean)类用来封装数据,只提供对数据进行存和取的方法
2、必须私有成员变量,并为每个变量通提供get、 set方法

案例一:

package com.sesameseed.javabean;

public class Student {

    //实体类(JavaBean)特点:用来封装数据,只提供对数据进行存和取的方法
    //1.必须私有成员变量,并为每个变量通提供get set方法
    private String name;
    private double score;

//    3.建议为类提供一个公开的有参数构造器给别人调用,公共的无参构造器,设计示例要求
    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }

    //2.必须为类提供一个公开的无参数构造器
    public Student() {
    }

    public String getName() { //调用get方法,需要次方法传输数据
        return name;
    }

    public void setName(String name) { //调用set方法,需要次方法接受数据
        this.name = name;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

7.6.1 实体类案例一

在这里插入图片描述

7.6.2 面向对象综合案例

Movie对象封装类

package com.sesameseed.oop.oopdemo2;

public class Movie {

    //set赋值
    //get取值
    private int id;
    private String name;
    private double price;
    private double score;
    private String director;
    private String actor;
    private String info;

    //公共的无参构造器,设计示例要求
    public Movie() {
    }

    //公共的有参构造器,方便创建对象赋值
    public Movie(int id, String name, double price, double score, String director, String actor, String info) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.score = score;
        this.director = director;
        this.actor = actor;
        this.info = info;
    }

    public int getId() { //get取值
        return id;
    }

    public void setId(int id) { //set赋值
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public String getDirector() {
        return director;
    }

    public void setDirector(String director) {
        this.director = director;
    }

    public String getActor() {
        return actor;
    }

    public void setActor(String actor) {
        this.actor = actor;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

MovieOperator 操作类

package com.sesameseed.oop.oopdemo2;

public class MovieOperator {
    private Movie[] movies; //定义一个电影类型的数组

    public MovieOperator(Movie[] movies){
        //因为系统中有多部电影,所以电影操作类中,需要有一个Movie的数组
        this.movies = movies;
    }

//    1、展示系统全部电影信息 movies = [m1, m2, m3, ...]
    public void printAllMovies(){
        System.out.println("==系统全部信息如下==");
        for (int i = 0; i < movies.length; i++) {
            Movie m = movies[i];
            System.out.println("编号" + m.getId());
            System.out.println("名称" + m.getName());
            System.out.println("价格" + m.getPrice());
            System.out.println("==========");
        }
    }

//    2、根据电影的编号查询出该电影的详细信息并展示
    public void searchMovieById(int id){ //展示信息,不用返回
        for (int i = 0; i < movies.length; i++) {
            Movie m = movies[i]; //遍历电影中每个对象,用变量m记住
            if (m.getId() == id){
                System.out.println("已查询到该电影,该电影的信息如下");
                System.out.println(m.getId());
                System.out.println(m.getName());
                System.out.println(m.getScore());
                System.out.println(m.getDirector());
                System.out.println(m.getActor());
                System.out.println(m.getInfo());
                return;
            }
        }
        System.out.println("无此电影");
    }

    //    2、根据电影的名称查询出该电影的详细信息并展示
    public void searchMovieByName(String name){
        for (int i = 0; i < movies.length; i++) {
            Movie m = movies[i]; //遍历电影中每个对象,用变量m记住
//            if (m.getName() == name){
            if (m.getName().equals(name)){
                System.out.println("已查询到该电影,该电影的信息如下");
                System.out.println(m.getId());
                System.out.println(m.getName());
                System.out.println(m.getScore());
                System.out.println(m.getDirector());
                System.out.println(m.getActor());
                System.out.println(m.getInfo());
                return;
            }
        }
        System.out.println("无此电影");
    }
}

Test测试类

package com.sesameseed.oop.oopdemo2;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Movie[] m = new Movie[4];
        //调用公共的有参构造器
        Movie m1 = new Movie(1,"水门桥", 38.9, 9.8, "徐克", "吴京","12万人想看");
        Movie m2 = new Movie(2, "出拳吧", 39, 7.8, "唐晓白", "田雨","3.5万人想看");
        Movie m3 = new Movie(3,"月球陨落", 42, 7.9, "罗兰", "贝瑞","17.9万人想看");
        Movie m4 = new Movie(4,"一点就到家", 35, 8.7, "许宏宇", "刘昊然","10.8万人想看");
        m[0] = m1;
        m[1] = m2;
        m[2] = m3;
        m[3] = m4;
        MovieOperator movieOperator = new MovieOperator(m);
//        movieOperator.printAllMovies();
//        movieOperator.searchMovieById(5);
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入命令1.展示全部 2.id查询 3.名称查询");
//            Scanner scanner = new Scanner(System.in); //放置循环外,减少内存占用
            int command = scanner.nextInt();
            switch (command){
                case 1:
                    System.out.println("全部信息如下");
                    movieOperator.printAllMovies();
                    break;
                case 2:
                    System.out.println("输入影片id信息");
                    int i = scanner.nextInt();
                    movieOperator.searchMovieById(i);
                    break;
                case 3:
                    System.out.println("输入影片名称信息");
                    String s =  scanner.next();
                    movieOperator.searchMovieByName(s);
                    break;
                default:
                    System.out.println("无此操作");
            }
        }
    }
}

7.7 成员变量和局部变量的区别

Java Study Notes_Design in 2023(Day01~Day14)_第20张图片
在这里插入图片描述

Day08: Java常用API

8.1 String类

string 的指针从0开始,它是有下标的!

package com.sesameseed.string;

public class Demo2 {
    public static void main(String[] args) {
        //TODO 快速熟悉String提供的处理字符串的常用方法。
        String s1 = "sdas小明";

        // 1、获取字符串的长度
        System.out.println(s1.length());

        // 2、提取字符串中某个索引位置处的字符
        System.out.println(s1.charAt(2));

        // 字符串的遍历
        for (int i = 0; i < s1.length(); i++) {
            char c1 = s1.charAt(2);
            System.out.println(c1);
        }

        // 3、把字符串转换成字符数组,再进行遍历
        char[] c2 = s1.toCharArray();
        for (int i = 0; i < c2.length; i++) {
            System.out.println(c2[i]);
        }

        //4、判断字符串内容,内容一样就返回true
//        String s2 = new String("54sdaA");
//        String s3 = new String("54sdaA");
        String s2 ="54sdaA";
        String s3 = "54sdaA";
        //true 解释:都是在一个容器内创建,此种方式在字符串常量池中进行创建,第二次创建,跟字符串常量池进行比较,如果有直接饮用

        System.out.println(s2 == s3);
        //false 解释:
        System.out.println(s2.equals(s3)); //true

        // 5、忽略大小写比较字符串内容
        String s4 ="54sdaa";
        String s5 = "54sdaA";
        System.out.println(s4.equals(s5)); //false
        System.out.println(s4.equalsIgnoreCase(s5)); //true

        // 6、截取字符串内容 (包前不包后的)
        String s7 = s1.substring(0,2);
        System.out.println(s7);

        // 7、从当前索引位置一直截取到字符串的末尾
        String s6 = s1.substring(2);
        System.out.println(s6);

        // 8、把字符串中的某个内容替换成新内容,并返回新的字符串对象给我们
        String trans = "好垃圾";
        String s8 = trans.replace("垃圾","**");
        System.out.println(s8);
    }
}
package com.sesameseed.string;

import java.util.Random;

public class StringTest2 {
    public static void main(String[] args) {
        //TODO 随机生成验证码
        System.out.println(createCode(4));

    }
    public static String createCode(int n){
        // 2、定义2个变量
        //一个是记住最终产生的随机验证码
        //一个是记住可能用到的全部字符
        String ranCode = "";
        String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        Random r1 = new Random(); // 3、开始定义一个循环产生每位随机字符
        for (int i = 0; i < n; i++) { //循环n次产生n个随机数
            int index = r1.nextInt(data.length()); // 4、随机一个字符范围内的索引。
            ranCode += data.charAt(index); // 2、提取字符串中某个索引位置处的字符
        }
        return ranCode;
    }
}

8.2 ArrayList类

package com.sesameseed.arraylist;

import java.util.ArrayList;

public class Demo2 {
    public static void main(String[] args) {
        //1.创建一个ArrayList的集合对象
        ArrayList<String> list = new ArrayList<>();
        list.add("第一个");
        list.add("第二个");
        list.add("第三个");
        System.out.println(list); //[第一个, 第二个, 第三个]

        // 2、往集合中的某个索引位置处添加一个数据
        list.add(1,"mysql");
        System.out.println(list); //[第一个, mysql, 第二个, 第三个]

        // 3、根据索引获取集合中某个索引位置处的值
        String st1 = list.get(1);
        System.out.println(st1); //mysql

        // 4、获取集合的大小(返回集合中存储的元素个数)
        System.out.println(list.size()); //4

        // 5、根据索引删除集合中的某个元素值,会返回被删除的元素值给我们
        System.out.println(list.remove(1));
        System.out.println(list); //[第一个, 第二个, 第三个]

        // 6、直接删除某个元素值,删除成功会返回true,反之
        System.out.println(list.remove("java")); //false
        System.out.println(list); //[第一个, 第二个, 第三个]

        // 默认删除的是第一次出现的数据的
        list.add("第一个");
        System.out.println(list); //[第一个, 第二个, 第三个, 第一个]
        System.out.println(list.remove("第一个")); //true 删除成功
        System.out.println(list); //[第二个, 第三个, 第一个]

        // 7、修改某个索引位置处的数据,修改后会返回原来的值给我们
        System.out.println(list.set(1,"修改后的第三个")); //第三个
        System.out.println(list); //[第二个, 修改后的第一次, 第一个]
    }
}
package com.sesameseed.arraylist;


import java.util.ArrayList;

public class Demo1 {
    public static void main(String[] args) {
        //TODO 删除指定元素
        ArrayList<String> l1 = new ArrayList<>();// 1、创建一个ArrayList的集合对象
        l1.add("枸杞");
        l1.add("Java入门");
        l1.add("宁夏枸杞");
        l1.add("黑枸杞");
        l1.add("人字拖");
        l1.add("枸杞子");
        System.out.println(l1);

        // 2、开始完成需求:从集合中找出包含枸杞的数据并删除它
//        for (int i = 0; i < l1.size(); i++) {
//            String del = l1.get(i);
//            if (del.contains("枸杞")){
//                l1.remove(i);
//                i--; //处理每次元素删除,元素重新前移,不能删除成功 bug
//            }
//        }

        for (int i = l1.size() - 1; i >= 0; i--) {
            String del = l1.get(i);
            if (del.contains("枸杞")){ // 9、contains关键字判断字符串中是否包含某个关键字
//                l1.remove(i);//使用索引删除
//                l1.remove(i);//使用指定元素删除??????
            }
        }
        System.out.println(l1);
    }
}

Day09: Java基础项目(ATM系统)

package com.sesameseed.atm;

public class Account {
    /*
    * 有无参构造:
    * 为外部类调用方法提供接口
    * construction构造器:同理
    * */

    //封装相关对象
    private String carID;
    private String userName;
    private char sex;
    private String pwd;
    private double money;
    private double limit; //限制

    public String getCarID() {
        return carID;
    }

    public void setCarID(String carID) {
        this.carID = carID;
    }

    public String getUserName() {
//        return userName;
        return userName + (sex == '男' ? "先生" : "女士");
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public double getLimit() {
        return limit;
    }

    public void setLimit(double limit) {
        this.limit = limit;
    }

    public Account() {
    }

    public Account(String carID, String userName, char sex, String pwd, double money, double limit) {
        this.carID = carID;
        this.userName = userName;
        this.sex = sex;
        this.pwd = pwd;
        this.money = money;
        this.limit = limit;
    }
}

package com.sesameseed.atm;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class ATM {
    //优化代码
    //定义在全局变量方便所有方法调用
    //scanner定义在全局变量,这样就不用每次都创建一个扫描器
    private ArrayList<Account> accounts = new ArrayList<>();
    Scanner sc1 = new Scanner(System.in);
    private Account loginAcc; //记住登录后的用户账户

    //开始界面方法
    public void start() {
        while (true) {
            System.out.println("==欢迎登录ATM系统==");
            System.out.println("1.用户登录");
            System.out.println("2.用户开户");
            System.out.println("3.退出系统");
            System.out.println("请选择:");
//        Scanner sc1 = new Scanner(System.in);//放置全局变量处,方便全部方法调用
            int command = sc1.nextInt();
            switch (command) {
                case 1:
                    //1.调用用户登录方法
                    login();
                    break;
                case 2:
                    //2.用户开户
                    createAccount();
                    break;
                case 3:
                    //3.退出系统
                    return;
                default:
                    System.out.println("没有此操作");
                    break;
            }
        }
    }

    //账户开户方法
    public void createAccount() {
        System.out.println("==账户开户操作==");
        Account acc = new Account();
        System.out.println("请输入你的账户名:");
        String name = sc1.next();
        acc.setUserName(name);
        while (true) {
            System.out.println("==请输入您的性别==");
            String st1 = sc1.next();
            char sex = st1.charAt(0);
//            char sex = sc1.next().charAt(0);
            if (st1.length() == 1 && (sex == '男' || sex == '女')) {
                acc.setSex(sex);
                break;
            } else {
                System.out.println("输入只能是男、女,请重新输入");
            }
        }
        while (true) {
            System.out.println("请输入账户密码");
            String pwd = sc1.next();
            System.out.println("请再次输入密码");
            String retpwd = sc1.next();

            //密码校验
            if (pwd.equals(retpwd)) {
                acc.setPwd(retpwd);
                break;
            } else {
                System.out.println("输入不一致,请重新输入");
            }
        }
        System.out.println("请输入您的取现额度");
        double limit = sc1.nextDouble();
        acc.setLimit(limit);

        String newCarId = createCarId();
        acc.setCarID(newCarId);

        accounts.add(acc);
        System.out.println("恭喜您" + acc.getUserName() + "开户成功,你的卡号是:" + acc.getCarID());
    }

    //生成卡号方法
    private String createCarId() {
        while (true) {
            // 1、使用循环,循环8次,每次产生一个随机数给cardId连接起来
            Random r = new Random();
            // 2、定义一个String类型的变量记住8位数字作为一个卡号
            String cardId = "";
            for (int i = 0; i < 8; i++) {
                int data = r.nextInt(10);
                cardId += data;
            }
            // 3、判断cardId中记住的卡号,是否与其他账户的卡号重复了,没有重复,才可以做为一个新卡号返回。
            Account acc = getAccountByCardId(cardId);
            if (acc == null) {
                // 说明cardId没有找到账户对象,因此cardId没有与其他账户的卡号重复,可以返回它做为一个新卡号
                return cardId;
            }
        }
    }

    //判断卡号是否存在的方法
    private Account getAccountByCardId(String cardId) {
        for (int i = 0; i < accounts.size(); i++) {
            Account acc = accounts.get(i);
            if (acc.getCarID().equals(cardId)) {
                return acc;
            }
        }
        return null;
    }

    //登录方法
    private void login() {
        System.out.println("系统登录");
        //1.判断系统中是否有账户对象,存在才能登录,不存在,结束登录
        if (accounts.size() == 0) {
            System.out.println("当前无账户,请开户");
            return;
        }
        //2.系统中存在账户,可以登陆
        while (true) {
            System.out.println("请输入您的卡号");
            String carId = sc1.next();
            //调用getAccountByCardId 通过地址值,判断账户对象中是否有此账户
            Account acc = getAccountByCardId(carId);
            if (acc == null) {
                System.out.println("无此卡号,请确认");
            } else {
                while (true) {
                    System.out.println("请您输入密码");
                    String pwd = sc1.next();
                    if (acc.getPwd().equals(pwd)) {
                        System.out.println("恭喜您," + acc.getUserName() + "成功登录系统,您的卡号是:" + acc.getCarID());
//                        System.out.println("i am here");

                        loginAcc = acc;//为了在其他任何地方调用,使用acc变量,将acc变量变为成员变量loginAcc
                        //调用展示用户登录页面方法
                        showUserCommand();
                        return;//调用并结束当前登录方法
                    } else {
                        System.out.println("您输入的密码不正确,请确认");
                    }
                }
            }
        }
    }

    //展示用户登录页面
    private void showUserCommand() {
        while (true) {
//            System.out.println("i am here");
            System.out.println(loginAcc.getUserName() + "您可以选择如下功能进行账户的处理");
            System.out.println("1.查询账户");
            System.out.println("2.存款");
            System.out.println("3.取款");
            System.out.println("4.转账");
            System.out.println("5.密码修改");
            System.out.println("6.退出");
            System.out.println("7.注销当前账户");
            System.out.println("请选择");
            int command = sc1.nextInt();
            switch (command) {
                case 1:
                    //                1.查询账户
                    showLoginAccount();
                    break;
                case 2:
                    //                2.存款
                    saveMoney();
                    break;
                case 3:
                    //                3.取款
                    drawMoney();
                    break;
                case 4:
                    //                4.转账
                    transmoney();
                    break;
                case 5:
                    //                5.密码修改
                    updatePwd();
                    return;
                case 6:
                    System.out.println(loginAcc.getUserName() + "您退出成功!");
                    //                6.退出
                    return;
                case 7:
                    //                7.注销当前账户
                    if (delectAccount()){
                        return;
                    }
                    break;
                default:
                    System.out.println("不存在次操作请重新输入");
            }
        }
    }

    //密码修改
    private void updatePwd() {
        System.out.println("账户密码修改操作");
        while (true) {
            //1.提醒用户认证当前密码
            System.out.println("请输入当前账户密码");
            String pwd = sc1.next();
            //验证当前密码是否正确
            if (loginAcc.getPwd().equals(pwd)){
                while (true){
                    //当前密码正确
                    System.out.println("请输入新密码");
                    String newPwd = sc1.next();
                    System.out.println("请再次输入新密码");
                    String okPwd = sc1.next();
                    //判断两次输入的密码是否一致
                    if (okPwd.equals(newPwd)){
                        loginAcc.setPwd(okPwd);
                        System.out.println("密码修改成功");
                        return;
                    }else {
                        System.out.println("您输入的两次密码不一致");
                    }
                }
            }else {
                //当前密码不正确
                System.out.println("您当前输入密码不正确");
            }
        }
    }

    //销户
    private boolean delectAccount() {
        System.out.println("进行销户操作");
        //1.询问用户是否确定销户
        System.out.println("请问确认销户吗?y/n");
        String command = sc1.next();
        switch (command){
            case "y":
                //2.确实要销户
                //判断用户账户是否有钱
                if (loginAcc.getMoney() == 0){
                    accounts.remove(loginAcc);
                    System.out.println("销户成功");
                    return true;
                }else {
                    System.out.println("您的账户存在余额,不能销户");
                    return false;
                }
            default:
                System.out.println("好的,账户保留");
                return false;
        }
    }

    //转账
    private void transmoney() {
        System.out.println("用户转账");
        //判断系统中是否存在其他账户
        if (accounts.size() < 2){
            System.out.println("一个账户,不能转账");
            return;

            //判断自己账户是否有钱
        }else if (loginAcc.getMoney() == 0){
            System.out.println("金额不足");
            return;
        }
        //判断自己是否有钱
        if (loginAcc.getMoney()  == 0){
            System.out.println("你没钱了");
            return;
        }
        //开始转账
        while (true) {
            System.out.println("请输入对方的卡号");
            //扫描器,得到对方卡号
            String cardId = sc1.next();
            Account acc = getAccountByCardId(cardId); //把getAccountByCardId相关对象的信息赋值给Account这个变量类型
            if (acc == null){
                System.out.println("对方的卡号不存在");
            }else {
                //对方卡号存在,继续让用户认证姓氏
                String name = "*" + acc.getUserName().substring(1);
                System.out.println("请输入【" + name + "】的姓氏");
                String preName = sc1.next();
                if (acc.getUserName().startsWith(preName)){
                    while (true){
                        System.out.println("请输入转账金额");
                        double money = sc1.nextDouble();
                        //判断这个金额是否超过自己的余额
                        if (loginAcc.getMoney() >= money){
                            loginAcc.setMoney(loginAcc.getMoney() - money);
                            acc.setMoney(acc.getMoney() + money); //acc为对方的相关信息,因此可以完成对方账户的转账操作
                            System.out.println("转账成功");
                            return;
                        }else {
                            System.out.println("余额不足,最多可转" + loginAcc.getMoney());
                        }
                    }
                }
            }
        }
    }

    //取钱
    private void drawMoney() {
        System.out.println("取钱操作");
        if (loginAcc.getMoney() < 100){
            System.out.println("余额不足100,禁止取钱");
            return;
        }
        while (true) {
            System.out.println("请输入取款金额");
            double money = sc1.nextDouble();
/*//        if (loginAcc.getMoney() >= money || money > loginAcc.getLimit()){
        if (loginAcc.getMoney() >= money) {
            if (money > loginAcc.getLimit()) {
                System.out.println("取款超过限额,每次最多可取" + loginAcc.getMoney());
            } else {
                loginAcc.setMoney(loginAcc.getMoney() - money);
                System.out.println("取款" + money + "成功,余额:" + loginAcc.getMoney());
                return;
            }
        }
        else {
            System.out.println("余额不足,您的账户余额是" + loginAcc.getMoney());
        }
    }*/

            if (loginAcc.getMoney() <= money && money > loginAcc.getLimit()) {
                System.out.println("取款超过限额,每次最多可取" + loginAcc.getMoney());
            } else {
                loginAcc.setMoney(loginAcc.getMoney() - money);
                System.out.println("取款" + money + "成功,余额:" + loginAcc.getMoney());
                return;
            }
            if (money > loginAcc.getMoney()){
                System.out.println("余额不足,您的余额" + loginAcc.getMoney() );
            }
        }
    }

    //存钱
    private void saveMoney() {
        System.out.println("存钱操作");
        System.out.println("请输入存款金额");
        double money = sc1.nextDouble();
        loginAcc.setMoney(loginAcc.getMoney() + money);
        System.out.println("您存款" + money + "成功,当前余额:" + loginAcc.getMoney());
    }

    //展示当前用户所有信息
    private void showLoginAccount() {
        System.out.println("当前账户信息如下");
        System.out.println("卡号:" + loginAcc.getCarID());
        System.out.println("户主:" + loginAcc.getUserName());
        System.out.println("性别:" + loginAcc.getSex());
        System.out.println("余额:" + loginAcc.getMoney());
        System.out.println("每次取现额度:" + loginAcc.getLimit());
    }
}
package com.sesameseed.atm;

public class Test {
    public static void main(String[] args) {
        // TODO ATM系统
        ATM atm = new ATM(); //创建一个ATM对象
        atm.start(); //调用ATM的start方法
    }
}

Day10:面向对象高级

10.1 “static” 关键字

10.1.1 static修饰成员变量

Java中的成员变量按照有无static修饰分为两种:类变量、实例变量
在这里插入图片描述

注意:
由于静态变量是属于类的,只需要通过类名就可以调用:类名.静态变量.
实例变量是属于对象的,需要通过对象才能调用:对象.实例变量

10.1.1.1 static修饰成员变量 案例一

package com.sesameseed.p1_staticdemo.demo2;

public class Student {
    // 类变量
    static String name;

    //实例变量(对象的变量)
    int age;
}

package com.sesameseed.p1_staticdemo.demo2;

public class Test {
    public static void main(String[] args) {
        // 目标:掌握有无static修饰成员变量的用法,特点。
        // 1、类变量的用法。
        // 类名.类变量(推荐)
        Student.name = "李明";
        System.out.println(Student.name);

        // 对象.类变量(不推荐)
        Student student = new Student();
        student.age = 22;
        System.out.println(student.age);
    }
}

10.1.1.2 static修饰成员变量 案例二

package com.sesameseed.p1_staticdemo.demo1;

public class User {
    //类变量:记录变量的创建次数
    public static int number;

    //构造器
    public User(){
        // 如何在自己的类中,获取类变量
        //方式一 :this所在的方法被哪个对象调用,this代表哪个对象
//        this.number++;

        //方式二 类名
        User.number++;  //推荐!!!

        //方式三 就近原则 先在自己所在的位置找,然后再在全局中找
//        User.number++;
    }
}
package com.sesameseed.p1_staticdemo.demo1;

public class Test {
    public static void main(String[] args) {
        //创建4个对象
        User u1 = new User();
        User u2 = new User();
        User u3 = new User();

        //查看系统创建了多少个User对象
        System.out.println(User.number);
    }
}

10.1.2 内存原理

在这里插入图片描述

注意:

  • 1.类变量属于类,在内存中只有一份,用类名调用
  • 2.实例变量属于对象,每一个对象都有一份,用对象调用

10.1.3 static修饰成员方法

有无static也分为两类:类方法、实例方法
在这里插入图片描述
有static修饰的方法,是属于类的,称为类方法;调用时直接用类名调用即可

10.1.3.1 static修饰成员方法案例一

package com.sesameseed.p1_staticdemo.demo3;

public class Student {
    double score;

    //类方法:
    public static void printHelloWorld(){
        System.out.println("Hello World!");
        System.out.println("Hello World!");
    }

    public Student() {
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public Student(double score) {
        this.score = score;
    }

    //实例方法(对象的方法)
    public void printPass(){
        //打印成绩是否合格
        System.out.println(score>=60?"成绩合格":"成绩不合格");
    }
}

package com.sesameseed.p1_staticdemo.demo3;

public class Test {
    public static void main(String[] args) {
        //1.调用Student类中的类方法
        Student.printHelloWorld();

        //2.调用Student类中的实例方法
        Student student = new Student();
        student.setScore(99.0);
        student.printPass();
    }

}

10.1.4 内存分析

  • 1.类方法static修饰的方法,可以被类名调用,是因为它是随着类的加载而加载的。
  • 2.实例方法非static修饰的方法,需要创建对象后才能调用,是因为实例方法中可能会访问实例变量,而实例变量需要创建对象后才存在。

在这里插入图片描述

10.1.5 static的注意事项

在这里插入图片描述

10.2 代码块(匿名、静态)

package com.oop.demo07;

public class Person {

    //2:附初始值
    {
        System.out.println("匿名代码块"); //代码块(匿名代码块)
    }

    //1 只执行一次
    static {
        //代码块(静态代码块)
        System.out.println("静态代码块");
    }

    //3
    public Person() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("====================");
        Person person2 = new Person();
    }
}

10.2 单例设计模式

10.2.1 单例设计模式之饿汉式

单例设计模式(饿汉式)调用对象之前,对象已经创建好了

  • 特点
  • 地址值都一样(单例)
package com.sesameseed.p4_singleinstance;

public class A {
    //TODO 单例设计模式(饿汉式)调用对象之前,对象已经创建好了
    //2.定义一个类变量记住一个对象
    private static A a = new A();

    //1.必须私有类的构造器
    private A(){

    }

    //3.定义一个类方法返回类的对象
    public static A getObject(){
        return a;
    }
}

10.2.2 单例设计模式之懒汉式

package com.sesameseed.p4_singleinstance;

public class B {
    //TODO 单例设计模式(懒汉式)第一次调用对象时,才开始创建对象
    //2.定义一个类变量,用于存放这个类的一个对象
    private static B b; //默认值null

//    1.把类的构造器私有
   private B(){

   }

//   3.定义一个类方法,这个方法保证第一次调用时才创建一次
   public static B getInstance(){
       if (b == null){
           b = new B();
       }
       return b;
   }
}
package com.sesameseed.p4_singleinstance;

public class TestAB {
    public static void main(String[] args) {
        //TODO 掌握单例模式的写法(饿汉式、懒汉式)
        A a1 = A.getObject();
        A a2 = A.getObject();
        System.out.println(a1);
        System.out.println(a2);

        System.out.println("============");

        B b1 = B.getInstance();
        B b2 = B.getInstance();
        System.out.println(b1);
        System.out.println(b2);
    }
}

10.2.3 懒汉式与饿汉式区别

从时间和空间上分析

  • 饿汉式:空间换时间,创建对象时速度更快,但是有可能会造成资源的浪费
  • 懒汉式:时间换时间,创建对象的素的鳗鱼饿汉式,但是可以省空间

从安全性分析

  • 饿汉式,没有线程安全问题
  • 懒汉式,存在线程安全问题,有可能创建多个实例
  • 线程安全问题的解决
  • ① sychronized锁,此实现方案,所有线程在获取实例的时候,不管实例有没有,都需先竞争锁,然后才能获取实例,性能会受影响。
  • ② 双重判断加锁,此实现当有实实例时,就不创建了,性能相对较高。
    Java Study Notes_Design in 2023(Day01~Day14)_第21张图片

Day11: 面向对象高级二

11.1 多态

什么是多态?

  • 多态是在继承、实现情况下的一种现象,表现为: 对象多态行为多态

对象多态与行为多态:

本引用模块中Teacher和Student都是People的子类

  • 对象多态在这里插入图片描述
    注意:
  1. 像这种父类变量接收子类对象的现象是 对象多态
  2. p1和p2都是People类型,但是p1和p2指向的对象不一样,这种现象称之为对象多态
  • 行为多态
    在这里插入图片描述
    注意:
  1. p1本质上代表学生对象p2本质上代表老师对象
  2. p1和p2可以调用run方法,但是两个run方法表现的行为不同,这种现象就认为是: 行为多态

11.2 多态优点

多态形式下右边的代码是解耦合的,更便于扩展和维护

  • 内聚与耦合

内聚是指一个模块内的交互程度,耦合是指模块间的交互程度。我们需要尽力做到高内聚低耦合

多态优点概念引入在这里插入图片描述
解释:刚开始p1指向Student对象run执行Student对象的业务;假如p1指向Teacher对象 ,run方法执行Teacher对象的业务。

11.2.1 案例一

注意点:
构成多态的规则

  • 1.必须有继承、实现关系
  • 2.必须有方法重写
  • 3.必须有父类引用指向子类对象
  • 4.多态访问变量时,编译看左,运行也看左
  • 5.多态访问方法时,编译看左,运行看右
package com.sesameseed.d1_polymorphism;

public class Peolple {
    String name = "父类";

    public void run(){
        System.out.println("人会跑");
    }
}

package com.sesameseed.d1_polymorphism;

public class Student extends Peolple{
    String name = "学生";

    @Override
    public void run() {
        System.out.println("学生跑的飞快");
    }

    public void study() {
        System.out.println("学生学习");
    }
}

package com.sesameseed.d1_polymorphism;

public class Teacher extends Peolple{
    String name = "老师";

    @Override
    public void run() { //重写快捷键,重写的方法名+enter键
        System.out.println("老师跑得慢");
    }

    public void teach(){
        System.out.println("老师教书");
    }
}

package com.sesameseed.d1_polymorphism;

public class Test {
    //TODO 认识多态
    /*
    * 构成多态的规则:
    * 1.必须有继承、实现关系
    * 2.必须有方法重写
    * 3.必须有父类引用指向子类对象
    * */public static void main(String[] args) {

        //多态访问变量时,编译看左,运行也看左
        Peolple p1 = new Teacher();
        System.out.println(p1.name);

        //多态访问方法时,编译看左,运行看右
        p1.run();

        Peolple p2 = new Student();
        System.out.println(p2.name);
        p2.run();
    }
}

package com.sesameseed.d1_polymorphism.demo1;

public class Test2 {
    public static void main(String[] args) {
  /*      TODO 使用多态的好处,以及多态下的类型转换问题
        多态
        好处  耦合性低,扩展性强
        弊端 不能调用子类独有的方法*/
        Teacher t = new Teacher();
        go(t);
    }

    public static void go(Peolple p){ //底层变成多态样子:People p = new Teacher();
        System.out.println("==开始==");
        p.run();
       /* p.teach();
        p.study();
        //两个方法在多态形式下是不能直接调用
        */

        if (p instanceof Student){
            Student s = (Student) p;
            s.study();
        }else if (p instanceof Teacher){
            Teacher t = (Teacher) p;
            t.teach();
        }
//        关于多态转型问题:原本是什么类型,才能还原成什么类型

    }
}

11.3 final关键字

final关键字最终的意思

  • final修饰类:该类称为最终类,特点是不能被继承
  • final修饰方法:该方法称之为最终方法,特点是不能被重写
  • final修饰变量:该变量只能被赋值一次

11.3.1 案例一

package com.sesameseed.d4_finaldemo;

final class A { }
//class B extends A{}//Cannot inherit from final 'com.sesameseed.d4_finaldemo.A' ,修饰符,类不能被继承了

11.3.2 案例二

package com.sesameseed.d4_finaldemo;

public class C {
    public final void test(){}
}

class D extends C{
/*    @Override
    public void test(){
        //test()' cannot override 'test()' in 'com.sesameseed.d4_finaldemo.C'; overridden method is final
        //不能重写C类的test方法,因为C类的test方法被final修饰
    }*/
}

11.3.3 案例二

package com.sesameseed.d4_finaldemo;

public class FinalDemo1 {
    public static void main(String[] args) {
        //目标 :掌握final关键字的基本作用
        //变量有几种? 局部变量,成员变量(类变量,实例变量)
        final double a = 3.14;
//        a = 3.15;Cannot assign a value to final variable 'a' 不能再给a赋值,因为a是被final修饰的
        final int[] arr1 = {10, 20, 30};
//        arr1 = null; //Cannot assign a value to final variable 'arr1'  不能给final修饰arr1变量赋值
        arr1[1] = 222;
    }
}

11.4 抽象类

  • 1.认识一下什么是抽象类

在Java中有一个关键字叫abstract,它就是抽象的意思,它可以修饰类也可以修饰方法

  • 被abstract修饰的类,就是抽象类
  • 被abstract修饰的方法,就是抽象方法(不允许有方法体)
  • 2.认识一下什么是抽象类
  • 抽象类中可以不写抽象方法,但有抽象方法的类一定是抽象类
  • 类有的成员(成员变量、方法、构造器),抽象类都具备。
  • 抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
  • 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类

11.4.1 案例一

package com.oop.demo08;

//abstract  抽象类关键字      extends:只能单继承,接口(interface)可以多继承
public abstract class Action {

    //约束~有人帮我们实现
    //abstract , 抽象方法,只有方法的名字,没有方法的实现
    public abstract void  doSomething();

    /*抽象类特点
    1.不能new这个抽象类,只能靠子类去实现它:约束
    2.抽象类中可以写普通方法
    3.抽象方法必须写在抽象类中
    4.抽象的抽象:就是一个约束
     */
    //思考题?  new ,里面是否存在构造器?
            //存在意义  抽象出来一些要重复的东西,提高开发效率

}

11.4.2 案例二

package com.sesameseed.d2_abstract.demo2;

//abstract修饰类,这个类就是抽象类
public abstract class A {
    private String name;
    static String schoolName;

    //构造方法
    public A() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //实例方法
    public static String getSchoolName() {
        return schoolName;
    }

    public static void setSchoolName(String schoolName) {
        A.schoolName = schoolName;
    }

    //abstract修饰方法,这个方法就是抽象方法
    public abstract void test();
}

package com.sesameseed.d2_abstract.demo2;

public class B extends A{
    //TODO 抽象类虽然不能创建对象,但是它可以作为父类让子类继承。而且子类继承父类必须重写父类的所有抽象方法。
//B类继承A类,必须复写test方法
    @Override
    public void test() {

    }
}

package com.sesameseed.d2_abstract.demo2;

//TODO 子类继承父类如果不复写父类的抽象方法,要想不出错,这个子类也必须是抽象类
public abstract class C extends A{
    //B类基础A类,此时B类也是抽象类,这个时候就可以不重写A类的抽象方法
}

package com.sesameseed.d2_abstract.demo2;

public class Test {
    public static void main(String[] args) {
        //抽象类是不能创建对象的,如果抽象类的对象就
//        A a = new A();A' is abstract; cannot be instantiated
//        a.test();
    }
}

11.4.3 案例三

注意:在此案例中,每种动物都有其独特的叫声,因此将父类Animal定义成抽象类,这样的好处就是利用抽象类子类必须被重写的特点满足各场景使用需求。

package com.sesameseed.d2_abstract.demo1;

public abstract class Animal {
    private String name;

    //动物叫的行为:不具体,是抽象的
    public abstract void cry();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

package com.sesameseed.d2_abstract.demo1;

public class Cat extends Animal{
    @Override
    public void cry() {
        System.out.println(getName() + "喵喵喵");
    }
}

package com.sesameseed.d2_abstract.demo1;

public class Dog extends Animal{
    public void cry(){
        System.out.println(getName() + "汪汪汪");
    }
}

package com.sesameseed.d2_abstract.demo1;

public class Pig extends Animal{
    @Override
    public void cry() {
        System.out.println(getName() + "嚯嚯嚯");
    }
}

package com.sesameseed.d2_abstract.demo1;

public class Test2 {
    public static void main(String[] args) {
/*      TODO 掌握抽象类的使用场景和好处
        应用场景1.先写父类,让子类继承,拓展性更好
                2.先写子类,抽取共性内容到父类,代码更灵活

       * 多态三种方式
        1.具体类多态(所继承父类方法时普通书写类型)
        2.抽象类多态

        应用场景选择注意点:
        必须 抽象,不是必须 普通
        * */
        Animal a = new Pig();
        a.cry();
    }
}

11.5 设计模式——模板方法模式

  • 设计模式:是解决某一类问题最优方案
  • 模板方法模式主要解决方法中存在重复代码的问题

11.5.1 案例一

注意:此案例中AB都会有System.out.println("唱一首你喜欢的歌");此类的重复代码,因此我们将此类重复代码封装在一个方法中,利用模板设计模式减少重复代码。

package com.sesameseed.p3_abstract_template;

//模板方法设计模式
public abstract class C {
    //模板方法
    public final void sing(){
        System.out.println("唱一首你喜欢的歌");
        doSing();
        System.out.println("唱完了");
    }
    public abstract void doSing();
}

package com.sesameseed.p3_abstract_template;

public class A extends C{
    @Override
    public void doSing() {
        System.out.println("我们唱p2");
    }
}

package com.sesameseed .p3_abstract_template;

public class B extends C{
    @Override
    public void doSing() {
        System.out.println("我们唱P1");
    }
}

package com.sesameseed.p3_abstract_template;

public class Test {
    public static void main(String[] args) {
        //TODO 设计模式解决什么问题,以及怎么写
        B b = new B();
        b.sing();
    }
}

11.6 接口

  • Java提供了一个关键字interface,可以定义出一个特殊的结构: 接口
public interface 接口名{
// 成员变量(常量)
// 成员方法(抽急方法
}

注意:

  • 接口不能创建对象;接口是用来被类实现( implements)的,实现接口的类称为实现类修饰符 class 实现类
  • 实现类实现多个接口,必须重写完全部接口的全部推象方法,或者实现类需要定义成抽象类
implements 接口1,接口2,接口3..[
一个类可以实现多个接口(接口可以理解成干爹)
11.6.1 案例一
package com.oop.demo09;

//抽象的思维
//interface 定义的关键字,接口都需要有现实类  命名都需要以Impl结尾
public interface UserService {

    //常量 public static final
    public static final int AGE = 99;
    //接口中所有定义其实都是抽象的 public abstract
    public abstract void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}

对应的现实类
package com.oop.demo09;

//抽象类 extends
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法 (ALT + INS  -> Override)

//多继承 利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}

接口作用:
1.接口就是一个约束
2.定义一个方法,让不同的人实现
3.方法都是 public static
4.常量都是public static final
5.接口不能实例化,接口中没有构造方法
6.implements可以实现多个接口
7.必须要重写接口中的方法(ALT + INS -> Override)
接口优点:
1.弥补了类单继承的不足,一个类同时可以实现多个接口
2.让程序可以面向接口编程,这样可以灵活切换各种业务实现.

11.6.2 案例二

注意:

  • 接口是不能创建对象
  • 接口使用implements类实现,然后就可以再newi一个mplements类对象实现所需方法,
package com.sesameseed.d5_interfacedemo.demo1;

public interface A {
    //这里public static final可以加,可以不加。
//    public static final String SCHOOL_NAME = "家里蹲";

    String SCHOOL_NAME = "家里蹲";
}


package com.sesameseed.d5_interfacedemo.demo1;

public interface B {
    void testb1();
    void testb2();
}

package com.sesameseed.d5_interfacedemo.demo1;

public interface C {
    void testc1();
    void testc2();
}

package com.sesameseed.d5_interfacedemo.demo1;

public class D implements B,C{
    //实现类D,同时实现B接口和C接口,此时就需要复写四个方法,如下代码
    @Override
    public void testc1() {

    }

    @Override
    public void testc2() {

    }

    @Override
    public void testb1() {

    }

    @Override
    public void testb2() {

    }
}

package com.sesameseed.d5_interfacedemo.demo1;

public class Test {
    public static void main(String[] args) {
        //打印A接口中的常量
        System.out.println(A.SCHOOL_NAME);

        接口是不能创建对象的
//        A a = new A();'A' is abstract; cannot be instantiated

//        D类是接口的实现类,对D类创建对象
        D d = new D();
    }
}

Day12: 面向对象高级三

12.1 内部类

在这里插入图片描述

12.1.1 成员内部类

成员内部类就是类中的一个普通成员,类似于成员变量、成员方法。

10.2.1.1 成员内部类案例

package com.sesameseed.d1_inner.peopleinner;

public class Outer {
    private int age = 99;
    public static String a = "李明";

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static String getA() {
        return a;
    }

    public static void setA(String a) {
        Outer.a = a;
    }

    // 成员内部类
    public class Inner{
        private String name;
        private int age = 88;

//    在内部类中既可以访问自己类的成员,也可以访问外部类的成员
        public void test(){
            System.out.println(age); //88
            System.out.println(a); //李明

            int age = 77;
            System.out.println(age); //77
            System.out.println(this.age); //88
            System.out.println(Outer.this.age);//99
        }


    }
}

package com.sesameseed.d1_inner.peopleinner;

public class Test {
    public static void main(String[] args) {
        //外部类.内部类 变量名 = new 外部类().new 内部类();
        Outer.Inner inner = new Outer().new Inner();
        //调用内部类的方法
        inner.test();
    }
}

12.2.2 静态内部类

成员内部类的前面加了一个static关键字。静态内部类属于外部类自己持有

12.2.2.1 静态内部类案例

package com.sesameseed.d1_inner.staticinner;

public class Outer {
    private int age = 90;
    public static String schoolName = "家里蹲";

    // 静态内部类
    public static class Inner{
        public void test(){
            System.out.println(schoolName);//静态内部类访问外部类的静态变量,是可以的;
//            System.out.println(age);    //报错 静态内部类访问外部类的实例变量,是不行的
        }
    }

}

package com.sesameseed.d1_inner.staticinner;

public class Test {
    public static void main(String[] args) {
        //格式:外部类.内部类 变量名 = new 外部类.内部类();
        Outer.Inner inner = new Outer.Inner();
        inner.test();
    }
}

12.2.3 局部内部类

定义在方法中的类,和局部变量一样,只能在方法中有效局限性很强,一般在开发中是不会使用的。

12.2.3.1 局部内部类案例

package com.sesameseed.d1_inner.partinner;

public class Outer {
    public void test(){
        //局部内部类
        class Inner{
            public void show(){
                System.out.println("partInner");
            }
        }

    //局部内部类只能在方法中创建对象,并使用
        Inner inner = new Inner();
        inner.show();
    }
}

package com.sesameseed.d1_inner.partinner;

public class Test {
    public static void main(String[] args) {
        //new对象调用
        Outer outer = new Outer();
        outer.test();
    }
}

12.2.4 匿名内部类

是一种特殊的局部内部类;所谓匿名,指需要类声明名字

new 父类/接口(参数值){
    @Override
    重写父类/接口的方法;
}

12.2.4.1 匿名内部类案例

package com.sesameseed.d1_inner.anonymousinner;

//继承单继承,实现多实现
/*
实现法比较:
    1.普通方法:每一个都要做个类,代码冗余
    2.抽象类继承方法:由于继承单继承,只能实现继承一个方法,抽象类虽然必须重写方法,
      但是如果想继承实现父类多个方法,又不行了
    3.接口实现:接口实现可以多实现,就可以实现父类中多个方法,同时实现类中也必须重写接口类中方法,所以后期可扩展高,适用于动物会游泳,后期他会跑也行,此业务
*/
public interface Swimming {
//    public abstract void swim();
    void swim(); //public abstract默认有
}

package com.sesameseed.d1_inner.anonymousinner;

public class Test {
    public static void main(String[] args) {
        //这里后面new 的部分,其实就是一个Swimming的子类对象
        //这里隐含的有多态的特性: Swimming swimming = Swimming子类对象;

       //第一种书写方法
        Swimming swimming = new Swimming(){

            @Override
            public void swim() {
                System.out.println("猫游泳1");
            }
        };
        go(swimming);

        //匿名内部类规范写法
        go(new Swimming(){
            @Override
            public void swim() {
                System.out.println("猪会游泳2");
            }
        });
    }



    public static void go(Swimming swimming){
        swimming.swim();
    }
}

12.3 枚举

枚举是一种特殊的类,它的格式是:

public enum 枚举类名{
    枚举项1,枚举项2,枚举项3;
}

12.3.1 枚举案例

package com.sesameseed.d2_enumdemo;

public enum Constant {
    //Enum:应用场景,用来表示一组信息,进行传参
//    public static final int BOY = 0;
//    public static final int GIRL = 1;
    BOY, GIRL;
}

package com.sesameseed.d2_enumdemo;

public class Test {
    public static void main(String[] args) {
        //目标: 掌握枚举的使用场景

    }
    public static void printdeIndo(Constant sex){
        switch (sex){
            case BOY:
                System.out.println("男生");
                break;
            case GIRL:
                System.out.println("男生");
                break;
        }
    }
}

12.4 泛型

Java Study Notes_Design in 2023(Day01~Day14)_第22张图片

  • 泛型的好处:在编译阶段可以避免出现一些非法的数据。
  • 泛型的本质:把具体的数据类型传递给类型变量。

12.5 常用API

12.5.1 Object类

Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法

package com.sesameseed.d6_api_object;

public class Student {
    private String name;
    private int age;

    //Object中equals比较地址值,重写equals比较内容
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

//    @Override
//    public int hashCode() {
//        int result = name != null ? name.hashCode() : 0;
//        result = 31 * result + age;
//        return result;
//    }

    //Object中toString返回地址值,重写toString方法返回字符串内容
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
package com.sesameseed.d6_api_object;

public class Test {
    public static void main(String[] args) {
        //目标:掌握object类提供的常用方法
        Student student = new Student("李明",20);
//        System.out.println(student.toString()); 默认调用toString
        System.out.println(student);

        Student student1 = new Student("李明",20);
        System.out.println(student1.equals(student));
    }
}

12.5.2 基本类型包装类

Java中的8种基本数据类型还不是对象,所以要把它们变成对象,变成对象之后,可以提供一些方法对数据进行操作。
Java Study Notes_Design in 2023(Day01~Day14)_第23张图片

    1. 创建包装类的对象方式、自动装箱和拆箱的特性;
    1. 利用包装类提供的方法对字符串和基本类型数据进行相互转换
package com.sesameseed.d7_wrapperclass;

public class Test {
    public static void main(String[] args) {
        //目标:掌握包装类的使用
        //自动装箱:可以自动把基本类型的数据转换成对象
        int a1 = 12;
        Integer a2 = a1;

        Character c1 = 'a';
//        System.out.println(c1 instanceof String);
        //自动拆箱:可以自动把包装类类型的对象转换成对应的基本数据类型
        int a3 = a2;

        System.out.println("===========");
        //基本类型  -->字符串
        int ii = 22;
        //方式一
        String s1 = Integer.toString(ii);
        System.out.println("s1是" + s1);
        //方式二
        String s2 = ii + "";
        System.out.println("s2是" + s2);
        System.out.println("s2是String:" + s2 instanceof String); //true

        //字符串 -->基本类型
        String ss = "111";
        //方式一
        int i = Integer.parseInt(ss);
        System.out.println("i是" + i);
        //方式二
        Integer i2 = Integer.valueOf(ss);
        System.out.println("i2是" + i2);
        System.out.println("i2是Integer:" + (i2 instanceof Integer)); //true
    }
}
//1.创建Integer对象,封装基本类型数据10
Integer a = new Integer(10);

//2.使用Integer类的静态方法valueOf(数据)
Integer b = Integer.valueOf(10);

//3.还有一种自动装箱的写法(意思就是自动将基本类型转换为引用类型)
Integer c = 10;

//4.有装箱肯定还有拆箱(意思就是自动将引用类型转换为基本类型)
int d = c;

//5.装箱和拆箱在使用集合时就有体现
ArrayList<Integer> list = new ArrayList<>();
//添加的元素是基本类型,实际上会自动装箱为Integer类型
list.add(100);
//获取元素时,会将Integer类型自动拆箱为int类型
int e = list.get(0);

Day13: 常用API

13.1 StringBuilder与StringBuffer类

StringBuilder代表可变字符串对象,是线程不安全的。相当于是一个容器,它里面的字符串是可以改变的,就是用来操作字符串的。

StringBuilder的效率比String更高
理由:string用+号做拼接,拼接底层会进行new对象操作。
Java Study Notes_Design in 2023(Day01~Day14)_第24张图片

package com.sesameseed.d1_stringbuild;

public class Test {

    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        System.out.println("###" + stringBuilder + "@@@@");//###@@@@

        StringBuilder stringBuilder1 = new StringBuilder();
        System.out.println(stringBuilder1); //111cdetrue

        //拼接字符串,追加
        //链式编程
        stringBuilder.append(111).append("cde").append(true);
        System.out.println(stringBuilder);

        //2.反转字符
        stringBuilder.reverse();
        System.out.println(stringBuilder);//eurtedc111

        //3.长度
        int lenght = stringBuilder.length();
        System.out.println(lenght);//10

        //4.stringBuilder转String
        String s = stringBuilder.toString(); //eurtedc111
        System.out.println(s);
    }
}
package com.sesameseed.d1_stringbuild;

public class Test2 {
    public static void main(String[] args) {
        int[] arr ={11, 22, 33, 44};
//        arr = null;  如果数组为空校验测试
        System.out.print(getArrContent(arr));
        System.out.print("]");
    }

    //拼接数组内容并返回
    public static String getArrContent(int[] arr){
        //加参数的非法校验
        if (arr == null){
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder();
//        stringBuilder.append("[");
        System.out.print("[");
        for (int i = 0; i < arr.length; i++) {
            //判断如果是最后一个树,不拼接“,”号
            if (arr[i] == arr[arr.length-1]){
                stringBuilder.append(arr[i]);
            }else {
                stringBuilder.append(arr[i]).append(",");
            }
        }
//        stringBuilder.append("]");
//        System.out.print("]");
        return stringBuilder.toString();
    }
}

StringBuffer是线程安全的,因为底层都加了synchronized关键字(线程同步锁),确保线程安全
Java Study Notes_Design in 2023(Day01~Day14)_第25张图片

public class Demo {
    public static void main(String[] args) {
        StringBuffer sbf = new StringBuffer("班金莲");;//线程安全的 效率低 1,同样的代码,同一时刻只能被一个线程执行
        StringBuffer sbf1 = sbf;
        sbf.append("爱大朗");
        System.out.println(sbf);//班金莲爱大朗
        System.out.println(sbf1);//班金莲爱大朗
        System.out.println(sbf == sbf1);//true
    }
}

13.2 Math类

Math是数学的意思,该类提供了很多个进行数学运算的方法,如求绝对值,求最大值,四舍五入等

package com.sesameseed.d2_math;

public class Test {
    public static void main(String[] args) {
// 1、public static int abs(int a):取绝对值(拿到的结果一定是正数)
        System.out.println(Math.abs(-12)); // 12
        System.out.println(Math.abs(123)); //123
        System.out.println(Math.abs(-3.14)); //3.14

// 2、public static double ceil(double a): 向上取整
        System.out.println(Math.ceil(4.00001)); //5.0
        System.out.println(Math.ceil(4.0)); //4.0

// 3、public static double floor(double a): 向下取整
        System.out.println(Math.floor(4.99999)); //5.0
        System.out.println(Math.floor(4.0)); //4.0

// 4、public static long round(double a):四舍五入
        System.out.println(Math.round(4.99999)); //5
        System.out.println(Math.round(4.0)); //4

// 5、public static int max(int a, int b):取较大值
        //   public static int min(int a, int b):取较小值
        System.out.println(Math.max(10,20)); //20
        System.out.println(Math.min(10,20)); //10

// 6、 public static double pow(double a, double b):取次方
        System.out.println(Math.pow(2,3));
        System.out.println(Math.pow(3,2));

// 7、public static double random(): 取随机数 [0.0 , 1.0) (包前不包后)
        System.out.println(Math.random());
    }
}

13.3 System类

这是系统类,提供了一些获取获取系统数据的方法。比如获取系统时间

package com.sesameseed.d2_math;

public class Test2 {
    public static void main(String[] args) {
// 1、public static void exit(int status):
//   终止当前运行的Java虚拟机。
//   该参数用作状态代码; 按照惯例,非零状态代码表示异常终止。
//        System.exit(0);

//   public static long currentTimeMillis():
//    获取当前系统的时间
//    返回的是long类型的时间毫秒值:指的是从1970-1-1 0:0:0开始走到此刻的总的毫秒值,1s = 1000ms
        long time = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            System.out.println("输出了:" + i);
        }

        long time2 = System.currentTimeMillis();
        System.out.println((time2 - time) / 1000.0 + "s");
    }
}

13.4 Runtime类

这个类可以用来获取JVM的一些信息,也可以用这个类去执行其他的程序

package com.sesameseed.d3_runtime;

import java.io.IOException;

public class RuntimeTest {
    public static void main(String[] args) throws IOException, InterruptedException {
// 1、public static Runtime getRuntime() 返回与当前Java应用程序关联的运行时对象。
        Runtime runtime = Runtime.getRuntime();
//        System.out.println(runtime);

// 2、public void exit(int status) 终止当前运行的虚拟机,该参数用作状态代码; 按照惯例,非零状态代码表示异常终止。
//        runtime.exit(0);

// 3、public int availableProcessors(): 获取虚拟机能够使用的处理器数。
        System.out.println(runtime.availableProcessors());

// 4、public long totalMemory() 返回Java虚拟机中的内存总量。
        System.out.println(runtime.totalMemory());

// 5、public long freeMemory() 返回Java虚拟机中的可用内存量
        System.out.println(runtime.freeMemory());

// 6、public Process exec(String command) 启动某个程序,并返回代表该程序的对象。
    Process p = runtime.exec("C:\\Users\\jiaoxin\\Desktop\\FeiQ.exe");
    Thread.sleep(5000); //让程序在这里暂停5000/1000 = 5 s后继续走
    p.destroy();
    }
}

13.5 BigDecimal类

解决计算精度损失的问题,Java给我们提供了BigDecimal类

package com.sesameseed.d4_bigdecimal;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Test {
    public static void main(String[] args) {
        //目标 掌握BigDecimal进行精确运算的方案
        double a = 0.1;
        double b = 0.2;

        //1.把浮点型数据封装成BigDecimal对象,再来参与运算
        // a、public BigDecimal(double val) 得到的BigDecimal对象是无法精确计算浮点型数据的。 注意:不推荐使用这个
        BigDecimal bigDecimal1 = new BigDecimal(0.2);  //不建议使用   输出:bigDecimal10.200000000000000011102230246251565404236316680908203125
        System.out.println("bigDecimal1" + bigDecimal1);

        // b、public BigDecimal(String val)  得到的BigDecimal对象是可以精确计算浮点型数据的。 可以使用。
        // c、public static BigDecimal valueOf(double val): 通过这个静态方法得到的BigDecimal对象是可以精确运算的。是最好的方案。
        BigDecimal bigDecimal = BigDecimal.valueOf(a);
        BigDecimal b1 = BigDecimal.valueOf(b);

        // 2、public BigDecimal add(BigDecimal augend): 加法
        BigDecimal add = bigDecimal.add(b1);
        System.out.println(add); //0.3

        // 3、public BigDecimal subtract(BigDecimal augend): 减法
        BigDecimal subtract = bigDecimal.subtract(b1);
        System.out.println(subtract); //-0.1

        // 4、public BigDecimal multiply(BigDecimal augend): 乘法
        BigDecimal multiply = bigDecimal.multiply(b1);
        System.out.println(multiply); //0.02

        // 5、public BigDecimal divide(BigDecimal b): 除法
        BigDecimal divide = bigDecimal.divide(b1);
        System.out.println(divide); //0.5

//        BigDecimal bigDecimal2 = BigDecimal.valueOf(0.1);
//        BigDecimal bigDecimal3 = BigDecimal.valueOf(0.3);
//        BigDecimal divide1 = bigDecimal2.divide(bigDecimal3);
//        System.out.println(divide1);  //ArithmeticException 返回的值是循环的  bigdecial返回值得是精确地

        // 6、public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式) : 除法,可以设置精确几位。
        BigDecimal bigDecimal2 = BigDecimal.valueOf(0.1);
        BigDecimal bigDecimal3 = BigDecimal.valueOf(0.3);
        BigDecimal divide1 = bigDecimal2.divide(bigDecimal3, 2, RoundingMode.HALF_UP);//四舍五入
        System.out.println("结果" + divide1);

        // 7、public double doubleValue() : 把BigDecimal对象又转换成double类型的数据。
        double v = bigDecimal3.doubleValue();
        double v1 = bigDecimal2.doubleValue();
        print(v);
        print(v1);
    }

    public static void print(double a){
        System.out.println(a);
    }
}

13.6 Date类

学习一下Date类,Java中是由这个类的对象用来表示日期或者时间。

Date对象记录的时间是用毫秒值来表示的。Java语言规定,1970年1月1日0时0分0秒认为是时间的起点,此时记作0,那么1000(1秒=1000毫秒)就表示1970年1月1日0时0分1秒,依次内推。

Java Study Notes_Design in 2023(Day01~Day14)_第26张图片

public class Test1Date {
    public static void main(String[] args) {
        // 目标:掌握Date日期类的使用。
        // 1、创建一个Date的对象:代表系统当前时间信息的。
        Date d = new Date();
        System.out.println(d);

        // 2、拿到时间毫秒值。
        long time = d.getTime();
        System.out.println(time);

        // 3、把时间毫秒值转换成日期对象: 2s之后的时间是多少。
        time += 2 * 1000;
        Date d2 = new Date(time);
        System.out.println(d2);

        // 4、直接把日期对象的时间通过setTime方法进行修改
        Date d3 = new Date();
        d3.setTime(time);
        System.out.println(d3);
    }
}

13.7 SimpleDateFormat类

SimpleDateFormat类就可以转换Date对象表示日期时间的显示格式

  • 我们把Date对象转换为指定格式的日期字符串这个操作,叫做日期格式化,
  • 反过来把指定格式的日期符串转换为Date对象的操作,叫做日期解析

Java Study Notes_Design in 2023(Day01~Day14)_第27张图片

		常用的几种日期/时间格式
字母	   表示含义
yyyy	年
MM		月
dd		日
HH		时
mm		分
ss		秒
SSS		毫秒

案例一:

package com.sesameseed.d5_time;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test2SimpleDateFormat {
    //目标:掌握SimpleDateFormat的使用
    public static void main(String[] args) throws ParseException {
        //1.准备一个时间
        Date date = new Date();
        System.out.println("i am here :" + date);
        //2.格式化日期对象 时间 毫秒值
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
        String timeFormat = simpleDateFormat.format(date);
        System.out.println(timeFormat);

        System.out.println("-------------");

        //String -> Date
        //目标 掌握SimpleDateFormat解析字符串时间 成为日期对象
        String dateStr = "2023-1-6 15:26:26";
       //1.创建日期格式化对象,指定的时间格式必须与被解析的时间格式一模一样,否则会出bug
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date timeParse = simpleDateFormat1.parse(dateStr);
        System.out.println(timeParse);
    }
}

案例二:

package com.sesameseed.d5_time;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class SaleDemo {
    public static void main(String[] args) throws ParseException {
        /*
        目标 完成秒杀判定案例
        做时间计算,将string转data 转long
        做时间展示:将long 转Date 转 String
        * */
        //1.把开始时间 结束时间 小贾 小皮下单时间 拿到程序中
        String start = "2023年11月11日 0:0:0";
        String end = "2023年11月11日 0:10:0";
        String xj = "2023年11月11日 0:01:18";
        String xp = "2023年11月11日 0:10:57";
        //2.把字符串的时间解析成日期对象
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date starParse = simpleDateFormat.parse(start);
        Date endParse = simpleDateFormat.parse(end);
        Date xjParse = simpleDateFormat.parse(xj);
        Date xpParse = simpleDateFormat.parse(xp);
        //3.开始判断小皮小贾是否秒杀成功
        //把日期对象转换成时间毫秒值
        long starTime = starParse.getTime();
        long endTime = endParse.getTime();
        long xjTime = xjParse.getTime();
        long xpTime = xpParse.getTime();

        //逻辑判断
        if (xjTime >= starTime && xjTime <= endTime){
            System.out.println("小贾成功");
        }else {
            System.out.println("小贾失败");
        }
        if (xpTime >= starTime && xpTime <= endTime){
            System.out.println("小皮成功");
        }else {
            System.out.println("小皮失败");
        }
    }
}

13.8 Calendar类

Calendar类表示日历,它提供了一些比Date类更好用的方法。

Java Study Notes_Design in 2023(Day01~Day14)_第28张图片

public class Test4Calendar {
    public static void main(String[] args) {
        // 目标:掌握Calendar的使用和特点。
        // 1、得到系统此刻时间对应的日历对象。
        Calendar now = Calendar.getInstance();
        System.out.println(now);

        // 2、获取日历中的某个信息
        int year = now.get(Calendar.YEAR);
        System.out.println(year);

        int days = now.get(Calendar.DAY_OF_YEAR);
        System.out.println(days);

        // 3、拿到日历中记录的日期对象。
        Date d = now.getTime();
        System.out.println(d);

        // 4、拿到时间毫秒值
        long time = now.getTimeInMillis();
        System.out.println(time);

        // 5、修改日历中的某个信息
        now.set(Calendar.MONTH, 9); // 修改月份成为10月份。
        now.set(Calendar.DAY_OF_YEAR, 125); // 修改成一年中的第125天。
        System.out.println(now);

        // 6、为某个信息增加或者减少多少
        now.add(Calendar.DAY_OF_YEAR, 100);
        now.add(Calendar.DAY_OF_YEAR, -10);
        now.add(Calendar.DAY_OF_MONTH, 6);
        now.add(Calendar.HOUR, 12);
        now.set(2026, 11, 22);
        System.out.println(now);
    }
}

13.9 JDK8日期、时间、日期时间

为什么以前的Date类就可以表示日期,为什么要有新增的日期类呢?
Java Study Notes_Design in 2023(Day01~Day14)_第29张图片

13.9.1 LocalDate类

public class Test1_LocalDate {
    public static void main(String[] args) {
        // 0、获取本地日期对象(不可变对象)
        LocalDate ld = LocalDate.now(); // 年 月 日
        System.out.println(ld);

        // 1、获取日期对象中的信息
        int year = ld.getYear(); // 年
        int month = ld.getMonthValue(); // 月(1-12)
        int day = ld.getDayOfMonth(); // 日
        int dayOfYear = ld.getDayOfYear();  // 一年中的第几天
        int dayOfWeek = ld.getDayOfWeek().getValue(); // 星期几
        System.out.println(year);
        System.out.println(day);
        System.out.println(dayOfWeek);

        // 2、直接修改某个信息: withYear、withMonth、withDayOfMonth、withDayOfYear
        LocalDate ld2 = ld.withYear(2099);
        LocalDate ld3 = ld.withMonth(12);
        System.out.println(ld2);
        System.out.println(ld3);
        System.out.println(ld);

        // 3、把某个信息加多少: plusYears、plusMonths、plusDays、plusWeeks
        LocalDate ld4 = ld.plusYears(2);
        LocalDate ld5 = ld.plusMonths(2);

        // 4、把某个信息减多少:minusYears、minusMonths、minusDays、minusWeeks
        LocalDate ld6 = ld.minusYears(2);
        LocalDate ld7 = ld.minusMonths(2);

        // 5、获取指定日期的LocalDate对象: public static LocalDate of(int year, int month, int dayOfMonth)
        LocalDate ld8 = LocalDate.of(2099, 12, 12);
        LocalDate ld9 = LocalDate.of(2099, 12, 12);

        // 6、判断2个日期对象,是否相等,在前还是在后: equals isBefore isAfter
        System.out.println(ld8.equals(ld9));// true
        System.out.println(ld8.isAfter(ld)); // true
        System.out.println(ld8.isBefore(ld)); // false
    }
}

13.9.2 LocalTime类

public class Test2_LocalTime {
    public static void main(String[] args) {
        // 0、获取本地时间对象
        LocalTime lt = LocalTime.now(); // 时 分 秒 纳秒 不可变的
        System.out.println(lt);

        // 1、获取时间中的信息
        int hour = lt.getHour(); //时
        int minute = lt.getMinute(); //分
        int second = lt.getSecond(); //秒
        int nano = lt.getNano(); //纳秒

        // 2、修改时间:withHour、withMinute、withSecond、withNano
        LocalTime lt3 = lt.withHour(10);
        LocalTime lt4 = lt.withMinute(10);
        LocalTime lt5 = lt.withSecond(10);
        LocalTime lt6 = lt.withNano(10);

        // 3、加多少:plusHours、plusMinutes、plusSeconds、plusNanos
        LocalTime lt7 = lt.plusHours(10);
        LocalTime lt8 = lt.plusMinutes(10);
        LocalTime lt9 = lt.plusSeconds(10);
        LocalTime lt10 = lt.plusNanos(10);

        // 4、减多少:minusHours、minusMinutes、minusSeconds、minusNanos
        LocalTime lt11 = lt.minusHours(10);
        LocalTime lt12 = lt.minusMinutes(10);
        LocalTime lt13 = lt.minusSeconds(10);
        LocalTime lt14 = lt.minusNanos(10);

        // 5、获取指定时间的LocalTime对象:
        // public static LocalTime of(int hour, int minute, int second)
        LocalTime lt15 = LocalTime.of(12, 12, 12);
        LocalTime lt16 = LocalTime.of(12, 12, 12);

        // 6、判断2个时间对象,是否相等,在前还是在后: equals isBefore isAfter
        System.out.println(lt15.equals(lt16)); // true
        System.out.println(lt15.isAfter(lt)); // false
        System.out.println(lt15.isBefore(lt)); // true
    }
}

13.9.3 LocalDateTime类

public class Test3_LocalDateTime {
    public static void main(String[] args) {
        // 0、获取本地日期和时间对象。
        LocalDateTime ldt = LocalDateTime.now(); // 年 月 日 时 分 秒 纳秒
        System.out.println(ldt);

        // 1、可以获取日期和时间的全部信息
        int year = ldt.getYear(); // 年
        int month = ldt.getMonthValue(); // 月
        int day = ldt.getDayOfMonth(); // 日
        int dayOfYear = ldt.getDayOfYear();  // 一年中的第几天
        int dayOfWeek = ldt.getDayOfWeek().getValue();  // 获取是周几
        int hour = ldt.getHour(); //时
        int minute = ldt.getMinute(); //分
        int second = ldt.getSecond(); //秒
        int nano = ldt.getNano(); //纳秒

        // 2、修改时间信息:
        // withYear withMonth withDayOfMonth withDayOfYear withHour
        // withMinute withSecond withNano
        LocalDateTime ldt2 = ldt.withYear(2029);
        LocalDateTime ldt3 = ldt.withMinute(59);

        // 3、加多少:
        // plusYears  plusMonths plusDays plusWeeks plusHours plusMinutes plusSeconds plusNanos
        LocalDateTime ldt4 = ldt.plusYears(2);
        LocalDateTime ldt5 = ldt.plusMinutes(3);

        // 4、减多少:
        // minusDays minusYears minusMonths minusWeeks minusHours minusMinutes minusSeconds minusNanos
        LocalDateTime ldt6 = ldt.minusYears(2);
        LocalDateTime ldt7 = ldt.minusMinutes(3);


        // 5、获取指定日期和时间的LocalDateTime对象:
        // public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour,
        //                                  int minute, int second, int nanoOfSecond)
        LocalDateTime ldt8 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);
        LocalDateTime ldt9 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);

        // 6、 判断2个日期、时间对象,是否相等,在前还是在后: equals、isBefore、isAfter
        System.out.println(ldt9.equals(ldt8));
        System.out.println(ldt9.isAfter(ldt));
        System.out.println(ldt9.isBefore(ldt));

        // 7、可以把LocalDateTime转换成LocalDate和LocalTime
        // public LocalDate toLocalDate()
        // public LocalTime toLocalTime()
        // public static LocalDateTime of(LocalDate date, LocalTime time)
        LocalDate ld = ldt.toLocalDate();
        LocalTime lt = ldt.toLocalTime();
        LocalDateTime ldt10 = LocalDateTime.of(ld, lt);

    }
}

13.10 JDK8日期(时区)

public class Test4_ZoneId_ZonedDateTime {
    public static void main(String[] args) {
        // 目标:了解时区和带时区的时间。
        // 1、ZoneId的常见方法:
        // public static ZoneId systemDefault(): 获取系统默认的时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId.getId());
        System.out.println(zoneId);

        // public static Set getAvailableZoneIds(): 获取Java支持的全部时区Id
        System.out.println(ZoneId.getAvailableZoneIds());

        // public static ZoneId of(String zoneId) : 把某个时区id封装成ZoneId对象。
        ZoneId zoneId1 = ZoneId.of("America/New_York");

        // 2、ZonedDateTime:带时区的时间。
        // public static ZonedDateTime now(ZoneId zone): 获取某个时区的ZonedDateTime对象。
        ZonedDateTime now = ZonedDateTime.now(zoneId1);
        System.out.println(now);

        // 世界标准时间了
        ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());
        System.out.println(now1);

        // public static ZonedDateTime now():获取系统默认时区的ZonedDateTime对象
        ZonedDateTime now2 = ZonedDateTime.now();
        System.out.println(now2);

        // Calendar instance = Calendar.getInstance(TimeZone.getTimeZone(zoneId1));
    }
}

13.11 JDK8日期(Instant类)

通过获取Instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数+不够1秒的纳秒数

作用:可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点

/**
 * 目标:掌握Instant的使用。
 */
public class Test5_Instant {
    public static void main(String[] args) {
       // 1、创建Instant的对象,获取此刻时间信息
        Instant now = Instant.now(); // 不可变对象

        // 2、获取总秒数
        long second = now.getEpochSecond();
        System.out.println(second);

        // 3、不够1秒的纳秒数
        int nano = now.getNano();
        System.out.println(nano);

        System.out.println(now);

        Instant instant = now.plusNanos(111);

        // Instant对象的作用:做代码的性能分析,或者记录用户的操作时间点
        Instant now1 = Instant.now();
        // 代码执行。。。。
        Instant now2 = Instant.now();

        LocalDateTime l = LocalDateTime.now();
    }
}

13.12 JDK8日期(格式化器DateTimeFormater)

DateTimeFormater。它可以从来对日期进行格式化和解析。它代替了原来的SimpleDateFormat类
在这里插入图片描述

/**
 *  目标:掌握JDK 8新增的DateTimeFormatter格式化器的用法。
 */
public class Test6_DateTimeFormatter {
    public static void main(String[] args) {
        // 1、创建一个日期时间格式化器对象出来。
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");

        // 2、对时间进行格式化
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);

        String rs = formatter.format(now); // 正向格式化
        System.out.println(rs);

        // 3、格式化时间,其实还有一种方案。
        String rs2 = now.format(formatter); // 反向格式化
        System.out.println(rs2);

        // 4、解析时间:解析时间一般使用LocalDateTime提供的解析方法来解析。
        String dateStr = "2029年12月12日 12:12:11";
        LocalDateTime ldt = LocalDateTime.parse(dateStr, formatter);
        System.out.println(ldt);
    }
}

13.13 JDK8日期(Period类和Duration类)

  • 都用来对计算两个时间点的时间间隔
  • 其中Period用来计算日期间隔(年、月、日),
    Java Study Notes_Design in 2023(Day01~Day14)_第30张图片
  • Duration用来计算时间间隔(时、分、秒、纳秒)
    Java Study Notes_Design in 2023(Day01~Day14)_第31张图片

Period案例:

/**
 * 目标:掌握Period的作用:计算机两个日期相差的年数,月数、天数。
 */
public class Test7_Period {
    public static void main(String[] args) {
        LocalDate start = LocalDate.of(2029, 8, 10);
        LocalDate end = LocalDate.of(2029, 12, 15);

        // 1、创建Period对象,封装两个日期对象。
        Period period = Period.between(start, end);

        // 2、通过period对象获取两个日期对象相差的信息。
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
    }
}

Duration案例:

ublic class Test8_Duration {
    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2025, 11, 11, 11, 10, 10);
        LocalDateTime end = LocalDateTime.of(2025, 11, 11, 11, 11, 11);
        // 1、得到Duration对象
        Duration duration = Duration.between(start, end);

        // 2、获取两个时间对象间隔的信息
        System.out.println(duration.toDays());// 间隔多少天
        System.out.println(duration.toHours());// 间隔多少小时
        System.out.println(duration.toMinutes());// 间隔多少分
        System.out.println(duration.toSeconds());// 间隔多少秒
        System.out.println(duration.toMillis());// 间隔多少毫秒
        System.out.println(duration.toNanos());// 间隔多少纳秒

    }
}

13.14 Arrays类

Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作

13.14 .1 Arrays基本使用

Java Study Notes_Design in 2023(Day01~Day14)_第32张图片

/**
 * 目标:掌握Arrays类的常用方法。
 */
public class ArraysTest1 {
    public static void main(String[] args) {
        // 1、public static String toString(类型[] arr): 返回数组的内容
        int[] arr = {10, 20, 30, 40, 50, 60};
        System.out.println(Arrays.toString(arr));

        // 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)
        int[] arr2 = Arrays.copyOfRange(arr, 1, 4);
        System.out.println(Arrays.toString(arr2));

        // 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。
        int[] arr3 = Arrays.copyOf(arr, 10);
        System.out.println(Arrays.toString(arr3));

        // 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
        double[] prices = {99.8, 128, 100};
        //                  0     1    2
        // 把所有的价格都打八折,然后又存进去。
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {
                // value = 0  1  2
                return prices[value] * 0.8;
            }
        });
        System.out.println(Arrays.toString(prices));

        // 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
        Arrays.sort(prices);
        System.out.println(Arrays.toString(prices));
    }
}

13.14.2 Arrays操作对象数组实现排序

  • 排序方式1:让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。
package com.sesameseed.d1_arrays;

public class Student implements Comparable<Student>{
    private String name;
    private double height;
    private int age;

    /*
    * /指定比较规则
    步骤:
    1、让比较的类,实现Comparable接口
    2、重写compareTo方法,指定排序规则
    // 正整数:将即将排序的对象O 放左边/
    * 负整数:将即将排序的对象0,放右边
    * 0:默认按额序依次放
    * */
    // this: 已经排好序的对象 0: 即将排序的对象

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student() {
    }

    public Student(String name, double height, int age) {
        this.name = name;
        this.height = height;
        this.age = age;
    }

    @Override
    public int compareTo(Student A) {
        return this.age - A.age; //升序
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", height=" + height +
                ", age=" + age +
                '}';
    }
}

  • 排序方式2:在调用Arrays.sort(数组,Comparator比较器);时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。
package com.sesameseed.d1_arrays;

import java.util.Arrays;
import java.util.Comparator;
import java.util.function.ToDoubleFunction;

import static java.util.Arrays.*;

public class ArraysDemo {
    public static void main(String[] args) {
        //目标 堂握如何对数组中的对象进行排序。
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精",169.5,23);
        students[1] = new Student("紫霞",163.8,26);
        students[2] = new Student("紫霞",163.8,26);
        students[3] = new Student("至尊宝",167.5,24);

        /*
        方式实现Comparable接口 和 方式二 匿名内部类Comparator比较器对象
         区别 :方式一必须在数组的元素类中,进行实现。
               方式二不需要修改数组的元素类,直接以匿名内部类的方式指定排序规则
        * */

        //对于int型数组会直接排序,为啥呢?因为底层会自动装箱为Integer
        //1、public static void sort(类型[] arr): 对数组进行排序
        sort(students);
        System.out.println(Arrays.toString(students));

        String[] arr1 = {"ca", "bv" , "aa"};
        /*
        当原本类中定义的的排序规不能满足我们的需求时
       需要使用排序规则二,在不改变原本类的代码,满足我们的需求
       */

        // 2、public static  void sort(T[] arr, Comparator
        // 参数一:需要排序的数组
        // 参数二: Comoartor比较聚对象 (用来制定对象的比较规则)
        sort(arr1, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // o1: 已经好序的对象 o2: 即将排序的对象
                // 正警数:将即将排序的对象02 放左边
                // 负整数:将即将排序的对象02,放右边
                // 0,默认按按顺序依次比较
                return o2.compareTo(o1);
            }
        });
        System.out.println(Arrays.toString(arr1));

//        Arrays.sort(students, new Comparator() {  //匿名内部类中不能斜构造器,所有不能用comparable
//            @Override
//            public int compare(Student o1, Student o2) {
//                return Double.compare(o1.getHeight(), o2.getHeight());
//            }
//        });
        // Lambda简化
        /*
        * 前提:  1、必须是接口接
        *       2.口中只能有一个抽、象方法
        * */
        //匿名内部类中不能斜构造器,所有不能用comparable

        Arrays.<Student>sort(students, Comparator
                .comparingDouble(new ToDoubleFunction<Student>() {
            @Override
            public double applyAsDouble(Student student) {
                double height = student.getHeight();
                double height1 = height;
                double height11 = height1;
                return height11;
            }
        }));
        System.out.println(Arrays.toString(students));
    }
}

Day14: 算法和数据结构

14.1 Lambda表达式

作用:用于简化匿名内部类代码的书写
14.1.1 Lambda表达式基本使用
语法格式如下:

(被重写方法的形参列表) -> {
	被重写方法的方法体代码;
}

注意:

在使用Lambda表达式之前,必须先有一个接口,而且接口中只能有一个抽象方法。(注意:不能是抽象类,只能是接口),且底层被"@FunctionalInterface"注解声明。

14.2 JDK8新特性(方法引用)

方法引用是用来进一步简化Lambda表达式的

14.3 常见算法

14.3.1 冒泡排序

冒泡排序核心思想:每轮对数组中元素两两之间进行比较,将较大的放右边,每轮比较结束后,都会定位出一个最大的数 (最右边),下一轮比较去描最大数,依次再比较其他的款

package com.sesameseed.d2_algorithm;

import java.util.Arrays;

//TODO  冒泡排序
public class Test1 {
    public static void main(String[] args) {
        // 1、准备一个数组
        int[] arr = {5,2,3,1};
        //冒泡排序核心思想:每轮对数组中元素两两之间进行比较,将较大的放右边,每轮比较结束后,都会定位出一个最大的数 (最右边),下一轮比较去描最大数,依次再比较其他的款

        // 2、定义一个循环控制排几轮
        for (int i = 0; i < args.length-1; i++) {
            //i=0 1 2           [5, 2, 3, 1]  次数
            // i = @ 第一轮       0  1   2       3
            // i = 1 第二轮       0  1           2
            // i = 2 第三轮       0              1

            // 3、定义一个循环控制每轮比较几次。
            for (int j = 0; j < arr.length - i -1; j++) {
                // 判断当前位置的元素值,是否大于后一个位置处的元素值,如果大则交换,
                if (arr[j] > arr[j + 1]){
                    int temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

14.3.2 选择排序

核心思路是,每一轮选定一个固定的元素,和其他的每一个元素进行比较;经过几轮比较之后,每一个元素都能比较到了。

public class Test2 {
    public static void main(String[] args) {
        // 1、准备好一个数组
        int[] arr = {5, 1, 3, 2};
        //           0  1  2  3

        // 2、控制选择几轮
        for (int i = 0; i < arr.length - 1; i++) {
            // i = 0 第一轮    j = 1 2 3
            // i = 1 第二轮    j = 2 3
            // i = 2 第三轮    j = 3
            // 3、控制每轮选择几次。
            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;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

14.3.3 查找算法

  • 基本查找:只能从0索引开始一个一个往后找,但是如果元素比较多,你要查找的元素比较靠后的话,这样查找的此处就比较多。性能比较差。
  • 二分查找特点,每次查找能排除一般元素,这样效率明显提高,要求元素必须有序
  • 二分查找最多查找的次数公式:①log2N=总元素数(算出折半次数
    ②N+1(算出最终查找次数)

例如:32个有序数字的数组,查询出所需元素最多需要查找几次?
①公式推出折半次数4次,②公式加一推出查找次数5次。

二分查找的核心思路
第1步:先定义两个变量,分别记录开始索引(left)和结束索引(right)
第2步:计算中间位置的索引,mid = (left+right)/2;
第3步:每次查找中间mid位置的元素,和目标元素key进行比较
	如果中间位置元素比目标元素小,那就说明mid前面的元素都比目标元素小
		此时:left = mid+1
	如果中间位置元素比目标元素大,那说明mid后面的元素都比目标元素大
		此时:right = mid-1
	如果中间位置元素和目标元素相等,那说明mid就是我们要找的位置
		此时:把mid返回		
注意:一搬查找一次肯定是不够的,所以需要把第1步和第2步循环来做,只到left>end就结束,如果最后还没有找到目标元素,就返回-1.
/**
 * 目标:掌握二分查找算法。
 */
public class Test3 {
    public static void main(String[] args) {
        // 1、准备好一个数组。
        int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};

        System.out.println(binarySearch(arr, 150));

        System.out.println(Arrays.binarySearch(arr, 81));
    }

    public static int binarySearch(int[] arr, int data){
        // 1、定义两个变量,一个站在左边位置,一个站在右边位置
        int left = 0;
        int right = arr.length - 1;

        // 2、定义一个循环控制折半。
        while (left <= right){
            // 3、每次折半,都算出中间位置处的索引
            int middle = (left + right) / 2;
            // 4、判断当前要找的元素值,与中间位置处的元素值的大小情况。
            if(data < arr[middle]){
                // 往左边找,截止位置(右边位置) = 中间位置 - 1
                right = middle - 1;
            }else if(data > arr[middle]){
                // 往右边找,起始位置(左边位置) = 中间位置 + 1
                left = middle + 1;
            }else {
                // 中间位置处的元素值,正好等于我们要找的元素值
                return middle;
            }
        }
        return -1; // -1特殊结果,就代表没有找到数据!数组中不存在该数据!
    }
}

14.4 正则表达式

正则表达式其实是由一些特殊的符号组成的,它代表的是某种规则。需要用到一个方法叫`matches(String regex)
在这里插入图片描述

Java Study Notes_Design in 2023(Day01~Day14)_第33张图片
案例:正则表达式校验手机号码

/**
 * 目标:校验用户输入的电话、邮箱、时间是否合法。
 */
public class RegexTest3 {
    public static void main(String[] args) {
        checkPhone();
    }

    public static void checkPhone(){
        while (true) {
            System.out.println("请您输入您的电话号码(手机|座机): ");
            Scanner sc = new Scanner(System.in);
            String phone = sc.nextLine();
            // 18676769999  010-3424242424 0104644535
            if(phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")){
                System.out.println("您输入的号码格式正确~~~");
                break;
            }else {
                System.out.println("您输入的号码格式不正确~~~");
            }
        }
    }
}

你可能感兴趣的:(JavaSE入门与进阶,java,学习,数据结构)