初涉反射机制

本文主要是针对初学者首先是对反射概念的描述,然后介绍反射中关键类Class相关介绍与代码演示,最后介绍反射的应用案例。     

1. 反射机制概念

如果在正常的情况下,如果要使用一个类,则需下列步骤:

1)使用import导入类所在的包(类:java.lang.Class)

2)通过“对象.方法()”调用类中方法

3)产生对象可以使用“对象.属性”进行类中属性的调用

4)通过关键字new进行类对象实例化

5)明确使用类名称或接口名称定义对象

而反射的过程呢?,不需要有明确类型的对象,所有的对象使用Object表示。

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

获取字节码对象的方式有以下几种方式:

1)Class clazz1 = Class.forName("全限定类名");  //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。

2)Class clazz2  = Student.class;    //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。

3)Class clazz3 = s.getClass();    //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段 

有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。

2. CLASS类API信息

2.1 获取实例对象


注意:Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象。


通过newInstance方法获取实例对象。代码如下:

class Demo1{
    Demo1(){
        System.out.println("反射调用无参构造方法");
    }
}
public class Main {
    public static  void main(String []args) throws  Exception {
       Class<?> demoCls = Class.forName("reflexDemo.Demo1");
       Object object = demoCls.newInstance();
    }
}

首先获取全部的构造函数,然后初始化对象。代码如下:

class Demo1{
    Demo1(String para){
        System.out.println("反射调用有1个参构造方法 string");
    }

    Demo1(String para,int a){
        System.out.println("反射调用有2个参构造方法string int");
    }

    public  Demo1(String para,String a){
        System.out.println("反射调用有2个参构造方法,string string");
    }
}
public class Main {
    public static  void main(String []args) throws  Exception {
        Class<?> demoCls = Class.forName("reflexDemo.Demo1");

        //getConstructors()方法只能获取反射类的公共构造函数(public)
        Constructor constructors[] =demoCls.getConstructors();
        System.out.println("getConstructors方法获取的方法数:"+constructors.length);

        //getDeclaredConstructors()方法获取所有的构造函数
        Constructor  declaredConstructors[] = demoCls.getDeclaredConstructors();
        System.out.println("getDeclaredConstructors()方法获取的方法数:"+declaredConstructors.length);


        System.out.println(demoCls.getSimpleName()+"的方法有如下几个");
        for (int i=0;i<declaredConstructors.length;i++){
            Constructor constructor = declaredConstructors[i];
            Class[] paraTypes = constructor.getParameterTypes();
            System.out.print(constructor.getName()+"(");
            for (int j = 0; j < paraTypes.length; j++) {
                Class paraType = paraTypes[j];
                if (j==(paraTypes.length-1)){
                    System.out.print(""+paraType.getSimpleName()+")");
                    break;
                }
                System.out.print(""+paraType.getSimpleName()+",");
            }
            System.out.println();
        }

        Constructor constructor = demoCls.getDeclaredConstructor(String.class,int.class);

        Demo1 demo1 = (Demo1) constructor.newInstance("wxt",123456);
    }
}

        //代码效果:getConstructors方法获取的方法数:1
        //getDeclaredConstructors()方法获取的方法数:3
        //Demo1的方法有如下几个
        //reflexDemo.Demo1(String)
        //reflexDemo.Demo1(String,int)
        //reflexDemo.Demo1(String,String)
        //反射调用有2个参构造方法string int

2.2 获取方法和成员变量并使用 


注意:获取任何信息的时候,类中的API都有两种选择,分别是带有Declared与不带此关键字的方法,区别在于带有的可以获取所有的变量或者方法。对私有的变量赋值需先调用setAccessible(true)设置访问权限,对公有变量不需要此操作。


 

代码如下:

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

class Demo1{

    public String para1;
    public  int para2;

    private int privatePara1;
    private String privatePara2;

    Demo1(String para){
        System.out.println("反射调用有1个参构造方法 string");
    }

    public Demo1(int privatePara1, String privatePara2) {
        this.privatePara1 = privatePara1;
        this.privatePara2 = privatePara2;
    }

    @Override
    public String toString() {
        return "para1:"+para1 +",para2:"+para2+
                ",privatePara1:"+privatePara1+",privatePara2:"+privatePara2;
    }
}
public class Main {
    public static  void main(String []args) throws  Exception {
        Class<?> demoCls = Class.forName("reflexDemo.Demo1");

        //getConstructors()方法只能获取反射类的公共构造函数(public)
        Constructor constructors[] =demoCls.getConstructors();
        System.out.println("getConstructors方法获取的方法数:"+constructors.length);

        //getDeclaredConstructors()方法获取所有的构造函数
        Constructor  declaredConstructors[] = demoCls.getDeclaredConstructors();
        System.out.println("getDeclaredConstructors()方法获取的方法数:"+declaredConstructors.length);


        System.out.println(demoCls.getSimpleName()+"的方法有如下几个");
        for (int i=0;i<declaredConstructors.length;i++){
            Constructor constructor = declaredConstructors[i];
            Class[] paraTypes = constructor.getParameterTypes();
            System.out.print(constructor.getName()+"(");
            for (int j = 0; j < paraTypes.length; j++) {
                Class paraType = paraTypes[j];
                if (j==(paraTypes.length-1)){
                    System.out.print(""+paraType.getSimpleName()+")");
                    break;
                }
                System.out.print(""+paraType.getSimpleName()+",");
            }
            System.out.println();
        }

        //getFields()方法获取所有的公共变量(public);
        Field fields[] = demoCls.getFields();
        System.out.println(demoCls.getSimpleName()+"类有"+fields.length+"公共变量");

        //getDeclaredFields()获取所有的变量
        Field declaredFields[] = demoCls.getDeclaredFields();
        System.out.println(demoCls.getSimpleName()+"类有"+declaredFields.length+"个变量");

        for (int i = 0; i <declaredFields.length ; i++) {
            Field field = declaredFields[i];
            System.out.println(Modifier.toString(field.getModifiers())+
                    " "+ field.getType().getSimpleName() +" "+field.getName());
        }

        Constructor constructor = demoCls.getDeclaredConstructor(int.class,String.class);
        Demo1 demo1 = (Demo1) constructor.newInstance(123,"wxt");

        System.out.println("反射前得到的实例对象是:"+demo1.toString());

        Field publicField = demoCls.getDeclaredField("para1");
        publicField.set(demo1,"liming");
        System.out.println("反射后,对公有变量赋值后得到的实例对象是:"+demo1.toString());


        Field privateFiled = demoCls.getDeclaredField("privatePara1");
        privateFiled.setAccessible(true);
        privateFiled.set(demo1,1);
        System.out.println("反射后,对私有变量赋值后得到的实例对象是:"+demo1.toString());

    }
}

代码效果:

3. 反射机制的应用举例


注意:只写了一个用例,后续还会补充。感谢!


3.1. 在泛型为int的arryaList集合中存放一个String类型的对象(原理:合中的泛型只在编译器有效,而到了运行期,泛型则会失效

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class reflexExample {
    public static void main(String []args) throws Exception {
        List<Integer> integerList = new ArrayList<>();

        integerList.add(123);
        integerList.add(23);
        integerList.add(44);

        Class listCls = integerList.getClass();
        Method method = listCls.getDeclaredMethod("add", Object.class);
        method.invoke(integerList,"1add");

        System.out.println(integerList);
    }
}

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值