JDK1.5新特性之注解

时间:2017-1-2 20:14

——注解的概述

注释是给人看的,而注解是给程序(框架)看的。
    在Servlet3.0中可以使用注解来替代配置文件,开发者就不用再写配置文件了,而是写注解,然后Tomcat来读取注解。

注解也是类,需要定义了才能使用。
    在Servlet3.0中又一个注解类是@WebServlet,然后我们就可以在Servlet中使用@WebServlet这个注解了,这个朱姐就是用来替代<servlet>,然后Tomcat会通过反射来读取注解中的信息。

——Java中的注解

*   @Overrid:作用在方法上的注解,当方法不是重写父类的方法时会报错。
    *   @Deprecated:作用在方法上,标记该方法为作废方法(已过时)。
    *   @SuppressWarnings:作用在方法上,压制警告。

——定义注解类

定义注解类不能使用class、enum和interface,而是使用@interface

>   public @interface MyAnn{ }

——使用注解目标

所有注解都是Annotation的子类。

注解可以作用在:类(接口或枚举)、属性、方法、构造器、包、参数、局部变量

*   定义注解类:框架的工作
    *   使用注解:我们的工作
    *   读取注解(反射):框架的工作

——注解的定义

*   定义属性
        >   格式:类型 属性名()

@interface MyAnno1{

String name();

int age();

}

*   使用注解时给属性赋值
        >   @MyAnno(name="zhangsan", age=20)

*   注解属性的默认值
        >   int age() default 100;
        >   在使用注解时,可以不给带有默认值的属性赋值。

*   名为value的属性的特权
        >   在使用注解时,如果只给名为value的属性赋值,那么可以不给出属性的名称而直接赋值,当存在其他属性时,必须加上“value=”。
        >   @MyAnno("zhangsan"):表示给value="zhangsan"赋值。

*   注解属性的类型
        >   8种基本类型
        >   String类型
        >   枚举类型
        >   Class类型
        >   注解类型
        >   以上类型的一维数组类型

>   定义:
            @MyAnno1{
                int a();
                String b();
                MyEnum c();
                Class d();
                MyAnno2 e();
                String f();
            }

>   使用:
            @MyAnno1(
                a=100,
                b="zhangsan",
                c=MyEnum.option,
                d=String.class,
                [email protected](age=20,name="zhangsan"),
                f={"123", "456"}
            )

——注解的作用目标限定以及保存策略限定

1、目标限定
    让一个注解的作用目标只能在类上,而不能在方法上,这就叫作用目标的限定。

在定义注解时,给注解添加注解,这个注解时@Target
    Target注解有一个属性:ElementType[] value(),这个属性是一个枚举类型。

使用方法:
        @Target(value={ElementType.TYPE, ElementType.METHOD, ElementType/FIELD})
        @interface MyAnno{ }

2、保留策略
    *   源代码文件(SOURCE)
        >   注解只在源代码中存在,当编译时就被忽略了(不能被反射)

*   字节码文件(CLASS)
        >   注解在源代码中存在,编译时会把注解信息放到class文件中,但JVM在加载类时,会忽略注解。

*   JVM中(RUNTIME)
        >   注解在源代码、字节码文件中存在,并且在JVM加载类时,会把注解加载到JVM内存中(它是唯一可以反射的注解)

限定注解的保留策略:
        使用RetentionPolicy注解:
            @Retention(RetentionPolicy.RUNTIME)

——读取注解(反射)

1、要求:
    注解的保留策略必须是RUNTIME

2、反射注解需要从作用目标上反射
    *   类上的注解,需要使用Class来获取
    *   方法上的注解,需要用Method来返回
    *   构造器上的注解,需要用Constructor来获取

*   成员上的注解,需要用Field来获取

Class类方法概要:
    <T extends Annotation>  getAnnotation(Class<A> annotationClass)
        如果存在该元素的指定类型的注解,则返回这些注解,否则返回null。

Annotation[]  getAnnotations()
        返回此元素上存在的所有注解。

Method、Field、Constructor:
    这三个类都是AccessibleObject的子类。

AccessibleObject类方法概要:
    <T extends Annotation>  getAnnotation(Class<T> annotationClass)
        如果存在该元素的指定类型的注解,则返回这些注解,否则返回null。

Annotation[]  getAnnotations()
        返回此元素上存在的所有注解。

Annotation[]  getDeclaredAnnotations()
        返回直接存在于此元素上的所有注解。

示例代码:

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.reflect.Field;

import org.junit.Test;

public class Demo {

@Test

public void fun1() {

/*

* 1、得到作用目标

*/

Class<A> c = A.class;

/*

* 2、获取指定类型的注解

*/

MyAnno1 myAnno1 = c.getAnnotation(MyAnno1.class);

System.out.println(myAnno1.name() + ", " + myAnno1.age());

}

@Test

public void fun2() throws Exception {

/*

* 1、得到作用目标

*/

Class<A> c = A.class;

// Field权限必须为public

Field field = c.getField("name");

/*

* 2、获取指定类型的注解

*/

MyAnno1 myAnno1 = field.getAnnotation(MyAnno1.class);

System.out.println(myAnno1.name() + ", " + myAnno1.age());

}

}

@MyAnno1(name = "zhangsan", age = 20)

class A {

@MyAnno1(name = "lisi", age = 21)

public String name;

}

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnno1 {

String name();

int age();

}

——反射泛型信息

public Type getGenericSuperclass()
        返回表示此Class所表示的实体(类、接口、基本类型或void)的直接父类的Type。
        获取传递给父类的泛型信息。
        返回的类型是Type接口的子接口:ParameterizedType(参数化类型) == A<String>

1、子类:得到当前类的Class对象:this.getClass()
    2、Class:得到当前类父类的参数化类型(A<String, Integer...>):Type  getGenericSuperclass(),因为返回值是ParameterizedType,所以需要强制类型转换。
    3、ParameterizedType:得到所有的类型参数<String, Integer...>:Type[]  getActualTypeArguments()

示例代码:

package demo2;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import org.junit.Test;

public class Demo1 {

@Test

public void fun() {

new B();

new C();

}

}

abstract class A<T> {

public A() {

/*

* 在这里获取子类传递的泛型信息,得到一个Class对象

*/

Class c = this.getClass(); // 得到子类的类型

// 得到的type就是A<String>

Type type = c.getGenericSuperclass();

// 因为type的类型是ParameterizedType,所以需要强转

ParameterizedType pType = (ParameterizedType) type;

// 获取类参数,得到的是一个数组<String, Integer...>

Type[] types = pType.getActualTypeArguments();

// 得到String

Class c2 = (Class) types[0];

System.out.println(c2); // String或者Integer

// 简写

Class c3 = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

System.out.println(c3);

}

}

class B extends A<String> {

}

class C extends A<Integer> {

}

——反射泛型和反射注解的应用案例

User类:

package demo2;

@Table("tb_user") // 它的值表示当前类所对应的表

public class User {

@ID("u_id") // 表示当前属性对应的列名,而且说明这个字段是主键字段

private String uid;

@Column("username")

private String username;

@Column("password")

private String password;

@Test

public void fun(){

Class<User> c = User.class;

Table a = c.getAnnotation(Table.class);

System.out.println(a.value());

Field f = c.getDeclaredField("uid");

f.setAccessible(true);

ID id = f.getAnnotation(ID.class);

System.out.println(id.value());

}

}

----------------------------------------------------------------------------------------------------------------------------

Table注解:

package demo2;

@Retention(RetentionPolicy.RUNTIME)

public @interface Table {

String value();

}

----------------------------------------------------------------------------------------------------------------------------

ID注解:

package demo2;

@Retention(RetentionPolicy.RUNTIME)

public @interface ID {

String value();

}

----------------------------------------------------------------------------------------------------------------------------

Column注解:

package demo2;

@Retention(RetentionPolicy.RUNTIME)

public @interface Column {

String value();

}

----------------------------------------------------------------------------------------------------------------------------

BaseDAO:

package demo2;

import java.lang.reflect.Field;

import java.lang.reflect.ParameterizedType;

import java.util.List;

-------------------------

public class Demo2 {

private QueryRunner qr = new TxQueryRunner();

/*

* 使用dbutils

*/

public void addUser(User user) {

String sql = "";

Object[] params = {};

qr.update(sql, params);

}

public void addCustomer(Customer customer) {

String sql = "";

Object[] params;

qr.update(sql, params);

}

}

-------------------------

/**

* 因为普通DAO有许多重复的工作

* 所以可以考虑编写一个BaseDAO来完成重复操作

* 功能与BaseServlet相似。

* @author WYC

*

* @param <T>

*/

class BaseDAO<T> {

private QueryRunner qr = new TxQueryRunner();

private Class<T> beanClass;

private int length;

public BaseDAO() {

// 获取泛型参数,用于获得表名

this.beanClass = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

// 获取属性个数,用于获得参数个数、参数值、参数列名

Field[] fields = beanClass.getDeclaredFields();

this.length = fields.length;

}

public void add(T bean) {
        // 可以将表名作为注解配置到类上,然后通过反射注解来获取配置的表名信息

String sql = "insert into " + beanClass.getSimpleName() + " values(";

// 指定参数个数

for (int i = 0; i < this.length; i++) {

if (i == length - 1) {

sql += "?)";

} else {

sql += "?,";

}

}

// 可以通过反射Field来获取参数值

Object[] params = {/* 参数值是什么 */};

qr.update(sql, params);

}

public void update(T bean) {

}

public void delete(String uuid) {

}

public T load(String uuid) {

return null;

}

public List<T> findAll() {

return null;

}

}

-------------------------

class UserDAO extends BaseDAO<User> {

public void addUser(User user) {

super.add(user);

}

}

时间: 2024-11-08 22:26:32

JDK1.5新特性之注解的相关文章

JDK1.8新特性(二): Lambda表达式 (参数列表) -&gt; { } 和函数式接口@FunctionalInterface

Lambda表达式 二:简介 JDK的升级的目的有以下几个:增加新的功能.修复bug.性能优化.简化代码等几个方面,Lambda表达式就是属于简化代码,用于简化匿名实现类,提供一种更加简洁的写法.Lambda表达式在Swift语言中称之为代码块,Lambda表达式可以认为是一种特殊的接口,该接口必须只有一个抽象方法. 语法 (参数类型 参数名, 数参数类型 参数名2...) -> { // code }; 小括号()中的内容就是方法中的参数列表包括参数类型.参数名,其中参数类型是可以省略的,当参

图解jdk1.8新特性(1)

图解jdk1.8新特性(1) 函数式接口 总结起来就以下几点: 如果一个接口要想成为函数接口(函数接口可以直接用lambda方式简化),则必须有且仅有一个抽象的方法(非default和static) 可以通过注解@FunctionalInterface注解通过在编译时报错防止其他人破坏函数式接口 接口默认和静态方法 总结如下: jdk1.8之后接口可以实现default方法和static方法,其实就是将接口当做了一个抽象类 default方法是非静态,必须通过接口的实现类来调用,接口实现类中可以

jdk1.5新特性和jdk1.7新特性

jdk1.5新特性 1.自动装箱和自动拆箱 自动装箱,把基本类型的值变成对象类型 Integer a = 2; 自动拆箱,把对象类型变成基本类型 int b = new Integer(2); 而不需要调用intValue int b = new Integer(2).intValue(); 包装类有 Integer Boolean Float Double Short Byte 2.枚举 java枚举具有简单和安全性. 3.泛型 泛型在编译的时候可以控制类型,比如说List<String>

黑马程序员——java高新---JDK1.5新特性和反射

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.JDK1.5新特性 ——>静态导入 import和import static之间的区别: 1.import是导入一个类或某个包中所有的类. 2.import static是导入一个类中的某个静态成员或所有的静态成员. 注意: 1.当导入的两个类中有同名成员时,需要在成员前加上相应的类名. 2.当类名重名时,需要指定具体的包名. 3.方法重名时,需要指定具体所属的对象或者类. 代码示例: 1

接口、接口优点、接口的属性和方法特性、接口与继承的区别、接口与抽象类的区别、匿名实现类、JDK1.8新特性、打印类名称

接口里的属性,必须是公共的/默认的&静态的&Final&初始化后的属性: 接口里所有方法都是抽象的. 接口和继承---先天有的用继承,后天学习的用接口: 接口特性-------- 1.接口不可以被实例化: 2.实现类必须实现接口中所有方法,否则实现类必须是抽象类 3.实现类可以实现多个接口,来弥补Java不能多继承: 4.接口中的变量都是静态常量:(静态的-可以通过类的名字点-直接调用:) ----------------------------------------------

jdk1.5新特性

package cn.itcast.jdk15; import java.util.ArrayList; /* jdk1.5新特性之-----自动装箱与自动拆箱. java是面向对象 的语言,任何事物都可以使用类进行描述,sun就使用了 一些类描述java中八种基本数据类型数据 基本数据类型 包装类型 byte Byte short Short int Integer long Long float Float double Double boolean Boolean char Charact

黑马程序员------Java中jdk1.5新特性

Java培训.Android培训.iOS培训..Net培训.期待与您交流! JDK1.5新特性: 为什么会出现新特性: 新的技术出现是为了解决老的问题,Java语言为了提高开发者的开发效率,对之前的某些不利于提高效率的技术进行改进. 静态导入: 静态导入:可以导入某个类下的静态方法,静态导入后,可以不写类名而直接使用此类下的静态方法. 语法:import static 包名.类名.静态方法 代码示例: package com.itheima.day1; /** * 静态导入 * @author

jdk1.5新特性之-------&gt;可变参数

/* jdk1.5新特性之------->可变参数 需求: 定义一个函数做加法功能(函数做几个数据 的加法功能是不确定). 可变参数的格式: 数据类型... 变量名 可变参数要 注意的细节: 1. 如果一个函数 的形参使用上了可变参数之后,那么调用该方法的时候可以传递参数也可以不传递参数. 2. 可变参数实际上是一个数组对象. 3. 可变参数必须位于形参中的最后一个参数. 4. 一个函数最多只能有一个可变 参数,因为可变参数要位于形参中最后一个位置上. */ public class Demo4

spring4.0.6最新稳定版新特性学习,注解自动扫描bean,自动注入bean(二)

Spring4.0的新特性我们在上一章已经介绍过了.包括它对jdk8的支持,Groovy Bean Definition DSL的支持,核心容器功能的改进,Web开发改进,测试框架改进等等.这张我们主要介绍spring4.0的自动扫描功能,以及对bean的过滤等特性进行学习. 好吧,废话少说,我们来看看代码吧. package com.herman.ss.test; import org.springframework.context.ApplicationContext; import org