目录
1.枚举
2.匿名内部类
3.Lambda表达式
4.Arrays类
5.日期与时间
6.Objects的克隆
1.它是一种特殊类型
2.作用:信息的标识和分类,
3.好处:可读性好,入参约束更严格
//第一个案例
package com.itheima.day04.teacher.b_enum;
/*
如果
某个类 只允许有 固定个数的对象
按照之前的设计方式 就不好实现。
比如
交通灯
红 黄 绿
季节
春 夏 秋 冬
月份
12 个月
一一列举的对象
枚举定义格式
枚举是一个特殊的类,表示一一列举对象,限定对象个数。
class enum 枚举类名{
枚举项1,枚举项2,枚举项3;
//跟类中成员
}
*/
public enum JiaoTongdeng {
//GREEN相当于构造了方法的常量
RED,YELLOW,GREEN("jack");//列举出有三个对象
private String name;
private JiaoTongdeng(){}
private JiaoTongdeng(String name){
this.name = name;
}
public void show(){
System.out.println("灯灯");
}
}
------------------
package com.itheima.day04.teacher.b_enum;
/**
* 测试类
*/
public class Demo {
public static void main(String[] args) {
//相当于创建了一个对象
JiaoTongdeng red = JiaoTongdeng.RED;
//red 交通灯对象
JiaoTongdeng yellow = JiaoTongdeng.YELLOW;
JiaoTongdeng green = JiaoTongdeng.GREEN;
JiaoTongdeng red1 = JiaoTongdeng.RED;
System.out.println(red==red1); //true
System.out.println(red==yellow); //false
red.show();
}
}
--------------------------
第二个案例:
package com.itheima.day04.teacher.b_enum;
//定义枚举
public enum Sex {
BOY,GIRL
}
-----
package com.itheima.day04.teacher.b_enum;
/**
测试类
*/
public class Test {
public static void main(String[] args) {
//调用 如果引用类型 搞出它的对象
recommend(Sex.GIRL);
}
/*
设计一个方法
用于接收 性别 根据不同性别 图书给不同的推荐
*/
public static void recommend(Sex sex){// 引用类型做参数 调用传递必然是其对象 枚举类型 对象 枚举项
// switch 表达式可以是 枚举类型
switch (sex){
case BOY:
System.out.println("推荐 修仙小说...带着超市穿越到古代....");
break;
case GIRL:
System.out.println("推荐 霸道总裁爱上我.....");
break;
}
}
}
1.好处:方便构建子类对象
2.格式:
new 接口/抽象类(){
方法重写
}
3. 匿名内部类就是没有名字的子类对象
new 名字{ }这个“ { }”就是一个子类对象
package com.itheima.day04.teacher.c_interclass;
/**
* 动物类,抽象类
*/
public abstract class Animal {
public abstract void eat();
}
-----------
package com.itheima.day04.teacher.c_interclass;
/**
* 继承类
*/
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃醉鱼...");
}
}
----------
package com.itheima.day04.teacher.c_interclass;
/**
* 测试类
*/
public class Demo {
public static void main(String[] args) {
/*
我想养一只动物 并且让它吃饭
*/
/*
思路1:外部类思路
1:创建一个 继承Animal的Cat类型 子类
2:重写方法
3:在测试类中 创建外部类对象
4:调用方法
*/
Cat c = new Cat();
c.eat();
System.out.println("------------------------");
/*
思路2:内部类思路
1:在main中创建一个 继承Animal的Dog类型 子类
2:重写方法
3:在测试类中 创建外部类对象
4:调用方法
*/
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头.....");
}
}
Dog d = new Dog();
d.eat();
System.out.println("======================================");
//目的 就是调用 eat方法 至于是哪只动物 具体的是什么动物 重要吗不重要!!
// 代码层面 最重要的 方法的重写和调用!!
// 想能不能一步到位 不用创建内部类 也不用外部类 一步到位的方式 完成方法重写和调用!!
/*
思路3 一步到位
1:构建一个Animal子类对象
2:调用方法
匿名内部类的结构
来实现方法,实现过程中产生了一个对象。一个没有名字的子类对象。
*/
Animal a = new Animal() {
@Override
public void eat() {
System.out.println("老虎吃鸡....");
}
} ;
a.eat();
/*
new Animal() {
@Override
public void eat() {
}
} 等价于 new Cat()
*/
/*
理论
匿名内部类
是一个特殊的局部内部类。
匿名就是没有给这个类起名字。
本质
匿名内部类就是创建一个没有名字子类对象。
好处--作用
快捷的创建一个子类对象!!
格式:
new 类名/接口(..){ 方法的重写;}
*/
}
}
1.Lambda表达式是JDK 8开始新增的一种语法形式
2.作用:用于简化匿名内部类的代码写法。
3.语法格式:
4.注意 : Lambda表达式只能简化函数式接口的匿名内部类
什么是函数式接口:接口中只有一个抽象方法或者是这个@FunctionalInterface的注解
5.Lambda表达式的省略规则:
参数类型可以省略
如果只有一个参数 (参数) “ () ”也可以省略
如果子类方法体只有一行代码,“{ }”可以省略
不写return
package com.itheima.day04.teacher.e_lambda;
/**
* 函数式接口
*/
@FunctionalInterface
public interface Swimming {
void swim();
}
---------------
package com.itheima.day04.teacher.e_lambda;
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
/*
匿名内部类--本质是子类对象
*/
goSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("朕在游泳....好多泡泡....");
}
});
System.out.println("=========================");
/*
如果 一个方法的参数 是一个接口类型---可以使用匿名内部类完成调用
这个接口里面有且只有一个抽象方法 可以使用Lambda进行简化。
JDK8之后 函数式接口---有且只有一个抽象方法的接口。
出了 一个标注函数式接口的注解 @FunctionalInterface
lambda使用 目的 简化代码 接口名 方法名 修饰符 返回值类型 不重要的简化 参数 方法体 不去简化
前提
用于替换 函数式接口的 匿名内部类对象
格式
一些参数 一个箭头 一段代码
(方法参数列表)->{方法体}
*/
// 使用lambda 完整格式
goSwimming(
()->{
System.out.println("朕在游泳....好多美女....");
}
);
System.out.println("下面是简化");
goSwimming(()-> System.out.println("朕在游泳....好多猛男...."));
}
/*
去游泳的方法
跟 会游泳的 游泳
*/
public static void goSwimming(Swimming swimming){//传递的游泳接口--只要是它的子类对象 肯定会游泳
swimming.swim();
}
}
1.作用:代表数组操作类,工具类,里面都是操作数组的静态方法
2.方法:
public static String toString(类型[] arr) //返回数组内容
public static void sort(类型[] arr) //默认升序,字符默认是首字母
3.Arrays类对于Comparator比较器
1、让对象的类实现比较规则:
2、sort方法自带比较器:public stativ void sort(类型[] arr, Comparator
注意,都写自带比较优先
package com.itheima.day04.teacher.d_arrays;
/**
* Comparable的比较方式
* 继承接口Comparable
* 重写compareTo方法
*/
public class Student implements Comparable{
private String name;
private double height;
private int age;
public Student() {
}
public Student(String name, double height, int age) {
this.name = name;
this.height = height;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return height
*/
public double getHeight() {
return height;
}
/**
* 设置
* @param height
*/
public void setHeight(double height) {
this.height = height;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{name = " + name + ", height = " + height + ", age = " + age + "}";
}
@Override
public int compareTo(Student o) {
// o1 前 o2 后
Student o1 = this; //表前
Student o2 = o; //表后
//身高降序 double类型
return Double.compare(o2.getHeight(),o1.getHeight());
}
}
---------------
package com.itheima.day04.teacher.d_arrays;
import java.util.Arrays;
import java.util.Comparator;
public class ArraysDemo01 {
public static void main(String[] args) {
//已有一个数组
Integer[] arr = {6,5,7,9,3,1,2};
//请完成数组排序
// Arrays.sort(arr);
// System.out.println("展示数组内容:"+Arrays.toString(arr));
// 进行的是一个升序排序
//问题 数组中的元素完成降序排序
// public static void sort(数组) 对数组进行 排序(排序规则 默认 升序)
// public static void sort(数组,排序规则)
// Comparator -- 比较器
// public interface Comparable 泛型 <类型需要排序>
// public int compareTo(T o);抽象方法
// 接口作为参数 -- 传递实现类对象 匿名内部类
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
System.out.println("展示数组内容:"+Arrays.toString(arr));
/*
原始规则
升序
左边数据>右边数据 返回 正整数 交换位置
左边数据<右边数据 返回 负整数 不交换
左边数据=右边数据 返回 0 不交换
降序
左边数据<右边数据 返回 正整数 交换位置
左边数据>右边数据 返回 负整数 不交换
左边数据=右边数据 返回 0 不交换
简单规则
前 - 后 升序
后 - 前 降序
*/
/*
总结:
如果 我们在开发中 想要对 整数 小数 (包装)数组 不满足使用Arrays的默认排序
那么可以采用 Arrays.sort(引用类型数组,自己实现定义的规则)
自己定义规则就是实现 Comparator接口 建议使用 匿名内部类形式去写
重写 比较的方法
特点 前-后 升序 后-前 降序
*/
Double[] arr2 = {3.14,5.34,1.22,4.33};
//排序
// Arrays.sort(arr2);//默认规则
Arrays.sort(arr2, new Comparator() {
@Override
public int compare(Double o1, Double o2) {
// Double里面有 比较的方法 compare
// return Double.compare(o1,o2); 升序 前后
// o2 > o1 的时候 要交换
// if(o2>o1){
// return 1;
// }else{
// return -1;
// }
return Double.compare(o2,o1);//降序 后前
}
});
System.out.println("展示数组内容:"+Arrays.toString(arr2));
}
}
--------------
package com.itheima.day04.teacher.d_arrays;
import java.util.Arrays;
import java.util.Comparator;
public class ArraysDemo02 {
public static void main(String[] args) {
Student[] students = new Student[4];
Student stu1 = new Student("姚明",2.26,43);
Student stu2 = new Student("郭敬明",1.5,45);
Student stu3 = new Student("蔡徐坤",1.88,25);
Student stu4 = new Student("潘子",1.6,60);
students[0] = stu1;
students[1] = stu2;
students[2] = stu3;
students[3] = stu4;
//输出对象数组
System.out.println(Arrays.toString(students));
//按照年龄 进行升序
// Arrays.sort(students);//你说按照年龄 你那里给计算机说了....
// 报错了 因为你的数组中的引用类型 没有排序规则
// 临时抱佛脚 临时进行排序 .... 只适用于 当前排序下
Arrays.sort(students, new Comparator() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
// 上面使用 sort(两个参数) 只是在当前sort方法执行时 定义临时规则
System.out.println("排序后的:"+Arrays.toString(students));
// 下面报错---因为
// Arrays.sort(students);
// 还有一种方式 解决上面报错 让 我们学生类型 具备排序规则 需要学生类型去实现 Comparable--比较规则接口
System.out.println("====================");
Arrays.sort(students);
System.out.println("按照升高排序 降序:"+Arrays.toString(students));
/*
总结
如果对 对象类型数组 进行排序
有两种方式
临时抱佛脚
Arrays.sort(数组,排序规则Comparator )
采用匿名内部类形式。
仅仅 这一次排序有效.
让类去实现一个接口Comparable---永久性
重写 compareTo方法 注意this o1 前 传递 o o2 后
不管哪一种
前 后 升序
后 前 降序
临时抱佛脚 更灵活 适合于多变情况 --- 球星排名 搜索 进球数 喜爱
类去实现 --- 不变的情况 一旦确定了 排序规则 不再变化
*/
}
}
1.Date 作用:代表当前此刻日期和时间的。
构造器和常用方法:
/*
目标 掌握Date类的基本使用
表达 时间和日期的。
基本单位是毫秒。
有两个构造
有两个方法
*/
public static void main(String[] args) {
// 程序运行到这一行的系统时间。
// 1:创建Date对象,使用空参构造表达式 当前的时间。
Date date = new Date();//util包下
System.out.println(date);//重写toString 有一个展示时间的格式(符合老外的思想)
// 2: 拿到时间毫秒值
long time = date.getTime();
System.out.println(time);
//3: 创建Date对象 使用带参 传入时间毫秒值的
Date date1 = new Date(1490958602444L);
System.out.println("指定时间毫秒值:"+date1);
time += 1000*60*60;
Date date2 = new Date(time);
System.out.println(date2);
//4:每个date对象表示时间不同
/// 还可以手动更改时间
date.setTime(1000);//重新设置时间
System.out.println(date);
}
}
2.SimpleDateFormat 作用:格式化、解析时间的。
/*
目标 掌握 日期和字符串的转换
*/
public static void main(String[] args) throws ParseException {
// 程序运行到这一行的系统时间。
// 1:创建Date对象,使用空参构造表达式 当前的时间。
Date date = new Date();//util包下
System.out.println(date);//重写toString 有一个展示时间的格式(符合老外的思想)
// 2: 拿到时间毫秒值
long time = date.getTime();
System.out.println(time);
/*
日期格式 就是一个 字符串 符合某种规则的字符串!!!
日期格式类的玩法
先有格式 --- 构造
再完成格式化 -- 普通方法
*/
//创建带有日期格式的格式化类对象 SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
// 日期对象---符合格式的字符串
String format1 = sdf.format(date);
// 时间毫秒值---符合格式的字符串
String format2 = sdf.format(time);
System.out.println(format1);
System.out.println(format2);
// 问 能不能把指定格式字符串 转换成 日期对象呢?
// 将字符串解析成 日期对象 要求 字符串得符合 日期格式 否则会报错!!
// format1 2023年08月02日 15:03:18
// 转换成 Date对象 需要使用 格式化对象的 解析方法 Date parse(String format)
Date date1 = sdf.parse(format1);
System.out.println(date1);
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date date2 = sdf.parse("2011-11-11 13:30:26");//日期不匹配会爆红哦
System.out.println(date2);
}
}
3.Calender就是获取当前日历 ,
public class Test4Calendar {
public static void main(String[] args) {
//1:获取当前系统的日历对象
Calendar now = Calendar.getInstance();
System.out.println(now);
//2:获取 日历中的 年
int year = now.get(Calendar.YEAR);
// int year = now.get(1);
System.out.println(year);
//获取 月中日
int day1 = now.get(Calendar.DAY_OF_YEAR);//年中日
int day2 = now.get(Calendar.DAY_OF_MONTH);//月中日
int day3 = now.get(Calendar.DATE);// 日--月中日
System.out.println(day1);//214
System.out.println(day2);//2
System.out.println(day3);//2
System.out.println(now.get(Calendar.DAY_OF_WEEK));//周中日
//3:将 日历对象转换日期对象
Date date = now.getTime();
System.out.println(date);
//4:获取日历对象的毫秒值
long time = now.getTimeInMillis();
System.out.println(time);
// 5:可以修改 指定日历信息
now.set(Calendar.YEAR,2028);
//月份改查10月
now.set(Calendar.MONTH,9);//9是10 11是12 0 是 1
System.out.println(now);
// 2028年 10月
//偏移
now.add(Calendar.YEAR,-2000);// 对指定的日历信息 进行偏移 负数 左偏移 正数 右偏移
System.out.println(now);
now.set(2011,10,11);//设置指定的日历信息
System.out.println(now);
}
}
1.protected Object clone()
当某个对象调用这个方法时,这个方法会复制一个一模一样的新对象返回。
2.浅克隆
拷贝出的新对象,与原对象中的数据一模一样(引用类型拷贝的只是地址)
3.深克隆
对象中还包含的其他对象,不会拷贝地址,会创建新对象。
package com.itheima.day04.teacher.f_clone;
public class User implements Cloneable{
private String id; //编号
private String username; //用户名
private String password; //密码
private double[] scores; //分数
public User() {
}
public User(String id, String username, String password, double[] scores) {
this.id = id;
this.username = username;
this.password = password;
this.scores = scores;
}
/**
* 获取
* @return id
*/
public String getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(String id) {
this.id = id;
}
/**
* 获取
* @return username
*/
public String getUsername() {
return username;
}
/**
* 设置
* @param username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取
* @return password
*/
public String getPassword() {
return password;
}
/**
* 设置
* @param password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取
* @return scores
*/
public double[] getScores() {
return scores;
}
/**
* 设置
* @param scores
*/
public void setScores(double[] scores) {
this.scores = scores;
}
@Override
public String toString() {
return "User{id = " + id + ", username = " + username + ", password = " + password + ", scores = " + scores + "}";
}
@Override
public Object clone() throws CloneNotSupportedException {
User u = (User) super.clone();//先克隆出来一份新的 User对象 只是里面数组 是相同地址
//u 新的空间 this 旧空间
// u.scores 数组 this.scores 数组 同一个地址
//对象里面引用类型 再次进行克隆
// 数组再次进行克隆 数组两个地址
// 让这个u.scores 数组 克隆出来一份 有新地址 把新地址 给 u.scores
u.scores = u.scores.clone();// 搞出一个新的数组地址 复制 新的对象
return u;
}
}
------------------
package com.itheima.day04.teacher.f_clone;
public class CloneDemo {
/*
如何完成对象克隆
1:javabean类 实现 Cloneable接口。
2:javabean重写clone方法。
3:在测试类调用 注意需要抛出一个异常。
4:调用完成就得到一个克隆出来的对象
这种克隆称为 浅克隆
新建了一份空间
把上一份空间
基本类型 -- 数据值复值过来了
引用类型 -- 地址值复制过来了
浅克隆 克隆出来 所有的数据都一模一样(引用属性 地址一样的)
不是特别的好!!!
深克隆
基本类型 -- 数值复制
字符串 -- 地址复制
引用类型 -- 不再地址复制 创建新的对象 -- 再用一次克隆
*/
public static void main(String[] args) throws CloneNotSupportedException {
//提前告诉你 你这里可能出问题
double[] scores = {100,50,0};
User u1 = new User("9527","华安","qiuxiang",scores);
// User u2 = u1;
//两个对象指向同一个地址不是克隆
//克隆出来之后 内容一样 但是 地址不一样!
// protected 受保护的 本类 子类中
User u2 = (User) u1.clone();//默认是Object类型接收 强转
System.out.println(u1==u2);//地址不相等
System.out.println("查看u1中的属性:");
System.out.println(u1.getId());
System.out.println(u1.getUsername());
System.out.println(u1.getPassword());
System.out.println(u1.getScores());
System.out.println("==============");
System.out.println("查看u2中的属性:");
System.out.println(u2.getId());
System.out.println(u2.getUsername());
System.out.println(u2.getPassword());
System.out.println(u2.getScores());
}
}