目录

这里记录一下Java语言的新特性,以版本号区分。

介绍一些注解,一些注意Java语言的注意事项。

第二章-多线程

KLT和ULT

线程是调度CPU的最小单元,也叫轻量级进程LWP (Light Weight Process)

两种线程模型:

内核级线程KLT(Kemel-Level Threads)

  • 线程管理的所有工作(创建和撤销)由操作系统内核完成
  • 操作系统内核提供一个应用程序设计接口API,供开发者使用KLT

纯内核级线程特点:

进程中的一个线程被阻塞,内核能调度同一进程的其他线程(就绪态)占有处理器运行 多处理器环境中,内核能同时调度同一进程的多线程,将这些线程映射到不同的处理器核心上,提高进程的执行效率。 应用程序线程在用户态运行,线程调度和管理在内核实现。线程调度时,控制权从一个线程改变到另一线程,需要模式切换,系统开销较大。

用户级线程ULT(User-Level Threads ULT)

线程切换不需要内核模式,能节省模式切换开销和内核资源。 允许进程按照特定的需要选择不同的调度算法来调度线程。调度算法需要自己实现。 由于其不需要内核进行支持,所以可以跨OS运行。 不能利用多核处理器有点,OS调度进程,每个进程仅有一个ULT能执行,一个ULT阻塞,将导致整个进程的阻塞。

简单区分:

用户线程(ULT):用户程序实现,不依赖操作系统核心,应用提供创建、同步、调度和管理线程的函数来控制用户线 程。不需要用户态/核心态切换,速度快。内核对ULT无感知,线程阻塞则进程(包括它的所有线程)阻塞。

内核线程(KLT):系统内核管理线程(KLT),内核保存线程的状态和上下文信息,线程阳塞不会引起进程阻塞。在多 处理器系统上,多线程在多处理器上并行运行。线程的创建、调度和管理由内核完成,效率比ULT要慢,比进程操 作快。

一句话区分,一个App若线程交给操作系统管理就是内核级线程KLT,若是交给APP自己管理就是用户级线程ULT。

线程池

Executors类可以创建各种线程池。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
//压力测试 线程池 
CyclicBarrier cyclicBarrier = new CyclicBarrier(1000);

ExecutorService executorService = Executors.newFixedThreadPool(1000);
for (int i = 0; i <1000 ; i++) {
  executorService.execute(new PressureThread(1,userMapper,redisTemplate,
                                             cyclicBarrier));
}
executorService.shutdown();

while(!executorService.isTerminated()){
}
System.out.println("程序结束");

//线程中使用,让线程聚集在此一起运行
cyclicBarrier.await();

常用线程池讲解

new ThreadPoolExecutor();

有五个参数:

  • corePoolSize:核心线程数量

  • maximumPoolSize:线程池最大容量

  • keepAliveTime:非核心线程存活时间

  • TimeUnit:时间单位 (second /sek(ə)nd/ 秒)

  • BlockingQueue:阻塞队列,一旦线程池用完,任务讲进入阻塞队列。

    在任意时刻,不管并发有多高,永远只有一个线程能够进行队列的入队或者出队操作! 线程安全的队列。

    当队列满了,所有入队的操作都必须等待,也就是被阻塞。

    当队列空了,所有出队的操作都必须等待,也就是被阻塞。

  • RejectedExecutionHandler 拒绝策略,可选参数,默认为AbortPolicy,队列满了之后再有任务,就会抛异常。

poo.shutdown()和shutdownNow()区别

  • shutdown()不再接受新的任务,而是把原来任务执行完.
  • shutdownNow()不再接受新的任务,队列任务也不再执行,当前执行任务执行到安全点退出。
1
2
3
4
5
6
 ThreadPoolExecutor pool=new ThreadPoolExecutor
   ( corePoolSize: 2, maximumPoolSize: 3 , keepAliveTime: 60,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>( capacity: 5));
 for (int i = 0; i < 9; i++) {
   pool.execute(new Task());//使用线程池,要传入任务接口(必须实现Runnable/Callable接口),
   }

线程池五种状态

Running 能接受新任务以及处理己添加的任务 Shutdown 不接受新任务,可以处理已经添加的任务 Stop 不接受新任务,不处理已经添加的任务,并且中断正在处理的任务 Tidying 所有的任务已经终止,ct1记录的”任务数量”为0,ctl负责记录线程池的运行状态与活动线程数量 Termi nated 线程池彻底终止,则线程池转变为terminated状态

定时任务

TimerTask

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
        // 具体任务。
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                // task to run goes here
                System.out.println("Hello !!!");
            }
        };

        // Timer类可以调度任务。 Timer实例可以调度多任务,它是线程安全的。
        Timer timer = new Timer();
        long delay = 0;
        long intevalPeriod = 1 * 1000;
        // schedules the task to be run in an interval
        timer.scheduleAtFixedRate(task,delay:0, period:1000);
 }

ScheduledExecutorService

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
    ScheduledExecutorService  pool = new ScheduledThreadPoolExecutor(4);
        pool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                // task to run goes here
                System.out.println("Hello !");
            }
        }, 2, 5, TimeUnit.SECONDS);
}

第三章-JDK8新特性

1接口默认方法

1
2
3
4
5
6
7
interface Formula {
    double calculate(int a);

    default double sqrt(int a) {
        return Math.sqrt(a);
    }
}

2Lambda

(参数) -> (lambda操作符) 一行代码可以直接写在()中 多行在()中加{}

1
2
3
4
5
//正常写法
Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});

每一个lambda表达式都对应一个类型,通常是接口类型,而“函数式接口”是指仅仅只包含一个抽象方法的接口

3::语法

类名::方法名

1
2
3
4
5
6
表达式person -> person.getAge();
使用双冒号Person::getAge
  
  ////
表达式new HashMap<>()
使用双冒号: HsahMap :: new

4Stream流

流(Stream) 到底是什么呢? 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 “集合讲的是数据,流讲的是计算!”

生成

  • stream() − 为集合创建串行流。
  • parallelStream() − 为集合创建并行流。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 User u1 = new User(11,"a",23);
   User u2 = new User(12,"b",24);
   User u3 = new User(13,"c",22);
   User u4 = new User(14,"d",28);
   User u5 = new User(16,"e",26);

   List<User> list = Arrays.asList(u1,u2,u3,u4,u5);

   list.stream().filter(p -> {
       return p.getId() % 2 == 0;
   }).filter(p -> {
       return p.getAge() > 24;
   }).map(f -> {
       return f.getUserName().toUpperCase();
   }).sorted((o1, o2) -> {
       return o2.compareTo(o1);
   }).limit(1).forEach(System.out::println);

5函数接口

image-20200716211752880

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
        //R apply(T t);函数型接口,一个参数,一个返回值
        Function<String,Integer> function = t ->{return t.length();};
        System.out.println(function.apply("abcd"));

//boolean test(T t);断定型接口,一个参数,返回boolean
        Predicate<String> predicate = t->{return t.startsWith("a");};
        System.out.println(predicate.test("a"));

// void accept(T t);消费型接口,一个参数,没有返回值
        Consumer<String> consumer = t->{ System.out.println(t);
        };
        consumer.accept("javaXXXX");

//T get(); 供给型接口,无参数,有返回值
        Supplier<String> supplier =()->{return UUID.randomUUID().toString();};
        System.out.println(supplier.get());

6日期时间类

Date/Calendar

1Date 2Calendar

一Date类(历史悠久) 月份与小时从0开始,天数从1开始,年从1900开始

Date()的构造函数,仅有两个推荐使用。

  • Date():生成一个代表当前日期时间的 Date 对象。该构造器在底层调用 System.currentTimeMillis() 获得 long 整数作为日期参数。
  • Date(long date):根据指定的 long 型整数来生成一个 Date 对象。该构造器的参数表示创建的 Date 对象和 GMT 1970 年 1 月 1 日 00:00:00 之间的时间差,以毫秒作为计时单位。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
//获取当前时间
Date d=new Date();

//获取当前时间一百秒后的时间
Date d2=new Date(System.currentTimeMillis()+100);

//比较时间d是否在d2之前  true
System.out.println(d.before(d2));

//比较时间先后顺序,若在此之前则返回-1,若相等则返回0,否则返回1
System.out.println(d.compareTo(d2));

**二.Calendar类 ** ==月最大为11==

①抽象类

②不能直接实例化

Calendar和Date都是表示日期的工具类,可以直接自由转换。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
========== Calendar-->Date =======
//创建一个默认的Calendar对象
Calendar calendar = Calendar.getInstance();
//从Calendar对象中取出Date对象
//注意毫秒会四舍五入 若想让毫秒为0 calendar.set(Calendar.MILLISECOND,0)
Date date = calendar.getTime();

=========== Date-->Calendar =========
//通过Date对象获得对应的calendar对象
//因为没有构造函数可以接收Date对象
//所以必须先获得一个calendar实例,然后调用其setTime()方法
Calendar calendar2 = Calendar.getInstance();
calendar2.setTime(date);

Calendar 类提供了大量访问、修改日期时间的方法,常用方法如下。

  • void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
  • int get(int field):返回指定日历字段的值。
  • int getActualMaximum(int field):返回指定日历字段可能拥有的最大值。例如月,最大值为11。
  • int getActualMinimum(int field):返回指定日历字段可能拥有的最小值。例如月,最小值为0。
  • void roll(int field, int amount):与 add() 方法类似,区别在于加上 amount 后超过了该字段所能表示的最大范围时,也不会向上一个字段进位。
  • void set(int field, int value):将给定的日历字段设置为给定值。
  • void set(int year, int month,int day):设置 Calendar 对象的年、月、日三个字段的值。
  • void set(int year, int month,int day, int hourOfDay, int minute, int second):设置 Calendar 对象的年、月、日、时、分、秒6个字段的值。

上面的很多方法都需要一个 int 类型的 field 参数,field 是 Calendar 类的类变量,如 Calendar.YEAR、Calendar.MONTH 等分别代表了年、月、日、小时、分钟、秒等时间字段。需要指出的是,Calendar.MONTH 字段代表月份,月份的起始值不是1,而是0,所以要设置8月时,用7而不是8。如下程序示范了Calendar 类的常规用法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 Calendar c = Calendar.getInstance();
// 取出年
System.out.println(c.get(YEAR));

// 取出月份
System.out.println(c.get(MONTH));

// 取出日
System.out.println(c.get(DATE));

//获得本月最大天
instance.getActualMaximum(Calendar.DATE)
  
// 分别设置年、月、日、小时、分钟、秒
c.set(2003, 10, 23, 12, 32, 23); // 2003-11-23 12:32:23
System.out.println(c.getTime());

// 将Calendar的年前推1年
c.add(YEAR, -1); // 2002-11-23 12:32:23
System.out.println(c.getTime());

// 将Calendar的月前推8个月
c.roll(MONTH, -8); // 2002-03-23 12:32:23
System.out.println(c.getTime());

add和roll区别


add(int field, int amount) 的功能非常强大,add 主要用于改变 Calendar 的特定字段的值。如果需要增加某字段的值,则让 amount 为正数;如果需要减少某字段的值,则让 amount 为负数即可。

当被修改的字段超出它允许的范围时,会发生进位,即上一级字段也会增大。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Calendar cal1 = Calendar.getInstance();
cal1.set(2003, 7, 23, 0, 0, 0); // 2003-8-23
cal1.add(MONTH, 6); // 2003-8-23 => 2004-2-23
System.out.println(cal1.getTime());

//若下一字段也需要改变,也会改变
Calendar cal2 = Calendar.getInstance();
cal2.set(2003, 7, 31, 0, 0, 0); // 2003-8-31
// 因为进位到后月份改为2月,2月没有31日,自动变成29日
cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
System.out.println(cal2.getTime());

==roll不会改变其它字段==

容错性:cal.setLenient(false);默认Calendar是容错的,使用这个代码可以把容错性关闭。这样设置月份为13时就会报错。

日期时间包

Java 8 开始专门新增了一个 java.time 包,该包下包含了如下常用的类。

  • Clock:该类用于获取指定时区的当前日期、时间。该类可取代 System 类的 currentTimeMillis() 方法,而且提供了更多方法来获取当前日期、时间。该类提供了大量静态方法来获取 Clock 对象。

  • Duration:该类代表持续时间。该类可以非常方便地获取一段时间。

  • Instant:代表一个具体的时刻,可以精确到纳秒。该类提供了静态的 now() 方法来获取当前时刻,也提供了静态的 now(Clock ck) 方法来获取 clock 对应的时刻。除此之外,它还提供了一系列 minusXxx() 方法在当前时刻基础上减去一段时间,也提供了 plusXxx() 方法在当前时刻基础上加上一段时间。

  • LocalDate:该类代表不带时区的日期,例如 2007-12-03。该类提供了静态的 now() 方法来获取当前日期,也提供了静态的 now(Clock clock) 方法来获取 clock 对应的日期:除此之外,它还提供了 minusXxx() 方法在当前年份基础上减去几年、几月、几周或几日等,也提供了 plusXxx() 方法在当前年份基础上加上几年、几月、几周或几日等。==年月天正常==

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
     LocalDate localDate = LocalDate.now();
    LocalTime localTime = LocalTime.now();
    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println("localDate="+localDate);         //localDate=2019-09-16
    System.out.println("localTime="+localTime);         //localTime=10:11:01.625851400
    System.out.println("localDateTime="+localDateTime); //localDateTime=2019-09-16T10:11:01.625851400
    System.out.println("localDate="+localDate.getDayOfWeek().getValue());         //获取星期几
    System.out.println("localDate="+localDate.get(ChronoField.ALIGNED_WEEK_OF_MONTH));         //获取当前月的第几周
    System.out.println(localDate.getDayOfYear());            //获取本年中截止到今天已经过去的天数
      
    System.out.println(localDate.with(TemporalAdjusters.firstDayOfMonth()));  //得到所在月的第一天
    System.out.println(localDate.withDayOfMonth(2));  //得到所在月的第二天
    System.out.println(localDate.with(TemporalAdjusters.lastDayOfMonth()));  //得到所在月的最后一天
    System.out.println(localDate.plusDays(20));  //得到20天后的日期
      
    
  • LocalTime:该类代表不带时区的时间,例如 10:15:30。该类提供了静态的 now() 方法来获取当前时间,也提供了静态的 now(Clock clock) 方法来获取 clock 对应的时间。除此之外,它还提供了 minusXxx() 方法在当前年份基础上减去几小时、几分、几秒等,也提供了 plusXxx() 方法在当前年份基础上加上几小时、几分、几秒等。

  • LocalDateTime:该类代表不带时区的日期、时间,例如2007-12-03T10:15:30。该类提供了静态的 now() 方法来获取当前日期、时间,也提供了静态的 now(Clock ck) 方法来获取 clock 对应的日期、时间。除此之外,它还提供了 minusXxx() 方法在当前年份基础上减去几年、几月、几日、几小时、几分、几秒等,也提供了 plusXxx() 方法在当前年份基础上加上几年、几月、几日、几小时、几分、几秒等。

  • MonthDay:该类仅代表月日,例如–04-12。该类提供了静态的 now() 方法来获取当前月日,也提供了静态的 now(Clock ck) 方法来获取 clock 对应的月日。

  • Year:该类仅代表年,例如2014。该类提供了静态的 now() 方法来获取当前年份,也提供了静态的 now(Clock clock) 方法来获取 clock 对应的年份。除此之外,它还提供了 minusYears() 方法在当前年份基础上减去几年,也提供了 plusYears() 方法在当前年份基础上加上几年。

  • YearMonth:该类仅代表年月,例如2014-04。该类提供了静态的 now() 方法来获取当前年月,也提供了静态的 now(Clock ck) 方法来获取 clock 对应的年月。除此之外,它还提供了 minusXxx() 方法在当前年月基础上减去几年、几月,也提供了 plusXxx() 方法在当前年月基础上加上几年、几月。

    • 1
      2
      3
      4
      5
      
      //以字符串构建YearMonth对象
      YearMonth yearMonth=YearMonth.parse("2020-12")
            
      //其月份为1-12 ,在使用其构建Canlendar和Date时
      //注意月份-1  
      
  • ZonedDateTime:该类代表一个时区化的日期、时间。

  • ZoneId:该类代表一个时区。

  • DayOfWeek:这是一个枚举类,定义了周日到周六的枚举值。

  • Month:这也是一个枚举类,定义了一月到十二月的枚举值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.time.*;


public class NewDatePackageTest {
    public static void main(String[] args) {
        // -----下面是关于Clock的用法-----
        // 获取当前Clock
        Clock clock = Clock.systemUTC();
        // 通过Clock获取当前时刻
        System.out.println("当前时刻为:" + clock.instant());
        // 获取clock对应的毫秒数,与System.currentTimeMillis()输出相同
        System.out.println(clock.millis());
        System.out.println(System.currentTimeMillis());
        // -----下面是关于Duration的用法-----
        Duration d = Duration.ofSeconds(6000);
        System.out.println("6000秒相当于" + d.toMinutes() + "分");
        System.out.println("6000秒相当于" + d.toHours() + "小时");
        System.out.println("6000秒相当于" + d.toDays() + "天");
        // 在clock基础上增加6000秒,返回新的Clock
        Clock clock2 = Clock.offset(clock, d);
        // 可看到clock2与clock1相差1小时40分
        System.out.println("当前时刻加6000秒为:" + clock2.instant());
        // -----下面是关于Instant的用法-----
        // 获取当前时间
        Instant instant = Instant.now();
        System.out.println(instant);
        // instant添加6000秒(即100分钟),返回新的Instant
        Instant instant2 = instant.plusSeconds(6000);
        System.out.println(instant2);
        // 根据字符串中解析Instant对象
        Instant instant3 = Instant.parse("2014-02-23T10:12:35.342Z");
        System.out.println(instant3);
        // 在instant3的基础上添加5小时4分钟
        Instant instant4 = instant3.plus(Duration.ofHours(5).plusMinutes(4));
        System.out.println(instant4);
        // 获取instant4的5天以前的时刻
        Instant instant5 = instant4.minus(Duration.ofDays(5));
        System.out.println(instant5);
        // -----下面是关于LocalDate的用法-----
        LocalDate localDate = LocalDate.now();
        System.out.println(localDate);
        // 获得2014年的第146天
        localDate = LocalDate.ofYearDay(2014, 146);
        System.out.println(localDate); // 2014-05-26
        // 设置为2014年5月21日
        localDate = LocalDate.of(2014, Month.MAY, 21);
        System.out.println(localDate); // 2014-05-21
        // -----下面是关于LocalTime的用法-----
        // 获取当前时间
        LocalTime localTime = LocalTime.now();
        // 设置为22点33分
        localTime = LocalTime.of(22, 33);
        System.out.println(localTime); // 22:33
        // 返回一天中的第5503秒
        localTime = LocalTime.ofSecondOfDay(5503);
        System.out.println(localTime); // 01:31:43
        // -----下面是关于localDateTime的用法-----
        // 获取当前日期、时间
        LocalDateTime localDateTime = LocalDateTime.now();
        // 当前日期、时间加上25小时3分钟
        LocalDateTime future = localDateTime.plusHours(25).plusMinutes(3);
        System.out.println("当前日期、时间的25小时3分之后:" + future);
        // 下面是关于Year、YearMonth、MonthDay的用法示例-----
        Year year = Year.now(); // 获取当前的年份
        System.out.println("当前年份:" + year); // 输出当前年份
        year = year.plusYears(5); // 当前年份再加5年
        System.out.println("当前年份再过5年:" + year);
        // 根据指定月份获取YearMonth
        YearMonth ym = year.atMonth(10);
        System.out.println("year年10月:" + ym); // 输出XXXX-10,XXXX代表当前年份
        // 当前年月再加5年,减3个月
        ym = ym.plusYears(5).minusMonths(3);
        System.out.println("year年10月再加5年、减3个月:" + ym);
        MonthDay md = MonthDay.now();
        System.out.println("当前月日:" + md); // 输出--XX-XX,代表几月几日
        // 设置为5月23日
        MonthDay md2 = md.with(Month.MAY).withDayOfMonth(23);
        System.out.println("5月23日为:" + md2); // 输出--05-23
    }
}

第四章-其它

给方法加删除线

可以在方法前加@Deprecated表示这个方法过时,即将删除。

abstract interface

如果有人问你为什么有abstract interface 修饰类,答案一定是他看到的这种方式一定是反编译出来的结果。 实际中abstract interface和interface修饰的类没有区别。 接口是特殊的抽象类。

1反射

反射获得类对象的三种方法

1
2
3
4
5
//反射获得类对象 方式1
Class classBook = Class.forName("com.lsl.entity.Books");
 //反射获得类对象 方式2、3
Class<? extends Books> aClass = books.getClass();
Class<Books> booksClass = Books.class;

利用获得的反射的对象:

1
2
3
4
5
6
7
//1可以创建对象
 Books books= (Books) classBook.newInstance();

//2获得这个类的方法,字段(私有也可以),
//方法名称,参数.class
Method setBookID = classBook.getMethod("setBookID", Integer.class);
setBookID.invoke(books,25);//要执行方法的对象,实参

还可以获得反射的字段。Constructor类

1
2
3
//构造方法、也可以传构造方法参数的class
Constructor<? extends Books> constructor = aClass.getConstructor();
//创建对象也是使用newInstance();

2泛型

https://www.cnblogs.com/coprince/p/8603492.html

泛型类,是在实例化类的时候指明泛型的具体类型;

泛型方法,是在调用方法的时候指明泛型的具体类型 。

?是一种类型实参,可以看做为Number等所有类的父类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 //在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型。可以类型与T相同,也可以不同。
//由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,编译器也能够正确识别泛型方法中识别的泛型。
public <E> void show_3(E t){
  System.out.println(t.toString());
}

//在泛型类中声明了一个泛型方法,使用泛型T,注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。
public <T> void show_2(T t){
  System.out.println(t.toString());
}

泛型中方法的返回

@param tClass 传入的泛型实参

  • @return T 返回值为T类型
  • 说明:
  • 1)public 与 返回值中间非常重要,可以理解为声明此方法为泛型方法。
  • 2)只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
  • 3)表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
  • 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
1
2
3
4
//这里虽然用到了泛型,但并不是泛型方法 
public T getKey(){
            return key;
        }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultObj<T> {
    Integer code;
    String msg;
    T data;

    public ResultObj(int code, String msg, T data) {
        this.code=code;
        this.msg=msg;
        this.data=data;
    }
  
    public static <T>ResultObj<T> getSuccess(T data){
        return new ResultObj<>(200,"成功",data);
    }

    public static <T>ResultObj<T> getUsing(T data){
        return new ResultObj<>(200,"正在使用中",data);
    }

    public static ResultObj getFail(Integer code,String message){
        return new ResultObj(code,message,null);
    }

}

3自定义注解

https://blog.csdn.net/zt15732625878/article/details/100061528

JDK中有一些元注解,主要有@Target,@Retention,@Document,@Inherited用来修饰注解。

@Target 表明该注解可以应用的java元素类型

Target类型 描述
ElementType.TYPE 应用于类、接口(包括注解类型)、枚举
ElementType.FIELD 应用于属性(包括枚举中的常量)
ElementType.METHOD 应用于方法
ElementType.PARAMETER 应用于方法的形参
ElementType.CONSTRUCTOR 应用于构造函数
ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.ANNOTATION_TYPE 应用于注解类型
ElementType.PACKAGE 应用于包
ElementType.TYPE_PARAMETER 1.8版本新增,应用于类型变量)
ElementType.TYPE_USE 1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

@Retention 表明该注解的生命周期

生命周期类型 描述
RetentionPolicy.SOURCE 编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASS JVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME 由JVM 加载,包含在类文件中,在运行时可以被获取到

@Document 表明该注解标记的元素可以被Javadoc 或类似的工具文档化

@Inherited 表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解