Java反射

为什么需要java反射?

        在编写代码的时候,当你仅仅知道一个类名,并且想要动态得到类的定义消息,包含的方法和属性等的时候,我们就需要通过java反射来获得这些.由于像框架,tomcat,或者一些其他的组件(jackson 对象-->json),事先不知道是哪个类,只能根据配置文件中配置的类的地址决定要创建并且操作哪一个类.

Java反射的概念

        java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,并且对于任意一个对象,都可以调用他的任意一个方法和属性.这种动态的获得类中的方法和属性的操作就叫做java反射.那么我们如何在只有一个类名的情况下获得这个类?

Java反射的实例

首先我们应该知道java反射获得对象的原理,首先通过forName("java类的名称")来获得该类的class类的对象,之后该类的class类会到达内存的方法区,注意的是任意类的class类只有一个,无论创建几次,都是同一个class类.之后可以通过newInstance()方法来获得该类的对象.代码如下:

Class userClass=Class.forName("com.ffyc.javaerflect.Admin");
        Constructor constructor =userClass.getConstructor();
        Object userObj = constructor.newInstance();

接下来我会为大家解释反射中常用的几种方法:

  • getConstructor()和getDeclaredConstructor()方法:
Class userClass=Class.forName("com.ffyc.javaerflect.User");
//        Constructor constructor=userClass.getConstructor();//获取指定参数个数的公共构造方法
//        Constructor constructor=userClass.getConstructor(int.class);//获取指定参数个数的公共构造方法
        /*Constructor constructor=userClass.getConstructor(int.class,String.class);//获取指定参数个数的公共构造方法
        Constructor[] constructors=userClass.getConstructors();
        Object obj = constructor.newInstance(10,"134"); //创建一个对象,通过Constructor.newInstance()方法来创建对象*/

        /*Constructor declareConstructor = userClass.getDeclaredConstructor(int.class,String.class);
        //默认情况下,私有成员不能访问,可以设置允许访问私有成员
            declareConstructor.setAccessible(true);
        Object obj = declareConstructor.newInstance(10,"134");*/

        Constructor[] declareConstructors = userClass.getDeclaredConstructors();//获取类中所有的构造方法,包括私有的

两个方法如果不传参数的话,就会自动调用无参构造方法,而在框架中,框架在通过反射获得类的对象的时候,就是默认调用无参构造方法,所以当我们定义了有参构造方法后,必须定义一个无参构造方法来满足后面框架的需求.如果想要获得有参的构造方法,我们需要在调用方法的时候在参数里写入所需的参数类型的class类.

两个方法在功能上是一致的,都是为了获得类的构造方法,但是区别是getConstructor只能获得该类中的公共方法,而getDeclaredConstructor看可以获得该类中的所有方法,包含私有方法.

  • getFields()和getDeclaredFields()方法
HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put("account","11111");
        hashMap.put("password","1877124");
        Class userClass=Class.forName("com.ffyc.javaerflect.Admin");
        Constructor constructor =userClass.getConstructor();
        Object userObj = constructor.newInstance();
//        Field filed = userClass.getDeclaredField("id");
        Field[] fields = userClass.getDeclaredFields();
        for (Field f:fields) {
//            System.out.println(f.getName());
            f.setAccessible(true);
            f.set(userObj,hashMap.get(f.getName()));
        }
        System.out.println(userObj);

两个方法都是用于获取类的属性,但是getFields()只能获得该类的所有公共属性,但是getDeclaredFields()可以获得该类中的所有属性(包括私有属性).

  • getMethod()和getDeclaredMethods()方法
Class userClass = Class.forName("com.ffyc.javaerflect.User");
        Constructor constructor = userClass.getConstructor();
        Object objUser = constructor.newInstance();
        Method method1 = userClass.getDeclaredMethod("eat",String.class);
        method1.invoke(objUser,"123");

二者共同点是在获取方法的时候,可以通过在getMthods()参数中写入方法名称和参数类型的class类,从而在后面的invoke中运行.

二者的不同点是getMethod可以获得父类中可访问到的方法和本类中的所有公共方法,而getDeclaredMethods可以访问到本类中的所有方法(包括私有方法).

最后我们可以通过一个实例来验证框架中前后端交互中的数据模板:

public class JsonUtil {
    public static  String objectTJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String json= "{";
        Class classobj = object.getClass();
        Field[] fields = classobj.getFields();//获取所有的属性
        for (Field f:fields) {
            //循环属性  拼接属性的get方法名称
            String get = "get"+String.valueOf(f.getName().charAt(0)).toUpperCase()+f.getName().substring(1);
            Method method = classobj.getMethod(get);
            json+=f.getName()+":"+method.invoke(classobj)+",";//调用get方法获得返回值
        }
        json=json.substring(0,json.length()-1);
        json+="}";
        return json;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        User user = new User();
        user.setId("100");
        user.setName("tom");

        Admin admin = new Admin();
        admin.setAccount("1111");
        admin.setPassword("222200");

        System.out.println(objectTJson(user));
        System.out.println(objectTJson(admin));
    }
}

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值