java反射

Java反射机制允许程序在运行时动态获取类的信息并创建对象,调用方法和访问属性。通过Class对象可以获取类的构造方法、方法和属性,Constructor和Method类分别封装了构造方法和方法的信息,Field类则封装了属性信息。反射在框架开发、动态代理等方面有广泛应用,但其可能导致性能下降和安全性问题。
摘要由CSDN通过智能技术生成

1.引入案例支持

(1)配置servlet

    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>com.ffyc.dormms.servlet.LoginServlet</servlet-class>
    </servlet>

服务器启动时,就会创建该类的对象,使用的就是反射机制创建该类的对象

(2)mybatis

 resultType="com.ffyc.mybatispro.model.Admin"

配置了哪个类,就创建出该类的对象

(3)加载mysql驱动类

 Class.forName("com.mysql.cj.jdbc.Driver"); 

2.什么是Java反射?

 回忆一下之前如何使用一个Java类?

    已知一个类的类名、以及、类中的方法属性、构造方法等
    使用new关键字创建对象
    使用对象调用方法或属性

为什么用反射机制?

   就是像框架一样,可以写一套机制,来处理任意的类,就使得程序更急灵活,
   以不变应万变.

什么是反射机制 ?

       仅知道类的地址(字符串).(  com.mysql.cj.jdbc.Driver )类地址
       就需要在运行时,可以动态的获取任意一个类的信息,可以创建任意类的对象,调用任意对象中的方法,属性,这种动态获取类信息的功能,称为java反射机制.  称为反向使用类

Java反射的概念

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

Java反射的作用

动态获取类的信息

Java反射相关API

Class 类型(在java.lang包中):表示一个正在运行中的类或接口

       一旦一个类被加载到内存中去,都会为该类创建一个对象,可以通过该对象获取类中的信息.

       要使用反射机制动态获取,创建对象,首先就是要获得类的class对象.

package com.ffyc.javareflect.model;

public class User {
    private int id;
    private String account;
    private String password;

    public User() {
        System.out.println("user无参构造");
    }

    private User(int id, String account, String password) {
        this.id = id;
        this.account = account;
        this.password = password;
        System.out.println("有3个参构造方法");
    }
    public User(int id, String account) {
        this.id = id;
        this.account = account;
        System.out.println("有2个参构造方法");
    }
    public int getId() {
        return id;
    }

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

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
package com.ffyc.javareflect.model;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
         //new User(); 正向使用
        /*
           反射的起点,就是要获得类的Class对象,获取类的信息
           获取类的class对象方式有3种,无论类创建了多少个对象,一个类的class对象只有一个
         */
        Class c1 = User.class;
        System.out.println(c1);

        Class c2 = new User().getClass();
        System.out.println(c2);
        //根据类的地址加载类,并获得该类的class对象
        String className = "com.ffyc.javareflect.model.User";
        Class c3 = Class.forName(className);
        System.out.println(c3);

    }
}

Constructor 构造方法

package com.ffyc.javareflect.model;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        /*
        演示通过Class类的对象获取构造方法
        forName();
        Class类中 c.newInstance(); 也是创建对象的一种方式
        Constructor类中constructor.newInstance();
         */
        String className = "com.ffyc.javareflect.model.User";
        Class c = Class.forName(className);
        //Object object = c.newInstance();

        //获取类中公共的指定的构造方法 用Constructor类的对象来表示构造方法的信息
        // Constructor constructor = c.getConstructor();
        // Object obj = constructor.newInstance();

        //Constructor constructor = c.getConstructor(int.class,String.class,String.class );
        //System.out.println(Arrays.toString(constructor.getParameters()));

        //获取私有的构造方法,打破了隐蔽性
        Constructor constructor = c.getDeclaredConstructor(int.class,String.class,String.class);
        constructor.setAccessible(true);//开权限
        constructor.newInstance(1,"jim","111");

        //获得类中所有的构造方法
        Constructor[] constructors = c.getDeclaredConstructors();
        for (Constructor constructor1 : constructors){
            if (constructor1.isAccessible()){
                constructor1.setAccessible(true);
            }else{

            }
        }
    }
}

Method 方法

Method类将类中的方法进行封装,可以动态获得方法的信息,例如
getName:获得方法名字
getParameterTypes:获得方法参数类型
除了动态获得方法信息外,Method还能动态调用某一个对象的具体方法
invoke(Object obj, Object... args) :使用obj调用该方法,参数为args
Field 属性
Field类将类的属性进行封装,可以获得属性的基本信息、属性的值,也 可以对属性进行赋值.
getName:返回属性的名字
set:设置属性值
package com.ffyc.javareflect.model;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String className = "com.ffyc.javareflect.model.User";
        Class c = Class.forName(className);
        Object obj = c.newInstance();//创建对象

        //c.getField("account");
        Field[] fields  = c.getDeclaredFields();//可以获取类中的所有属性
        for (Field f : fields){
            System.out.println(f.getName());

            System.out.println("set"+f.getName().substring(0,1).toUpperCase()+f.getName().substring(1));
            //通过反射机制获取类中的方法
            Method method = c.getMethod("set"+f.getName().substring(0,1).toUpperCase()+f.getName().substring(1),f.getType());
            method.invoke(obj,"1111");

        }
    }
}

小案例

package com.ffyc.javareflect.model;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyJson {
     //简单反射案例
    public  static String objToJson(Object obj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        String json = "{";
         Class c = obj.getClass();
         Field[] fs = c.getDeclaredFields();//获取到任意一个类中的所有属性
        for (Field f:fs){
            String name = f.getName();
            json+=name+":";
            Method m = c.getMethod("get"+name.substring(0,1).toUpperCase()+name.substring(1));//动态构成get方法名称,并获取到get方法
            Object value = m.invoke(obj);//调用了属性的get方法
            json +=value+",";
        }
        json = json.substring(0,json.length()-1);
        json+="}";
        return json;//{id:值,account:值}
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

        User user = new User();
        user.setId(10);
        user.setAccount("admin");
        user.setPassword("111");
        String json = MyJson.objToJson(user);
        System.out.println(json);

    }

}

反射优缺点

优点
● 1. 增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作
● 2. 提高代码的复用率,比如动态代理
● 3. 可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态调用
缺点
● 1. 反射会涉及到动态类型的解析,导致性能要比非反射调用更低
● 2. 使用反射技术通常要在一个没有安全限制的程序运行 .
● 3. 反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的抽象性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值