文章目录
1.枚举
假设我们定义一个颜色类:
//三原色 典型的多例模式
class Color{
private String title;
private Color(String title){
this.title = title;
}
public static final int RED_FLAG = 1;
public static final int GREEN_FLAG = 5;
public static final int BLUE_FLAG = 10;
private static final Color RED = new Color("红");
private static final Color GREEN = new Color("绿");
private static final Color BLUE = new Color("蓝");
public static Color getInstance(int flag){
switch (flag){
case RED_FLAG:return RED;
case GREEN_FLAG:return GREEN;
case BLUE_FLAG:return BLUE;
default:return null;
}
}
@Override
public String toString() {
return this.title;
}
}
public class Test{
public static void main(String[] args) {
Color color = Color.getInstance(Color.RED_FLAG);
System.out.println(color);
}
}
使用多例模式这种方法,扩展会非常的麻烦,JDK1.5之后产生了枚举类,使用枚举类修改以上代码:
enum Color{
RED,BLUE,GREEN
}
public class Test{
public static void main(String[] args) {
Color color = Color.RED;
System.out.println(color);
}
}
1.1 语法
enum 类名{
//属性通常大写
属性1,属性2,属性3
}
- 使用enum关键字定义的枚举结构实际上是默认继承了Enum枚举类(java.long.Enum)
- Enum中存在两大属性
name:枚举对象名称
ordinal:枚举对象的数字下标
//枚举类.name() 取得枚举对象名称
public final String name() {return name; }
//取得枚举对象下标
public final int ordinal() {return ordinal;}
//枚举类.value()取得所有枚举类的对象
enum Color{
RED,BLUE,GREEN
}
public class Test{
public static void main(String[] args) {
for(Color color : Color.values()){
System.out.println(color);
}
}
}
1.2 enum和Enum的区别
enum是一个关键字,使用enum定义的枚举类本质上就相当于一个类继承了Enum这个抽象类而已。
1.3 枚举中定义其他结构
枚举类和普通类有很多相似的地方、可以定义成员、静态属性、方法
- 枚举中若定义构造方法,构造方法必须使用private封装(枚举类是多例类,枚举类外部不可以产生对象)
- 枚举类中若定义其他结构,枚举对象声明必须放在枚举类的首行
- 枚举可以实现接口
interface IColor{
String color();
}
enum Color implements IColor{
RED("红"),BLUE("蓝"),GREEN("绿");
private String title;
Color(String title) {
this.title = title;
}
@Override
public String color() {
return this.name();
}
}
public class Test{
public static void main(String[] args) {
for(Color color : Color.values()){
System.out.println(color);
}
//枚举类向上转型成接口
IColor color = Color.RED;
System.out.println(color.color());
}
}
1.4 枚举类的应用与总结
/**
4. 枚举类
5. 1.枚举类型不能被用户实例化(用户不能new)
6. 2.定义枚举对象(通常名字是大写)
7. 3.使用枚举对象通过 枚举类.属性
8. 4.枚举类是典型的多例设计、每个枚举对象有且只有一个
9. 5.列举所有枚举对象 枚举类.values()
10. 6.枚举对象名称 枚举对象.name()
11. 7.通过枚举类的valueOf方法获取枚举对象(枚举常量),name必须要存在否则会有非法参数异常
12. 8.枚举类和普通类有很多相似的地方、可以定义成员-静态属性-方法
13. 9.枚举对象有一个方法ordinal可以表示一个下标,从0开始依次加1 在开发中避免使用,它的值基于枚举对象定义的顺序
14. 10.枚举类继承自java.lang.Enum,不能继承其他类
15. 11.枚举类的构造方法是私有的,外部不可以new
16. 12.枚举类可以实现接口
*/
enum Color{
RED("#dd0000"),GREEN("#00dd00"),BLUE("#0000dd");
private String rgb;
Color(String rgb) {
this.rgb = rgb;
}
//为什么不提供set方法 枚举对象全局唯一 有且只有一个
//要是有set方法,意味着我们可以改枚举对象,那么所有使用到它的地方都被改了
public String getRgb() {
return rgb;
}
public void print(){
System.out.println(this+" 颜色的rgb为:"+this.rgb);
}
}
public class Test {
public static void main(String[] args) {
Color color = Color.RED;
Color color1 = Color.RED;
System.out.println(color == color1);
//列举所有枚举对象
Color[] colors = Color.values();
for(Color c:colors){
//枚举对象名称
System.out.println(c.name());
}
//通过枚举类的valueOf方法获取枚举对象(枚举常量),name必须要存在否则会有非法参数异常
System.out.println(Color.valueOf("RED"));
Color.RED.print();
//ordinal:枚举对象的数字下标
System.out.println(Color.RED.ordinal());
System.out.println(Color.GREEN.ordinal());
System.out.println(Color.BLUE.ordinal());
System.out.println(Color.class.getSuperclass());
}
}
2.注解
2.1 @Override 准确覆写
当子类覆写父类方法时,此注解检查覆写的方法是否正确声明,只有满足覆写方法要求才会编译通过,否则编译出错
2.2 @Deprecated 过期声明
建议用户不使用原有类或者方法时,可以在类或者方法上加@Deprecated表示在当前版本中不推荐使用
2.3 @SuppressWarnings 压制警告
调用某些操作可能产生问题的时候会出现警告信息,但是警告信息并不是异常
3. JDK1.8新特性
3.1 接口定义加强
JDK1.8之前,接口中只允许有抽象方法和常量,如果此时某一个接口想增加一个方法,就必须去父接口增加这个方法,但是父接口增加了这个方法,其他的子接口和子类又必须全部覆写这个方法,有些工具接口有成百上千个子接口,为了一个接口中有某一个方法,其他的接口和该都必须跟着改变,十分麻烦。
JDK1.8之后接口中允许出现以下两类构造方法
- 用default定义的普通方法,需要通过接口对象来调用
- 用static定义的静态方法,直接使用接口名调用
interface IInterface{
void test();
//用default定义的普通方法,需要通过接口对象来调用
//default不可以省略
default void fun(){
System.out.println("JDK1.8新增的普通方法,通过接口对象调用");
}
//用static定义的静态方法,直接使用接口名调用
static void method(){
System.out.println("JDK1.8新增的静态方法,通过接口名称调用");
}
}
class InterfaceImpl implements IInterface{
@Override
public void test() {
System.out.println("子类覆写抽象方法");
}
}
public class Test {
public static void main(String[] args) {
IInterface iInterface =
new InterfaceImpl();
iInterface.fun();
iInterface.test();
IInterface.method();
}
}
3.2 Lambda表达式
interface Add{
void add(int x,int y);
}
class AddImpl implements Add{
@Override
public void add(int x, int y) {
System.out.println(x+y);
}
}
public class Test {
public static void main(String[] args) {
Add add = new AddImpl();
add.add(10,20);
}
}
此程序用于计算两个数的加法,如果此时想要计算两个数的和再加10,为了不影响其他数据求和,就必须重新写一个专门的类来计算x+y+10,当然也可以使用匿名内部类来实现
interface Add{
void add(int x,int y);
}
public class Test {
public static void main(String[] args) {
Add add = new Add() {
@Override
public void add(int x, int y) {
System.out.println(x+y);
}
};
add.add(10,20);
}
}
在JDK1.8之后有了一种新的方法:函数式编程
interface Add{
void add(int x,int y);
}
public class Test {
public static void main(String[] args) {
//(x,y)--掉膘参数 System.out.println(x+y)函数实现
Add add = (x,y)-> System.out.println(x+y);
Add add1 = (x,y)-> System.out.println(x+10+y);
add.add(10,20);
add1.add(10,20);
}
}
要想使用函数式编程有一个前提,接口必须只有一个抽象方法,如果存在两个以上的抽象方法就无法使用函数式编程,如果某个接口就是为函数编程而生的,在定义时只能存在一个抽象方法,因此有一个新的注解**@FunctionalInterface**,此注解会检查该接口是否只存在一个抽象方法,存在两个抽象方法以上编译出错。
3.2.1 语法
当方法体中只有一行代码时:(方法参数)->具体的方法体实现
当方法有返回值时,单行代码的lambda表达式可以省略return语句
@FunctionalInterface
interface Add{
void add(int x,int y);
}
@FunctionalInterface
interface AddTest{
int add(int x,int y);
}
public class Test {
public static void main(String[] args) {
//(x,y)--参数 System.out.println(x+y)函数实现
Add add = (x,y)-> System.out.println(x+y);
add.add(10,20);
AddTest add1 = (x,y)-> x+y+10;
System.out.println(add1.add(10,20));
}
}
当方法体中有多行代码时:
(方法参数) ->{
.......
.......
[return 语句];
};
@FunctionalInterface
interface Add{
int add(int x,int y);
}
public class Test {
public static void main(String[] args) {
Add add = (p1,p2) ->{
int result = p1+p2;
result+=20;
return result;
};
System.out.println(add.add(20,20));
}
}
4.方法引用
方法引用只是给现有方法起别名
方法引用一共有四大形式:
4.1 引用类中的静态方法
类名称::静态方法名称
interface IUnit<P,R>{
R switchPara(P p);
}
public class Test {
public static void main(String[] args) {
//相当于给String类的valueOf方法起了一个别名switchPara
IUnit<Integer,String> util
= String::valueOf;
//相当于调用String.valueOf() 将Integer类型的值变成String类
String str = util.switchPara(123);
System.out.println(str);
}
}
4.2 引用类中的普通方法
类名称::普通方法名
//调用类中普通方法
interface IUnit<R,P>{
R compare(P p1,P p2);
}
public class Test {
public static void main(String[] args) {
IUnit<Integer,String> util
= String::compareTo;
//相当于调用String.comparTo
System.out.println(util.compare("a","v"));
}
}
4.3 引用类中的构造方法
类名称::new
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
interface IUtil<R,PN,PR>{
R createPer(PN p1,PR p2);
}
public class Test {
public static void main(String[] args) {
IUtil<Person,String,Integer> util =
Person::new;
System.out.println(util.createPer("张三",12));
}
}
4.4 引用某个对象的方法
实例化对象::普通方法
// 引用某个对象的方法
interface IUnit<R>{
R switchPara();
}
public class Test {
public static void main(String[] args) {
IUnit<String> util
= "hello"::toUpperCase;
//相当于调用"hello".toUpperCase(10)
System.out.println(util.switchPara());
}
}