笔记
序列号与反序列号
泛型
JDK5提出了泛型这个概念,但是JDK5以前是没有泛型的
解决问题:对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患
优点
- (1)类型安全
- (2)消除强制类型转换
- (3)更高的效率
- (4)潜在的性能收益
泛型类型必须为引用数据类型,不能为基本数据类型
泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法
七、泛型擦除
泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。
枚举类
枚举是Java1.5引入的新特性,通过关键字enum来定义枚举类。枚举类是一种特殊类,它和普通类一样可以使用构造器、定义成员变量和方法,也能实现一个或多个接口,但枚举类不能继承其他类。
概念
-
定义
- 被enum关键字修饰的类型就是枚举类型
- 如果枚举不添加任何方法,枚举值默认为从0开始的有序数值
-
示例
- enum Color{RED,GREEN,BLUE}
-
优点
- 讲常量组织起来,统一进行管理
-
场景
- 错误码,状态机等
-
本质
- 枚举的本质是Enum的自雷
方法
-
values()
- 有序的枚举数组
-
name()
- 返回实例名称
-
ordinal()
- 返回实例声明时的次序,从0开始
-
getDeclaringClass()
- 返回实例所属的enum类型
-
equals()
- 判断是否为同个枚举
- 也可用 == 比较枚举实例
工具类
-
EnumSet
- 是枚举类型的高性能set实现,他要求放入他的枚举常量必须属于同一枚举类型
-
EnumMap
- 是专门为枚举类型定制的MAP实现
缓存
问题
-
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
设置热点数据永远不过期- 大量同时过期
-
缓存穿透
描述:
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻- 数据库不存在的数据
-
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案:
设置热点数据永远不过期。- 数据库存在的数据
预读取
预读取就是预先读取将要载入的数据,也可以称作“预存预热”,它是在系统中先将硬盘中的一部分加载到内存中,然后再对外提供服务
延迟写
它是预先将需要写入磁盘或数据库的数据,暂时写入到内存,然后返回成功,再定时将内存中的数据批量写入到磁盘
缓存之所以快是因为缓存是基于内存去建立的,而内存的读写速度比硬盘快很多倍
缓存类别
- 1、浏览器缓存
- 2、CDN缓存
- 3、网关(代理)缓存
- 4、进程内缓存
- 5、进程外缓存
- 6、数据库缓存
注解
注解用于为Java代码提供元数据
注解本质上就是接口,是继承了Annotation接口的接口
元注解
-
元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,它能够应用到其它的注解上面
-
@Retention
- Retention,中文释义保留期的意思
当@Retention应用到注解上的时候,它解释说明了这个注解的生命周期 - RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到JVM中。
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载到JVM中。
- Retention,中文释义保留期的意思
-
@Documented
- 顾名思义,这个元注解肯定和文档有关。它的作用是能够将注解中的元素包含到Javadoc中去。
-
@Target
- ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
- ElementType.CONSTRUCTOR 可以给构造方法进行注解
- ElementType.FIELD 可以给属性进行注解
- ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
- ElementType.METHOD 可以给方法进行注解
- ElementType.PACKAGE 可以给一个包进行注解
- ElementType.PARAMETER 可以给一个方法内的参数进行注解
- ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
-
@Inherited
- 如果一个超类被@Inherited注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
-
@Repeatable
-
Repeatable 自然是可重复的意思。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。
-
使用实例
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Persons {
Person[] value();
}@Repeatable(Persons.class)
public @interface Person{
String role() default “”;
}@Person(role=“CEO”)
@Person(role=“husband”)
@Person(role=“father”)
@Person(role=“son”)
public class Man {
String name="";
}
-
注解的属性
- 注解的属性也叫做成员变量,注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型
- 如果一个注解内仅仅只有一个名字为 value 的属性时,应用这个注解时可以直接接属性值填写到括号内。
Java预置的注解
-
@Override
- 这个大家应该很熟悉了,提示子类要复写父类中被 @Override 修饰的方法
-
@Deprecated
- 加上这个注解之后,表示此方法或类不再建议使用,调用时会出现删除线,但不代表不能用,只是说,不推荐使用,因为有更好的方法可以调用。
-
@SuppressWarnings
- 该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。
-
@FunctionalInterface
- ava 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。它们主要用在Lambda表达式和方法引用(实际上也可认为是Lambda表达式)上。
注解与反射
-
需要注意的是,如果一个注解要在运行时被成功提取,那么 @Retention(RetentionPolicy.RUNTIME) 是必须的。
-
isAnnotationPresent()
- 判断是否应用了某个注解。
-
getAnnotation()
-
方法返回指定类型的注解
-
Test.class.getAnnotation(TestAnnotation.class)
- 获取类上的注解
-
Field a = Test.class.getDeclaredField(“a”);
a.setAccessible(true);
//获取一个成员变量上的注解
Check check = a.getAnnotation(Check.class);- 获取字段上的注解
-
Method testMethod = Test.class.getDeclaredMethod(“testMethod”);
-
Annotation[] ans = testMethod.getAnnotations();
- 获取方法上的注解
-
getAnnotations()
- 返回注解到这个元素上的所有注解
注解的使用场景
- ① 提供信息给编译器:编译器可以利用注解来探测错误或警告信息
- ② 编译阶段时的处理:软件工具可以利用注解信息来生成代码、HTML文档或其它响应处理。
- ③ 运行时的处理:某些注解可以在程序运行时接受代码的提取。