注解和反射

一、什么是注解

1.1 注解简介

  • Annotation是从JDK5开始引入的新技术
  • Annotation的作用
    1. 不是程序本身,可以对程序做出解释,
    2. 可以被其他程序(比如编译器)读取
  • Anntation的格式:
    • 注释是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value=“unchecked”).
  • Annotation在哪使用:
    • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们就可以通过反射机制编程实现对这些元数据的访问

1.2 内置注解

  • @Override:定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个声明。
  • @Deprecated:定义在java.lang.Deprecated中,此注释可以用于修饰方法,属性,类,表示不建议使用,通常是因为它很危险或者存在更好的选择。
  • @SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息,带有参数:
    • @SuppressWarnings("all")
    • @SuppressWarnings("unchecked")
    • @SuppressWarnings(value={"unchecked","deprecation"})
    • 等等

1.3 定义注解

java语言使用@interface语法来定义注解,格式如下:

public @interface Demo03 {
    int type() default 0;
    String level() default "info";
    String level() default "";
    
}

注解的参数类似无参数方法,可以用default设定一个默认值,最常用的参数应当命名为value

分析:

  • @interface用来声明一个注解,格式:public @interface 注解名{定义内容}
  • 其中每一个方法实际上是声明了一个配置参数
  • 方法的名称就是参数的名称
  • 返回值类型就是参数的类型(返回值只能是基本类型Class,String,enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value
  • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值

二、元注解

  • @Target
  • @Retention
  • @Documented
  • @Inherited

2.1 @Target

使用@Target可以定义Annotation能够被应用与于源码的哪些位置

  • 类或接口: ElementType.TYPE;
  • 字段:ElementType:FILED;
  • 方法:ElementType.METHOD;
  • 构造方法:ElementType.CONSTRUCTOR;
  • 方法参数:ElementType.PARAMETER;

2.2 @Retention

另一个重要的元注解@Retention定义了Annotation的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE;
  • 仅class文件:RetentionPolicy.CLASS;
  • 运行期:RetentionPolicy.RUNTIME;
    如果@Retention不存在,则该Annotation默认为CLASS,
    因为通常我们自定义的Annotation都是RUNTIME,所以,务必要加上@Retention(RetentionPolicy.RUNTIME)这个元注解

2.3 @Repeatable

这个元注解可以定义Annotation是否可重复,这个注解应用不是特别广泛

@Repeatable(Demo03.class)
@Target(ElementType.METHOD)
public @interface Demo03 {
    int type() default 0;
    String level() default "info";
    String value() default "";


}

经过@Repeatable修饰后,在某个类型声明处,就可以添加多个@Report注解:

@Report(type=1,level="debug")
@Report(type=2,level="warning")
public class Hello{
	
}




2.4 @Inherited

定义子类是否可继承父类定义的Annotation,@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效:

三、反射

3.1 得到Class类的几种方式

  • 已知具体的类,通过类的class属性获取
    Class class = Person.class;
  • 已知某一个类的实例,调用实例的getClass()方法获取
    Class class = person.getClass();
  • 已知一个类的全类名,且该类在类路径下,通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException
    Class class = Class.forName("demo.Student");
  • 内置基本数据类型可以直接使用类名.Type
  • 还可以利用ClassLoader
  • 还可以获取父类的Class类:class.getSuperclass();

3.2 Class类常用方法

  • getName() :返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
  • newInstance():为类创建一个实例,但只能调用默认构造器(无参数构造器)
  • getClassLoader():返回该类的类加载器
  • getComponentType():返回表示数组组件类型的Class
  • getSuperClass():返回表示此Class所表示的实体(类、接口、基本类型或void)的超类的Class
  • isArray()判定此Class对象是否表示一个数组类。

3.3 获取类运行时的结构

获取属性:
1. getFields():获取所有的公有字段
2. getDeclaredFields():获取所有字段,包括私有,受保护,默认,公有。
3. getField(String fieldName)获取某个公有字段
4. getDeclareField(String fieldName)

获取方法:
1. public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
2. public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)

获取构造器:
1. public Constructor[] getConstructors():所有"公有的"构造方法
2. public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护的、默认的、公有的)

3.4 动态创建对象执行方法

package com.zlf;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestClassLoader {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        获取系统类加载器可以加载的路径
      /*  System.out.println(System.getProperty("java.class.path"));
        System.out.println(ClassLoader.getSystemClassLoader());
        System.out.println(ClassLoader.getSystemClassLoader().getParent());
        System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());*/


        Class personClass = Class.forName("com.zlf.Person");

//      构造一个对象
        Person person = (Person) personClass.newInstance();//默认调用无参构造
        System.out.println(person);

//        通过构造器创建对象

        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);
        Person person2 = (Person) declaredConstructor.newInstance("周霖峰");
        System.out.println(person2);

//        通过反射调用方法
        Person person3 = (Person) personClass.newInstance();
        Method setName = personClass.getDeclaredMethod("setName", String.class);
//      使用invoke调用方法
        setName.invoke(person3,"周旋");
        System.out.println(person3.getName());

//        通过反射操作属性
        Person person4 = (Person) personClass.newInstance();
        Field name = personClass.getDeclaredField("name");
        name.setAccessible(true);//暴力访问(忽略访问修饰父)
        name.set(person4,"person4");
        System.out.println(person4.getName());

    }
}


3.5 获取泛型的信息

  • ParameterizedType:表示一种参数化类型比如Collection<String>
  • GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
  • TypeVariable:是各种类型变量的公共父接口
  • WildcardType:代表一种通配符类型表达式
package com.zlf;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class GenericGetReflect {
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = GenericGetReflect.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType:genericParameterTypes
             ) {
            System.out.println("#" + genericParameterType);
            if(genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument:actualTypeArguments
                     ) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
    }

    public void test01(Map<String,Person> map, List<Person> list){
        System.out.println("test01");
    }

    public Map<String,Person> test02(){
        System.out.println("test02");
        return null;
    }
}

3.6 获取注解信息

package com.zlf;

import java.lang.annotation.*;

public class AnnotationReflect {
    public static void main(String[] args) throws NoSuchFieldException {
        Class StuClass = Students.class;
//        通过反射获取注解
        Annotation[] annotations = StuClass.getAnnotations();
        for (Annotation annotation: annotations
             ) {
            System.out.println(annotation);
        }


//        获取注解的value值
        Table table = (Table) StuClass.getAnnotation(Table.class);
        String value = table.value();
        System.out.println(value);

//        获取指定注解
        java.lang.reflect.Field name = StuClass.getDeclaredField("name");
        Field annotation = name.getAnnotation(Field.class);
        System.out.println(annotation.colName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());



    }
}


@Table("db_stu")
class Students{
    @Field(colName = "db_id",type = "int",length = 10)
    private int id;

    @Field(colName = "db_name",type = "varChar",length = 10)
    private String name;

    @Field(colName = "db_age",type = "int",length = 10)
    private int age;

    public Students(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Students() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Students{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}



//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String value();
}


//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
    String colName();
    String type();
    int length();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值