一、泛型
泛型的参数类型可以用在类,接口和方法创建中分别称为:泛型类,泛型接口和泛型方法。
ArrayList<E>:整个称为泛型类型,E表示泛型变量或泛型参数
ArralyList<Integer>:整个称为参数化类型,Integer称为类型参数的实例或者实际类型参数
1.泛型类的定义和使用
class Par<T> {
private T value;
public Pair(T value){
this.value=value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value=value
}
}
======================================
2.泛型接口跟泛型类一样
3泛型方法
public static<T> T get(T t1,T t2){
//此时会编译失败,需要对类型变量T限定类型,不然下面的compareTo会报错
if(t1.compareTo(t2)>=0) {
retrun t1;
}
}
------------------------------------------------------
public static<T extends Comparable> T get(T t1,T t2){
//类型限定在泛型类,泛型接口和泛型方法都可以使用,都用关键字extends,可以&加多个限定
if(t1.compareT(t2)>=0) {
retrun t1;
}
}
1自定义泛型:自定义泛型就是一个数据类型的占位符或者一个数据类型的变量
方法中的泛型类型参数声明非常重要:
2方法上自定义泛型:
修饰<声明自定义泛型>返回值类型 函数名(使用自定义泛型){}
public static <T>T getDate(T t){return t}
与普通方法不一样的得地方是修饰符和返回类型之间需要添加一个泛型类型参数的声明,表明方法作用域中
谁才是泛型类型参数
------------------------------------------------------------
类型参数作用域:
class A<T>{}中T的作用于就是整个A
public<T> func(){}中T的作用域就是方法func,
会有作用域覆盖问题
泛型方法类型参数可以指定上限,必须在类型参数声明的地方定义上限,不能再方法参数中定义上限。
<T extends X>void func(List<T>list){}//正确
<T extends X> void fun(T t){}//正确
<T> void func (List<T extends S>){}//编译错误
所有能用类型通配符的地方都可用泛型方法解决问题,并且泛型方法可更好的解决
类型通配符: void func(List<? extends A> list)
完全可以用泛型方法替换:<T extends A> void func(List<T> list
---------------------------------------------------------------------------------
数组类型参数不能是类型变量,除非采用通配符方式
List<?>[] lsa = new List<?>[10];
二、枚举
=============枚举类
public enum CacheNames {
DICTIONARY_CACHE_NAME("credit:dict"), //字典缓存
ENTITY_CACHE_NAME("credit:entity"),
ORGAN_CACHE_NAME("credit:organ"),
定义一个参数,并且设置get和set方法,有几个参数就设置几个变量
private String value;
private CacheNames(String value){
this.value = value;
}
public String value(){
return value;
}
}
================枚举常量
public enum TypeValue {
ROLE_AUTHORIZE_CHANGE(1), //角色权限修改
SCHEDULED_TASK_DEF_CHANGE(3), // 定时任务定义修改
FUNCTION_MENU_CHANGE(2); //功能菜单修改
private Integer value;
private TypeValue(Integer value){
this.value = value;
}
public Integer value(){
return this.value;
}
}
---------------可放在枚举类中,也可以单独放在其他类中,用法就是定义的TypeValue.ROLE_AUTHORIZE_CHANGE.value()
使用enum关键字定义枚举类
>2.1其中常用的方法:values() valueOf(String name);
>2.2枚举类如何实现接口 :①让类实现此接口,类的对象共享同一套接口的抽象方法的实现。
①让类的每一个对象都去实现接口的抽象方法,进而通过类的对象调用被重写的抽象方法时,执行的效果不同
public class TestSeason1 {
public static void main(String[] args) {
Season1 spring = Season1.SPRING;
System.out.println(spring);
spring.show();
System.out.println(spring.getSeasonName());
System.out.println();
//1.values()
Season1[] seasons = Season1.values();
for(int i = 0;i < seasons.length;i++){
System.out.println(seasons[i]);
}
//2.valueOf(String name):要求传入的形参name是枚举类对象的名字。
//否则,报java.lang.IllegalArgumentException异常
String str = "WINTER";
Season1 sea = Season1.valueOf(str);
System.out.println(sea);
System.out.println();
Thread.State[] states = Thread.State.values();
for(int i = 0;i < states.length;i++){
System.out.println(states[i]);
}
sea.show();
}
}
interface Info{
void show();
}
//枚举类
enum Season1 implements Info{
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 Season1(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 + "]";
}
// public void show(){
// System.out.println("这是一个季节");
// }
}
三、注解
注解Annotation
1.JDK提供的常用的三个注解
@Override: 限定重写父类方法, 该注释只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告
2.如何自定义注解
以SuppressWarnings为例进行创建即可
3.元注解:可以对已有的注解进行解释说明。
Retention: SOURCE CLASS RUNTIME
Target::
Documented:javadoc
Inherited
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value ();
}
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
TYPE_PARAMETER 类型注解
@Retention
表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
RetentionPolicy的取值包含以下三种:
SOURCE:源码级别保留,编译后即丢弃。
CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
@Documented
表明这个注解应该被 javadoc工具记录.,默认情况下javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所有注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。
@Inherited
@Inherited是一个标记注解,阐述了某个被标注的类型是被继承的。 如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
三、重复注解
使用 @Repeatable
1、在 @Value
注解上添加 @Repeatable
元注解,@Repeatable
里面的的值是 @Value
的集合注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Values.class)
public @interface Value {
String value();
}
2、Values
注解,value
方法的返回值为 @Value
数组
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Values {
Value[] value();
}
约束
- @Target 范围,单个注解范围必须大于等于集合注解。
报错:// Target of container annotation 'Values' is not a subset of target of this annotation
- @Retention 范围,单个注解范围必须小于等于集合注解:SOURCE(源码) < CLASS (字节码) < RUNTIME(运行)
报错:// Container annotation 'Values' has shorter retention ('CLASS') than the contained annotation
事例:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Values.class)
public @interface Value {
String value();
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Values {
Value[] value();
}