前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java-reflection

java-reflection

作者头像
Remember_Ray
发布2020-09-15 10:07:31
4330
发布2020-09-15 10:07:31
举报
文章被收录于专栏:Ray学习笔记

Java 反射机制概述

  • Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
  • 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以我们形象称之为:反射

理解Class类并获取Class实例

在 Object 类中定义了以下的方法,此方法将被所有子类继承

代码语言:javascript
复制
public final native Class<?> getClass();

以上方法返回值的类型是一个 Class 类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即可以通过对象反射求出类的名称

对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个结构的有关信息。

  • Class 本身也是一个类
  • Class 对象只能由系统建立对象
  • 一个加载的类再 JVM 中只会有一个 Class 实例
  • 一个 Class 对象对应的是一个加载到 JVM 中的一个 .class 文件
  • 每个类的实例都会记得自己是由哪个 Class 实例所生成
  • 通过 Class 可以完整地得到一个类中的所有被加载的结构
  • Class 类是 Reflection 的根源,针对任何你想动态加载、运行的类,唯有先获得相应的 Class 对象

常用方法

方法名

功能说明

static ClassforName(String name)

返回指定类名name的Class对象

Object newInstance()

调用无参构造函数,返回Class对象的一个实例

getName()

返回此Class对象所表示的实体(类、接口、数组类或void)的名称

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class[] getInterfaces()

返回当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Constructor[] getConstructors()

返回一个包含某些Constructor对象的数组

Method getMothed(String name, Class.. T)

返回一个Method对象,此对象的形参类型为paramType

Field[] getDeclaredFields()

返回Field对象的一个数组

获取 Class 类的实例

  1. 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。
代码语言:javascript
复制
Class c1 = User.class;
  1. 已知某个类的实例,调用该实例的getClass()方法获取Class对象。
代码语言:javascript
复制
User user = new User();
Class c2 = user.getClass();
  1. 已知一个类的全限定类型,且该类在类路径下,可通过Class类的静态方法forName()获取,要抛出异常。
代码语言:javascript
复制
Class c3 = Class.forName("com.ray.pojo.User");
  1. 内置基本数据类型可以直接用类型.Type
代码语言:javascript
复制
Class c4 = Integer.TYPE;
  1. 还可以利用ClassLoader。

示例

代码语言:javascript
复制
public class Person {
    public String name;
}
代码语言:javascript
复制
public class Student extends Person {
    public Student() {
        this.name = "学生";
    }
}
代码语言:javascript
复制
public class Demo03 {

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

        Person person = new Student();
        System.out.println("这个人是: " + person.name);

        // 方式一:通过对象获取
        Class c1 = person.getClass();
        System.out.println("c1.hashCode() = " + c1.hashCode());

        // 方式二:forName获取
        Class c2 = Class.forName("com.ray.pojo.Student");
        System.out.println("c2.hashCode() = " + c2.hashCode());

        // 方式三:通过类名.class获取
        Class c3 = Student.class;
        System.out.println("c3.hashCode() = " + c3.hashCode());

        // 方式四:基本内置类型的包装类都有一个Type类型
        Class c4 = Integer.TYPE;
        System.out.println("c4 = " + c4);

        // 获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println("c5 = " + c5);
    }
}

结果

代码语言:javascript
复制
这个人是: 学生
c1.hashCode() = 460141958
c2.hashCode() = 460141958
c3.hashCode() = 460141958
c4 = int
c5 = class com.ray.pojo.Person

所有类型的Class

代码语言:javascript
复制
public class Demo04 {

    public static void main(String[] args) {
        Class c1 = Object.class;      // 类
        Class c2 = Comparable.class;  // 接口
        Class c3 = String[].class;    // 一维数组
        Class c4 = int[][].class;     // 二维数组
        Class c5 = Override.class;    // 注解
        Class c6 = ElementType.class; // 枚举
        Class c7 = Integer.class;     // 基本数据类型
        Class c8 = void.class;        // void
        Class c9 = Class.class;       // Class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);
    }
}

结果

代码语言:javascript
复制
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class

Java 内存分析

类的加载过程(了解)

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

类的加载与ClassLoader的理解

什么时候会发生类的初始化

类的主动引用(一定会发生类的初始化)

  • 当虚拟机启动,先初始化main方法所在的类
  • new一个类的对象
  • 调用类的静态成员(除了final常量)和静态方法
  • 使用 java.lang.reflect 包的方法对类进行反射调用
  • 当初始化一个类,如果其父类没有被初始化,则先回初始化它的父类

类的被动引用(不会发生类的初始化)

  • 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化
  • 通过数组定义类引用,不会触发此类的初始化
  • 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中)
代码语言:javascript
复制
package com.ray.demo;

/**
 * @Description: 测试类什么时候会初始化
 * @Author Administrator
 * @Date 2020/9/5 11:53
 * @Version 1.0
 */
public class Demo06 {

    static {
        System.out.println("Main类被加载");
    }

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

        /**
         * Main类被加载
         * 父类被加载
         * 子类被加载
         * */
        //Son son = new Son();


        /**
         * 反射也会产生主动引用
         * Main类被加载
         * 父类被加载
         * 子类被加载
         * */
        //Class.forName("com.ray.demo.Son");


        /**
         * 不会产生类的引用的方法
         * Main类被加载
         * 父类被加载
         * 2
         * */
        //System.out.println(Son.b);

        /** Main类被加载 */
        //Son[] array = new Son[5];


        /**
         * Main类被加载
         * 1
         * */
        System.out.println(Son.A);
    }
}

class Father {

    static int b = 2;

    static {
        System.out.println("父类被加载");
    }
}

class Son extends Father {

    static {
        System.out.println("子类被加载");
        m = 300;
    }

    static int m = 100;
    static final int A = 1;
}

类加载器的作用

  • 类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
  • 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。
代码语言:javascript
复制
package com.ray.demo;

/**
 * @Description: 类加载器
 * @Author Administrator
 * @Date 2020/9/5 14:33
 * @Version 1.0
 */
public class Demo07 {

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

        // 获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println("systemClassLoader = " + systemClassLoader);

        // 获取系统类加载器的父类加载器 -> 扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println("parent = " + parent);

        // 获取扩展类加载器的父类加载器 -> 根加载器(无法直接获取)
        ClassLoader parent1 = parent.getParent();
        System.out.println("parent1 = " + parent1);

        // 测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("com.ray.demo.Demo07").getClassLoader();
        System.out.println("classLoader = " + classLoader);

        // 测试JDK内置的类是谁加载的
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println("classLoader = " + classLoader);

        // 如何获得系统类加载器可以加载的路径
        //System.out.println(System.getProperty("java.class.path"));
    }
}

结果

代码语言:javascript
复制
systemClassLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
parent = sun.misc.Launcher$ExtClassLoader@1b6d3586
parent1 = null
classLoader = sun.misc.Launcher$AppClassLoader@18b4aac2
classLoader = null

创建运行时类的对象

代码语言:javascript
复制
package com.ray.demo;

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

/**
 * @Description: 获得类的信息
 * @Author Administrator
 * @Date 2020/9/5 14:39
 * @Version 1.0
 */
public class Demo08 {

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

        Class c1 = Class.forName("com.ray.pojo.User");

        System.out.println("-------- 获取类的名字 ---------");

        // 获取类的名字
        System.out.println("c1.getName() = " + c1.getName());  // 获得包名 + 类名
        System.out.println("c1.getSimpleName() = " + c1.getSimpleName()); // 获得类名

        System.out.println("-------- 获得类的属性 - 只能找到 public 属性 ---------");

        // 获得类的属性 - 只能找到 public 属性
        Field[] fields = c1.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("-------- 获得类的属性 - 能找到全部属性 ---------");

        // 获得类的属性 - 能找到全部属性
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        System.out.println("-------- 获得指定属性的值 - 只能找到 public 属性 ---------");

        // 获得指定属性的值 - 只能找到 public 属性
        //Field name = c1.getField("name");
        //System.out.println("name = " + name); // java.lang.NoSuchFieldException: name

        System.out.println("-------- 获得指定属性的值 - 能找到全部属性 ---------");

        // 获得指定属性的值 - 能找到全部属性
        Field name = c1.getDeclaredField("name");
        System.out.println("name = " + name);


        System.out.println("-------- 获得类的方法 - 获得本类及其父类的public方法 ---------");

        // 获得类的方法
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("method = " + method);
        }

        System.out.println("-------- 获得类的方法 - 获得本类的所有方法 ---------");

        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("declaredMethod = " + declaredMethod);
        }


        System.out.println("-------- 获得类的指定方法 ---------");
        // 添加参数可避免重载
        Method getName = c1.getMethod("getName", null);
        System.out.println("getName = " + getName);

        Method method = c1.getMethod("setName", String.class);
        System.out.println("method = " + method);


        System.out.println("-------- 获得类的构造器 ---------");
        // 只获得 public 构造方法
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("constructor = " + constructor);
        }

        // 获得本类的全部构造方法
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("declaredConstructor = " + declaredConstructor);
        }

        // 获得指定构造方法
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("++ declaredConstructor ++ = " + declaredConstructor);
    }
}

结果

代码语言:javascript
复制
-------- 获取类的名字 ---------
c1.getName() = com.ray.pojo.User
c1.getSimpleName() = User
-------- 获得类的属性 - 只能找到 public 属性 ---------
-------- 获得类的属性 - 能找到全部属性 ---------
private java.lang.String com.ray.pojo.User.name
private int com.ray.pojo.User.id
private int com.ray.pojo.User.age
-------- 获得指定属性的值 - 只能找到 public 属性 ---------
-------- 获得指定属性的值 - 能找到全部属性 ---------
name = private java.lang.String com.ray.pojo.User.name
-------- 获得类的方法 - 获得本类及其父类的public方法 ---------
method = public java.lang.String com.ray.pojo.User.toString()
method = public java.lang.String com.ray.pojo.User.getName()
method = public int com.ray.pojo.User.getId()
method = public void com.ray.pojo.User.setName(java.lang.String)
method = public void com.ray.pojo.User.setAge(int)
method = public void com.ray.pojo.User.setId(int)
method = public int com.ray.pojo.User.getAge()
method = public final void java.lang.Object.wait() throws java.lang.InterruptedException
method = public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method = public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method = public boolean java.lang.Object.equals(java.lang.Object)
method = public native int java.lang.Object.hashCode()
method = public final native java.lang.Class java.lang.Object.getClass()
method = public final native void java.lang.Object.notify()
method = public final native void java.lang.Object.notifyAll()
-------- 获得类的方法 - 获得本类的所有方法 ---------
declaredMethod = public java.lang.String com.ray.pojo.User.toString()
declaredMethod = public java.lang.String com.ray.pojo.User.getName()
declaredMethod = public int com.ray.pojo.User.getId()
declaredMethod = public void com.ray.pojo.User.setName(java.lang.String)
declaredMethod = public void com.ray.pojo.User.setAge(int)
declaredMethod = public void com.ray.pojo.User.setId(int)
declaredMethod = public int com.ray.pojo.User.getAge()
declaredMethod = private void com.ray.pojo.User.testPrivate()
-------- 获得类的指定方法 ---------
getName = public java.lang.String com.ray.pojo.User.getName()
method = public void com.ray.pojo.User.setName(java.lang.String)
-------- 获得类的构造器 ---------
constructor = public com.ray.pojo.User()
constructor = public com.ray.pojo.User(java.lang.String,int,int)
declaredConstructor = public com.ray.pojo.User()
declaredConstructor = public com.ray.pojo.User(java.lang.String,int,int)
++ declaredConstructor ++ = public com.ray.pojo.User(java.lang.String,int,int)

Process finished with exit code 0

有了 Class 对象,能做什么?

创建类的对象:调用Class对象的newInstance()方法

  1. 类必须有一个无参数的构造器。
  2. 类的构造器的访问权限需要足够。

思考:难道没有无参的构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进入之后,才可实例化操作。

步骤:

  1. 通过Class类的getDeclaredConstructor(Class … parameterTypes) 取得本类指定的形参类型的构造器。
  2. 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
  3. 通过 Constructor 实例化对象。

调用指定的方法

通过反射,调用类中的方法,通过Method类完成。

步骤:

  1. 通过Class类的getMethod(String name, Class … parameterTypes) 方法取得一个 Method 对象,并设置此方法操作时所需要的参数类型。
  2. 之后使用 Object invoke(Object obj, Object[] args) 进行调用,并向方法中传递要设置的 obj 对象的参数信息。
  3. 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。

setAccessible 说明

  • Method 和 Field、Constructor 对象都有 setAccessible() 方法。
  • setAccessible 作用是启动和禁用访问安全检查的开关。
  • 参数值为 true 则表示反射的对象在使用时应该取消Java语言访问检查。
    • 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
    • 使得原本无法访问的私有成员也可以访问
  • 参数值为 false 则表示反射的对象应该实施 Java 语言访问检查。

setAccessible 性能检查

代码语言:javascript
复制
package com.ray.demo;

import com.ray.pojo.User;

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

/**
 * @Description: 分析性能问题
 * @Author Administrator
 * @Date 2020/9/5 15:36
 * @Version 1.0
 */
public class Demo10 {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test1();
        test2();
        test3();
    }

    // 普通方法调用
    public static void test1() {
        User user = new User();

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }

        long end = System.currentTimeMillis();

        System.out.println("普通方式执行10亿次: " + (end - start) + "ms");
    }

    // 反射方式调用
    public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user, null);
        }

        long end = System.currentTimeMillis();

        System.out.println("反射方式执行10亿次: " + (end - start) + "ms");
    }

    // 反射方式调用 -- 关闭检测
    public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
        Method getName = c1.getDeclaredMethod("getName", null);
        getName.setAccessible(true); // 关闭

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user, null);
        }

        long end = System.currentTimeMillis();

        System.out.println("反射方式(关闭检测)执行10亿次: " + (end - start) + "ms");
    }
}

结果

代码语言:javascript
复制
普通方式执行10亿次: 3ms
反射方式执行10亿次: 1283ms
反射方式(关闭检测)执行10亿次: 871ms

完整示例

代码语言:javascript
复制
package com.ray.demo;

import com.ray.pojo.User;

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

/**
 * @Description: 动态的创建对象,通过反射
 * @Author Administrator
 * @Date 2020/9/5 14:58
 * @Version 1.0
 */
public class Demo09 {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 获得 Class 对象
        Class<?> c1 = Class.forName("com.ray.pojo.User");

        // 构造一个对象
        User user = (User) c1.newInstance();  // 调用的是无参构造器
        System.out.println("user = " + user);

        // 通过构造器创建对象
        Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User) constructor.newInstance("Ray", 123, 22);
        System.out.println("user2 = " + user2);


        // 通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        // invoke 激活、调用
        // invoke(对象, "方法的值")
        setName.invoke(user3, "ray");
        System.out.println("user3 = " + user3);


        // 通过反射操作属性
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        // can not access a member of class com.ray.pojo.User with modifiers "private"
        // private 属性不能直接访问,需要关闭程序的安全检测 setAccessible(true)
        name.setAccessible(true);
        name.set(user4, "ray2");
        System.out.println("user4 = " + user4);
    }
}

结果

代码语言:javascript
复制
user = User{name='null', id=0, age=0}
user2 = User{name='Ray', id=123, age=22}
user3 = User{name='ray', id=0, age=0}
user4 = User{name='ray2', id=0, age=0}

反射操作泛型

  • Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是一旦编译完成,所有和泛型有关的类型全部擦除。
  • 为了通过反射操作这些类型,Java新增了 ParameterizedType,GenericArrayType,TypeVariable 和 WildcardType 几种类型来代表不能被归一到 Class 类中的类型但是又和原始类型齐名的类型。

类型

说明

ParameterizedType

表示一种参数化类型,比如Collection<String>

GenericArrayType

表示一种元素类型是参数化类型或者类型变量的数组类型

TypeVariable

是各种类型变量的公共父接口

WildcardType

代表一种通配符类型表达式

代码语言:javascript
复制
package com.ray.demo;

import com.ray.pojo.User;

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

/**
 * @Description: 通过反射获取泛型
 * @Author Administrator
 * @Date 2020/9/5 15:42
 * @Version 1.0
 */
public class Demo11 {

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

        Method test01 = Demo11.class.getMethod("test01", Map.class, List.class);
        // 获取通用参数类型
        Type[] genericParameterTypes = test01.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 = " + actualTypeArgument);
                }
            }
        }

        System.out.println("-----------------------------------------------");

        Method test02 = Demo11.class.getMethod("test02", null);
        // 获取通用返回类型
        Type genericReturnType = test02.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            // 获取返回类型表示的类
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("actualTypeArgument = " + actualTypeArgument);
            }
        }
    }

    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;
    }
}

反射操作注解

元注解

  • 元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型说明。 这些类型和它们所支持的类再java.lang.annotation包中可以找到。 注解 说明 @Target 用于描述注解的使用范围(即注解可以用在什么地方) @Retention 表示需要在什么级别保存该注释信息,用于描述注解的生命周期(SOURCE < CLASS < RUNTIME) @Document 说明该注解将被包含在javadoc中 @Inherited 说明子类可以继承父类中的该注解
代码语言:javascript
复制
package com.ray.demo;

import com.ray.annotation.Table;

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

/**
 * @Description: 练习反射操作注解
 * @Author Administrator
 * @Date 2020/9/5 15:58
 * @Version 1.0
 */
public class Demo12 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {

        // 通过反射获得对象
        Class c1 = Class.forName("com.ray.pojo.Teacher");

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

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


        // 获得类指定的注解
        Field name = c1.getDeclaredField("name");
        com.ray.annotation.Field annotation = name.getAnnotation(com.ray.annotation.Field.class);
        System.out.println("annotation.columnName() = " + annotation.columnName());
        System.out.println("annotation.type() = " + annotation.type());
        System.out.println("annotation.length() = " + annotation.length());
    }
}

结果

代码语言:javascript
复制
annotation = @com.ray.annotation.Table(value=db_teacher)
table.value() = db_teacher
annotation.columnName() = db_name
annotation.type() = varchar
annotation.length() = 10
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-10|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java 反射机制概述
  • 理解Class类并获取Class实例
    • 常用方法
      • 获取 Class 类的实例
        • 所有类型的Class
        • Java 内存分析
          • 类的加载过程(了解)
            • 类的加载与ClassLoader的理解
              • 什么时候会发生类的初始化
                • 类加载器的作用
                • 创建运行时类的对象
                  • 有了 Class 对象,能做什么?
                    • 调用指定的方法
                      • setAccessible 说明
                      • setAccessible 性能检查
                    • 反射操作泛型
                    • 反射操作注解
                      • 元注解
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档