Java8新特性

需求: 获取年龄大于35岁的用户信息
POJO

package com.example.pojo;

public class User {
    private String userName;
    private String sex;
    private Integer age;
    private Integer salary;
    public User() {
    }

    public User(String userName, String sex, Integer age, Integer salary) {
        this.userName = userName;
        this.sex = sex;
        this.age = age;
        this.salary = salary;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSalary() {
        return salary;
    }

    public void setSalary(Integer salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}
  1. 获取方法
List<User> userList= Arrays.asList(
            new User("张三", "男", 19, 1000),
            new User("李四", "男", 36, 2000),
            new User("王五", "男", 39, 3000),
            new User("JACK", "男", 28, 2500),
            new User("LUCY", "女", 40, 1500)
    );
    // 获取年龄大于35的用户信息
    List<User> findAge(List<User> userList){
        ArrayList<User> users = new ArrayList<>();
        for (User user : userList) {
            if(user.getAge() >= 35){
                users.add(user);
            }
        }
        return users;
    }
     @Test
    void test() {
		System.out.println(findAge(userList));
    }
  1. 第一次优化(策略设计模式)
package com.example.pojo;

public interface MyPredicate<T> {
    public boolean test(T t);
}

实现接口做不同的处理

package com.example;

import com.example.pojo.MyPredicate;
import com.example.pojo.User;

public class FilterUserByAge implements MyPredicate<User> {
    @Override
    public boolean test(User user) {
        return user.getAge()>35;
    }
}
package com.example;

import com.example.pojo.MyPredicate;
import com.example.pojo.User;

public class FilterUserSalary implements MyPredicate<User> {
    @Override
    public boolean test(User user) {
        return user.getSalary()>=2000;
    }
}

调用

 @Test
    void test() {
        // 年龄大于35
        System.out.println(filterUser(userList, new FilterUserByAge()));
        // 薪资大于2000
        System.out.println(filterUser(userList, new FilterUserSalary()));
    }
    // 优化方式一: 策略设计模式

    List<User> filterUser(List<User> list, MyPredicate<User> mp){
        ArrayList<User> users = new ArrayList<>();
        for (User user : list) {
            if (mp.test(user)){
                users.add(user);
            }
        }
        return users;
    }
  1. 第二次优化(匿名内部类)
    @Test
    void test() {
       List<User> users = filterUser(userList, new MyPredicate<User>() {
            @Override
            public boolean test(User user) {
                return user.getAge() >= 35;
            }
        });
        System.out.println(users);
    }
  1. 第三次优化(Lambda表达式)
 @Test
    void test() {
        List<User> users = filterUser(userList, (user) -> user.getAge() >= 35);
        users.forEach(System.out::println);
    }
  1. 第四次优化(Stream API)
    @Test
    void test() {
        userList.stream()
                .filter((user) -> user.getAge() >= 35)
                .forEach(System.out::println);
    }

1.Lambda表达式*

为什么使用Lambda表达式: Lambda是一个匿名函数,可以吧Lambda理解为一段可以传递的代码


基本用法

  • 无参无返回值
@Test
    public void test1(){
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello Word!");
            }
        };
        r.run();
        
        Runnable r2 = () -> System.out.println("Hello Lambda!");
        r2.run();
    }
  • 一个参数, 无返回值,只有一个参数()可以不写
@Test
    public void test2(){
        Consumer<String> consumer = (t) -> System.out.println(t);
        consumer.accept("Hello Lambda!");
    }
  • 两个以上参数, 有返回值,Lambda体有多条语句
@Test
    public void test3(){
        Comparator<Integer> com = (x, y) -> {
            System.out.println("Lambda体1");
            System.out.println("Lambda体2");
            return x + y;
        };
        System.out.println(com.compare(3, 4));
    }

2.函数式接口

Lambda表达式需要函数式接口的支持, 函数式接口是指接口中只有一个抽象方法的接口
可以通过注解@FunctionalInterface,检查接口是不是函数式接口
在这里插入图片描述
四大内置核心函数式接口

函数式接口参数类型返回类型用途
Consumer消费型接口Tvoid对类型为T的对象应用操作:void accept(T t)
Supplier提供型接口T返回类型为T的对象:T get()
Function<T, R>函数型接口TR对类型为T的对象应用操作,并返回结果为R类型的对象:R apply(T t)
Predicate断言型接口Tboolean确定类型为T的对象是否满足某约束,并返回boolean值:boolean test(T t)
  • Consumer : 消费型接口
    void accept(T t);
@Test
    void test3(){
        happy(1000, (x) -> System.out.println("消费了" + x + "元"));
    }
    void happy(double money, Consumer<Double> con){
        con.accept(money);
    }
  • Supplier : 供给型接口
    T get();
@Test
    void test4(){
        System.out.println(getNumList(6, () -> (int)(Math.random()*100)));
    }
    List<Integer> getNumList(int num, Supplier<Integer> sup){
        ArrayList<Integer> integers = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            integers.add(sup.get());
        }
        return integers;
    }
  • Function<T, R> : 函数型接口
    R apply(T t);
 @Test
    void test5(){
        System.out.println(strHandler("\t\t\t Hello Function!!!! ", s -> s.trim()));
    }
    String strHandler(String str, Function<String, String> fun){
        return fun.apply(str);
    }
  • Predicate : 断言型接口
    boolean test(T t);
List<String> strList=Arrays.asList(
            "Jack",
            "Back",
            "AAA",
            "BDC"
    );
    @Test
    void test6(){
        System.out.println(filterStr(strList, (s) -> s.length() < 4));
    }
    List<String>  filterStr(List<String> str, Predicate<String> pre){
        ArrayList<String> strings = new ArrayList<>();
        for (String s : str) {
            if (pre.test(s)){
                strings.add(s);
            }
        }
        return strings;
    }

3.方法引用与构造引用

4.Stream API*

什么是Stream
流,是数据渠道,用于操作数据源所生成的元素序列
Stream的操作步骤

  1. 创建Stream
// 创建Stream
    @Test
    void  test7(){
        // 通过Collection提供的stream()
        ArrayList<String> strings = new ArrayList<>();
        Stream<String> stream = strings.stream();

        // 通过Arrays中的静态方法stream创建数组流
        User[] users = new User[10];
        Stream<User> stream1 = Arrays.stream(users);

        // 通过Stream类中的静态方法of()
        Stream<String> a = Stream.of("a", "b", "c");

        // 创建无限流
        Stream.generate(() -> Math.random())
                .limit(5)
                .forEach(System.out::println);
    }
  1. 中间操作

筛选与切片

  • filter 从流中排除某些元素
  • limit 截断流,使其不超过指定数量
  • skib 跳过流的前n个元素
  • distinct 去重,通过重写equals()和hashCode()
List<User> userList= Arrays.asList(
            new User("张三", "男", 19, 1000),
            new User("李四", "男", 36, 2000),
            new User("王五", "男", 39, 3000),
            new User("JACK", "男", 28, 2500),
            new User("LUCY", "女", 40, 1500),
            new User("LUCY", "女", 40, 1500)
    );

    @Test
    void test8(){
        // 中间操作
        Stream<User> userStream = userList.stream()
                .filter((e) -> e.getAge() >= 30)
                .limit(4)
                .skip(2)
                .distinct();

        // 终止操作
        userStream.forEach(System.out::println);
    }

打印结果:User{userName=‘LUCY’, sex=‘女’, age=40, salary=1500}

映射

  • map 接收一个lambda, 提取信息, 接收一个函数作为参数, 该函数会被应用到每个元素上。
@Test
    void test9(){
        // 获取所有用户的名字
        userList.stream()
                .map(User::getUserName)
                .forEach(System.out::println);
    }
  • flatmap 接收一个函数作为参数,将流中的每一个值换成另一个流,然后把所有流连接成一个流。

排序

  • sorted() – 自然排序
  • sorted(Comparator com) – 定制排序
List<User> userList= Arrays.asList(
            new User("张三", "男", 19, 2000),
            new User("王五", "男", 39, 3000),
            new User("JACK", "男", 28, 2500),
            new User("LUCY", "女", 40, 1500),
            new User("LUCY", "女", 40, 1500),
            new User("李四", "男", 19, 1000)
    );

    List<String> list = Arrays.asList("bbb", "aaa", "ddd", "ccc");

    @Test
    void test10(){
        list.stream()
                .sorted()
                .forEach(System.out::println);

        userList.stream()
                .sorted((e1, e2) -> {
                    if (e1.getAge() == e2.getAge()){
                        return e1.getSalary().compareTo(e2.getSalary());
                    }else {
                        return e1.getAge().compareTo(e2.getAge());
                    }
                })
                .forEach(System.out::println);
    }

结果
在这里插入图片描述

  1. 终止操作

查找与匹配

  • allMatch – 检查是否匹配所有元素
  • anyMatch – 检查是否至少匹配一个元素
  • noneMatch – 检查是否没有匹配所有元素
  • findFirst – 返回第一个元素
  • findAny – 返回当前流中的任意元素
  • count – 返回流中元素的总个数
  • max – 返回流中的最大值
  • min – 返回流中的最小值
	List<User> userList= Arrays.asList(
            new User("张三", "男", 19, 2000, User.Status.BENCH),
            new User("张三", "男", 19, 2000, User.Status.BENCH),
            new User("王五", "男", 39, 3000, User.Status.VOCATION),
            new User("JACK", "男", 28, 2500, User.Status.BUSY),
            new User("LUCY", "女", 40, 1500, User.Status.BENCH),
            new User("LUCY", "女", 40, 1500, User.Status.VOCATION),
            new User("李四", "男", 19, 1000, User.Status.BUSY)
    );

    @Test
    void test11(){
        boolean b = userList.stream()
                .allMatch((e) -> e.getStatus().equals(User.Status.BUSY));
        System.out.println(b);
        boolean b1 = userList.stream()
                .anyMatch((e) -> e.getStatus().equals(User.Status.BUSY));
        System.out.println(b1);
        boolean b2 = userList.stream()
                .noneMatch((e) -> e.getStatus().equals(User.Status.BUSY));
        System.out.println(b2);

        Optional<User> first = userList.stream()
                .sorted((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(first.get());
        System.out.println("---------");
        // parallelStream并行的方式,谁先找到是谁的
        Optional<User> any = userList.parallelStream()
                .filter((e) -> e.getStatus().equals(User.Status.BENCH))
                .findAny();
        System.out.println(any.get());

        long count = userList.stream()
                .count();
        System.out.println(count);

        Optional<User> max = userList.stream()
                .max((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()));
        System.out.println("薪资最高的用户"+max.get());
        Optional<User> min = userList.stream()
                .min((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()));
        System.out.println("薪资最低的用户"+max.get());
    }

规约

  • reduce(T identity, BinaryOperator)/reduce(BinaryOperator) – 可以将流中的元素反复结合起来,得到一个值
List<User> userList = Arrays.asList(
            new User("张三", "男", 19, 2000, User.Status.BENCH),
            new User("张三", "男", 19, 2000, User.Status.BENCH),
            new User("王五", "男", 39, 3000, User.Status.VOCATION),
            new User("JACK", "男", 28, 2500, User.Status.BUSY),
            new User("LUCY", "女", 40, 1500, User.Status.BENCH),
            new User("LUCY", "女", 40, 1500, User.Status.VOCATION),
            new User("李四", "男", 19, 1000, User.Status.BUSY)
    );
    List<Integer> intList = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    /**
     * identity为初始值
     */
    @Test
    void test12(){
        Integer intReduce = intList.stream()
                .reduce(3, Integer::sum);
        System.out.println(intReduce);

        Integer reduce = userList.stream()
                .map(User::getSalary)
                .reduce(0, Integer::sum);
        System.out.println(reduce);
    }

在这里插入图片描述
收集

  • collect – 将流转换成其他形式.接收一个Collector接口的实现,用于给Stream中元素做汇总
    通过Collectors中的静态方法
@Test
    void test13() {
        Set<String> SetCollect = userList.stream()
                .map(User::getUserName)
                .collect(Collectors.toSet());
        SetCollect.forEach(System.out::println);

        // 自己new的集合
        ArrayList<String> listCollect = userList.stream()
                .map(User::getUserName)
                .collect(Collectors.toCollection(ArrayList::new));

        // 总和
        Long collect = userList.stream()
                .collect(Collectors.counting());
        System.out.println(collect);
        // 分组
        Map<User.Status, List<User>> groupCollect = userList.stream()
                .collect(Collectors.groupingBy(User::getStatus));
        System.out.println("将用户按状态分组" + groupCollect);
        // 平均薪资
        Double avgSalaryCollect = userList.stream()
                .collect(Collectors.averagingInt(User::getSalary));
        System.out.println("用户平均薪资"+avgSalaryCollect);
        // 最大
        Optional<User> maxSalaryCollect = userList.stream()
                .collect(Collectors.maxBy((e1, e2) -> e1.getSalary().compareTo(e2.getSalary())));
        System.out.println("薪资最高用户" + maxSalaryCollect.get());
        // 最小
        Optional<User> minSalaryCollect = userList.stream()
                .collect(Collectors.minBy((e1, e2) -> e1.getSalary().compareTo(e2.getSalary())));
        System.out.println("薪资最低用户" + minSalaryCollect.get());
    }

在这里插入图片描述
中间操作不会执行任何操作, 直到终止操作一次性执行全部内容,即惰性求值

并行流与顺序流

并行流: 把一个内容分成多个数据块,用不同的线程处理每个数据块的流
顺序流: 是单线程的
Stream API可以声明性地通过parallel()并行流与sequential()顺序流之间进行切换。

@Test
    void test14() {
        long parallelStartTime = System.currentTimeMillis();
        LongStream.rangeClosed(0, 1000000000L)
                .parallel()
                .reduce(0, Long::sum);
        long parallelEndTime = System.currentTimeMillis();
        System.out.println("并行流" + (parallelEndTime - parallelStartTime));
        System.out.println("-----------------------");
        long orderStartTime = System.currentTimeMillis();
        LongStream.rangeClosed(0, 1000000000L)
                .sequential()
                .reduce(0, Long::sum);
        long orderEndTime = System.currentTimeMillis();
        System.out.println("顺序流" + (orderEndTime - orderStartTime));
    }

在这里插入图片描述

Optional类

Optional < T > 类是一个容器类, 代表一个值存在或者不存在, 能更好的避免空指针异常。
常用方法

方法作用
Optional.of(T t)创建一个Optional实例
Optional.empty()创建一个空的Optional实例
Optional.ofNullable(T t)若t不为null,创建Optional实例,否则创建空实例
@Test
    void test15(){
        Optional<User> userOptional = Optional.of(new User());
        System.out.println(userOptional.get());

        Optional<User> userNullOptional = Optional.empty();
        System.out.println(userNullOptional.get());

        Optional<User> userNullOptional3 = Optional.ofNullable(null);
        System.out.println(userNullOptional3.get());
    }

实质上为null的话,可以快速定位到空值的地方。

方法作用
isPresent()判断是否包含空值
orElse(T t)如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s)如果调用对象包含值, 返回该值, 否则返回s获取的值
map(Function f)如果有值对其进行处理,并返回处理后的Optional,否则返回Option.empty()
flatMap(Function mapper)与map类似,要求返回值为Option
@Test
    void test16() {
        Optional<User> userNullOptional1 = Optional.ofNullable(null);
        if (userNullOptional1.isPresent()) {
            System.out.println("userNullOptional1:" + userNullOptional1.get());
        } else {
            System.out.println("为空不做任何操作");
        }

        Optional<User> userNullOptional2 = Optional.ofNullable(new User("XQ", "女", 11, 10000, User.Status.BUSY));
        if (userNullOptional2.isPresent()) {
            System.out.println("userNullOptional2:" + userNullOptional2.get());
        }

        // 避免空指针异常
        System.out.println("Optional为null时" + userNullOptional1.orElse(new User("XQ", "女", 11, 10000, User.Status.BUSY)));
        System.out.println("Optional不为null时"+userNullOptional2.orElse(new User("XQ", "女", 11, 10000, User.Status.BUSY)));

        Optional<String> userName = userNullOptional2.map((user -> user.getUserName()));
        System.out.println(userName.get());

        Optional<String> userNameOptional = userNullOptional2.flatMap((e) -> Optional.of(e.getUserName()));
        System.out.println(userNameOptional.get());
    }

在这里插入图片描述

5.接口中的默认方法与静态方法

默认方法: 在接口总用default修饰的方法可以直接实现

public interface MyFun {
    default String getMsg() {
        return "哈哈哈";
    }

	public static void show(){
        System.out.println("接口中的静态方法");
    }
}

接口中默认方法的类优先原则
一个接口定义了一个默认方法,而另一个父类或接口中又定义了一个同名的方法

1.选择父类中的方法
2.接口冲突,如果两个接口中提供了相同名称和参数的默认方法,那么实现类必须重写该方法解决冲突。

新建一个类,方法与接口中的默认方法一样

public class MyClass {
    public String getMsg(){
        return "嘿嘿嘿";
    }
}

同时继承类和实现接口

public class SubClass extends MyClass implements MyFun {
}

调用

@Test
    void test17(){
    	MyFun.show();
        String msg = new SubClass().getMsg();
        System.out.println(msg);
    }

打印结果为 嘿嘿嘿

6.新时间日期API

传统的时间API存在线程安全的问题,多线程开发的时候必须上锁, 所以java8提供了一套全新的时间API:
在这里插入图片描述
1. LocalDate, LocalTime, LocalDateTime

LocalDate、 LocalTime、 LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。

@Test
 void test18(){
    //获取当前时间日期 now
    LocalDateTime ldt1 = LocalDateTime.now();
    System.out.println(ldt1);

    //指定时间日期 of
    LocalDateTime ldt2 = LocalDateTime.of(2020, 05, 17, 16, 24, 33);
    System.out.println(ldt2);

    //加 plus
    LocalDateTime ldt3 = ldt2.plusYears(2);
    System.out.println(ldt3);

    //减 minus
    LocalDateTime ldt4 = ldt2.minusMonths(3);
    System.out.println(ldt4);

    //获取指定的你年月日时分秒... get
    System.out.println(ldt2.getDayOfYear());
    System.out.println(ldt2.getHour());
    System.out.println(ldt2.getSecond());
}

LocalDate, LocalTime雷同
2. Instant 时间戳
以 Unix 元年 1970-01-01 00:00:00 到某个时间之间的毫秒值

@Test
void test18(){
    // 默认获取 UTC 时区 (UTC:世界协调时间)
    Instant ins1 = Instant.now();
    System.out.println(ins1);

    //带偏移量的时间日期 (如:UTC + 8)
    OffsetDateTime odt1 = ins1.atOffset(ZoneOffset.ofHours(8));
    System.out.println(odt1);

    //转换成对应的毫秒值
    long milli1 = ins1.toEpochMilli();
    System.out.println(milli1);

    //构建时间戳
    Instant ins2 = Instant.ofEpochSecond(60);
    System.out.println(ins2);
}

3. 时间/日期 间隔

  • Duration:计算两个时间之间的间隔
  • Period:计算两个日期之间的间隔
@Test
void test19(){
    // 计算两个时间之间的间隔 between
    Instant ins1 = Instant.now();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Instant ins2 = Instant.now();
    Duration dura1 = Duration.between(ins1, ins2);
    System.out.println(dura1.getSeconds());
    System.out.println(dura1.toMillis());
}

@Test
 void test20(){
    LocalDate ld1 = LocalDate.of(2018, 10, 1);
    LocalDate ld2 = LocalDate.now();
    // ISO 标准
    Period period = Period.between(ld1, ld2);  
    System.out.println(period.getYears());
    System.out.println(period.toTotalMonths());
}

3. 时间校正器
在这里插入图片描述

@Test
void test21(){
    //TemporalAdjusters:时间校正器
    LocalDateTime ldt1 = LocalDateTime.now();
    System.out.println(ldt1);

    //指定日期时间中的 年 月 日 ...
    LocalDateTime ldt2 = ldt1.withDayOfMonth(10);
    System.out.println(ldt2);

    //指定时间校正器
    LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
    System.out.println(ldt3);

    //自定义时间校正器
    LocalDateTime ldt5 = ldt1.with((l) -> {
        LocalDateTime ldt4 = (LocalDateTime) l;
        DayOfWeek dow1 = ldt4.getDayOfWeek();
        if (dow1.equals(DayOfWeek.FRIDAY)) {
            return ldt4.plusDays(3);
        } else if (dow1.equals(DayOfWeek.SATURDAY)) {
            return ldt4.plusDays(2);
        } else {
            return ldt4.plusDays(1);
        }
    });
    System.out.println(ldt5);
}

4. 时间日期格式化

  • DateTimeFormatter:格式化时间 / 日期
@Test
void test22(){
    //默认格式化
    DateTimeFormatter dtf1 = DateTimeFormatter.ISO_DATE_TIME;
    LocalDateTime ldt1 = LocalDateTime.now();
    String str1 = ldt1.format(dtf1);
    System.out.println(str1);

    //自定义格式化 ofPattern
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTime ldt2 = LocalDateTime.now();
    String str2 = ldt2.format(dtf2);
    System.out.println(str2);

    //解析
    LocalDateTime newDate = ldt1.parse(str1, dtf1);
    System.out.println(newDate);
}

5. 时区

  • ZonedDate
  • ZonedTime
  • ZonedDateTime
@Test
void test23(){
    //查看支持的时区
    Set<String> set = ZoneId.getAvailableZoneIds();
    set.forEach(System.out::println);

    //指定时区
    LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
    System.out.println(ldt1);

    //在已构建好的日期时间上指定时区
    LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
    ZonedDateTime zdt1 = ldt2.atZone(ZoneId.of("Europe/Tallinn"));
    System.out.println(zdt1);
}

格式的转换

@Test
public void test03(){
	// Date 转 LocalDateTime 
	Date date = new Date();
    Instant instant = date.toInstant();
    ZoneId zoneId = ZoneId.systemDefault();
    LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();

	// LocalDateTime 转 Date
	LocalDateTime localDateTime = LocalDateTime.now();
	ZoneId zoneId = ZoneId.systemDefault();
    ZonedDateTime zdt = localDateTime.atZone(zoneId);
    Date date = Date.from(zdt.toInstant());
	
	// 原则:利用 时间戳Instant
}

7.其他新特性

重复注解
定义注解:

@Repeatable(MyAnnotations.class) //指定容器类
@Target({ElementType.TYPE, ElementType.METHOD,  ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String value() default "Java 8";
}

定义容器:

@Target({ElementType.TYPE, ElementType.METHOD,  ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotations {

    MyAnnotation[] value();
}

public class Test01 {

    //重复注解
    @Test
    @MyAnnotation("Hello")
    @MyAnnotation("World")
    public void test01() throws NoSuchMethodException {
        Class<Test01> clazz = Test01.class;
        Method test01 = clazz.getMethod("test01");
        MyAnnotation[] mas = test01.getAnnotationsByType(MyAnnotation.class);
        for (MyAnnotation ma : mas) {
            System.out.println(ma.value());
        }
    }
}

类型注解
新增ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值