文章目录

  • 前言
  • 一、自定义枚举类
  • 二、enum定义枚举类
  • 1.常用的方法
  • 2.枚举类实现接口
  • 三、注解
  • 1、JDK内置的基本注解类型
  • 2、自定义注解
  • 3、元注解
  • 4、解析注解
  • 5、注解练习

前言

JDK1.5之前需要自定义枚举类

JDK1.5新增的enum关键字用于定义枚举类

若枚举只有一个成员,则可以作为一种单例模式的实现方式

一、自定义枚举类

package com.enums;

/**
 * 季节测试枚举
 */
public class TestSeason {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring);
        System.out.println(spring.getSeasonName());
    }
}

/**
 * 枚举类
 */
class Season {
    //1.提供类的属性,声明为private final
    private final String seasonName;
    private final String seasonDesc;

    //2.声明final的属性,在构造器中初始化
    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //3.通过公共的方法的来调用属性
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    //4.创建枚举类的对象
    public static final Season SPRING = new Season("spring", "春天");
    public static final Season SUMMER = new Season("summer", "夏天");
    public static final Season AUTUMN = new Season("autumn", "秋天");
    public static final Season WINTER = new Season("winter", "冬天");

    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

二、enum定义枚举类

1.常用的方法

package com.enums;

/**
 * 季节测试枚举
 */
public class TestSeason2 {
    public static void main(String[] args) {
        SeasonEnum spring = SeasonEnum.SPRING;
        System.out.println(spring);
        System.out.println(spring.getSeasonName());
        //1.values
        SeasonEnum[] seasonEnums = SeasonEnum.values();
        for (SeasonEnum season : seasonEnums) {
            System.out.println(season);
        }
        //2.valueOf
        String str = "SPRING";
        SeasonEnum seasonEnum2 = SeasonEnum.valueOf(str);
        System.out.println(seasonEnum2);
    }
}

/**
 * enum枚举类
 */
enum SeasonEnum {

    SPRING("spring", "春天"),
    SUMMER("summer", "夏天"),
    AUTUMN("autumn", "秋天"),
    WINTER("winter", "冬天");

    private final String seasonName;
    private final String seasonDesc;

    private SeasonEnum(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

2.枚举类实现接口

可以让不同的枚举类对象(SPRING、SUMMER 就是实例化的对象public static final Season SPRING = new Season("spring", "春天"); )调用被重写的抽象方法,执行的重新的方法效果不同。

package com.enums;

/**
 * 季节测试枚举
 */
public class TestSeason2 {
    public static void main(String[] args) {
        SeasonEnum spring = SeasonEnum.SPRING;
        System.out.println(spring);
        System.out.println(spring.getSeasonName());
        //1.values
        SeasonEnum[] seasonEnums = SeasonEnum.values();
        for (SeasonEnum season : seasonEnums) {
            System.out.println(season);
        }
        //2.valueOf
        String str = "SPRING";
        SeasonEnum seasonEnum2 = SeasonEnum.valueOf(str);
        System.out.println(seasonEnum2);
        //3.枚举类实现接口
        spring.show();
    }
}

interface Info {
    void show();
}

/**
 * enum枚举类
 */
enum SeasonEnum implements Info {
    /**
     * SPRING、SUMMER、AUTUMN、WINTER都重写了接口的show()方法
     */
    SPRING("spring", "春天") {
        public void show() {
            System.out.println("春天来了");
        }
    },
    SUMMER("summer", "夏天") {
        public void show() {
            System.out.println("夏天来了");
        }
    },
    AUTUMN("autumn", "秋天") {
        public void show() {
            System.out.println("秋天来了");
        }
    },
    WINTER("winter", "冬天") {
        public void show() {
            System.out.println("冬天来了");
        }
    };

    private final String seasonName;
    private final String seasonDesc;

    private SeasonEnum(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }

//    @Override
//    public void show() {
//        System.out.println("枚举类实现接口");
//    }
}

三、注解

注解:注解是对代码的一种增强,可以在程序运行或者编译期间获取注解的信息,然后根据这些注解信息做各种事情,比如重写父类的方法等。

从JDK1.5开始,Java增加了对元数据的支持,也就是annotation注解

1、JDK内置的基本注解类型

@Override重写父类方法
@Deprecated表示某个程序的类方法已过时
@SuppressWarnings抑制警告

2、自定义注解

1.注解的语法

public @interface MyAnnotation {
}

2.注解中定义参数

public @interface 注解名称{
[public] 参数类型 参数名称1()[default 参数默认值];
[public] 参数类型 参数名称2()[default 参数默认值];

}

注解中可以定义多个参数,参数的定义有以下特点:
1)访问修饰符必须为public,不写默认为public
2)该元素的类型只能是基本数据类型、String、Class、枚举类型、注解类型(体现了注解的嵌套效果)以及上述类型的一位数组
3)该元素的名称一般定义为名词,如果注解中只有一个元素,请把名字起为value(后面使用会带来便利操作)
4)参数名称后面的()不是定义方法参数的地方,也不能在括号中定义任何参数,仅仅只是一个特殊的语法
5)default代表默认值,值必须和第2点定义的类型一致
6)如果没有默认值,代表后续使用注解时必须给该类型元素赋值
7)成员无参无异常方式声明
3.使用范围
@Target

package java.lang.annotation;
/*注解的使用范围*/
public enum ElementType {
       /*类、接口、枚举、注解上面*/
    TYPE,
    /*字段上*/
    FIELD,
    /*方法上*/
    METHOD,
    /*方法的参数上*/
    PARAMETER,
    /*构造函数上*/
    CONSTRUCTOR,
    /*本地变量上*/
    LOCAL_VARIABLE,
    /*注解上*/
    ANNOTATION_TYPE,
    /*包上*/
    PACKAGE,
    /*类型参数上*/
    TYPE_PARAMETER,
    /*类型名称上*/
    TYPE_USE
}

3、元注解

元注解就是给注解进行注解

@Target 使用范围

@Retention:用指定注解可以保留多长时间(@Retention有一个value参数,类型为RetentionPolicy枚举)

public enum RetentionPolicy {
    /*注解只保留在源码中,编译为字节码之后就丢失了,也就是class文件中就不存在了*/
    SOURCE,
    /*注解只保留在源码和字节码中,运行阶段会丢失*/
    CLASS,
    /*源码、字节码、运行期间都存在*/
    RUNTIME
}

@Inherited
作用:让子类可以继承父类中被@Inherited修饰的注解,注意是继承父类中的,如果接口中的注解也使用@Inherited修饰了,那么接口的实现类是无法继承这个注解的。只会继承类上的注解

@Documented 生成Javadoc时会包含注解

4、解析注解

方式一:

public static void main(String[] args) {
        try {
            //1.使用类加载器加载类
            Class c = Class.forName("com.annotations.Person");
            //2.找到类上面的注解,判断这个注解是否存在
            boolean isExist = c.isAnnotationPresent(MyAnnotation.class);
            if (isExist) {
                //3.拿到注解的实例
                MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
                System.out.println("获取类上面的注解:"+myAnnotation.value());
            }
            //4.找到方法上的注解
            Method[] methods = c.getMethods();
            for (Method m :methods){
                boolean isMExist = m.isAnnotationPresent(MyAnnotation.class);
                if(isMExist){
                    MyAnnotation myMethod =  m.getAnnotation(MyAnnotation.class);
                    System.out.println("获取方法上面的注解:"+myMethod.value());
                }

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

方式二:

public static void main(String[] args) {
        try {
            //1.使用类加载器加载类
            Class c = Class.forName("com.annotations.Person");
            //2.找到类上面的注解,判断注解是否存在
            boolean exist = c.isAnnotationPresent(MyAnnotation.class);
            if (exist) {
                //3.获取注解的实例
                MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
                System.out.println("获取类上面的注解:" + myAnnotation.value());
                //4.找到方法上面的注解
                Method[] methods = c.getMethods();
                for (Method m : methods) {
                    //5.获取所有的注解
                    Annotation[] myAnnotation1 = m.getAnnotations();
                    for (Annotation my : myAnnotation1){
                        if(my instanceof MyAnnotation){
                            MyAnnotation mn = (MyAnnotation) my;
                            System.out.println("获取方法上面的注解:"+mn.value());
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

5、注解练习

注解类

package com.annotations;
/**
 * 注解类
 */
@Table("job")
public class Filter {
    @Column("id")
    private String id;

    @Column("phone")
    private String phone;

    @Column("email")
    private String email;

    @Column("address")
    private String address;

    @Column("job_name")
    private String jobName;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    @Override
    public String toString() {
        return "Filter{" +
                "id='" + id + '\'' +
                ", phone='" + phone + '\'' +
                ", email='" + email + '\'' +
                ", address='" + address + '\'' +
                ", jobName='" + jobName + '\'' +
                '}';
    }
}

表名注解

package com.annotations;

import java.lang.annotation.*;

/**
 * 用于注解表名
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}

字段的注解

package com.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 用于注解字段
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}

测试类

package com.annotations;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 测试注解的表
 */
public class TableAnnotationTest {
    public static void main(String[] args) {

        Filter f1 = new Filter();
        f1.setId("10");//查询id为10的用户

        Filter f2 = new Filter();
        f2.setJobName("lucy");//查询名为lucy用户
        f2.setAddress("陆家嘴");
        Filter f3 = new Filter();
        f3.setEmail("li@qq.com,ming@163.com,yuan@sina.com");

        String sql1 = query(f1);

        String sql2 = query(f2);

        String sql3 = query(f3);

        System.out.println(sql1);
        System.out.println(sql2);
        System.out.println(sql3);

    }

    /**
     * 查询sql
     *
     * @param f
     * @return
     */
    private static String query(Object f) {
        //1.获取加载的类
        Class c = f.getClass();
        //2.获取表名,并判断是否存在
        boolean tableExist = c.isAnnotationPresent(Table.class);
        if (!tableExist) {
            return null;
        }
        //3.获取表名注解的实例对象
        Table table = (Table) c.getAnnotation(Table.class);
        //4.获取表名
        String tableName = table.value();
        //5.存放拼装sql
        StringBuffer sb = new StringBuffer();
        sb.append("select * from ").append(tableName).append(" where 1 = 1 ");
        //6.利用反射获取所有的字段
        Field[] files = c.getDeclaredFields();
        for (Field field : files) {
            //7.获取注解的字段实例,并判断是否存在
            boolean columnExist = field.isAnnotationPresent(Column.class);
            if (!columnExist) {
                continue;
            }
            Column column = (Column) field.getAnnotation(Column.class);
            //8.获取所有注解上的字段值
            String columnValue = column.value();
            //9.利用反射获取所有字段名称
            String fieldName = field.getName();
            //10.获取方法名..利用getName
            String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
            Object fieldValue = null;
            try {
                //11.获取所有的方法
                Method methods = c.getMethod(getMethodName);
                //12.通过反射调用,传入对象和参数
                fieldValue = methods.invoke(f);
                //拼装sql
                if (fieldValue == null ||
                        (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
                    continue;
                }
                sb.append(" and ").append(columnValue);
                //如果拼接的sql的字段的是模糊查询加%
                if (fieldValue instanceof String) {
                    if (((String) fieldValue).contains(",")) {
                        String[] array = ((String) fieldValue).split(",");
                        sb.append(" in(");
                        for (String em : array) {
                            sb.append("'").append(em).append("'").append(",");
                        }
                        sb.deleteCharAt(sb.length() - 1);
                        sb.append(")");
                    } else {
                        sb.append(" = ").append("'" + fieldValue + "'");
                    }
                } else if (fieldValue instanceof Integer) {
                    sb.append(" = ").append(fieldValue);
                } else {
                    sb.append(" = ").append(fieldValue);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }
}