java 反射——使用详解

网上对于java反射的解释已经很多了,很多官方的语言我们并不能很好的理解。

我在这里说的通俗些,java反射的作用就是让我们从java虚拟机里面生成的class来进行反序列化得到这个类的实例。

那么它的用处就更加多了,例如android中startyactivity()方法传入的Intent对象。在内部其实用到的就是java的反射。

首先来写一个测试类 ReflectBean

/**
 * 反射实体类
 */
public class ReflectBean implements IReflect {

    @RetentionTest(hello = "hai", world = "sb")
    private int id;

    private String[] names;

    private ArrayList<Double> doubles;

    public int getId() {
        return id;
    }

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

    @Override
    public void onButtonClick(View v) {

    }

    @Override
    public void onCheckClick() {

    }

    public enum reflectEnum {
        ONE,
        TOW,
        THREE;
    }

    public ReflectBean() {

    }

    public ReflectBean(String aaa) {

    }

    public ReflectBean(String[] aaa) {

    }

    public void reflecteTest() {

    }

    @RetentionTest(world = "hahahhaa")
    public String reflectAdd(String aaa) {
        Log.i("test", "reflectAdd方法调用:" + aaa);
        return aaa;
    }
}
/**
 * 测试接口
 */
public interface IReflect {
    void onButtonClick(View v);

    void onCheckClick();
}

好。接下来我就来讲述一下java反射的使用。

首相定义一个ReflectMobel类

1,反射一个类的三种方法

private static final String className = "com.android.ui.reflect.ReflectBean";
             /**
             * 反射一个类有三种方法
             * */
            //1
            Class<ReflectBean> class1 = ReflectBean.class;
            Log.i("test", class1.getName());
            //2
            Class class2 = Class.forName(className);

            //3
            ReflectBean reflectBean = new ReflectBean();
            Class class3 = reflectBean1.getClass();

2,获得类加载器

Log.i("test", "类加载器  " + class1.getClass().getClassLoader().getClass().getName());

其实在java中有三种类类加载器。

1,Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。

2,Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类。

3,AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。

3,获取class对应的java对象

            /**
             * 获取对象
             * 调用了ReflectMobel的无参数构造方法.即对象
             * */
            Object object = class1.newInstance();
            ReflectBean reflectBean = class1.newInstance();
            if (!class1.isInstance(reflectBean)) return;//判断某个实例是否属于这个类

4,获取class中的方法对象

/**
             * 获得类中的一个方法
             */
            //有参数
            Method method = class1.getDeclaredMethod("reflectAdd", String.class);
            //无参数
            Method method1 = class1.getDeclaredMethod("reflecteTest");
            //多个参数
            Method method2 = class1.getDeclaredMethod("reflecteTest", new Class[]{String.class,int.class});
            Log.i("test", "reflectAdd方法:" + method.getName() + method1.getName());

5,获取class标记的注解

 if (method.isAnnotationPresent(RetentionTest.class)) {//判断该类有没有标记这个注解
                RetentionTest retentionTest = method.getAnnotation(RetentionTest.class);
                Log.i("test", "reflectAdd标记的注解:" + retentionTest.world());
            }

6,调用方法

            /**
             * 调用该方法
             * 如果该方法没有参数,则传入new Object[]{}
             * 如果该方法有参数,则传入参数
             * 返回结果为该方法的返回结果
             * */
            String aaa = (String) method.invoke(reflectBean, "bbbbbb");
            Log.i("test", "reflectAdd方法的返回结果:" + aaa);
            method1.invoke(reflectBean);//无参方法
            method2.invoke(reflectBean, new Object[]{});//无参方法

7,获取类的信息

//类的修饰符
            String classXiushifu = Modifier.toString(class1.getModifiers());
            Log.i("test", "类的修饰符:" + classXiushifu);
            //类的简单名字,指不带包路径的名字
            String classSimpleName = class1.getSimpleName();
            Log.i("test", "类的简单名字,指不带包路径的名字:" + classSimpleName);
            //类的带包路径的名字
            String className = class1.getName();
            Log.i("test", "类的带包路径的名字:" + className);

8,获得全部的构造函数

//取得全部的构造函数
            Constructor<?> cons[] = class1.getConstructors();
            Constructor constructor = class1.getConstructor();//无参构造函数
            Constructor constructor1 = class1.getConstructor(String.class);//带String参数的构造函数
            Constructor constructor2 = class1.getConstructor(new Class[]{String.class, double.class});//带String参数的构造函数
            Log.i("test", "类的构造函数:" + constructor1.getName());
            for (int i = 0; i < cons.length; i++) {
                Log.i("test", "类的构造函数:" + cons[i].getName());
            }

9,获取类中所有的接口

 //保存所有的接口
            Class<?> intes[] = class1.getInterfaces();
            for (int i = 0; i < intes.length; i++) {
                Log.i("test", "类的接口:" + intes[i].getName());
            }

10,获得当前类的父类

//取得父类
            Class<?> temp = class1.getSuperclass();

11,获取类中的属性,获取全部属性

            /**
             * 获取属性
             * 分为所有的属性和指定的属性
             * 1,获得所有属性
             * */
            //获取所有的属性
            Field[] fields = class1.getDeclaredFields();
            for (Field field : fields) {
                Log.i("test", "获得属性的修饰符:" + Modifier.toString(field.getModifiers()));//获得属性的修饰符,例如public,static等等
                Log.i("test", "属性的类型的名字:" + field.getType().getSimpleName());//属性的类型的名字
                Log.i("test", "属性的名字:" + field.getName());//属性的名字
            }

12,获取类中的属性,获取指定属性

/**
             * 2,获取特定的属性
             * */
            Field idF = class1.getDeclaredField("id");
            idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。设置可访问性
            idF.set(reflectBean, 111);
            Log.i("test", "属性的名字:" + idF.getName());//id的值
            Log.i("test", "属性的值:" + idF.get(reflectBean).toString());//string 值
            Field stringsF = class1.getDeclaredField("names");
            stringsF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。设置可访问性
            stringsF.set(reflectBean, new String[]{"aaa", "bbb", "ccc"});
            String[] aaas = (String[]) stringsF.get(reflectBean);
            Log.i("test", "属性的名字:" + stringsF.getName());//string 值
            Log.i("test", "属性的值:" + aaas[0]);//string 值
            Log.i("test", "属性的值:" + Array.get(aaas, 1));//string 值
            Log.i("test", "数组长度  " + Array.getLength(aaas));
            Log.i("test", "数组的第一个元素: " + Array.get(aaas, 0));

注意事项:

当我们用构造器获得类构造方法的时候,如下:

//2、根据构造器参数类型获取相应的构造器对象
        Constructor csr = cls.getConstructor(String[].class);
        //3、创建实体对象
        Object entity = csr.newInstance(new String[]{}); 

如果构造方法中需要传入且只传入一个数组的时候会报错。

那么,错误的原因是什么呢?

由于类构造方法(String strs[])只有一个String数组的参数所以这是编译器会把字符串数组当作一个可变长度参数传 给对象strs,而我们取得方法只有一个参数,所以就会出现wrong number of arguments的异常,我们只要把字符串数组强制转换为一 个Object对象就可以解决这个异常了, 。

正确的写法是:

//2、根据构造器参数类型获取相应的构造器对象
        Constructor csr = cls.getConstructor(String[].class);   

        String str[]={"111","123"};
        //3、创建实体对象
        Student entity = (Student)csr.newInstance((Object)str);  

还有一个细节需要注意

//有参数
            Method method = class1.getDeclaredMethod("reflectAdd", String.class);
            //无参数
            Method method1 = class1.getDeclaredMethod("reflecteTest");
            //多个参数
            Method method2 = class1.getDeclaredMethod("reflecteTest", new Class[]{String.class, int.class});
            String aaa = (String) method.invoke(reflectBean, "bbbbbb");

当我们需要去调用某个类中的方法的时候,用invoke去调用方法调用的只有公有的(public),如果调用private类型的会报错。

java反射的常用方法就使这些。我们可以根据反射的特性去做很多事情。例如和注解一起使用能够让自己的程序更加的灵活。

java反射的实际使用场景还需要根据自己的程序使用情况而定。

时间: 2024-10-07 00:13:06

java 反射——使用详解的相关文章

Java反射机制详解

Java反射机制详解 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制. 1.关于Class 1.Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性    2.对象照镜子后(反射)可以得到的信息:某个类的数据成员名.方法和构造器.某个类到底实现

Java 反射机制详解(下)

续:Java 反射机制详解(上) 三.怎么使用反射 想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象. 获取字节码文件对象的三种方式.  1.Class class1= Class.forName("全限定类名"); //通过Class类中的静态方法forName,

【转载】Java反射机制详解

转自:http://baike.xsoftlab.net/view/209.html#3_8 1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2反射机制能做什么 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类: 在运行时构造任意一个类的对象: 在运行时判断任意一个类所具有的成员变量和方法: 在运行时调用任意一个

java反射机制详解 及 Method.invoke解释 getMethod

JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理.1. 得到某个对象的属性 public Object getProperty(Obje

java反射机制详解 及 Method.invoke解释

JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在运行时判断任意一个类所具有的成员变量和方法:在运行时调用任意一个对象的方法:生成动态代理.1. 得到某个对象的属性 Java代码   public Object getProp

Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合.我们还可以对某对象所需要的其它对象进 行注入,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制, Spring还充当了工厂的角色,我们不需要自己建立工厂类.S

Java反射机制详解(1) -反射定义

---恢复内容开始--- 首先,我们在开始前提出一个问题: 1.在运行时,对于一个java类,能否知道属性和方法:能否去调用它的任意方法? 答案是肯定的. 本节所有目录如下: 什么是JAVA的反射机制 JDK中提供的Reflection API JAVA反射机制提供了什么功能 获取类的Class对象 获取类的Fields 获取类的Method 获取类的Constructor 新建类的实例        Class<T>的函数newInstance        通过Constructor对象的

java反射机制详解和应用

1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2反射机制能做什么 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类: 在运行时构造任意一个类的对象: 在运行时判断任意一个类所具有的成员变量和方法: 在运行时调用任意一个对象的方法: 生成动态代理. 3反射机制的相关API 通过一个对象获得完整的包名和类名 pub

[转]Java反射机制详解

目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为Integer的ArrayList中存放一个String类型的对象. ·通过反射取得并修改数