目录
1、枚举
1.1 概念
枚举(Enumeration)是一种特殊的数据类型,用于定义一组固定的常量值。枚举常量在Java中是具有唯一性的,它们被定义为枚举类型的静态常量。
之前的常量定义
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLUE = 3;
常量都是单独定义,单独调用,而且还会和常量和赋的值混淆,为了避免在代码中硬编码常量的值,只是单纯定义一种属性,这就有了 枚举
枚举类型可以帮助我们避免硬编码常量值,并提高程序的可读性和可维护性。
enum Color {
RED,GREEN,BLUE;
}
//使用红色
Color color = Color.RED;
优点:
- 可读性好:使用枚举常量可以使代码更具可读性,因为常量名称可以直接反映其含义。
- 可维护性更好:使用枚举常量可以使代码更容易维护,因为常量的值只需要在一个地方进行修改即可
- 安全性更高:使用枚举常量可以使代码更加安全,因为枚举类型会自动检查传递给它的参数是否为有效的枚举常量。
- 更加简单高效
缺点:
- 不可继承,无法扩展
本质:
是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。
1.2 用途
1. switch
case 的后面可以跟的数据类型:int 、long、char、枚举类型的常量或常量表达式,short 和 byte 也是可以,但是会被类型转换,可能会发生类型转换错误
枚举的使用
enum TestEnum {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
}
public static void main1(String[] args) {
// switch语句
TestEnum day = MONDAY;
//
switch (day){
case MONDAY:
System.out.println("星期一");
break;
case TUESDAY:
System.out.println("星期二");
break;
case WEDNESDAY:
System.out.println("星期三");
break;
//......
default:
break;
}
}
}
2. 常用方法
方法 | 描述 |
values() | 以数组形式返回枚举类型的所有成员 |
ordinal() | 获取枚举成员的索引位置 |
valueOf() | 将普通字符串转换为枚举实例 |
compareTo() | 比较两个枚举成员在定义时的顺序 |
注意:
- 枚举的构造方法默认是私有的
- 枚举对象有参数后,需要提供相应的构造函数
enum TestEnum {
MONDAY(1,"星期一"),
TUESDAY(2,"星期二"),
WEDNESDAY(3,"星期三"),
THURSDAY(4,"星期四"),
FRIDAY(5,"星期五"),
SATURDAY(6,"星期六"),
SUNDAY(7,"星期日");
private int ordinal;
private String day;
//构造方法 必须是私有(默认)
private TestEnum(int ordinal,String day){
this.ordinal = ordinal;
this.day = day;
}
方法:
public static void main(String[] args) {
//以数组形式返回枚举类型的所有成员
TestEnum[] testEnums = TestEnum.values();
for(TestEnum day:testEnums){
System.out.println(day+" 索引:"+day.ordinal);
}
System.out.println("====================");
//将普通字符串转换为枚举实例 枚举中成员
TestEnum testEnum = TestEnum.valueOf("SATURDAY");
System.out.println(testEnum);
System.out.println(SUNDAY.compareTo(SATURDAY));
System.out.println("====================");
//比较两个枚举成员在定义时的顺序
TestEnum testEnum1 = TestEnum.MONDAY;
TestEnum testEnum2 = TestEnum.FRIDAY;
int ret = testEnum1.compareTo(testEnum2);
System.out.println(ret); //-4
}
// MONDAY 索引:1
// TUESDAY 索引:2
// WEDNESDAY 索引:3
// THURSDAY 索引:4
// FRIDAY 索引:5
// SATURDAY 索引:6
// SUNDAY 索引:7
// ====================
// SATURDAY
// 1
// ====================
// -4
2、 lambda表达式
2.1 概念
1. 背景
Lambda表达式是Java8中一个重要的新特性,lambda表达式允许你通过表达式来代替功能接口。
Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure)
2.语法
基本语法:
(parameters) -> expression 或 (parameters) ->{ statements; }(参数) -> 表达式 或 (参数) ->{ 语句; }
- paramaters:类似方法中的形参列表,是函数式接口里的参数,可声明或不声明由JVM自动判端;
- ->:被用于;
- 方法体:可以是 表达式 或者 代码块,是函数式接口里方法的实现
3. 函数式接口
函数式接口定义:一个接口有且只有一个抽象方法
@FunctionalInterface
interface Test {
//注意:只能有一个方法
void test();
}
注意:
1. 一个接口只有一个抽象方法,这就是一个函数式接口;
2. 可以加上 @FunctionalInterface 注解,
- 加上就是这个接口为函数式接口,里面不为一个抽象方法,就会报错,建议加上;
- 不加,只要保证里面只有一个抽象方法,也会自动检测为函数式接口;
自JDK1.8新特性,函数式接口里可以加上 default方法
@FunctionalInterface
interface Test {
//注意:只能有一个方法
void test();
//default 方法
default void test2(){
System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");
}
}
2.2 使用
1. 前提
- java版本1.8及以上
- 必须用来创建函数式表达式的实例:Lambda表达式本质上是一种匿名函数;
- 在Lambda表达式中引用的外部变量必须是final修饰或在表达式中没有重新赋值
- Lambda表达式必须符合函数式接口的签名
2. 基本使用
函数式接口中的方法
- 有无返回值
- 参数的个数
没有lambda表达式,使用匿名内部类实现
interface NoParameterNoReturn {
void test();
}
public class Test {
public static void main(String[] args) {
//匿名内部类
//将接口 NoParameterNoReturn 的实例赋值给 变量 noParameterNoReturn
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("没有lambda表示式内部类使用");
}
};
noParameterNoReturn.test();
}
}
// 没有lambda表示式内部类使用
1. 无返回值
无参数、单参数、多参数
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,double b);
}
2. 有返回值
无参数、单参数、多参数
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
public static void main(String[] args) {
//1.有返回无参数
NoParameterReturn NoParameterReturn1_1 = ()->{
return 10;
};
//无参数可以省略 return
NoParameterReturn NoParameterReturn1_2 = ()->10;
int ret1 = NoParameterReturn1_2.test();
System.out.println(ret1);
System.out.println("====================");
//2.有返回单参数
OneParameterReturn oneParameterReturn2 = x-> x+10;
int ret2 = oneParameterReturn2.test(10);
System.out.println(ret2);
System.out.println("====================");
//3.有返回多参数
MoreParameterReturn moreParameterReturn = (x,y)->x+y;
int ret3 = moreParameterReturn.test(10,20);
System.out.println(ret3);
}
总结:
- 参数类型可以省略,多个参数就要一起省略;
- 参数的小括号里只有一个参数,小括号可以省略;
- 方法体只有一条语句,大括号可以省略;
- 方法体只有一条语句,且是return 语句,大括号可以省略,且去掉return关键字
2.3 变量捕获
内部类外的变量,被内部类捕获,这个变量必须是final修饰 或者是 在使用之前没在内部类修改
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
public static void main(String[] args) {
int ret = 10;
NoParameterNoReturn noParameterNoReturn = ()-> {
//ret = 666; ERROR
System.out.println("a:"+ret);
};
noParameterNoReturn.test();
}
//java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量