Java 注解和反射

注解和反射

页面-3

注解 Annotation

注解又称 Annotation,是JDK 5.0 开始引入的技术

通俗的讲注解相当于程序的解释说明,注解可以通过反射被读取

Annotation格式:@“注释名”,当然可以添加一些参数值(形如:@Retention(RetentionPolicy.RUNTIME)

注解可以使用在packageclassmethodfield 等上面

最典型的例子就是重写注解了

@override
public void run(){...}

元注解

元注解的作用就是负责注解其他注解

Java定义了四个标准的meta-annotation类型,它们被用来提供对其他annotation类型做说明。

所在包 java.langannotation

  1. @Target

    用于描述注解的使用范围,描述被注解的注解可以用在什么地方

  2. @Retention

    表示需要在什么级别保存该注解信息,用于描述注解的生命周期

    注解级别:SOURCE(源代码)< CLASS(字节码) < RUNTIEM(运行时)

  3. @Document

    说明该注解将被包含在javadoc

  4. @Inherited

    说明子类可以继承父类中的该注解

内置注解

定义在系统中java.lang.* 包内

  1. @Override

    此注释只适用于修饰方法,表示声明一个方法打算重写超类中的另一个方法。

  2. @Deprecated

    此注释只适用于修饰方法,属性,类,表示不支持使用这样的元素

  3. @SupperWarnings

    用来屏蔽警告信息,需要添加一个参数才能正确使用

    @SuppressWarnings("all")
    @SuppressWarnings("unchecked")
    @SuppressWarnings(value={"unchecked","deprecation"})
    

自定义注解

自定义注解允许自定义注解名称注解参数

使用自定义注解时,自动继承了java.lang.annotation.Annotation接口

@Target(value = {ElementType.TYPE,ElementType.METHOD})  //作用于 方法和类 可省略
@Retention(RetentionPolicy.RUNTIME)    //作用于 运行时 可省略
public @interface MyAnnotation{
  String value() default "null";//default 代表默认值
  ...
}

@Myannotation("Test")
public class Test{...}

反射 Reflection

Java反射(Reflection)是Java非常重要的动态特性

通过使用反射我们不仅可以获取到任何类的成员方法、成员变量、构造方法等信息

还可以动态创建Java类实例、调用任意的类方法、修改任意的类成员变量值等。

注解和反射是各种java web框架的底层实现机制与灵魂

Class类

Class类是一个描述类的类,是反射的根源。

一个在内存中加载的类在JVM中只会有一个对应的Class的实例化对象,通过Class可以完整的得

到一个类中所有被加载的结构

[了解] 类的常用方法
1.getName():返回String形式的该类的名称。
2.newInstance():根据某个Class对象产生其对应类的实例,它调用的是此类的默认构造方法(没有默认无参构造器会报错)
3.getClassLoader():返回该Class对象对应的类的类加载器。
4.getSuperClass():返回某子类所对应的直接父类所对应的Class对象
5.isArray():判定此Class对象所对应的是否是一个数组对象
6.getComponentType() :如果当前类表示一个数组,则返回表示该数组组件的 Class 对象,否则返回 null。
7.getConstructor(Class[]) :返回当前 Class 对象表示的类的指定的公有构造子对象。
8.getConstructors() :返回当前 Class 对象表示的类的所有公有构造子对象数组。
9.getDeclaredConstructor(Class[]) :返回当前 Class 对象表示的类的指定已说明的一个构造子对象。
10.getDeclaredConstructors() :返回当前 Class 对象表示的类的所有已说明的构造子对象数组。
11.getDeclaredField(String) :返回当前 Class 对象表示的类或接口的指定已说明的一个域对象。
12.getDeclaredFields() :返回当前 Class 对象表示的类或接口的所有已说明的域对象数组。
13.getDeclaredMethod(String, Class[]) :返回当前 Class 对象表示的类或接口的指定已说明的一个方法对象。
14.getDeclaredMethods() :返回 Class 对象表示的类或接口的所有已说明的方法数组。
15.getField(String) :返回当前 Class 对象表示的类或接口的指定的公有成员域对象。
16.getFields() :返回当前 Class 对象表示的类或接口的所有可访问的公有域对象数组。
17.getInterfaces() :返回当前对象表示的类或接口实现的接口。
18.getMethod(String, Class[]) :返回当前 Class 对象表示的类或接口的指定的公有成员方法对象。
19.getMethods() :返回当前 Class 对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承的方法。
20.isInstance(Object) :此方法是 Java 语言 instanceof 操作的动态等价方法。
21.isInterface() :判定指定的 Class 对象是否表示一个接口类型
22.isPrimitive() :判定指定的 Class 对象是否表示一个 Java 的基类型。
[了解] 获取Class类的方式
  1. 具体的类,通过类的class属性获取

    Class c = Object.class;
    
  2. 知道类全名,通过Class.forName()方法获取

    Class c = Class.forName("com.reflection.demmo");
    
  3. 实例化的类,通过调用.getClass()方法获取

    Person person = new Person();
    Class c = person.getClass();
    

三种获取方法的区别

1 类名.class(也称类字面常量) 方式生成Class对象不会初始化的静态块,不会初始化参数,不会调用构造函数
2 Class.forName()方式生成Class对象会初始化类静态块,但不会初始化非静态的代码块,也不调用构造函数
3 Object.getClass()方式生成Class对象会先初始化静态块,接着执行非静态块的初始化,最后调用构造函数
[了解] 可以获取Class的数据类型

类、接口、数组、注解、枚举、基本数据类型、void、Class

//代码
Class c1 = Object.class;    //类
Class c2 = Runnable.class;  //接口
Class c3 = String[].class;  //一维数组
Class c4 = String[][].class;    //二维数组
Class c5 = Override.class;  //注解
Class c6 = ElementType.class;   //枚举
Class c7 = Integer.class;   //基本数据类型包装类
Class c8 = void.class;  //void
Class c9 = Class.class; //Class
//输出
class java.lang.Object
interface java.lang.Runnable
class [Ljava.lang.String;
class [[Ljava.lang.String;
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class

Field类

代表类的成员变量

.getFields() 获取public修饰属性

.getDeclaredFields 可以获取所有属性

//getFields 只能找到pubilc属性
Field[] fields = c1.getFields();
//getDeclaredFields 可以找到所有属性
        fields = c1.getDeclaredFields();    

for (Field field : fields) {
    System.out.println(field);
}
//输出格式:全类名.属性
java.lang.String 注解和反射.自定义注解.name

Method 类

代表类的方法,该类型主要通过Class 中一下三个方法获取

.getMethods()获得本类和继承类的所有public方法

.getDeclaredMethods()获取本类的所有方法

.getMethod("方法名", 方法形参类型.class) 获得指定的方法,

//获得本类和继承类的所有public方法
Method[] methods = c1.getMethods(); 
for (Method method : methods) {
	System.out.println("getMethods(): " + method);
}
 
//获取本类的所有方法
methods = c1.getDeclaredMethods();  
for (Method method : methods) {
	System.out.println("getDeclaredMethods(): " + method);
}

//获得指定的方法
Method setName = c1.getMethod("setName", String.class);
Method getName = c1.getMethod("getName");

System.out.println(setName);
System.out.println(getName);

//输出格式 全类名.方法名

Invke方法的使用

Class c2 = Class.forName("com.reflaction.User");
User user = (User) c2.newInstance();
Method setName = c2.getMethod("setName", String.class);
setName.invoke(user,"形参");

Constructor 类

代表类的构造方法

.getConstructors 获取本类和父类的所有构造方法

.getDeclaredConstructors 获取本类所有构造方法

.getConstructor(String.class,int.Class,int.class) 获取指定参数类型构造器

//获取本类和父类的所有构造方法
Constructor[] constructors = c1.getConstructors();      
for (Constructor constructor : constructors) {
	System.out.println(constructor);
}

//获取本类所有构造方法
constructors = c1.getDeclaredConstructors();        

for (Constructor constructor : constructors) {
	System.out.println(constructor);
}

//获取指定的构造器
Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
System.out.println(constructor);

Array 类

提供了动态创建数组,以及访问数组的元素的静态方法。

动态创建一维数组并赋值

//动态创建数组
Object array = Array.newInstance(String.class, 10);

//对array数组的第五个元素赋值
Array.set(array, 5, "helloworld");

//获取数组元素
String str = (String) Array.get(array, 5);

动态创建多维数组

 //反射三维数组
int[] dims = new int[] { 5, 10, 15 };
Object array = Array.newInstance(Integer.TYPE, dims);//array 是个三维数组

//获取数组元素:二维数组
Object arrayObj =Array.get(array, 3);


//数组类型
Class<?> acls = arrayObj.getClass();
System.out.println(acls);

//数组元素类型,getComponentType()返回表示数组组件类型的 Class,如果此类不表示数组类,则此方法返回null。
Class<?> componentType = arrayObj.getClass().getComponentType();
System.out.println(componentType);

//获取数组元素:一维数组
arrayObj=Array.get(arrayObj, 5);

Array.set(arrayObj, 10, 30);

//获取打印
int [][][] arrayCast=(int [][][])array;
System.out.println(arrayCast[3][5][10]);//30

反射类构造器获取实例化对象

//调用无参构造实例化对象
Class c1 = Class.forName("com.reflaction.User");
User user = (User) c1.newInstance(); 

//获得有参构造方法
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);

//通过构造器获得实例化对象
User ago = (User) constructor.newInstance("ago", 18, 1);
System.out.println(ago);

反射获取调用普通方法

方法一

  1. 反射获取目标类的class对象(Class.forName()) ==>
  2. 获取有参构造器(class.getDeclaredConstructor()) ==>
  3. 获取目标类实例化对象(constructor1.newInstance(param1, param2, param3 ,...)) ==>
  4. 调用方法(实例化对象.Method())
Class c2 = Class.forName("com.reflaction.User");
Constructor constructor1 = c2.getDeclaredConstructor(String.class, int.class, int.class);
User zh1z3ven = (User) constructor1.newInstance("zh1z3ven", 20, 2);
System.out.println(zh1z3ven.getAge());
System.out.println(zh1z3ven.getName());
zh1z3ven.setId(20);
System.out.println(zh1z3ven.getId());

方法二

  1. 反射获取目标类class对象(Class.forName()) ==>
  2. 获取目标类实例化对象(constructor1.newInstance(param1, param2, param3 ,...))
  3. 获取指定方法(class.getMethod("方法名", 参数)) ==>
  4. 激活执行方法(.invoke(目标对象, 参数))
Class c2 = Class.forName("com.reflaction.User");
User user2 = (User) c2.newInstance();
Method setName = c2.getMethod("setName", String.class);

//invoke 代替调用user2对象的setName方法,并向方法内传参
setName.invoke(user2, "kfei");
System.out.println(user2.getName());

反射操作属性

  1. 获取class对象
  2. class.getDeclaredField("属性名") 获取属性
  3. .set() 方法设置属性
  4. 若为private修饰,出现无权限操作异常,可用.setAccessible(true) 关闭安全检测,获取操作权限
Class c3 = Class.forName("com.reflaction.User");
User user4 = (User) c3.newInstance();

Field name = c3.getDeclaredField("name");

name.setAccessible(true);
name.set(user4 ,"zgo");
System.out.println(user4.getName());

[了解] 反射操作泛型

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 TestFanXingDemo {

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

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

    public static void main(String[] args) throws NoSuchMethodException {

        Method method = TestFanXingDemo.class.getMethod("test01", Map.class, List.class);
        method.setAccessible(true);     //关闭安全检测,暴力反射
        Type[] genericParameterTypes = method.getGenericParameterTypes();   //获得泛型的参数类型

        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("#genericParameterType: " + genericParameterType);   //遍历泛型类型

            if (genericParameterType instanceof ParameterizedType){     //判断泛型参数类型是否是参数化类型
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();   //获得真实参数信息
                
                //循环遍历参数
                for (Type actualTypeArgument : actualTypeArguments) {       
                    System.out.println(actualTypeArgument);
                }
            }
        }
    }
}

[了解] 反射操作注解

import java.lang.annotation.*;
import java.lang.reflect.Field;

public class TestDemo12 {

    //反射操作注解
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.reflaction.Student2");

        //通过反射获得全部注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        //获得注解的value值
        TableStudent tableStudent = (TableStudent) 		    			                 c1.getAnnotation(TableStudent.class);
        String value = tableStudent.value();//获取注解的value
        System.out.println(value);

        //获取指定类的注解value
        Field f = c1.getDeclaredField("name");
        FieldStudent annotation = f.getAnnotation(FieldStudent.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());

    }

}

@TableStudent("db_student")
class Student2{
    @FieldStudent(columnName = "db_id", type = "int", length = 10)
    private int id;
    @FieldStudent(columnName = "db_age", type = "int", length = 10)
    private int age;
    @FieldStudent(columnName = "db_name", type = "varchar", length = 3)
    private String name;

    public Student2() {
    }

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

    public int getId() {
        return id;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

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

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

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

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

//类名的注解
@Target(ElementType.TYPE)   //作用范围为类
@Retention(RetentionPolicy.RUNTIME)     //作用为运行时可获取
@interface TableStudent{
    String value();
}

//属性的注解
@Target(ElementType.FIELD)   //作用范围为类
@Retention(RetentionPolicy.RUNTIME)     //作用为运行时可获取
@interface FieldStudent{
    String columnName();
    String type();
    int length();
}

参考

(3条消息) B站【狂神说Java笔记】-注解和反射_闲言-CSDN博客

Java之注解与反射 - CoLoo - 博客园 (cnblogs.com)

Java中的注解和反射 - itzhouq - 博客园 (cnblogs.com)

Java Class类常用方法描述 - 汴梁砍柴人 - 博客园 (cnblogs.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ABright.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值