博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
15、泛型、注解
阅读量:5797 次
发布时间:2019-06-18

本文共 5466 字,大约阅读时间需要 18 分钟。

一、泛型

JDK1.5出现的新特性。用于解决安全问题,是一个安全机制。它存在于编译器,运行期会擦除,避免强制类型转换的风险。

ArrayList
al = new ArrayList
();
  • 因为集合在初始化定义时没有指定类型,会导致安全隐患。
  • 所以泛型的出现解决了这个安全隐患。
  • 上面的意思就是只能往集合里添加String类型的元素。
  • 数组初始化定义会指定类型,而集合却没有。
ArrayList
中的E称为 类型参数变量ArrayList
中的Integer称为 实际类型参数整个称为ArrayList
泛型类型整个ArrayList
称为参数化的类型ParameterizedType

1.1、泛型类使用:

  • 当类中要操作的引用数据类型不确定的时候。
  • 早期定义Object来完成拓展,现在定义泛型来完成拓展。
public class Demo
{ public static void main(String[] args){ Demo
person = new Demo
(); person.show("哈哈"); } public void show(T t){ System.out.println(t); }}

1.2、自定义泛型:

(1)泛型类定义的泛型,在整个类中有效,同时它整个类的类型就已经固定了

(2)泛型被定义在方法上后,那么就 可以操作任意引用类型的数据。
(3)也可以在类和方法上同时定义泛型。(不重复)但是要注意方法和类的泛型是否一样。
(4)静态方法不可以访问类上定义的泛型。如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。

public static 
void method(W t):泛型放在修饰符后面,返回值前面。

1、方法泛型

定义在方法上的泛型就叫做方法泛型,作用的范围的当前方法内部

泛型在使用之前必须先定义<T>,其中的字母可以是任意字母,但是通常使用大写字母

可以认为,当方法在被调用到时,虚拟机自动判断出泛型的具体类型.

public static 
void method(T t);

比如我们定义一个方法可以交换数组的位置,方法不但要支持String类型的数组,还要支持Integer类型的数组,则可以使用泛型方法来实现:

/** * 交换任意类型数组的位置 * */public class Demo {        public static void main(String[] args) {        // String类型数组        String[] strs = {"a", "b", "c", "d"};        change(strs, 0, 2);        for (int i = 0; i < strs.length; i++) {            System.out.println(strs[i]);        }                // Integer类型数组        Integer[] ints = {1, 2, 3, 4};        change(ints, 0, 2);        for (int i = 0; i < ints.length; i++) {            System.out.println(ints[i]);        }    }        public static 
void change(T[] arrs, int i, int j){ T t = arrs[i]; arrs[i] = arrs[j]; arrs[j] = t; }}

2、 类上泛型

类上的泛型:定义在类上的放行叫做类泛型,作用范围是整个类中都可以使用

public class GenericDao
{}

可以认为,在使用这个类时,就需要指定出泛型的具体类型.如果不明确指定,则泛型是它的上边界类型的.

静态方法不能使用类上定义的泛型,如果想使用泛型静态方法必须自己定义泛型(因为静态方法不属于该类,而泛型存在运行期的)

3、泛型通配符

(1)? :通配符。也可以理解为占位符。可以接收任意类型。

因为泛型没有继承关系,所有当需要用一个泛型引用引用不同的泛型实现时,泛型中写他们共同的父类是不行的,这时该怎么做呢?引入一个新的概念,叫做泛型通配符?

注意泛型通配符只能用在泛型引用中,用来引用不同的泛型实现,不能出现在实现中.

List
list = null;list = new ArrayList
(); list = new ArrayList
();

4、 泛型的边界

(2)? extends E:可以接收E类型和E的子类型。上限限定不变。(父类已经固定,子类可以接收)。(这里的E为父类)

(3)? super E:可以接收E类型和E的父类型。 下限限定不变。(子类已经固定,父类都可以接收)。(这里的E为子类)(访问不到父类的方法。)

? extends E - 用来指定泛型的上边界,使用在泛型的通配符中和泛型定义中,指定具体的泛型实现必须是指定的类或其子类.

  • 利:在传入对象时,只能传入null
  • 弊:获取到泛型的对象时,可以调用上边界的方法.

? super E - 用来指定泛型的下边界,使用在泛型的通配符中,指定具体的泛型实现必须是指定类或其父类.

  • 利:可以传入对象时,可以传入下边界的子孙类对象
  • 弊:获取到泛型对象时,只能调用Object身上的方法
public class Demo1 {    public static void main(String[] args) {        // 上限限定        List
list = null;// 必须是Person和Person的子类 list = new ArrayList
();// Person or teacher // 下限限定 List
list1 = null; // 必须是Person和Person的父类 list1 = new ArrayList
();// Person or Animal } class Animal{ } class Person extends Animal { } class Teacher extends Person { }}

二、注解

Annotation 注解:程序中给人看到提示信息叫注释,给程序看的提示信息叫做注解

注解:可以作为配置信息控制程序的运行,注解可以在一些场合用来替代配置文件

@xxxx(....

1.1、jdk1.5内置的注解:

  • @Override: 限定重写父类方法, 该注解只能用于方法
  • @Deprecated: 用于表示某个程序元素(类, 方法等)已过时
  • @SuppressWarnings: 抑制编译器警告.

1.2、自定义注解

1、声明注解

(1)使用 @interface关键字来定义注解,在这个类中可以声明注解的属性

  • 注解属性的声明类似于在为接口声明一个方法,同时可以为属性设定默认值
  • 注解属性支持如下类型:String、基本数据类型、枚举、Class 、其它注解类型、以上数据类型相应一维数组
  • 如果注解中只包含一个名为value的属性,则这个属性在使用时可以省略注解的名字直接写值
public @interface tran{    //String name();      //String name2() default "xxx";    String value();}

(2)使用元注解对注解进行描述

@Retention:用来指定注解的保留范围

  • RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注解
  • RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值
  • !!RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释

@Target:指定被修饰的注解可以使用在什么位置

  • ElementType的成员变量。可以是类/方法/字段/构造方法/包声明.....

@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档。

@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation,则其子类将自动具有该注解

2、 使用注解

   在 @Target声明的位置上使用 @Tran(属性名 = 属性值,.....)

3、反射注解

   JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 该接口代表程序中可以接受注释的程序元素,

包括Class Field Method Constructor Package都是这个接口的实现,所以这个接口中定义的反射注解的方法,他们都具有

 

T getAnnotation(Class
annotationClass) // 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 Annotation[] getAnnotations() // 返回此元素上存在的所有注释。 Annotation[] getDeclaredAnnotations() // 返回直接存在于此元素上的所有注释。 boolean isAnnotationPresent(Class
annotationClass) // 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。

a) 首先我们自定义一个注解,并设定在运行期

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface DemoAnno {    public String name();    public int age() default 100;}

b) 定义一个Student类,对其使用自定义的注解,如果自定义的注解没有设置默认值时,@DemoAnno(name="zhangsan", age = 20)

@DemoAnno(name="zhangsan")public class Student {}

c) 在Main方法中通过反射去确定是否有注解和拿到Student的名字和年龄

public class Demo {    public static void main(String[] args) {        Class sc = Student.class;        if(sc.isAnnotationPresent(DemoAnno.class)){            DemoAnno da = (DemoAnno) sc.getAnnotation(DemoAnno.class);            String name = da.name();            int age = da.age();            System.out.println(name+":"+age);        }else{            System.out.println("没有注解");        }    }}

################################################################

转载于:https://www.cnblogs.com/pengjingya/p/5529384.html

你可能感兴趣的文章
DICOM简介
查看>>
Scrum之 Sprint计划会议
查看>>
List<T> to DataTable
查看>>
[Java]Socket和ServerSocket学习笔记
查看>>
stupid soso spider
查看>>
svn命令在linux下的使用
查看>>
Gradle之module间依赖版本同步
查看>>
java springcloud版b2b2c社交电商spring cloud分布式微服务(十五)Springboot整合RabbitMQ...
查看>>
SpringCloud使用Prometheus监控(基于Eureka)
查看>>
10g手动创建数据库
查看>>
Spring MVC EL表达式不能显示
查看>>
【致青春】我们挥霍时间的年代
查看>>
Windwos Server 2008 R2 DHCP服务
查看>>
SAS和SATA硬盘的区别
查看>>
现代程序设计 学生情况调查
查看>>
U盘安装linux后无法引导
查看>>
C# 矩阵作业
查看>>
俺的新书《Sencha Touch实战》终于出版了
查看>>
关于数据库查询时报“query block has incorrect number of result columns”
查看>>
li下的ul----多级列表
查看>>