四、lambda表达式、常用API
lambda表达式
-
函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”
语法:(形参) 箭头 {代码块}
(形参) -> {方法体}
形参:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
方法体:是我们具体要做的事情
前提
-
1必须是一个接口 不能是类 也不能是抽象类
-
2接口中只有一个抽象方法
演示:
public class Demo01 {
public static void main(String[] args) {
start(new Animal() {
@Override
public void eat() {
System.out.println("222");
}
});
// lambda ()->{}
start(() -> {
System.out.println("222");
});
}
public static void start(Animal a) {
a.eat();
}
}
interface Animal {
public void eat();
}
有参无返回值练习
案例
-
首先存在一个接口(StringHandler)
-
在该接口中存在一个抽象方法(printMessage),该方法是有参数无返回值
-
在测试类中存在一个方法(useStringHandler)方法的的参数是StringHandler类型的在方法内部调用了StringHandler的printMessage方法
代码
public class StringHandlerDemo {
public static void main(String[] args) {
//匿名内部类的形式
useStringHandler(new StringHandler() {
@Override
public void printMessage(String msg) {
System.out.println(msg);
}
});
//lambda表达式的形式
useStringHandler((String msg) -> {
System.out.println(msg);
});
}
public static void useStringHandler(StringHandler stringHandler) {
stringHandler.printMessage("itheima");
}
}
//必须是一个接口 不能是类 也不能是抽象类
//接口中只有一个抽象方法
interface StringHandler {
void printMessage(String msg);
}
省略注意点
-
参数类型可以省略
-
当形参只有一个的时候 小括号省略
-
当方法体只有一句的时候 大括号省略
无参有返回值
需求
-
首先存在一个接口(RandomNumHandler)
-
在该接口中存在一个抽象方法(getNumber),该方法是无参数但是有返回值
-
在测试类中存在一个方法(useRandomNumHandler)方法的的参数是RandomNumHandler类型的在方法内部调用了RandomNumHandler的getNumber方法返回一个随机数
代码
public class Demo01 {
public static void main(String[] args) {
//匿名内部类的形式
useStringHandler(new StringHandler() {
@Override
public void printMessage(String msg) {
System.out.println(msg);
}
});
//lambda表达式的形式 注意有参数
useStringHandler((String msg) -> {
System.out.println(msg);
});
//形参只有一个 类型和小括号可以省略, 方法体只有一句 大括号和分号可以省略
useStringHandler(msg -> System.out.println(msg));
}
public static void useRandomNumHandler(RandomNumHandler r) {
int num = r.getNumber();
System.out.println("获取到返回的数据num=" + num);
}
}
interface RandomNumHandler {
//方法 有返回值 无参数
int getNumber();
}
有参数 有返回值
-
只有一句代码 并且是返回值时 可以省略 return 省略分号 省略大括号
public class Demo01 {
public static void main(String[] args) {
userAdd(new Inter1() {
@Override
public int sum(int a, int b, int c) {
return a + b + c;
}
});
//有参数有返回值练习
userAdd((int a, int b, int c) -> {
return a + b + c;
});
//只有一句代码 并且是返回值时 可以省略 return 省略分号 省略大括号
userAdd(( a, b, c) ->a + b + c);
}
public static void userAdd(Inter1 i1) {
int number = i1.sum(10, 20, 30);
System.out.println(number);
}
}
interface Inter1 {
//有参数 有返回值
int sum(int a, int b, int c);
}
关于省略
-
1 参数类型可以省略 ,要省略就全部参数都省略
-
2 当形参只有一个的时候 小括号省略
-
3 当方法体只有一句的时候 大括号省略
-
只有一句代码 并且是返回值时 可以省略 return 省略分号 省略大括号
-
lambda和匿名内部类
-
匿名内部类 可以是类或者抽象类或者接口
-
lambda 只能是接口 只能有一个抽象方法
-
-
匿名内部类 在使用的时候,会编译出一个class文件
-
lambda 会在真正执行的时候,动态的生成一个class,运行完就没有了
-
代码块
局部代码块(很少用,理解作用 就可以 )
-
在方法中定义 方法调用时被执行
-
用于控制变量的生命周期
代码
public class Demo01 {
public static void main(String[] args) {
calc();
}
public static void calc() {
{
//计算两个数的和
int a = 10;
int b = 20;
int result = a + b;
}
//a = 30;
//计算两个数的差
int c = 100;
int d = 80;
int result1 = c - d;
}
}
构造代码块
-
在类中定义, 每次构造方法执行之前执行
-
实际应用:在多个构造方法中,如果有相同执行代码,就可以抽取到构造代码块中,写一次就好
代码演示
-
学生类
-
要求不管用有参还是无参构造,都希望初始化school的值为 黑马学校,所以把赋值代码写到构造代码块中
package com.heima.test5;
public class Student {
String name;
int age;
String school;
{
this.school = "黑马学校";
System.out.println("构造代码块");
}
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("走了有参构造");
}
public Student() {
System.out.println("走了空参构造");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school='" + school + '\'' +
'}';
}
}
测试代码
public class Demo02 {
public static void main(String[] args) {
Student stu = new Student("zhansgan", 20);
System.out.println(stu);
Student stu1 = new Student();
System.out.println(stu1);
}
}
//打印结果
//构造代码块
//走了有参构造
//Student{name='zhansgan', age=20, school='黑马学校'}
//构造代码块
//走了空参构造
//Student{name='null', age=0, school='黑马学校'}
静态代码块
-
在类中定义 用static修饰
-
第一次使用这个类时被执行,而且只执行一次。
-
用于初始化静态成员变量
代码
-
学生管理类
-
stus 是用来装学生的集合,定义为静态的,是为了 不论StuManager创建几次对象,都只有一个集合
-
static的静态代码块 是为了在类加载的时候就初始化stus 添加一些学生
-
import java.util.ArrayList;
public class StudentManager {
static ArrayList<Student> list = new ArrayList<>();
static {
list.add(new Student("张三",12));
list.add(new Student("lisi",13));
list.add(new Student("xming",14));
}
//public StudentManager() {
// list.add(new Student("张三",12));
// list.add(new Student("lisi",13));
// list.add(new Student("xming",14));
//}
public void addStu(Student stu) {
list.add(stu);
}
public void show() {
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
System.out.println(stu);
}
}
}
测试代码
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
//add();
//add();
//add();
new StudentManager().show();
new StudentManager().show();
}
public static void add() {
Scanner sc = new Scanner(System.in);
System.out.println("输入名字");
String name = sc.next();
System.out.println("输入年龄");
int age = sc.nextInt();
//创建学生对象
Student s = new Student(name, age);
//创建学生管理
StudentManager stu = new StudentManager();
//添加学生
stu.addStu(s);
//查看所有学生
stu.show();
}
}
常用API
Math(不用背,知道能做什么即可)
-
1、Math类概述
-
Math 包含执行基本数字运算的方法
-
-
2、Math中方法的调用方式
-
Math类中无构造方法,但内部的方法都是静态的,则可以通过 类名.进行调用
-
-
3、Math类的常用方法
代码
public static void main(String[] args) {
// public static int abs(int a) 返回参数的绝对值
// int abs = Math.abs(10);
// System.out.println(abs);
System.out.println(Math.ceil(3.14)); //4.0 向上 取整
System.out.println(Math.floor(3.14));//3.0 向下 取整
System.out.println(Math.ceil(-3.14)); //-3.0 向上 取整
System.out.println(Math.floor(-3.14));//-4.0 向下 取整
// public static int round(float a) 四舍五入
// long round = Math.round(10.1);
// System.out.println(round);
//
// long round1 = Math.round(1.9);
// System.out.println(round1);
// public static int max(int a,int b) 返回两个int值中的较大值
// int max = Math.max(10, 20);
// System.out.println(max);
// public static int min(int a,int b) 返回两个int值中的较小值
// int min = Math.min(10, 20);
// System.out.println(min);
// public static double pow(double a,double b)返回a的b次幂的值
// double pow = Math.pow(2, 3);
// System.out.println(pow);
// public static double random() 返回值为double的正值,[0.0,1.0)
for (int i = 0; i < 10 ; i++) {
double random = Math.random();
System.out.println(random);
}
}
System
-
System.exit() 停止虚拟机
package com.heima.test7;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean isRun = true;
while (isRun) {
System.out.println("请输入选择");
int num = sc.nextInt();
switch (num) {
case 1:
System.out.println("周一区 健身");
break;
case 2:
System.out.println("退出");
//isRun = false;
//break;
//return;
System.exit(0);
}
}
}
}
currentTimeMillis() 返回当前时间 从1970年开始到现在的毫秒数 (掌握)
long time = System.currentTimeMillis();//1664431123855
System.out.println(time);
arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数) 数组copy
public static void main(String[] args) {
//arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数) 数组copy
int [] arr1 = {1,2,3,4,5};
int [] arr2 = new int[10];
//需求:我要把arr1中的数据拷贝到arr2中.
//System.arraycopy(arr1,0,arr2,0,arr1.length);
/*for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}*/
//我要把arr1最后两个元素,拷贝到arr2的最后两个索引上
System.arraycopy(arr1,3,arr2,8,2);
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
}
Object类的toString和equals
toString方法 (会重写toString )
-
直接打印对象,就是打印的toString方法的返回值
-
可以重写toString,在方法中返回自己希望打印的内容,快捷键alt+insert 弹出框选中toString
-
查看一个类的继承机构 ctrl+h
-
ctrl+shift+alt+u 打开继承和实现的结构,在结构图内,进入某个源码,选中点击f4
-
alt+7 看当前类的结构
-
ctrl+n 弹出 搜索框,可以搜索类
equals方法(会重写,自己尝试看源码)
-
equals方法的作用
-
用于对象之间的比较,返回true和false的结果
-
举例:s1.equals(s2); s1和s2是两个对象
-
-
重写equals方法的场景
-
不希望比较对象的地址值,想要结合对象属性进行比较的时候。
-
-
重写equals方法的方式
-
-
alt + insert 选择equals() and hashCode(),IntelliJ Default,一路next,finish即可
-
-
-
在类的空白区域,右键 -> Generate -> 选择equals() and hashCode(),后面的同上。
-
-
-
示例代码:
class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.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;
}
@Override
public boolean equals(Object o) {
//this -- s1
//o -- s2
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o; //student -- s2
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
}
public class ObjectDemo {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("xiaoming");
s1.setAge(10);
Student s2 = new Student();
s2.setName("xiaoming");
s2.setAge(10);
//需求:比较两个对象的内容是否相同
System.out.println(s1.equals(s2));
}
}
面试题(理解打印结果)
-
看程序,分析结果
-
String类中的equals方法 要求参数必须字符串,否则不会比较属性值而直接返回false
-
StringBuilder类中是没有重写equals方法,用的就是Object类中的.
-
public class Demo03 {
public static void main(String[] args) {
String s = "abc";
StringBuilder sb = new StringBuilder("abc");
System.out.println(s.equals(sb));//false
System.out.println(sb.equals(s));//false
}
}
Objects(了解)
// public static String toString(对象) 返回参数中对象的字符串表示形式。
Student s = new Student("小罗同学", 50);
System.out.println(Objects.toString(s));
System.out.println(s);
System.out.println("------------------------------------------------------------------------");
// public static String toString(对象, 默认字符串) 返回对象的字符串表示形式。如果对象为空,那么返回第二个参数.
// Student s1 = new Student("小花同学", 23);
Student s1 = null;
System.out.println(s1);//null
String result1 = Objects.toString(s1, "我是一个默认值");
System.out.println(result1);
// public static Boolean isNull(对象) 判断对象是否为空
Student s2 = null;
//Student s2 = new Student();
boolean result2 = Objects.isNull(s2);
System.out.println(result2);
// public static Boolean nonNull(对象) 判断对象是为非空
Student s3 = new Student();
//Student s3 = null;
boolean result3 = Objects.nonNull(s);
System.out.println(result3);
二分查找
前提: 数据是有序的
查找一个数 在一个数组中的索引位置,如果存在返回索引,如果不存在返回-1
public static void main(String[] args) {
int[] arr = new int[]{1, 3, 6, 8, 10, 19, 27, 35, 53, 65};
int index = binarySearch(530, arr);
System.out.println("index=" + index);
}
/**
* 查询num在arr中的位置
*
* @param arr
* @param num
* @return 返回num的索引 如果不存在 返回-1
*/
private static int binarySearch(int[] arr, int num) {
int min = 0; //查找范围的最小索引
int max = arr.length - 1; //查找范围的最大索引
while (max >= min) {
int mid = (min + max) / 2;
if (num > arr[mid]) {
//如果比mid位置的数据大 说明num在mid的右侧
min = mid + 1; //把查找范围的最小索引 移动到mid+1的位置
} else if (num < arr[mid]) {
max = mid - 1; //查找范围的最大索引 移动到mid-1的位置
} else {
//如果相等 就找到了mid就是要返回的索引
return mid;
}
}
//如果代码走到这里 说明没有找到 返回-1
return -1;
}
神笔码农s: LocalDate nowDate = LocalDate.now(); System.out.println("本年第一天:" + nowDate.with(TemporalAdjusters.firstDayOfYear())); System.out.println("本年最后一天:" + nowDate.with(TemporalAdjusters.lastDayOfYear())); System.out.println("本月第一天:" + nowDate.with(TemporalAdjusters.firstDayOfMonth())); System.out.println("本月最后一天:" + nowDate.with(TemporalAdjusters.lastDayOfMonth())); System.out.println("本周第一天:" + nowDate.with(DayOfWeek.MONDAY)); System.out.println("本周最后一天:" + nowDate.with(DayOfWeek.SUNDAY));
Mickey2008_08: 个人纪录71695
weixin_42530658: 大佬 模仿王者的炫酷前端页面可以分享一下吗
渣鑫: 能让我看看js是怎么写的吗?
渣鑫: 能让我看看js是怎么写的吗?