复习
package com.study.c_review;
import java.io.*;
/**
* 字节输入输出综合复习
* @author big God
* @date 2022/12/30 9:04 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) throws IOException {
// 记录当前时间
long startTime = System.currentTimeMillis();
// 创建字节输入流对象并加上 缓冲 磁盘 => 内存
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/aaa/2.mp4"));
// 创建字节输出流对象并加上 缓冲 内存 => 磁盘
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/aaa/3.mp4"));
// 加缓冲数组会有一个内置数组,这里准备一个数组
byte[] buf = new byte[4];
int length;
while ((length = bis.read(buf)) != -1) {
bos.write(buf, 0, length);
}
// 关闭资源
bos.close();
bis.close();
// 这里结束记录一下时间
long endTime = System.currentTimeMillis();
// 输出时间差
System.out.println(endTime - startTime + "毫秒");
}
}
package com.study.c_review;
import java.io.*;
/**
* 字符输入输出流综合复习
* @author big God
* @date 2022/12/30 9:12 * @version 1.0
*/
public class Demo2 {
public static void main(String[] args) throws IOException {
// 记录当前时间
long startTime = System.currentTimeMillis();
// 创建一个字符输入流 并加上缓冲数组 磁盘 => 内存
BufferedReader br = new BufferedReader(new FileReader("D:/aaa/1.txt"));
// 创建一个字符输出流 并加上缓冲数组 内存 => 磁盘
BufferedWriter bw = new BufferedWriter(new FileWriter("D:/aaa/11.txt"));
// 准备一个缓冲数组
char[] cbuf = new char[4];
int length;
while ((length = br.read(cbuf)) != -1) {
bw.write(cbuf, 0, length);
}
// 关闭资源
br.close();
bw.close();
// 记录当前结束时间
long endTime = System.currentTimeMillis();
// 打印两个时间差
System.out.println(endTime - startTime + "毫秒");
}
}
package com.study.c_review;
import java.io.*;
/**
* 序列化和反序列化
* @author big God
* @date 2022/12/30 9:24 * @version 1.0
*/
public class Demo3 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 创建一个 Student 对象, Student 类需要实现 Serializable 接口,具备可序列化的能力
Student stu = new Student("张三",18,"三亚",123456);
// 创建序列化对象 磁盘 => 内存
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/aaa/emp.ser"));
// 创建反序列化对象 内存 => 磁盘
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/aaa/emp.ser"));
// 序列化:将目标对象写入目标文件中
oos.writeObject(stu);
// 反序列化:将目标文件中的目标对象写入当前对象中
Student student = (Student) ois.readObject();
// 调用对象中的方法
System.out.println(student.getName());
System.out.println(student.getAge());
System.out.println(student.getAddress());
System.out.println(student.getPhone());
}
}
今天的内容
1.递归(开发不用!!!)
2.常用类
1. 递归
递归:指的是在当前的方法中调用自己的现象
注意事项:
递归要有一定的条件的限制。保证递归能够停下来。否则会发生栈内存溢出,说明在栈区
压栈 出栈 的问题。在递归中虽然条件限制,但是递归的次数不能太多!!! 否则也会发生栈内存溢出
栈区中的数据存的多了,但是出栈的时候还没出来完。
package com.study.a_recursion;
/**
* @author big God
* @date 2022/12/29 22:41 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
// a();
b(1);
}
/**
*
* @param i
* b(1)
* sout(1)
* if(1 == 5)false
* b(++i) => b(2)
* sout(2)
* if(2 == 5)false
* b(++i) => b(3)
* sout(3)
* b(4)
* sout(4)
* b(5)
* sout(5)
* 但是递归的次数不能太多,太多的话也会报内存溢出的错误
*
*/
public static void b(int i) {
System.out.println(i);
// 添加一个递归结束的条件
if (i == 100000) {
return;
}
i++;
b(i);
}
/**
* 递归一定要有条件的限制,保证递归能够停下来。
* 以下代码是有问题的, 会有内存溢出的错误!!!
* */
public static void a() {
System.out.println("a 方法");
a();
}
}
递归累加求和
计算 1 ~ n 的和求 5 的累加的和 和 = 5 + 4
分析: num 累加和 = num
num = 5
return 5 + getSum(4)
num = 4
return 4 + getSum(3)
num = 3
return 3 + getSum(2)
num = 2
return 2 + getSum(1)
num = 1
return 1
package com.study.a_recursion;
/**
* @author big God
* @date 2022/12/29 22:54 * @version 1.0
*/
public class Demo2 {
public static void main(String[] args) {
System.out.println(getSum(5));
}
private static int getSum(int num) {
/**
* num = 1 的时候,返回值就是 1
* 相当于方法的出口 num 想法等于 1,递归要结束的
*
* num 不为 1 的时候,方法的返回值是 num + (num-1)的和
* 当 num = 5
* return 5 + getSum(4) => 15
* 4 + getSum(3) => 10
* 3 + getSum(2) => 6
* 2 + getSum(1)=> 3
*/
return num == 1 ? 1 : num + getSum(num - 1);
}
}
2. 常用类
2.1 StringBuffer
和字符串相关的类
线程安全,可变的字符序列。字符串缓冲区就像一个 String ,但可以修改。在任何时间点,它包含一些特定的字符序列,但可以通过某些方法调用来更改序列的长度和内容。
例如,如果 z 是指当前内容为 "start" 的字符串缓冲区对象,那么方法调用 z.append("le") 将使字符串缓冲区包含"startle", 而 z.insert(4, "le") 会将字符串缓冲区更改为包含"starlet"。
package com.study.b_stringbuffer;
/**
* @author big God
* @date 2022/12/29 23:16 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
String str = "xixi";
// "xixihaha" 值的内存和 str 的内存地址不一致
System.out.println(str + "haha");
// 新建一个字符串的缓冲区域, 放 16 个字符
StringBuffer stringBuffer = new StringBuffer();
// 进行字符串的添加 在末尾添加
stringBuffer.append("xixi");
stringBuffer.append("haha");
// xixihaha 的内存地址和 xixi 的内存地址是一致的
System.out.println(stringBuffer);
// 在进行大量的字符串拼接的时候,效率是比较高的
// 在字符串指定的位置插入一个字符串
stringBuffer.insert(3,"狗蛋 ");
System.out.println(stringBuffer);
// 字符串反转的方法 ahahi 蛋狗xix
System.out.println(stringBuffer.reverse());
// 要头不要尾 ahi 蛋狗xix
System.out.println(stringBuffer.delete(1,3));
}
}
StringBuilder 是线程不安全,所以效率比 StringBuffer 高!!!
String | StringBuffer | StringBuilder |
String 的值是不可变的,这就导致每次对 String 的操作都会生成新的 String 对象,不仅效率低下,而且浪费大量有限的内存空间 | StringBuffer 是可变类,和线程安全的字符操作类,任何对它指向的字符串的操作都不会产生新的对象。每个 StringBuffer 对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 | 可变类,速度更快 |
不可变 | 可变 | 可变 |
线程安全 | 线程不安全 | |
StringBuffer 是单线程的,因为里面的方法都是被 synchronize 修饰了,所以它线程安全,但是效率自然就降低。多线程操作字符串建议使用 StringBuffer。 | StringBuilder 不是单线程的,因为里面的方法没有被 synchronize 修饰了。所以它线程不安全,所以效率要更高。单线程操作字符串建议使用 StringBuilder |
所以为啥 String 不会被直接替代?啥时候效率低,是在进行字符串拼接的时候效率低。在没有字符串拼接的时候,人家的效率是很高的!!! String name;
StringBuffer 和 StringBuilder 开发的时候很少用!!! String 用的最多的!!!
2.2 枚举类
以后还会再讲,现在听不懂没关系。只要知道他是枚举就可以了
Java 中的枚举是特殊的类,枚举一般是表示一组常量
在 Java 中用什么来表示常量:
public static final String WEEK = "星期一"; 不可改变的量
现在可以使用枚举来辨识常量
Java 中定义枚举类的语法格式:
public enum 枚举类的名字 { 常量1, 常量2, 常量3 }
package com.study.d_enum;
/**
* @author big God
* @date 2022/12/30 10:43 * @version 1.0
*/
enum Color {
// 常量是 static 修饰的直接类名.常量
RED, GREEN, BLUE
}
public class Demo1 {
public static void main(String[] args) {
Color red = Color.RED;
// RED
System.out.println(red);
// BLUE
System.out.println(Color.BLUE);
}
}
枚举一般在 switch -case 中使用
package com.study.d_enum;
/**
* @author big God
* @date 2022/12/30 10:47 * @version 1.0
*/
enum Color1 {
RED, YELLOW, BLACK
}
public class Demo2 {
public static void main(String[] args) {
Color1 red = Color1.RED;
switch (red) {
case RED:
System.out.println("红色");
break;
case BLACK:
System.out.println("黑色");
break;
case YELLOW:
System.out.println("黄色");
break;
}
}
}
枚举类中的几个方法
values(); 枚举类中的所有的值
oridnal(); 可以找到枚举类中常量值的索引
valueOf(); 返回值是字符串的常量
package com.study.d_enum;
import java.util.Arrays;
/**
* @author big God
* @date 2022/12/30 10:51 * @version 1.0
*/
enum Color2 {
PINK, WHITE, GREEN
}
public class Demo3 {
public static void main(String[] args) {
Color2[] v = Color2.values();
System.out.println(Arrays.toString(v));
for (Color2 color2 : v) {
System.out.println(color2 + " 对应的索引为:" + color2.ordinal());
}
// valueOf 返回值是字符串的常量
Color2 color2 = Color2.valueOf("GREEN");
System.out.println(color2);
}
}
比如咱们定义很多的状态量,比如:订餐支付,未支付,订单完结,派送中,制作中。等有很多的状态
如果不使用枚举,思考这个状态定义成什么样的一个常量。写注释。如果使用枚举,基本不会出错
package com.study.d_enum;
/**
* @author big God
* @date 2022/12/30 11:00 * @version 1.0
*/
enum ProductEnum {
// 枚举写法是利用枚举类的有参构造对 code 和 message 进行赋值的
UP(0,"上架"), DOWN(1, "下架");
private Integer code;
private String message;
// 可以提供构造方法对其进行赋值
ProductEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
public class Demo4 {
public static void main(String[] args) {
System.out.println(ProductEnum.UP.getCode());
System.out.println(ProductEnum.UP.getMessage());
System.out.println(ProductEnum.DOWN.getCode());
System.out.println(ProductEnum.DOWN.getMessage());
}
}
练习:
Student 类: name 属性 sex 属性
package com.study.d_enum;
/**
* @author big God
* @date 2022/12/30 11:07 * @version 1.0
*/
enum Student {
MAN("宫本武藏",1),WOMAN("不知火舞",0);
private String name;
private int sex;
Student() {
}
Student(String name, int sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
public class Demo5 {
public static void main(String[] args) {
System.out.println(Student.MAN.getSex());
System.out.println(Student.MAN.getName());
System.out.println(Student.WOMAN.getName());
System.out.println(Student.WOMAN.getSex());
}
}
2.3 包装类
Java 有八大基本数据类型,都有与之对应的包装类
为啥要有对应的包装类?
int 类型是没有提供方法的。int 的包装类 Integer 类下面有很多方法,可以对 int 类型的数据进行方法的调用!!!
int => Integer
byte => Byte
short => Short
long => Long
char => Character
float => Float
double => Double
boolean => Boolean
【重点】
自从 JDK 1.5 之后,有自动拆箱和自动装箱
自动装箱:将基本数据类型转为包装类
自动拆箱:将包装类转为基本数据类型
package com.study.e_packing;
/**
* @author big God
* @date 2022/12/30 11:18 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
// 20 是什么类型的数据? int
// int 转为 Integer 自动装箱 所以不报错!!!
Integer i = 20;
System.out.println(i);
Integer i1 = new Integer(34);
// i1 是 Integer 类型的数据 赋值给 int 类型的数据,为啥没报错??
// Integer => int 自动拆箱
// 以后在开发中 int <==> Integer 是无缝连接 不用再管了
int i2 = i1;
System.out.println(i2); // 34
}
}
上午的内容
1.递归回顾开发不用
2.常用类, StringBuffer StringBuilder
类 创建对象 调用方法
枚举类:今天学的东西没学会也没关系,咱们后期还会再讲,在项目中加这个东西,就立体化了
包装类:
自动装箱: 基本数据类型自动转为包装类
自动拆箱: 将包装类转为基本数据类型
***Value(); 将包装类转为基本数据类型【类似于自动拆箱】
valueOf(); 静态方法,将基本数据类型转为包装类【类似于自动装箱】
toString(); 静态方法 将基本数据类型转为字符串
以上的三个方法开发不常用
parse***(); 将字符串转为基本数据类型【开发要用的】【重点】
package com.study.e_packing;
/**
* @author big God
* @date 2022/12/30 11:26 * @version 1.0
*/
public class Demo2 {
public static void main(String[] args) {
// ***Value(); 将包装类型的数据转为基本数据类型
Integer i1 = 250;
// i1 此时什么类型的数据 Integer 不是 int, 250 是int 类型.
int i = i1.intValue(); // 类似于自动拆箱
int i2 = i1; // 自动拆箱!!
// i 此时是 int 类型的数据
System.out.println(i);
Long l1 = 3479823L;
// 将 Long 类型的数据转为 long 类型的数据 包装类转为基本数据类型
long l = l1.longValue();
System.out.println(l);
Short s1 = 32;
// 将 Short 类型的数据转为 short 类型的数据 包装类转为基本数据类型
short s = s1.shortValue();
System.out.println(s);
// valueOf();
int i4 = 89;
// 将 int 转为 Integer 的包装类
Integer i5 = Integer.valueOf(i4);
String s2 = Integer.toString(328);
System.out.println(s2.getClass().getName());// 328
String str = "345";
int i6 = Integer.parseInt(str);
System.out.println(i6); // i6 是 int 类型的数据
// 将一个字符串转为 long 类型的数据
System.out.println(Long.parseLong("423749823745"));
}
}
2.4 Math 类
Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
专门处理数学的一个类,开发中用到指数?对数?平方根?都用不到!!! 你有,但是我用不到
开发中常用的:
绝对值
最大值
最小值
向上取整
向下取整
四舍五入
随机数
package com.study.f_math;
/**
* @author big God
* @date 2022/12/30 11:44 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
/**
* Math 是 JDK 封装好的一个类
* 你碰到一个类,用这个类咱们首先想到的是创建对象!!!
* 创建对象的目的是? 对象.方法 拿对象调用方法
* 有些时候有些类是没有构造方法就意味着你没办法 new 对象
* 但是人家封装的方法是静态的方法,静态属性
* 你可以直接使用类.方法 类.属性
*/
// 自然底数
System.out.println(Math.E);
// π
System.out.println(Math.PI);
// 绝对值 absolute 绝对的意思
System.out.println(Math.abs(-89)); // 89
// 求两个数的最大值
System.out.println(Math.max(45,89.8)); // 89.9
// 求三个数的最大值?
System.out.println(Math.max(89,Math.max(67,23))); // 89
// 求 100 个数据的其中的最大值? 借助与 for 循环 两两比较
// 数组装起来,调用 sort() 输出最后一个数据
// 最小值 min
System.out.println(Math.min(Math.max(34.12, 23),12.34));
// 向上取整 ceil 天花板
System.out.println(Math.ceil(7.46896));
// 向下取整 floor 地板
System.out.println(Math.floor(5.99));
// 四舍五入 round
System.out.println(Math.round(7.48)); //返回值是 long 类型的数据
// 随机数 double 大于或等于 0.0 并小于 1.0
System.out.println((int)(Math.random() * 100 + 100));
// 随机生成 [0, 100] 的 int 类型的整数
System.out.println((int) (Math.random() * 100));
}
}
2.5 Random 类
专门生成随机数的类
package com.study.g_random;
import java.util.Random;
/**
* @author big God
* @date 2022/12/30 15:04 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
Random random = new Random();
// int 数据的范围
System.out.println(random.nextInt());
System.out.println(random.nextDouble());
System.out.println(random.nextBoolean());
System.out.println(random.nextFloat());
}
}
2.6 System 类
System 类包含一些有用的类字段和方法。它不能被实例化。
在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。
package com.study.h_system;
import java.io.PrintStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.Scanner;
/**
* @author big God
* @date 2022/12/30 15:10 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) throws ParseException {
Scanner scanner = new Scanner(System.in); // 控制台 "标准" 输入流。
PrintStream out = System.out; // out "标准" 输出流 控制台打印的是黑色的
out.println("hello,world");
System.out.println("hello,world");
System.err.println("错误"); // "标准" 错误输出流, 控制台打印的是红色的字体
// 当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)。
long l = System.currentTimeMillis();
System.out.println(l); // 1672384594295
// 创建日期格式化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(l));
System.out.println(sdf.parse("2022-12-12 12:12:12"));
// 可以通过 System 获取当前 windows 系统的信息
Properties properties = System.getProperties();
// 属性列表中的,每个键及其对应的值都是一个字符串,
// properties 存的都是字符串
System.out.println(properties.get("os.name")); // window10
System.out.println(properties.get("os.version")); // 10.0
System.out.println(properties.get("user.name")); // lenovo
System.out.println(properties.get("user.dir")); // D:\AQF\idea\IDEA\work\work3\Day03_IDEA_YCL
System.out.println(properties.get("java.version")); // 1.8.0_331
}
}
2.7 Runtime【不重要】
每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
package com.study.i_runtime;
import org.omg.SendingContext.RunTime;
import java.io.IOException;
/**
* @author big God
* @date 2022/12/30 15:53 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
// 虚拟机试图使用的最大内存量,以字节为单位。
System.out.println(runtime.maxMemory()/1024 /1024); // 1685 MB
// 返回 Java 虚拟机中的空闲内存量,以字节为单位
System.out.println(runtime.freeMemory()/ 1024 /1024); // 112
// 返回 Java 虚拟机中的内存总量,以字节为单位
System.out.println(runtime.totalMemory()/ 1024 /1024); // 115
// 可以启动外部【电脑中】的应用程序
runtime.exec("D:\\AQF\\notepad\\Notepad++\\notepad++");
}
}
2.8 Date 类
专门处理日期的
先知道有这个类,然后后面和数据库进行结合,因为数据库里面存的可能是
date:2010-01-01 年月日
time: 00:00:00 时分秒
datetime: 2010-10-10 00:00:00 年月日 时分秒
timestamp: 时间戳
数据库设计字段的时候,一定要将数据库里面数据赋值给类,类转换异常的靠一些方法进行操作。
现在只需要学类,学类下面的方法即可,其他的不用管!!!
package com.study.j_date;
import java.util.Date;
/**
* @author big God
* @date 2022/12/30 16:09 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
Date date = new Date();
// Fri Dec 30 16:09:37 CST 2022
// CST 伊尔库茨克时间
System.out.println(date);
// 获取年份
// 已过时。 从 JDK 1.1 开始,由 Calendar.get(Calendar.YEAR) - 1900 取代。
// 这个日期代表的年份,减去 1900 年,如果要想获取真实的年份 + 1900
System.out.println(date.getYear() + 1900);
// 获取月份 返回表示月份的数字,该月份包含或开始于此 Date 对象所表示的瞬间。返回的值在 0 和 11 之间,值 0 表示 1 月。
System.out.println(date.getMonth() + 1);
// 获取日期
System.out.println(date.getDate());
// 此日期所表示的一周中的某一天。
System.out.println(date.getDay());
System.out.println(date.getHours());
System.out.println(date.getMinutes());
System.out.println(date.getSeconds());
}
}
自己玩两个类 LocalDate(2022-12-12),LocalDateTime(2022-12-12 12:12:12)
不幸的是,这些功能的 API 不适合国际化。从 JDK 1.1 开始, Calender 类应该用于在日期和时间字段之间进行转换,并且 DateFormat 类应用于格式化和解析日期字符串,在相应的方法 Date 被弃用
2.9 Calender 类
Calender 的 getInstance 方法返回一个 Calender 对象,其日历字段已使用当前日期和时间进行初始化
package com.study.k_canlendar;
import java.util.Calendar;
/**
* @author big God
* @date 2022/12/30 16:33 * @version 1.0
*/
public class Demo1 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 获取当前的年份
// get(int field) field - 指定的日历字段
int i = calendar.get(Calendar.YEAR);
System.out.println(i);
// 获取当前月份 0 ~ 11 月
System.out.println(calendar.get(Calendar.MONTH ) + 1);
// 获取当月的第几天
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 30
// 获取当年的第几天
System.out.println(calendar.get(Calendar.DAY_OF_YEAR)); // 364
// 获取当周的第几天
System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // 6
System.out.println(calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH)); // 5
// 获取时分秒.毫秒
System.out.println(calendar.get(Calendar.HOUR));
System.out.println(calendar.get(Calendar.HOUR_OF_DAY));
System.out.println(calendar.get(Calendar.MINUTE));
System.out.println(calendar.get(Calendar.SECOND));
System.out.println(calendar.get(Calendar.MILLISECOND));
}
}
扩展:将日期转为字符串格式的数据
package com.study.k_canlendar;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
/**
* @author big God
* @date 2022/12/30 16:50 * @version 1.0
*/
public class Demo2 {
public static void main(String[] args) throws ParseException {
Calendar time = Calendar.getInstance();
System.out.println(time);
// 可以将 Calender 转为 Date 类型数据的
System.out.println(time.getTime());
// Fri Dec 30 16:51:50 CST 2022 看不懂 可以将 Date 对象数据转为字符串
// 需要借助一个类 SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(time.getTime()));
System.out.println(sdf.parse("2022-12-12 12:12:12"));
}
}
在项目中还会再讲!!!!