Week03

Day11

Object

含义:所有类的基类/超类
理解:一个类没有明确继承的父类,都默认继承Object
equals():判断两个对象的地址是否相同

	 public boolean equals(Object obj){
		return (this == obj);
	}

​ getClass():获取类的字节码文件对象
​ hashCode():获取对象的hash码
​ hash码:对象的地址 + 散列算法(注意:hash码不等于内存地址)
​ toString():将对象转换为字符串格式,打印对象,默认调用toString方法

public String toString(){
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
//getClass().getName() 获取到当前类的全路径名
//Integer.toHexString(hashCode()) 将十进制的hash码转换为十六进制

类: A.java

对象:equals(): Test01.java

对象:equals()和getClass(): Test02.java

对象:hashCode(): Test03.java

对象: toString(): Test04.java

深入Object

含义:Object作为所有类的超类,起到标杆作用
equals()标杆作用:判断两个对象是否相同
理解:Object不同的子类,判断两个对象的方式是不一样的,所以在子类中重写该方法,定义适合当前子类判断两个对象的规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2TuP0TGq-1644159259789)(D:\2113java_workspace\Day11\Day11上午\equals理解图.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D0OCcyR8-1644159259789)(D:\2113java_workspace\Day11\Day11上午\equals深入理解图.png)]

​ toString()标杆作用:打印对象中的数据
​ 理解:Object不同的子类用于不同的属性,所以在子类中重写该方法,返回想要展示的属性即可

需求:模拟银行的用户类

User类: User.java

对象: Test01.java

需求:模拟千锋的学生类

​ 判断两个学生是否相同:班级号 + 学号

​ 总结 - 编写实体类的步骤:

​ 1.成员变量

​ 2.私有化成员变量

​ 3.无参构造

​ 4.有参构造

​ 5.get/set方法

​ 6.根据需求 – 重写equals

​ 7.根据需求 – 重写toString

Student类: Student.java

对象: Test01.java

深入Object — String

MyString 类: MyString.java

对象: Test01.java

final – 最终的

1.修饰类:该类不能被继承
2.修饰方法:该方法不能被重写
3.修饰变量:该变量变成常量不能被重新赋值,该常量存储在常量池中,直到项目结束才会被销毁

A类: A.java

B extends A: B.java

对象: Test01.java

抽象类及抽象方法

抽象类:使用abstract修饰
抽象方法:使用abstract修饰,该方法没有代码块
抽象方法的应用场景:
编写一个类,该类里的某个方法不太好实现,又觉得该方法应该在这个类里,就把该方法设置成抽象方法,交给非抽象的子类去重写/实现即可,该抽象方法所在的类必须是抽象类

需求:编写人类、中国人、日本人

​ 人类(抽象类):

  • 属性:姓名、性别、年龄

  • 方法:吃饭饭(抽象方法)、睡觉觉

    日本人 extends 人类:

  • 属性:年号

  • 方法:拍电影

  • 重写父类的吃饭饭

    中国人(抽象类) extends 人类:

  • 属性:身份证

  • 方法:打太极、爱好(抽象方法)

    四川人 extends 中国人

  • 属性:无

  • 方法:重写吃饭饭、重写爱好

Person类: Person.java

Chinese类: Chinese.java

Japanese类: Japanese.java

SiChuan类: SiChuan.java

GuangDong类: GuangDong.java

对象: Test01.java

深入抽象类及抽象方法

1.抽象类中只能有抽象方法?
不是,抽象类可以有抽象方法、构造方法、成员方法、静态方法
2.抽象类中不可以没有抽象方法?
可以,但是毫无意义
3.如果父类是抽象类,则子类必须实现父类的抽象方法?
不一定,
子类如果是抽象类,可以不实现父类的抽象方法,交给子类的非抽象类的子类去实现
子类如果不是抽象类,则必须实现父类的抽象方法
4.抽象类不能有构造方法?
可以
5.可以使用new关键字来创建抽象类对象?
不可以,创建的是匿名内部类的对象,抽象类是不能有对象的
创建匿名内部类(匿名子类)的对象
1.创建匿名内部类
2.继承Chinese,重写父类的抽象方法
3.创建匿名内部类的对象
4.将匿名内部类对象的地址赋值给父类的引用(多态)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f8VBgAH9-1644159259790)(D:\2113java_workspace\Day11\Day11下午\抽象类的匿名内部类的理解图.png)]

需求:编写人类、中国人、日本人

​ 人类(抽象类):

  • 属性:姓名、性别、年龄

  • 方法:吃饭饭(抽象方法)、睡觉觉

    日本人 extends 人类:

  • 属性:年号

  • 方法:拍电影

  • 重写父类的吃饭饭

    中国人(抽象类) extends 人类:

  • 属性:身份证

  • 方法:打太极、爱好(抽象方法)

    四川人 extends 中国人

  • 属性:无

  • 方法:重写吃饭饭、重写爱好

Person类: Person.java

Chinese类: Chinese.java

Japanese类: Japanese.java

SiChuan类: SiChuan.java

GuangDong类: GuangDong.java

对象: Test01.java

接口

知识点:接口
含义:特殊的抽象类
理解:
1.接口中只能有静态常量(默认添加 public static final)和抽象方法(默认添加 abstract)
2.JDK1.8开始接口中允许有默认方法和静态方法(JDK1.8新特性)

接口I1: I1.java

A implements I1: A.java

对象: Test01.java

知识点:接口的应用
理解:制定标准
需求:模拟用户操作

接口IUserService: IUserService.java

serServiceImpl implements IUserService: UserServiceImpl.java

对象: Test01.java

深入接口

类 - 接口的关系

​ 类 - 类:单继承

​ 类 - 接口:多实现

​ 接口与接口:多继承

1.一个类可以实现多个接口?
可以的
2.一个接口可以实现多个接口?
不可以
3.接口里面的方法不一定都是抽象的?
对的,JDK1.8开始接口中允许使用静态方法和默认方法
4.接口解决了类的单继承问题?
是的
5.一个类是否可以继承一个类并同时实现多个接口?
可以
6.接口可以new对象?
不可以,创建时匿名内部类的对象

​ 创建匿名内部类的对象
​ 1.底层创建匿名内部类
​ 2.实现I1接口中的抽象方法
​ 3.创建匿名内部类的对象
​ 4.将匿名内部类对象的地址赋值给接口的引用

7.接口里面的是抽象方法,想要重写接口里面的方法:
让类去实现这个接口然后在类里面重写接口里面的方法。
要在对象里面重写接口里面的方法,就通过匿名内部类的形式创建接口的对象,让对象去重写接口里面的方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sfj0ch59-1644159259790)(D:\2113java_workspace\Day11\Day11下午\接口的匿名内部类理解图.png)]

7.一个类实现了多个接口,多个接口中的方法名重复,是什么情况?
只实现一个方法

I1接口: I1.java

I2接口: I2.java

I3 extends I4,I5: I3.java

I4接口: I4.java

I5接口: I5.java

A extends Object implements I1,I2,I3: A.java

对象: Test01.java

Day12

多态

类的多态

子类对象指向父类引用
理解:父类引用中存的是子类对象在堆中地址

OCP – 开闭原则
O - open - 在需求更改时,对于创建类是欢迎的
C - close - 在需求更改时,对于修改原有类是拒绝的
P - principle(原则)

package com.qf.test01;

public class Test01 {
	
	public static void main(String[] args) {
		/**
		 * 知识点:多态
		 * 
		 * 需求:老师骑着自行车上班
		 * 分析:老师类、自行车类
		 * 
		 * 需求升级:自行车 --> 小汽车
		 * 步骤:
		 * 		1.创建Car类,添加open、close方法
		 * 		2.在Teacher类中,添加start、stop方法 -- 改动原有类的结构
		 * 需求升级:自行车 --> 小汽车 --> 飞机
		 * 步骤:创建Plane类,继承Vehicle类
		 */
		
		Teacher t = new Teacher();    
		Vehicle v = new Plane();
		v这个引用存的是Plane的对象在堆中开辟的地址
		t.start(v);
		System.out.println("欣赏沿途的风景...");
		t.stop(v);
	}
}

交通工具Vehicle 类: Vehicle.java

Plane类: Plane.java

Car类: Car.java

Bick类: Bick.java

Teacher类: Teacher.java

对象: Test01.java

接口的多态

实现类的对象指向接口的引用

理解:接口的引用存储的是实现类对象在堆中开辟的地址

需求:模拟电脑连接外部设备(鼠标、键盘、硬盘)

IUSB类: IUSB.java

Mouse类: Mouse.java

Keyboard类: Keyboard.java

Disk类: Disk.java

Computer类: Computer.java

对象: Test01.java

多态的实际应用

需求:设计一个方法输入编号,返回对应的动物对象
1-返回狗类对象
2-返回猫类对象
3-返回猪类对象

Animal类: Animal.java

Dog类: Dog.java

Cat类: Cat.java

Pig类: Pig.java

对象: Test01.java

对象转型

自动转型(向上转型)

注意:

1.向上转型其实就是类的多态

2.可以调用父类非私有化的属性

3.可以调用父类非私有化的方法

4.不可以调用子类的属性

5.不可以调用子类的方法

6.可以调用子类重写父类的方法

多态的优点:

遵循了OCP原则

多态的缺点:

不可以调用子类的属性和方法

A类: A.java

B extends A: B.java

对象: Test01.java

强转转型(向下转型)

强转转型(向下转型):父类类型 转 子类类型
注意:
1.向下转型有风险,ClassCastException - 类型转型异常
2.先向上转型,再向下转型

Animal类: Animal.java

Dog类: Dog.java

Cat类: Cat.java

对象: Test01.java

MyString类: MyString.java

对象: Test01.java

内部类

知识点:内部类
含义:一个类中还去声明了另一个类
分类:
1.成员内部类
2.静态内部类
3.接口内部类
4.局部内部类
5.匿名内部类

成员内部类

​ 可以调用外部类所有的属性

​ 创建成员内部类的对象
​ Inner inner = new Outter().new Inner();

​ 调用方法
​ inner.method();

Outter类(含成员内部类Inner): Outter.java

对象: Test01.java

静态内部类

注意:不用创建外部类对象,直接使用外部类类名.内部类的构造方法
总结:只能调用外部类的静态属性

创建静态内部类的对象
Inner inner = new Outter.Inner();

调用方法
inner.method();

Outter类(含静态内部类Inner): Outter.java

对象: Test01.java

接口内部类

注意:默认使用static修饰
总结:创建接口内部类的方式和静态内部类一样

创建接口内部类的对象
Inner inner = new I1.Inner();

调用方法
inner.method();

I1接口(含接口内部类Inner): I1.java

对象: Test01.java

局部内部类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cUTYtvDt-1644159259792)(D:\2113java_workspace\Day12\Day12下午\局部内部类扩展图.png)]

注意:局部内部类相当于局部变量,不能使用访问修饰符修饰

总结:局部内部类使用外部类的局部变量,JDK1.8开始该变量会自动使用final修饰

创建外部类对象
Outter outter = new Outter();
调用方法
outter.outterMethod();

Outter类(含局部内部类Inner): Outter.java

对象: Test01.java

Outter类(含局部内部类Inner): Outter.java

对象: Test01.java

匿名内部类

类的匿名内部类
接口的匿名内部类

匿名内部类

package com.qf.outter_inner_07;

public class Test01 {

	public static void main(String[] args) {
		
		//匿名内部类
		//1.创建匿名类,继承A类重写method方法
		//2.创建匿名类的对象
		//3.赋值给父类的引用
		A a = new A() {
			@Override
			public void method() {
			}
		};
		
		//匿名内部类
		//1.创建匿名类,实现I1接口中的method方法
		//2.创建匿名类的对象
		//3.赋值给接口的引用
		I1 i1 = new I1() {
			@Override
			public void method() {
			}
		}
	}
}

A类: A.java

接口: I1.java

对象: Test01.java

面向对象版本五子棋

类: GoBang.java

对象: Test01.java

学生管理系统

Student.java

StuInfoUtils.java

IStudentManagerSystem.java

StudentManageSystemImpl.java

Main.java

StuInfoType.java

Day13

包装类

package com.qf.test01;

import java.util.Arrays;

public class Test01 {
	
	public static void main(String[] args) {
		
知识点:包装类
含义:8种基本数据类型对应的类
出现原因:Java为纯面向对象语言(万物皆对象)8种基本数据类型不能创建对象,破坏了Java为纯面向对象语言的特征,所以Java又提供了8种基本数据类型对应的类,这种类叫做包装类/封装类
		 包装类及继承关系:
		 * 	基本数据类型		包装类
		 * 	byte			Object.Number.Byte
		 * 	short			Object.Number.Short
		 * 	int				Object.Number.Integer
		 * 	long			Object.Number.Long
		 * 	float			Object.Number.Float
		 * 	double			Object.Number.Double
		 * 	char			Object.Character
		 * 	boolean			Object.Boolean
             
		 手动装箱 -- valueOf():基本数据类型 -> 包装类
			int i = 100;
			Integer integer = Integer.valueOf(i);
			System.out.println(integer);
			
		 手动拆箱 -- intValue():包装类 -> 基本数据类型
			int intValue = integer.intValue();
			System.out.println(intValue);
		
		 JDK1.5开始有自动装箱和自动拆箱的功能
		 自动装箱:基本数据类型 -> 包装类
			int i = 100;
			Integer integer = i;//底层实现:Integer.valueOf(i);
			System.out.println(integer);
			
		 自动拆箱:包装类 -> 基本数据类型
			int intValue = integer;//底层实现:integer.intValue();
			System.out.println(intValue);
			
		 获取数值型的区间
			System.out.println(Byte.MAX_VALUE);
			System.out.println(Byte.MIN_VALUE);
			System.out.println(Integer.MAX_VALUE);//(1<<31)-1
			System.out.println(Integer.MIN_VALUE);//1<<31
			
			String str = "123";
			int num = Integer.parseInt(str);
			System.out.println(num);
			
		 需求:将String[] ss = {"1","2","3","4","5","6"}转换为int数组
		
			String[] ss = {"1","2","3","4","5","6"};
		
			int[] is = new int[ss.length];
		
			for (int i = 0; i < ss.length; i++) {
				//获取字符串数组中的元素
				String element = ss[i];
				//将元素转换为int值
				int num = Integer.parseInt(element);
				//赋值给int数组
				is[i] = num;
			}	
			System.out.println(Arrays.toString(is));	
		}	
	}

手撕包装类源码

包装类: MyInteger.java

对象: Test01.java

字符串类

String的使用

String是不可变类,即一旦一个String对象被创建, 包含在这个对象中的字符序列是不可改变的, 直至该对象被销毁。 String类是final类,不能有子类。

package com.qf.test03;
public class Test01 {	
	public static void main(String[] args) {
		
		String str = "123abc";
		
		str = str.concat("DEF123");//在此字符串末尾追加子字符串,并返回新的字符串
		str = str.substring(3);//从下标处截取到字符串末尾,并返回新的字符串
		str = str.substring(1, 6);//从开始下标处(包含)截取到结束下标处(不包含),并返回新的字符串
		str = str.toUpperCase();//转大写,并返回新的字符串
		str = str.toLowerCase();//转小写,并返回新的字符串
		
		str = "  123 a   b cD  EF  123    ";
		
		str = str.trim();//去掉首尾空格,并返回新的字符串
		str = str.replace('2', '-');//替换字符,并返回新的字符串
		str = str.replace("1-3", "钟燕");//替换字符串,并返回新的字符串
		
		//把空格字符串替换成 空内容的字符串
		str = str.replace(" ", "");//替换字符串,并返回新的字符串
		str = str.replaceFirst("燕", "馗");//替换第一个出现的字符串,并返回新的字符串
		
		System.out.println("判断两个字符串是否相同(区分大小写):" + str.equals("钟馗abcDEF钟燕"));//true
		System.out.println("判断两个字符串是否相同(不区分大小写):" + str.equalsIgnoreCase("钟馗abcdef钟燕"));//true
		
		System.out.println("判断此字符串是否以某个字符串开头:" + str.startsWith("钟馗"));//true
		System.out.println("判断此字符串是否以某个字符串结尾:" + str.endsWith("钟燕"));//true
		
		System.out.println("查询子字符串在此字符串中第一次出现的下标:" + str.indexOf("钟"));//0
		System.out.println("查询子字符串在此字符串中最后一次出现的下标:" + str.lastIndexOf("钟"));//8
		
		System.out.println("通过下标获取字符串中对应的字符:" + str.charAt(5));//D
		
		//钟馗abcDEF钟燕
		System.out.println(str);
		
		//将其他类型转为字符串
		String valueOf1 = String.valueOf(100);
		String valueOf2 = String.valueOf(123.12);
		String valueOf3 = String.valueOf(true);
		System.out.println(valueOf1);
		System.out.println(valueOf2);
		System.out.println(valueOf3);
		
		//将其他类型转为字符串 -- 更简单的方法
		System.out.println('a' + "");
		System.out.println(100 + "");
		System.out.println(123.12 + "");
		System.out.println(true + "");	
	}
}
深入String
面试题:这段代码在底层生成多少个String对象?
		1个(常量池中)
		String str1 = "abc";
		String str2 = "abc";
		
面试题:这段代码在底层生成多少个String对象?
		3("abc"一个,new了两个String)
		String str1 = new String("abc");
		String str2 = new String("abc");


		String str1 = "abc";
		String str2 = "abc";
		System.out.println(str1 == str2);//true
		
		//"ab"和"c"都是字面值常量,在编译时就直接拼接成"abc"
		String str3 = "ab" + "c";
		System.out.println(str1 == str3);//true
		
		//两个字面值常量,在编译时直接拼接
		final String s1 = "ab";
		final String s2 = "c";
		String str4 = s1 + s2;
		System.out.println(str1 == str4);//true
		
		//两个变量拼接底层会创建StringBuilder对象
		String s3 = "ab";
		String s4 = "c";
		String str5 = s3 + s4;//new StringBuilder(s3).append(s4).toString();
		System.out.println(str1 == str5);//false

StringBuffer的使用

StringBuffer代表可变的字符序列
StringBuffer称为字符串缓冲区
它的工作原理是:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer是可变对象,这个是String最大的不同

StringBuffer extends AbstractStringBuilder

package com.qf.test03;
public class Test02 {	
	public static void main(String[] args) {
		
		创建StringBuffer的对象 -- 默认缓冲区大小:16个字符
		StringBuffer sb = new StringBuffer();
		
		创建StringBuffer的对象 -- 自定义缓冲区大小:32个字符
		StringBuffer sb = new StringBuffer(32);
		
		创建StringBuffer的对象 -- 自定义缓冲区大小:"123abc".length() + 16个字符
		StringBuffer sb = new StringBuffer("123abc");
		
		sb.append("DEF123");//在末尾追加
		sb.insert(6, "-_-");//在指定下标上插入字符串
		sb.setCharAt(7, '+');//替换指定下标上的字符
		sb.deleteCharAt(7);//删除指定下标上的字符
		sb.delete(3, 6);//从开始下标处(包含)删除结束下标处(不包含)的字符串
		sb.replace(3, 5, "ABC");//从开始下标处(包含)替换结束下标处(不包含)的字符串
		sb.reverse();//反转字符串
		
		//321FEDCBA321
		System.out.println(sb);
	}
}

StringBuilder的使用

StringBuilder extends AbstractStringBuilder
StringBuffer extends AbstractStringBuilder
在使用层面上,StringBuilder和StringBuffer没有区别

StringBuilder 是线程不安全的,效率高,单线程下使用
StringBuffer 是线程安全的(因为有上锁解锁的步骤),效率低,多线程下使用

频繁的字符串拼接,请使用StringBuilder或StringBuffer

package com.qf.test03;
public class Test07 {
	public static void main(String[] args) {
		
		//System.currentTimeMillis();获取1970.1.1 0:0:0到现在的毫秒数(1000毫秒=1秒)
		
		long startTime = System.currentTimeMillis();
		String str = "钟燕小可爱,";
		for (int i = 0; i < 10000; i++) {
			str += "爱你~~~";
			//str = str+"爱你~~~";
			//str = new StringBuilder(str).append("爱你~~~").toString();
		}
		long endTime = System.currentTimeMillis();
		System.out.println(endTime - startTime);//272毫秒
		
		long startTime = System.currentTimeMillis();
		StringBuilder sb = new StringBuilder("钟燕小可爱,");
		for (int i = 0; i < 10000; i++) {
			sb.append("爱你~~~");
		}
		long endTime = System.currentTimeMillis();
		System.out.println(endTime - startTime);//3毫秒	
	}
}

Day14

date

知识点:日期时间类
Date:日期类
SimpleDateFormat:格式化日期类
Calendar:日历类

总结:
Date + SimpleDateFormat 联合使用,获取想要的日期格式
Calendar:获取某个日期信息

package com.qf.date;
import java.util.Date;
public class Test01 {
	public static void main(String[] args) {

		Date date = new Date();
		//星期  月份    日    时:分:秒      时区   年份
		//Thu Dec 30 10:27:37 CST 2021
		System.out.println(date);
	
		//从1970.1.1 0:0:0 + 时区 往后推1000毫秒
		Date date = new Date(1000);
		System.out.println(date);
	}
}
package com.qf.date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test02 {	
	public static void main(String[] args) throws ParseException {
		//创建格式化日期类的对象
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");	
		//日期类对象 --> 字符串
		String format = sdf.format(new Date());
		System.out.println(format);	
		//字符串 --> 日期类对象
		Date date = sdf.parse("2021年12月30日 10:33:70");
		System.out.println(date);
	}
}
package com.qf.date;
import java.util.Calendar;
public class Test03 {
	public static void main(String[] args){	
		 
		//获取日历类的对象
		Calendar c = Calendar.getInstance();
		
		//获取日历信息
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DAY_OF_MONTH);
		int hour = c.get(Calendar.HOUR);
		int minute = c.get(Calendar.MINUTE);
		int second = c.get(Calendar.SECOND);
		
		System.out.println(year);
		System.out.println(month);
		System.out.println(day);
		System.out.println(hour);
		System.out.println(minute);
		System.out.println(second);
	}
}

math

含义:数学类,提供了基本的运算和几何函数
注意:Math是final类,并且该类所有的属性和方法都是静态的

把Math类中所有的静态属性和静态方法都导入到当前类
让这些静态属性和静态方法成为当前类自己的静态属性和静态方法

静态导入的缺点:可读性较差,如果当前类自身就有abs方法,就会就近调用

package com.qf.math;
public class Test01 {
	public static void main(String[] args) {
		
		System.out.println("求平方:" + Math.pow(3, 2));//9.0
		System.out.println("求平方根:" + Math.sqrt(9.0));//3.0
		System.out.println("求最大值:" + Math.max(10, 20));//20
		System.out.println("求最小值:" + Math.min(10, 20));//10
		System.out.println("向上取整(天花板):" + Math.ceil(1.001));//2.0
		System.out.println("向下取整(地板):" + Math.floor(1.999));//1.0
		System.out.println("四舍五入:" + Math.round(1.49));//2
		System.out.println("随机值:" + Math.random());//0(包含)~1(不包含)
		System.out.println("绝对值:" + Math.abs(-100));//100	
	}
}
面试题:Math.abs()是否会返回负数	
		System.out.println("绝对值:" + Math.abs(Integer.MAX_VALUE+1));
package com.qf.math;
import static java.lang.Math.*;
public class Test03 {
	public static void main(String[] args) {
		
		System.out.println("求平方:" + pow(3, 2));//9.0
		System.out.println("求平方根:" + sqrt(9.0));//3.0
		System.out.println("求最大值:" + max(10, 20));//20
		System.out.println("求最小值:" + min(10, 20));//10
		System.out.println("向上取整(天花板):" + ceil(1.001));//2.0
		System.out.println("向下取整(地板):" +floor(1.999));//1.0
		System.out.println("四舍五入:" + round(1.49));//2
		System.out.println("随机值:" + random());//0(包含)~1(不包含)
		
		//静态导入的缺点:可读性较差,如果当前类自身就有abs方法,就会就近调用
		System.out.println("绝对值:" + abs(-100));//100	
	}
	public static int abs(int i){
		return -888;
	}
}

regex

正则表达式

用来描述或者匹配一系列符合某个语句规则的字符串

案例:把一个字符串中带电话号码替换成130****1111

package com.qf.regex;
public class Test01 {
	public static void main(String[] args) {
		
		String str = "小红13012341111 小绿13922221234";
		
		//正则表达式
		String regex = "(1\\d{2})(\\d{4})(\\d{4})";
		//替换
		String replaceAll = str.replaceAll(regex,"$1****$3");
		
		System.out.println(replaceAll);		
	}
}

Pattern/Matcher

Pattern:代表正则表达式的匹配模式
Matcher:提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持

案例1:校验QQ邮箱

package com.qf.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test02 {

	public static void main(String[] args) {
		
		String email = "1445584980@qq.com";
		
		String regex = "\\d{5,10}@qq.com";
		
		//验证email字符串是否匹配regex的正则表达式
		//boolean matches = email.matches(regex);
		//底层实现:
		Pattern pattern = Pattern.compile(regex);//获取正则表达式的对象
		Matcher matcher = pattern.matcher(email);//获取匹配结果的对象
		boolean matches = matcher.matches();//获取验证结果
		
		System.out.println(matches);	
	}
}

案例2:分隔路径

package com.qf.regex;
import java.util.regex.Pattern;
public class Test03 {
	public static void main(String[] args) {
		
		String str = "C:\\资源\\日韩\\波多野结衣.avi";
		
		String regex = ":?\\\\";// :\\ 或 \\
		
		//String[] split = str.split(regex);//分隔字符串
		//底层实现:
		Pattern pattern = Pattern.compile(regex);
		String[] split = pattern.split(str);
		
		for (String s : split) {
			System.out.println(s);
		}
	}
}

案例3:Pattern+Matcher 找到前端代码中的图片路径

package com.qf.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test04 {
	public static void main(String[] args) {
	
		String str = "<img src='hhy/aaa.jpg'/><div><div/> <input type='image' src='submit.gif' /><img src='bbb.jpg'/>";
	
		String regex = "<img\\b[^>]*\\bsrc\\b\\s*=\\s*('|\")?([^'\"\n\r\f>]+(\\.jpg|\\.bmp|\\.eps|\\.gif|\\.mif|\\.miff|\\.png|\\.tif|\\.tiff|\\.svg|\\.wmf|\\.jpe|\\.jpeg|\\.dib|\\.ico|\\.tga|\\.cut|\\.pic)\\b)[^>]*>";
	
//		System.out.println("在字符串中是否整个匹配:" + matcher.matches());
//		System.out.println("在字符串中是否开头就匹配:" + matcher.lookingAt());
//		System.out.println("在字符串中是否有包含匹配:" + matcher.find());
		
		//获取正则表达式的对象
		Pattern pattern = Pattern.compile(regex);
		//获取匹配结果的对象
		Matcher matcher = pattern.matcher(str);
		
		//查询匹配结果
		while(matcher.find()){
			String group = matcher.group(2);
			System.out.println(group);
		}	
	}
}

random

随机类

深入Random – 种子数
理解:Random类的随机数都是通过算法得到的,算法中最终要的就是种子数,种子数固定,得到的随机数也是固定的

MyRandom.java

Test01.java

Test02.java

runtime

运行时的类,表示运行时环境

package com.qf.runtime;
public class Test01 {
	public static void main(String[] args) {
		
		//获取运行时环境的对象
		Runtime run = Runtime.getRuntime();
		
		System.out.println("最大内存:" + run.maxMemory());
		System.out.println("闲置内存:" + run.freeMemory());
		System.out.println("最大处理数:" + run.availableProcessors());	
	}
}
package com.qf.runtime;
public class Test02 {
	public static void main(String[] args) {
		/**
		 * 知识点:代码性能
		 * 考虑消耗时长+内存
		 */
		
		Runtime run = Runtime.getRuntime();
		long startMemory = run.freeMemory();
		long startTime = System.currentTimeMillis();
		String str = "钟燕小可爱,";
		for (int i = 0; i < 10000; i++) {
			str += "爱你~~~";
			str = str+"爱你~~~";
			str = new StringBuilder(str).append("爱你~~~").toString();
		}
		long endTime = System.currentTimeMillis();
		long endMemory = run.freeMemory();
	
		System.out.println("消耗时长:" + (endTime - startTime));//272毫秒
		System.out.println("消耗内存:" + (startMemory - endMemory));//-247658072(当内存不够时,gc回收了,导致内存反而变大)
		
		Runtime run = Runtime.getRuntime();
		long startMemory = run.freeMemory();
		long startTime = System.currentTimeMillis();
		StringBuilder sb = new StringBuilder("钟燕小可爱,");
		for (int i = 0; i < 10000; i++) {
			sb.append("爱你~~~");
		}
		long endTime = System.currentTimeMillis();
		long endMemory = run.freeMemory();
		System.out.println("消耗时长:" + (endTime - startTime));//2毫秒
		System.out.println("消耗内存:" + (startMemory - endMemory));//196624	
	}
}

System

package com.qf.system;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;
public class Test01 {

	public static void main(String[] args) {
		/**
		 * 知识点:System的属性
		 */
		
		//系统标准的输入流(控制台->程序)
		InputStream in = System.in;
		Scanner scan = new Scanner(in);
		String str = scan.next();
		
		//系统标准的输出流(程序->控制台)
		//PrintStream extends FilterOutputStream extends OutputStream
		PrintStream ps = System.out;
		ps.println(str);
		
		//系统标准的错误输出流(程序->控制台)
		//PrintStream extends FilterOutputStream extends OutputStream
		PrintStream ps = System.err;
		ps.println(str);
	
		//关流(关闭资源)
		scan.close();
	}
}
package com.qf.system;
public class Test02 {
	public static void main(String[] args) {
		/**
		 * 知识点:研究System的out和err
		 * out是一个线程
		 * err是另一个线程
		 * 感受多线程之间争抢CPU资源的场景
		 */
		
		System.out.println("小明");
		System.err.println("小红");
		System.out.println("小强");
	}
}
package com.qf.system;
import java.util.Arrays;
import java.util.Properties;
public class Test03 {
	public static void main(String[] args) {
		/**
		 * 知识点:System的方法
		 */
		
		//退出当前虚拟机,0表示正常退出
		System.exit(0);
		
		//获取自1970.1.1 0:0:0到现在的毫秒数
		System.out.println(System.currentTimeMillis());
		
		//获取系统的配置文件
		Properties properties = System.getProperties();
		System.out.println(properties);
	
		//通过key获取value
		String value = System.getProperty("os.name");
		System.out.println(value);
	
		//拷贝数组
		String[] names = {"黄小龙1","黄小龙2","黄小龙3"};
		String[] newNames = new String[3];
		System.arraycopy(names, 0, newNames, 0, names.length);
		
		System.out.println(Arrays.toString(newNames));		
	}
}

大数值的运算类

package com.qf.big;
import java.math.BigInteger;
public class Test01 {
	public static void main(String[] args) {
		/**
		 * 知识点:整数类型的大数值的运算类 - BigInteger
		 */
		
		BigInteger big1 = new BigInteger("1234567890");
		BigInteger big2 = new BigInteger("1234567890");
		
		//加法
		BigInteger add = big1.add(big2);
		System.out.println(add);//2469135780
		
		//减法
		BigInteger subtract = big1.subtract(big2);
		System.out.println(subtract);//0
		
		//乘法
		BigInteger multiply = big1.multiply(big2);
		System.out.println(multiply);//1524157875019052100
		
		//除法
		BigInteger divide = big1.divide(big2);
		System.out.println(divide);//1	
    }
}
package com.qf.big;
import java.math.BigDecimal;
public class Test02 {
	public static void main(String[] args) {       
        /**
		 * 知识点:浮点类型的大数值的运算类 - BigDecimal
		 */
		
		BigDecimal big1 = new BigDecimal("0.5");
		BigDecimal big2 = new BigDecimal("0.4");
		
		//加法
		BigDecimal add = big1.add(big2);
		System.out.println(add);//0.9
		
		//减法
		BigDecimal subtract = big1.subtract(big2);
		System.out.println(subtract);//0.1
		
		//乘法
		BigDecimal multiply = big1.multiply(big2);
		System.out.println(multiply);//0.20
		
		//除法
		BigDecimal divide = big1.divide(big2);
		System.out.println(divide);//1.25
	}
}
package com.qf.big;
import java.math.BigDecimal;
public class Test03 {
	public static void main(String[] args) {
		/**
		 * 知识点:浮点类型的大数值的运算类 - BigDecimal
		 */
		
		BigDecimal big1 = new BigDecimal("10");
		BigDecimal big2 = new BigDecimal("3");
		
		//除法
		BigDecimal divide = big1.divide(big2, 2, BigDecimal.ROUND_HALF_UP);
		System.out.println(divide);//3.333333	
	}
}

常用类归纳

1.包装类(熟悉)
出现原因
装箱和拆箱
Integer中的IntegerCache
2.字符串类(熟悉)
String、StringBuilder、StringBuffer
3.正则表达式(了解)

4.日期时间类(了解)
Date + SimpleDateFormat
Calendar
5.Math(了解)
注意:静态导入
6.Random(了解)
注意:种子数
7.Runtime(了解)

8.System(了解)
System.in/out/err
System.arraycopy()
9.大数值运算类(熟悉)

Day15

初识枚举

概念

枚举(enum)全称为 enumeration, 是 JDK 1.5 中引入的新特性。

语法
public enum Color{
    //默认添加 public static final Color
    RED,GREEN,BLUE;
}
本质

尽管枚举看起来像是一种新的数据类型,实际上,枚举就是一种受限制的类,并且具有自己的方法。一个类有固定的几个对象时,就用枚举代替。创建自己的enum类时,这个类继承自 java.lang.Enum。

    public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable{
    ...
}
特点
  • 枚举就是一个受限制的类,默认继承Enum
  • 枚举的第一行必须定义该枚举类型的对象
  • 枚举类型对象默认添加: public static final 类型
  • 枚举没有继承明确类(自定义枚举类默认继承Enum,Enum默认继承Object)
  • 枚举类不能被继承
  • 枚举里可以有构造方法、成员方法、静态方法、抽象方法
  • 枚举可以实现接口
  • 枚举里没有定义方法,可以在最后一个对象后面加逗号、分号或什么都不加
优势
  • 增强代码可读性

  • 枚举型可直接与数据库交互

  • switch语句优势

  • 编译优势

    (枚举类编译时,没有把常量值编译到代码中,即使常量值发生改变,也不会影响引用常量的类 )

  • 将常量组织起来,统一管理

  • 去除equals两者判断 由于常量值地址唯一,使用枚举可以直接通过“==”进行两个值之间的对比,性能会有所提高

需求:编写季节类(Season),该类只有四个对象(spring,summer,autumn,winter)

类: Season.java

对象: Test01.java

需求:编写季节类(Season),该类只有四个对象(spring,summer,autumn,winter)使用枚举解决这个需求。

类: Season.java 默任添加public static final

对象: Test01.java

枚举的常用方法

方法名解释
Enum.valueOf(Class enumType, String name)根据字符串找到该枚举类中的对象
public static void values()获取该枚举类对象数组
public static void valueOf(String args0)根据字符串获取该枚举类中的对象
public final String name()获取该枚举对象名字
public final Class getDeclaringClass()获取枚举对象的枚举类型相对应的Class对象
public final int hashCode()获取该枚举对象的hash值
public final int compareTo(E o)两个枚举对象进行比较
public final boolean equals(Object other)比较两个枚举对象是否相同
package com.qf.enum02;
public class Test02 {
	public static void main(String[] args) {
		
		//将字符串转换为枚举对象(通过字符串找到对应的枚举对象)
		Season spring = Enum.valueOf(Season.class, "spring");
		System.out.println(spring);
		
		//获取枚举中所有的对象,并返回数组
		Season[] seasons = Season.values();
		for (Season season : seasons) {
			System.out.println(season);
		}
		
		//将字符串转换为枚举对象(通过字符串找到对应的枚举对象)
		Season spring = Season.valueOf("spring");
		System.out.println(spring);//春天 -- 春雨绵绵
		
		//获取枚举对象的名字
		String name = spring.name();
		System.out.println(name);//spring
		
		//通过枚举类的对象获取到枚举类的字节码文件对象
		Class<Season> c = spring.getDeclaringClass();
		System.out.println(c);//class com.qf.enum02.Season
	}
}

枚举案例

状态机

类: Signal.java

对象: Test01.java

状态码/错误码

场景:做项目(学生管理系统),每个功能都有不同的状态码
添加功能:-1学生信息不合法 -2有该学生 1-添加成功

类: AddStateCode.java

对象: Test01.java

组织枚举

含义:可以将类型相近的枚举通过接口或类组织起来(但是一般用接口方式进行组织)
原因是:
Java接口在编译时会自动为enum类型加上public static修饰符;
Java类在编译时会自动为 enum 类型加上static修饰符;
就是说,在类中组织 enum,如果你不给它修饰为 public,那么只能在本包中进行访问。场景:做项目(学生管理系统),每个功能都有不同的状态码
添加功能:-1学生信息不合法 -2有该学生 1-添加成功
删除功能:-1学生信息不合法 -2没有该学生 1-删除成功

类: StateCode.java

对象: Test01.java

策略枚举

类: Salary.java

对象: Test01.java

枚举工具类 - EnumSet 和 EnumMap

Java 中提供了两个方便操作enum的工具类——EnumSet 和 EnumMap。

EnumSet :枚举类型的高性能 Set实现。它要求放入它的枚举常量必须属于同一枚举类型。
EnumMap :专门为枚举类型量身定做的 Map 实现。虽然使用其它的 Map 实现(如HashMap)也能完成枚举类型实例到值得映射,但是使用 EnumMap 会更加高效,因为它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值。这使得 EnumMap 的效率非常高。

public class EnumTest {
	public static void main(String[] args) {
		
		//EnumSet的使用
        //把Signal枚举中所有对象抽取到Set集合中
		EnumSet<Signal> signalSet = EnumSet.allOf(Signal.class);
		for (Enum<Signal> en : signalSet) {
			System.out.println(en);
		}
		
		//EnumMap的使用
		EnumMap<Signal,Object> enumMap = new EnumMap<>(Signal.class);
		enumMap.put(Signal.RED, "红灯");
		enumMap.put(Signal.YELLOW, "黄灯");
		enumMap.put(Signal.GREEN, "绿灯");
        //把所有的映射关系对象抽取到Set集合中
		Set<Entry<Signal, Object>> entrySet = enumMap.entrySet();
		for (Entry<Signal, Object> entry : entrySet) {
			Signal key = entry.getKey();
			Object value = entry.getValue();
			System.out.println(key + " -- " + value);
		}
	}
}
enum Signal{RED, YELLOW, GREEN}

类:

package com.qf.enumset_map;

public enum Color {
	RED,GREEN,BLUE;
}

对象

package com.qf.enumset_map;
import java.util.EnumSet;
public class Test01 {
	public static void main(String[] args) {
		/**
		 * 知识点:EnumSet
		 */
		
		//将Color枚举类中所有的对象存入EnumSet集合中
		EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
		
		for (Color color : enumSet) {
			System.out.println(color);
		}
	}
}

对象

package com.qf.enumset_map;
import java.util.EnumMap;
import java.util.Map.Entry;
import java.util.Set;
public class Test02 {
	public static void main(String[] args) {
		/**
		 * 知识点:EnumMap
		 */
	
		//创建EnumMap的对象(注意:设置Key和value的类型)
		EnumMap<Color,String> map = new EnumMap<>(Color.class);
	
		//添加元素
		map.put(Color.RED, "红色");
		map.put(Color.GREEN, "绿色");
		map.put(Color.BLUE, "蓝色");
		
		//删除元素
		map.remove(Color.GREEN);
		
		//遍历
		Set<Entry<Color, String>> entrySet =  map.entrySet();
		for (Entry<Color, String> entry : entrySet) {
			Color key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + " -- " + value);
		}
	}
}

学生管理系统

Student.java

StuInfoUtils.java

IStudentManagerSystem.java

StudentManageSystemImpl.java

Main.java

StateCode.java

StuInfoType.java

初识集合

  1. 集合是Java API所提供的一系列类,可以用于动态存放多个对象 (集合只能存对象)(误导性太强,不去纠结)

  2. 集合与数组的不同在于,集合是大小可变的序列,而且元素类型可以不受限定,只要是引用类型。(集合中不能放基本数据类型,但可以放基本数据类型的包装类)

  3. 集合类全部支持泛型,是一种数据安全的用法。

  4. 集合与数组的不同

    数组:一旦初始化后长度不可变,元素类型受限定(String类型的数组只能装String的数据),数组可以存储基本数据类型

    集合:长度可变的序列,元素类型不受限定(一个集合可以存储多个数据类型的元素),集合只能存储引用数据类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOLBBp31-1644159259793)(D:\2113java_workspace\Day15\Day15下午\集合框架图.png)]

ArraryList

package com.dream.arraylist_class;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.ListIterator;
public class Test02 {
	public static void main(String[] args) {
		/**
		 * 知识点:ArrayList的方法
		 * ArrayList的底层数据结构就是一维数组,即ArrayList的底层数据存储到了一个一维数组里。
		 */

		//创建ArrayList对象
		ArrayList<String> list = new ArrayList<>();

		//添加元素
		list.add("麻生希");
		list.add("椎名空");
		list.add("北岛玲");
		list.add("朝桐光");
		list.add("黄小龙");

		//获取元素的个数
		int size = list.size();
		System.out.println("获取元素的个数:" + size);

		//设置指定下标上的元素
		list.set(2, "李尧尧");

		//获取指定下标上的元素
		String element = list.get(2);
		System.out.println("获取指定下标上的元素:" + element);

		//在指定下标上添加元素
		list.add(1, "马锡彬");

		//在list集合末尾添加newList1集合
		ArrayList<String> newList1 = new ArrayList<>();
		Collections.addAll(newList1, "aaa","bbb","ccc");//将元素批量添加到newList1中(注意:Collections-集合的工具类)
		list.addAll(newList1);

		//在list集合指定下标的位置添加newList2集合
		ArrayList<String> newList2 = new ArrayList<>();
		Collections.addAll(newList2, "xxx","yyy","zzz","黄小龙");
		list.addAll(3, newList2);

		//清空集合中的元素
		//list.clear();

		System.out.println("判断集合中是否有指定元素:" + list.contains("aaa"));
		System.out.println("判断集合中是否有指定集合的元素(包含关系):" + list.containsAll(newList1));
		System.out.println("判断集合中是否不包含元素:" + list.isEmpty());//true-没有元素 false-有元素

		System.out.println("获取第一次出现的元素的下标:" + list.indexOf("黄小龙"));//6
		System.out.println("获取最后一次出现的元素的下标:" + list.lastIndexOf("黄小龙"));//9

		//删除元素
		list.remove(2);//根据下标删除元素
		list.remove("朝桐光");//根据元素删除元素
		list.removeAll(newList1);//删除交集

		//保留交集
		list.retainAll(newList2);

		//将集合转换为数组
		Object[] array = list.toArray();
		System.out.println(Arrays.toString(array));

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

		//遍历集合 -- for循环
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("-----------");

		//遍历集合 -- foreach
		for (String str : list) {
			System.out.println(str);
		}
		System.out.println("-----------");

		//遍历集合 -- Iterator
		Iterator<String> it = list.iterator();
		while(it.hasNext()){//判断是否有可迭代的元素
			String next = it.next();//获取下一个元素
			System.out.println(next);
		}
		System.out.println("-----------");	


		//遍历集合 -- ListIterator
		ListIterator<String> listIt = list.listIterator();
		while(listIt.hasNext()){//判断是否有可迭代的元素
			String next = listIt.next();//获取下一个元素
			System.out.println(next);
		}
		System.out.println("-----------");	
	}
}

加newList1集合
ArrayList newList1 = new ArrayList<>();
Collections.addAll(newList1, “aaa”,“bbb”,“ccc”);//将元素批量添加到newList1中(注意:Collections-集合的工具类)
list.addAll(newList1);

	//在list集合指定下标的位置添加newList2集合
	ArrayList<String> newList2 = new ArrayList<>();
	Collections.addAll(newList2, "xxx","yyy","zzz","黄小龙");
	list.addAll(3, newList2);

	//清空集合中的元素
	//list.clear();

	System.out.println("判断集合中是否有指定元素:" + list.contains("aaa"));
	System.out.println("判断集合中是否有指定集合的元素(包含关系):" + list.containsAll(newList1));
	System.out.println("判断集合中是否不包含元素:" + list.isEmpty());//true-没有元素 false-有元素

	System.out.println("获取第一次出现的元素的下标:" + list.indexOf("黄小龙"));//6
	System.out.println("获取最后一次出现的元素的下标:" + list.lastIndexOf("黄小龙"));//9

	//删除元素
	list.remove(2);//根据下标删除元素
	list.remove("朝桐光");//根据元素删除元素
	list.removeAll(newList1);//删除交集

	//保留交集
	list.retainAll(newList2);

	//将集合转换为数组
	Object[] array = list.toArray();
	System.out.println(Arrays.toString(array));

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

	//遍历集合 -- for循环
	for (int i = 0; i < list.size(); i++) {
		System.out.println(list.get(i));
	}
	System.out.println("-----------");

	//遍历集合 -- foreach
	for (String str : list) {
		System.out.println(str);
	}
	System.out.println("-----------");

	//遍历集合 -- Iterator
	Iterator<String> it = list.iterator();
	while(it.hasNext()){//判断是否有可迭代的元素
		String next = it.next();//获取下一个元素
		System.out.println(next);
	}
	System.out.println("-----------");	


	//遍历集合 -- ListIterator
	ListIterator<String> listIt = list.listIterator();
	while(listIt.hasNext()){//判断是否有可迭代的元素
		String next = listIt.next();//获取下一个元素
		System.out.println(next);
	}
	System.out.println("-----------");	
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值