资讯专栏INFORMATION COLUMN

Java反射获取类和对象信息全解析

imtianx / 1929人阅读

摘要:反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。此处的对应种基本类型,如果该成员变量的类型是引用类型的,则去掉部分将对象的该成员变量设置为值。

反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。

在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了。

获取类对象

Class.forName(String clazzName)静态方法

调用类的class属性,Person.class返回的就是Person的class对象(推荐使用)

调用某个对象的getClass()方法

具体使用还是要根据实际来选择,第一种方式是比较自由的,只要知道一个类名就可以了,其不会做该类是否存在的校验,第二种、第三种则会做校验

获取类的信息
获取类构造器

Connstructor getConstructor(Class...parameterTypes):返回此Class对象对应类的带指定形参的public构造器

Constructor[] getConstructors():返回此Class对象对应类的所有public构造器

Constructor[] getDeclaredConstructor(Class...parameterTypes):返回此class对象对应类的带指定参数的构造器,与构造器的访问权限无关

Constructor[] getDeclaredConstructors():返回此class对象对应类的所有构造器,与构造器的访问权限无关

获取类成员方法

Method getMethod(String name,Class...parameterTypes):返回此class对象对应类的带指定形参的public方法

Method[] getMethods():返回此class对象所表示的类的所有public方法

Method getDeclaredMethod(string name,Class...parameterTypes):返回此class对象对应类的带指定形参的方法,与方法访问权限无关

Method[] getDeclaredMethods():返回此class对象对应类的全部方法,与方法的访问权限无关

获取类成员变量

Field getField(String name):返回此class对象对应类的指定名称的public成员变量

Field[] getFields():返回此class对象对应类的所有public成员变量

Field getDeclaredField(String name):返回此class对象对应类的指定名称的成员变量,与成员变量访问权限无关

Field[] getDeclaredFields():返回此class对象对应类的全部成员变量,与成员变量的访问权限无关

获取类注解

A getAnnotation(ClassannotationClass):尝试获取该class对象对应类上村子的指定类型的Annotation,如果该类型注解不存在,则返回null

A getDeclaredAnnotation(ClassannotationClass):这是Java 8中新增的,该方法获取直接修饰该class对象对应类的指定类型的Annotation,如果不存在,则返回null

Annotation[] getAnnotations():返回修饰该class对象对应类上存在的所有Annotation

Annotation[] getDeclaredAnnotations():返回修饰该Class对象对应类上存在的所有Annotation

A[] getAnnotationByType(ClassannotationClass):该方法的功能与前面介绍的getAnnotation()方法基本相似,但由于Java8增加了重复注解功能,因此需要使用该方法获取修饰该类的指定类型的多个Annotation

A[] getDeclaredAnnotationByType(ClassannotationClass):该方法发功能与前面介绍的getDeclaredAnnotations()方法相似,也是因为Java8的重复注解的功能,需要使用该方法获取直接修饰该类的指定类型的多个Annotation

获取该类内部类

Class[] getDeclaredClasses():返回该class队形对应类里包含的全部内部类

获取该类对象所在的外部类

Class getDeclaringClass():返回该Class对象对应类所在的外部类

获取该类对象对应类所实现的接口

Class[] getInterfaces():返回该Class对象对应类所实现的全部接口

获取该类对象对应类所继承的父类

Class getSuperclass():返回该Class对象对应类的超类的Class对象

获取该类对象对应类的修饰符、所在包、类名等基本信息

int getModifiers():返回此类或接口的所有修饰符,修饰符由public、protected、private、final、static、abstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码,才可以获取真是的修饰符

Package getPackage():获取该类的包

String getName():以字符串形式返回此CLass对象所表示的类的简称

判断该类是否为接口、枚举、注解类型

boolean isAnnotation():返回此class对象是否表示一个注解类型

boolean isAnnotationPresent(ClassannotationClass):判断此Class对象是否使用类Annotation修饰

boolean isAnonymousClass():返回此class对象是否是一个匿名类

boolean isArray():返回此class对象是否表示一个数组类

boolean isEnum():返回此class对象是否表示一个枚举

boolean isInterface():返回此class对象是否表示一个接口

boolean isInstance(Object obj):判断obj是否是此class对象的实例,该方法可以完全代替instanceof操作符

public interface Colorable {
     public void value();
}
public class ClassInfo {
    
    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        Class cls=Colorable.class;
        System.out.println(cls.getMethod("value"));
        System.out.println(cls.isAnnotation());
        System.out.println(cls.isInterface());
    }

}

结果

public abstract void com.em.Colorable.value()
false
true
Java8中新增的方法参数反射

int getParameterCount():获取该构造器或方法的形参个数

Parameter[] getParameters():获取该构造器或方法的所有形参

getModifiers():获取修饰该形参的修饰符

String getName():获取形参名

Type getParameterizedType():获取带泛型的形参类型

ClassgetType():获取形参类型

boolean isNamePresent():该方法返回该类的class文件中是否包含了方法的形参名信息

boolean isVarArgs():该方法用于判断该参数是否为个数可变的形参

public class Test {
    public void getInfo(String str,Listlist){
        System.out.println("成功");
    }
}
public class ClassInfo {
    
    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        Class cls=Test.class;
        Method med=cls.getMethod("getInfo", String.class,List.class);
        System.out.println(med.getParameterCount());
        Parameter[] params=med.getParameters();
        System.out.println(params.length);
        for(Parameter par:params){
            System.out.println(par.getName());
            System.out.println(par.getType());
            System.out.println(par.getParameterizedType());
        }
    }

}

结果

2
2
arg0
class java.lang.String
class java.lang.String
arg1
interface java.util.List
java.util.List
反射生成对象

使用Class对象的newInstance()方法创建Class对象的实例,该方法要求要有默认构造器(比较常用)

先使用Class对象获取指定的Constructor对象,在调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例

反射调用方法

Object invoke(Object obj,Object...args):该方法中的obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参

public class Test {
    
    public Test(String str) {
        System.out.println(str);
    }
    public void getInfo(String str){
        System.out.println(str);
    }
}
public class ClassInfo {
    
    public static void main(String[] args) throws Exception {
        Class cls=Test.class;
        Constructorconstruct=cls.getConstructor(String.class);
        Test test=construct.newInstance("初始化");
        Method med=cls.getMethod("getInfo", String.class);
        med.invoke(test, "调用方法成功");
    }

}

结果

初始化
调用方法成功

接下来看官仔细看下面的栗子

public class Test {
    
    public Test(String str) {
        System.out.println(str);
    }
    //私有方法
    private void getInfo(String str){
        System.out.println(str);
    }
}
public class ClassInfo {
    
    public static void main(String[] args) throws Exception {
        Class cls=Test.class;
        Constructorconstruct=cls.getConstructor(String.class);
        Test test=construct.newInstance("初始化");
      //为啥使用这个方法呢?
        Method med=cls.getDeclaredMethod("getInfo", String.class);
      //为啥使用这个方法呢?
        med.setAccessible(true);
        med.invoke(test, "调用方法成功");
    }

}

结果

初始化
调用方法成功

setAccessible(boolean flag):将值设为true,指示该Method在使用是应该取消Java语言的访问权限检查

访问成员变量值

getXxx(Object obj):获取obj对象的该成员变量的值。此处的Xxx对应8种基本类型,如果该成员变量的类型是引用类型的,则去掉Xxx部分

setXxx(Object obj,Xxx val):将obj对象的该成员变量设置为val值。此处的Xxx对应8中基本类型,如果该成员变量的类型是引用类型,则取消set后面的Xxx

以上两个方法可以方法所有的成员变量,包括private的私有成员变量

public class Test {
    private int num;
    
    public Test(String str) {
        System.out.println(str);
    }
    private void getInfo(String str){
        System.out.println(str);
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    
}
public class ClassInfo {
    
    public static void main(String[] args) throws Exception {
        Class cls=Test.class;
        Constructorconstruct=cls.getConstructor(String.class);
        Test test=construct.newInstance("初始化");
        Method med=cls.getDeclaredMethod("getInfo", String.class);
        med.setAccessible(true);
        med.invoke(test, "调用方法成功");
        Field fld=cls.getDeclaredField("num");
        fld.setAccessible(true);
        fld.setInt(test, 12);
        System.out.println(fld.getInt(test));
    }

}

结果

初始化
调用方法成功
12
操作数组

java.lang.reflect包下有一个Array类,其可以动态创建数组

static Object newInstance(ClasscomponentType,int...length):创建一个具有指定的元素类型、指定维度的新数组

static xxx getXxx(Object array,int index):返回array数组中第index个元素。其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为get()

static void setXxx(Object array,int index,xxx val):将array数组中低index 个元素的值设为val,其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为set()

public class ArrayInfo {

    public static void main(String[] args) {
        Object arrays=Array.newInstance(String.class, 3);
        Array.set(arrays, 0, "第一个");
        Array.set(arrays, 1, "第二个");
        Array.set(arrays, 2, "第三个");
        System.out.println(Array.get(arrays, 2));
    }
}

更多内容可以关注微信公众号,或者访问AppZone网站

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64783.html

相关文章

  • Java笔记-反射机制(一)

    摘要:反射机制一结合官方通过编写的反射教程,复习一下反射的知识。反射的概念反射是一种在运行时获取以及修改应用行为的一种工具。因为反射需要动态的解析类的信息,相比于非反射使用的方式要慢。反射需要获取一定的运行时权限,在特定的安全环境下不一定存在。 Java反射机制(一) 结合Oracle官方通过JDK8编写的反射教程,复习一下反射的知识。结尾篇补一个小例子。 主要内容 这次博客的主要内容就是简...

    AWang 评论0 收藏0
  • 反射机制与原理笔记

    反射机制与原理笔记 声明 文章均为本人技术笔记,转载请注明出处https://segmentfault.com/u/yzwall 反射机制 反射:当程序无法获知对象类型时,在运行期间动态获取类的所有属性和方法,这种动态获取类信息和动态调用对象方法的功能称为反射机制;反射机制实现:Class类与java.lang.reflect类库一起实现机制,java.lang.reflect类库包含Field...

    fobnn 评论0 收藏0
  • java

    摘要:多线程编程这篇文章分析了多线程的优缺点,如何创建多线程,分享了线程安全和线程通信线程池等等一些知识。 中间件技术入门教程 中间件技术入门教程,本博客介绍了 ESB、MQ、JMS 的一些知识... SpringBoot 多数据源 SpringBoot 使用主从数据源 简易的后台管理权限设计 从零开始搭建自己权限管理框架 Docker 多步构建更小的 Java 镜像 Docker Jav...

    honhon 评论0 收藏0
  • java反射-类

    摘要:使用反射可以在运行时检视类。类名类修饰符等包信息超类所实现的接口构造函数方法属性注解类中附加了很多信息,你可以在获得一个完整列表。全限定名包含所有的包名。构造函数你可以访问类的构造函数,代码如下构造函数的详细教程在章节。 使用反射可以在运行时检视Java类。检视类通常是使用反射时所做的第一件事情。从类中可以获得下面的信息。 类名 类修饰符(private、public、synchro...

    FrancisSoung 评论0 收藏0
  • Java面试通关要点汇总集(基础篇之基本功,非原作者)

    摘要:面试通关要点汇总集部分解答说明如果你有幸能看到的话,本文整体框架来自阿里梁桂钊的博文,总结的非常不错。这样做的目的是对内部数据进行了不同级别的保护,防止错误的使用了对象的私有部分。被继承的类称为基类和父类或超类。 showImg(https://segmentfault.com/img/remote/1460000013442471?w=1280&h=819); Java面试通关要点汇...

    smallStone 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<