Java反射机制&反射方法解析&反射案例

java反射

在一些组件或者框架开发中声明,他们本身不知道要处理哪些类,

例如Jackson组件,

在web.xml中配置了哪些servlet类,Tomcat就要创建哪些类对象

在mybatis中,给了什么类型,mybatis就可以将结果封装映射对给定的类的对象中

以前已知类名的使用方式,可以看作是正向使用类

框架只需要写一套程序,就可以处理我们给他的任意类

只需要知道类的名字,通过名字动态获取类中的信息,被称为反向使用

反射

在运行状态中,对于任意一个类,都能够知道这个类,都能知道这个类的所有属性和方法

对于任意一个对象,都能调用它的任意一个方法

如何实现反射机制

java.lang.Class

Claas类的对象,表示当前正在运行中的类和接口

一旦class文件被加载到内存堆,就会为其创建一个class对象

Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本信息

获得Class的方法

要使用Class类的方法,必须先哦的该类的Class类的实例,获得Class类实例的常用方法有如下三种

1.Object类中存在getClass方法,可以通过对象获得Class实例

2.使用类名.class的方式,适用于通过类名获得Class实例的情况

3.Class类的静态方法 forName(Strin name)

//使用反射机制时,只知道类的名称(包名+类名)
String classname ="com.ffyc.javareflect.User";
//如何类的信息?可以通过Class类来获得类中的信息
//如何获得类的Class对象?
//方式1:
Class clazz1=Class.forName(classname);
System.out.println(clazz1);
//方式2:
Class clazz2 =User.class;
System.out.println(clazz1==clazz2);
//方式3
User user = new User();
Class clazz3 = user.getClass();
System.out.println(clazz1==clazz3);

获得Constructor类实例

Constructor实例通过Class实例获得,Class类中定义了如下方法

constructor getConstructor(Class …parameterTypes);

通过指定参数类型,返回构造方法实例

constructor类可以通过getXXX方法获得构造方法的基本信息

getName:返回构造方法的名字

除了可以获得构造方法的基本信息,还可创造实例

使用newInstance(Object… initargs)可以创造实例

String classname="com.ffyc.javareflect.User";
//1.通过类名 获得到类的Class对象
Class aClass=Class.forName(classname);
//2.通过类的class对象,创建对象
0bject object =aClass.newInstance();
System.out.println(object);
//获得类中的构造方法,通过构造方法api中的方法创建对象
Constructor constructor1 = aClass.getconstructor();//获得指定的公共构造方法
0bject objectl=constructor1.newInstance();
Constructor constructor2 =aClass.getConstructor(String.class,String.class);
Object object2 = constructor2.newInstance( "zhangsan","1111");
System.out.println(object1);
System.out.println(object2)

获得Field实例

通过Class中的方法可以获得Field实例

public Field getField(String name)通过指定Field名字,返回Field实例

注意Field的访问权限(类中的属性是否私有)

Field类将类的属性进行封装,可以获得属性的基本信息,属性的值,也可以对属性进行赋值

getName:返回属性名字

set:设置属性值

//1.通过类名 获得到类的Class对象
Class aClass=Class.forName(classname);
//2.通过类的Class对象,创建对象
0bject object =aClass.newInstance();
/获得类中成员变量//
Field accountField = aclass.getField("account");//获得指定名称的公共的成员变量
/*Field accountField = aclass.getDeclaredField("account");//获得指定名称的成员变量,包含私有的
accountField.setAccessible(true);
accountField.set(object,"admin");
System.out.println(object);*/

//模拟从数据库中查询到的数
HashMap<String,String> map = new HashMap<>();
map.put("account","admin");
map.put("password","1111");
Field[] declaredFields = aClass.getDeclaredFields(); //获得类中所有的成员变量
for(Field field :declaredFields){
field.setccessible(true);//允许访问操作私有属性,不建议
field.set(object,map.get(field.getName()));
}
System.out.println(object);

获得Method实例

Method实例都是通过Class类的方法获得

Method get Method(String name,Class…parameterTypes);

通过指定方法名,参数类型,返回一个Method实例

Method类将类中的方法进行封装,可以动态获得方法的信息,例如:

getName:获得方法名字

getParameterTypes:获得方法的参数类型

除了动态获得方法之外,Method还能动态调用某一个对象的具体方法

invoke(Object obj,Object… args);

使用obj调用该方法,参数为args

String classname ="com.ffyc.javareflect.User"
//String classname ="com.ffyc.javareflect.Car";
//1.通过类名 获得到类的class对象
Class aClass =Class.forName(classname);
//2.通过类的class对象,创建对象
Object object =aClass.newInstance();
//演示通过属性的get和set方法,对类中私有属性进行赋值取值操作
//模拟从数据库中查询到的数据
HashMap<String,String> map = new HashMap<>():
map.put("account","admin");
map.put("password","1111");
//先拿到类中所有的私有属性

Field[] declaredFields = aclass.getDeclaredFields();
for(Field field :declaredFields){
//根据属性名 生成set方法名称
String setmethod = "set"+field.getName().substring(0,1).touppercase(+ field,getName(),substring(1);
//通过class对象,获得对应的set方法对象
Method setmethodobj= aClass.getMethod(setmethod,field.getType());
//调用set方法
setmethodObj.invoke(object,map.get(field.getName()));

反射案例

自定义java对象转换Json工具类

public class JsonUtil {


    public static String objectToJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clazz = object.getClass();
        String json = "{";
        Field[] declaredFields =  clazz.getDeclaredFields();
        for(Field field : declaredFields){
            //生成get方法名字
            String getmethod = "get"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
            //获得方法对象
            Method method = clazz.getMethod(getmethod);
            //调用方法
            String  value =(String) method.invoke(object);
            //把属性和名字拼接成键值
            json += field.getName()+":"+value+",";
        }
        //去掉多余的逗号
        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.setAccount("admin");
        user.setPassword("111");

        Car car = new Car();
        car.setColor("红色");
        car.setName("宝马");

        System.out.println(JsonUtil.objectToJson(user));
    }
}

反射优缺点

优点

1.增加程序的灵活性,可以在运行过程中动态对类进行修改和操作

2,提高代码效率,比如动态代理

3.可以在运行时轻松获取任意一个类的方法,属性,并且还能通过反射进行动态调用

缺点

1.反射会涉及到动态类型的解析.导致性能要比非反射调用更低

2,使用反射技术通常要在一个没有安全限制的程序运行

3,反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的抽象性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值