Java入门8---泛型、枚举、注解

java

1.为什么要有泛型?

  1. 解决元素存储的安全性问题
  2. 解决获取数据元素时,需要类型强转的问题。

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)泛型的声明

  1. interface List<T> 和class GenTest<K,V> 其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。 常用T表示,是Type的缩写。
  2. 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如: <E1,E2,E3> 

(2)泛型的实例化

  1. 泛型类的构造器如下:public GenericClass(){}。 而下面是错误的:public GenericClass<E>(){}
  2. 一定要在类名后面指定类型参数的值(类型)。如: List<String> strList = new ArrayList<String>(); Iterator<Customer> iterator = customers.iterator();
  3. T只能是类,不能用基本数据类型填充。但可以使用包装类填充
  4. 把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
  5. 泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价 于Object。经验:泛型要使用一路都用。要不用,一路都不要用。 
  6. 如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。 
  7. jdk1.7,泛型的简化操作:ArrayList<Fruit> flist = new ArrayList<>(); 

在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态 属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。 

异常类不能是泛型的

父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:

  1. 子类不保留父类的泛型:按需实现

    1. 没有类型 擦除
    2. 具体类型

  2. 子类保留父类的泛型:泛型子类

    1. 全部保留
    2. 部分保留

结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自 己的泛型

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 有限制的通配符

  1.  <?> 允许所有泛型的引用调用
  2. 通配符指定上限:不能往里存,只能往外取

    1. 上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=

  3. 通配符指定下限:不影响往里存,但往外取只能放在Object对象里

    1. 下限super:使用时指定的类型不能小于操作的类,即>= 

举例:

<? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用
<? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用

PESC(Producer Extends Consumer Super)原则:

  1. Producer Extends 生产者使用Extends来确定上界,往里面放东西来生产
  2. Consumer Super 消费者使用Super来确定下界,往外取东西来消费

频繁往外读取内容的,适合用上界Extends,即extends 可用于的返回类型限定,不能用于参数类型限定。

经常往里插入的,适合用下界Super,super 可用于参数类型限定,不能用于返回类型限定。

带有 super 超类型限定的通配符可以向泛型对象用写入,带有 extends 子类型限定的通配符可以向泛型对象读取

2.6 对于泛型类的注意事项

  1. 静态方法中不能使用类的泛型;
  2. 如果泛型类是一个接口或抽象类,则不可创建泛型类的对象;
  3. 不能在catch中使用泛型;
  4. 从泛型类派生子类,泛型类型需具体化;

二、枚举

  1. JDK1.5之前需要自定义枚举类
  2. JDK1.5新增的enum关键字用于定义枚举类
  3. 若枚举只有一个成员,则可以作为一种单例模式的实现方式。

1.如何自定义枚举类

枚举类:类的对象是有限个的,确定的。

  1. 私有化类的构造器,保证不能在类的外部创建其对象。
  2. 在类的内部创建枚举类的实例,声明为:public static final
  3. 若类有属性,那么属性声明为:private final,此属性在构造器中赋值。

2.使用enum定义枚举类

2.1 常用的方法

  1. values():以数组的形式,返回枚举类的所有对象
  2. valueOf(String name):要求传入的形参name是枚举类对象的名称,否则会报IllegalArgumentExecption异常。

2.2 如何让枚举类实现接口

  1. 让类实现此接口,类的对象共享同一套接口的抽象方法的实现。
  2. 让类的每一个对象都去实现接口的抽象方法,进而通过类的对象调用被重写的抽象方法时,执行的效果不同。

三、注解

1.JDK内置的基本注解类型(3个)

  1. @Override:限定重写父类方法,该注解只能用于方法
  2. @Deprecated:用于表示某个程序元素(类,方法等)已过时
  3. @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

回到顶部