枚举
若类的对象只有有限个,且是确定的。这样的类,我们通常定义为枚举类
枚举类如果只有一个对象,此时可以使用单例设计模式来实现
枚举类的特性:
- 枚举类对象的属性不允许被改动,因此应该使用pivate final修饰
- 枚举类使用private final修饰的属性应该在构造器中进行初始化
- 若枚举显式地定义了带参的构造器,在列出枚举值的时候必须对应地传入参数
自定义枚举类
1、私有化类的构造器
2、在类的内部创建枚举类的对象
3、对象如果有实例变量,应该声明为private final 并在构造器中初始化
public class Season {
private final String SEASONNAME;//季节名称
private final String SEASONDESC;//季节描述
private Season(String seasonName,String seasonDesc){
this.SEASONNAME = seasonName;
this.SEASONDESC = seasonDesc;
}
public static final Season SPRING = new Season("春天","春暖花开");
public static final Season SUMMER = new Season("夏天","骄阳似火");
public static final Season AUTUMN = new Season("秋天","硕果累累");
public static final Season WINTER = new Season("冬天","白雪皑皑");
}
使用enum定义枚举类
使用enum定义的类继承了java.lang.Enum 不能再使用extends继承其他类
特点:
- 构造方法默认为private
- 所有对象的默认修饰是public static final
- 枚举类的所有实例对象必须在第一行声明,对象和对象之间使用逗号分割,结尾使用分号。
public enum SeasonEnum {
//实例对象
SPRING("春天","春暖花开"),
SUMMER("夏天","骄阳似火"),
AUTUMN("秋天","硕果累累"),
WINTER("冬天","白雪皑皑");
//成员变量
private final String SEASONNAME;//季节名称
private final String SEASONDESC;//季节描述
//构造方法
SeasonEnum(String seasonName, String seasonDesc){
this.SEASONNAME = seasonName;
this.SEASONDESC = seasonDesc;
}
public String getSEASONNAME() {
return SEASONNAME;
}
public String getSEASONDESC() {
return SEASONDESC;
}
}
public class SeasonEnumTest {
public static void main(String[] args) {
SeasonEnum spring = SeasonEnum.SPRING;
System.out.println(spring.getSEASONNAME() +"----"+spring.getSEASONDESC());
}
}
枚举类的常用方法
int compareTo(E o)
boolean equals(Object other)
int hashCode()
String name()
String toString()
valueOf(String name) //返回对象名所对应的枚举对象
values() //返回枚举类中所有对象构成的数组
枚举类可以实现接口
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("红色",1),
GREEN("绿色",2),
BLUR("蓝色",3);
private final String name;
private final Integer index;
private Color(String name,Integer index){
this.name = name;
this.index = index;
}
@Override
public void print() {
System.out.println("颜色:" +name + "---索引:" +index);
}
@Override
public String getInfo() {
return this.name;
}
}
注解(Annotation)
注解是代码中的特殊标记,会在编译类加载运行时被读取,并执行相应的处理
注解可以在不改变程序原有逻辑的基础上,在原文件中嵌入一些补充信息,代码分析工具,开发工具,部署工具,可以
通过这些补充信息进行验证或者进行部署。
注解可以向修饰符一样被使用,可以用于修饰包 类 构造器 方法 成员变量 参数 局部变量的声明。
常见的注解
文档注释中的注解:
@param //方法的参数
@return //方法的返回值
@author //类的开发者
@version 1.0 //类的版本
@throws IOException //表明该方法抛出的异常
在编译时进行格式检查的内置的基本注解
@Override //限定重写父类方法 该注解只能用于方法
@Deprecated //表明这个方法已过时
@SuppressWarings //压制警告
//例如
@SuppressWarnings("unused")
int a = 10
java11 新特性
主要有 函数式接口,Lambda表达式,方法引用/构造器引用,StreamAPI接口的增强
Lambda表达式
Lambda表达式是一个匿名函数。使用lambda表达式可以写出更简洁,更灵活的代码
例如
语法一: 无参无返回值
Runnable r2 = ()-> System.out.println("hello world-----");
语法二:有一个参数 但是没有返回值
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
Consumer<String> c1 = s->System.out.println(s);
语法三:有多个参数 多条执行语句 并且可以有返回值
@Test
public void lambdaTest4(){
Comparator<Integer> com = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println("比较两个整数的大小");
int res = o1.compareTo(o2);
return res;
}
};
//lambda表达式 当有多条语句时 大括号不能省略
Comparator<Integer> comp = (o1, o2)->{
System.out.println("比较两个整数的大小");
int res = o1.compareTo(o2);
return res;
};
}
语法四:有多个参数 只有一条返回语句
//lambda表达式 有多个参数,只有一条返回语句 此时大括号可以省略 return 也可以省略
Comparator<Integer> comp = (o1, o2)-> o1.compareTo(o2);
System.out.println(comp.compare(10,20));
函数式接口
只包含一个抽象方法的接口 称为函数式接口
@FunctionalInterface 可以用来检测接口是否是函数式接口。
java.util .function包下定义了大量的函数式接口
因为在java中,lambda表达式是一个对象,而不是函数,他们必须依附于一类特别的对象类型—函数式接口
在java中,lambda表达式就是一个函数式接口的实现
自定义函数式接口
@FunctionalInterface
public interface InterFunction {
int getValue();//函数式接口只能有一个抽象方法
}
//使用泛型
@FunctionalInterface
public interface InterFunction<T> {
T getValue(T t);
}
@Test
public void lambdaTest5(){
InterFunction<String> fun = s-> s.toUpperCase();
System.out.println(fun.getValue("abc"));
}
作为参数传递Lambda表达式
public String toUpperCaseString(InterFunction<String> fun,String str){
return fun.getValue(str);
}
@Test
public void lambdaTest6(){
String newString = toUpperCaseString(s-> s.toUpperCase(),"abcdef");
System.out.println(newString);
}
JAVA 内置的四大核心函数式接口
Interface Consumer<T>
void accept(T t) 对类型T的对象应用操作。
Interface Supplier<T>
T get() 返回类型为T的对象
Interface Function<T,R>
R apply(T t) 将类型为T的对象进行相应的操作处理 之后返回一个R类型的对象
Interface Predicate<T>
boolean test(T t) 确定类型为T的对象是否满足要求
lambda表达式和匿名内部类的区别
-
所需的类型不同 匿名内部类 可以是接口 也可以是抽象类 还可以是具体的类,lambda表达式 只能是接口
-
使用的限制不同 如果接口中仅有一个抽象方法 可以使用lambda表达式 也可以是用匿名内部类
如果接口中有多个抽象方法 只能使用匿名内部类 不能使用lambda表达式 -
实现的原理不同 匿名内部类编译之后 产生一个单独的字节码文件
lambda表达式 编译之后 没有单独的字节码class文件 对应的字节码在运行时产生。
接口组成更新
-
常量 public static final
- 抽象方法 public abstract
jdk8引入 - 默认方法 public default
- 静态方法(public) static
- 私有方法
注意事项: - 默认方法不能是抽象方法 所以他不强制重写,但是也可以重写 重写的时候需要去掉default修饰符
- public可以省略 但是default不能省略
- 静态方法只能通过接口名调用, 不能通过实现类或者对象名调用 public可以省略 static 不能省略
- 默认方法可以调用私有方法和非静态方法
- 静态方法只能调用静态方法
方法引用
以下写法效果相同
TreeSet<String> ts2 = new TreeSet<>((s1,s2)-> s1.compareTo(s2));
TreeSet<String> ts3 = new TreeSet<>(Comparable::compareTo);
Consumer<String> c1 = s->System.out.println(s);
Consumer<String> c2 = System.out::println;
引用类方法
类名 :: 静态方法名
@FunctionalInterface
public interface Converter {
int converter(String s);
}
public class ConverterDemo {
public static void main(String[] args) {
// lambda
userConverter(s->Integer.parseInt(s),"123");
//方法引用
userConverter(Integer :: parseInt,"456");
}
public static void userConverter(Converter c,String s){
int i = c.converter(s);
System.out.println(i);
}
}
对象的实例方法的引用
对象::成员方法
@FunctionalInterface
public interface Printer {
void printUpCase(String str);
}
public class PrintString {
public void printUpper(String s){
String res = s.toUpperCase();
System.out.println(res);
}
}
public class PrinterDemo {
public static void main(String[] args) {
userPrinter(str -> System.out.println(str.toUpperCase()),"hello");
PrintString ps = new PrintString();
userPrinter(ps::printUpper,"world");
}
public static void userPrinter(Printer p ,String s){
p.printUpCase(s);
}
}
构造引用
类名 :: new
@FunctionalInterface
public interface StudentInterface {
Student build(String name,int age);
}
/******************************/
public 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;
}
}
/****************************************/
public class StudentDemo {
public static void main(String[] args) {
//lambda表达式
userStudent((name,age)->new Student(name,age));
//构造引用
userStudent(Student::new);
}
public static void userStudent(StudentInterface si){
Student stu = si.build("张三",21);
System.out.println(stu.getName() +"---"+stu.getAge());
}
}
常用Lambda
Integer[] d = {76,1,55,17,23,99};
Arrays.sort(d,(a,b)->b-a); //降序
list.forEach(a->System.out.println(a)); //集合增强for的简化方式
filter