Java入门8---泛型、枚举、注解
1.为什么要有泛型?
- 解决元素存储的安全性问题
- 解决获取数据元素时,需要类型强转的问题。
Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生 ClassCastException异常。同时,代码更加简洁、健壮。
2.怎么使用泛型?
2.1 集合中使用泛型
集合接口或集合类在jdk5.0时都修改为带泛型的结构。
在实例化集合类时,可以指明具体的泛型类型;
泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,拿包装类替换;
如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。
Map<String,Integer> map = new HashMap<>();//Map<String,Integer> map = new HashMap<String,Integer>();与上式等价
Set<Map.Entry<String,Integer>> set = map.entrySet();
for (Map.Entry<String,Integer> o:set){
}
List<Integer> list = new ArrayList<Integer>();
2.2 自定义泛型类、泛型接口、泛型方法
(1)泛型的声明
- interface List<T> 和class GenTest<K,V> 其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。 常用T表示,是Type的缩写。
- 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如: <E1,E2,E3>
(2)泛型的实例化
- 泛型类的构造器如下:public GenericClass(){}。 而下面是错误的:public GenericClass<E>(){}
- 一定要在类名后面指定类型参数的值(类型)。如: List<String> strList = new ArrayList<String>(); Iterator<Customer> iterator = customers.iterator();
- T只能是类,不能用基本数据类型填充。但可以使用包装类填充
- 把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
- 泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价 于Object。经验:泛型要使用一路都用。要不用,一路都不要用。
- 如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。
- jdk1.7,泛型的简化操作:ArrayList<Fruit> flist = new ArrayList<>();
在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态 属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。
异常类不能是泛型的
父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
子类不保留父类的泛型:按需实现
- 没有类型 擦除
- 具体类型
子类保留父类的泛型:泛型子类
- 全部保留
- 部分保留
结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自 己的泛型
2.3 泛型与继承的关系
类A是类B的父类===》但G<A>和G<B>二者不具备子父类关系,二者是并列关系,二者共同的父类是:G<?>
类A是类B的父类===》B<G>是A<G>的子类
2.4 通配符
List<?>是List<String>、List<Object>等各种泛型List的父类。
以List<?>为例,能读取其中的数据,因为不管存储的是什么类型的元素,其一定是Object类的或其子类的。
以List<?>为例,不可以向其中写入数据,因为没有指明可以存放到其中的元素的类型,唯一例外的是:null
2.5 有限制的通配符
- <?> 允许所有泛型的引用调用
通配符指定上限:不能往里存,只能往外取
- 上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
通配符指定下限:不影响往里存,但往外取只能放在Object对象里
- 下限super:使用时指定的类型不能小于操作的类,即>=
举例:
<? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用
<? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用
PESC(Producer Extends Consumer Super)原则:
- Producer Extends 生产者使用Extends来确定上界,往里面放东西来生产
- Consumer Super 消费者使用Super来确定下界,往外取东西来消费
频繁往外读取内容的,适合用上界Extends,即extends 可用于的返回类型限定,不能用于参数类型限定。
经常往里插入的,适合用下界Super,super 可用于参数类型限定,不能用于返回类型限定。
带有 super 超类型限定的通配符可以向泛型对象用写入,带有 extends 子类型限定的通配符可以向泛型对象读取
2.6 对于泛型类的注意事项
- 静态方法中不能使用类的泛型;
- 如果泛型类是一个接口或抽象类,则不可创建泛型类的对象;
- 不能在catch中使用泛型;
- 从泛型类派生子类,泛型类型需具体化;
二、枚举
- JDK1.5之前需要自定义枚举类
- JDK1.5新增的enum关键字用于定义枚举类
- 若枚举只有一个成员,则可以作为一种单例模式的实现方式。
1.如何自定义枚举类
枚举类:类的对象是有限个的,确定的。
- 私有化类的构造器,保证不能在类的外部创建其对象。
- 在类的内部创建枚举类的实例,声明为:public static final
- 若类有属性,那么属性声明为:private final,此属性在构造器中赋值。
2.使用enum定义枚举类
2.1 常用的方法
- values():以数组的形式,返回枚举类的所有对象
- valueOf(String name):要求传入的形参name是枚举类对象的名称,否则会报IllegalArgumentExecption异常。
2.2 如何让枚举类实现接口
- 让类实现此接口,类的对象共享同一套接口的抽象方法的实现。
- 让类的每一个对象都去实现接口的抽象方法,进而通过类的对象调用被重写的抽象方法时,执行的效果不同。
三、注解
1.JDK内置的基本注解类型(3个)
- @Override:限定重写父类方法,该注解只能用于方法
- @Deprecated:用于表示某个程序元素(类,方法等)已过时
- @SuppressWarnings:抑制编译器警告
2.自定义注解类型
以SuppressWarnings为例进行创建即可。
3.元注解(4个)
JDK的元注解用于修饰其他Annotation。JDK5.0提供了专门在注解上的注解类型,分别是:
@Retention | ||
@Target | ||
@Documented | ||
@Inherited |
参考链接:
【1】Java泛型解惑之 extends T>和 super T>上下界限_ystyaoshengting的专栏-CSDN博客
以上是 Java入门8---泛型、枚举、注解 的全部内容, 来源链接: utcz.com/z/392568.html