Java反射机制

反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性。

项目开发中常见的使用反射的场景:

使用JDBC连接数据库、

Servlet在Web容器中加载和运行

Java反射机制提供了以下的功能:

1、在运行是获取类的修饰符,包名,类名,实现的接口,继承的父类

2、在运行时获取类的所有属性名,属性修饰符,属性类型

3、运行时获取所以方法,方法的返回值类型,方法名,方法参数值,方法参数类型

4、在运行时调用加载类的方法

通过Class类的对象可以获取类的属性、方法;生成类的实例;调用实例的方法、属性

反射:通过操控Class类的对象实现对类的操作;实现对对象的操作;

类的执行过程:

Java常用的反射类:

java.lang.Class:反射核心类,可获取类的属性,方法等信息,生成类的实例

Class类常用方法:

forName()--获取类型

newInstance()--构造对象,只能够调用 无参的构造函数,即默认的构造函数;要求被调用的构造函数是可见的,也即必须是 public类型的;

获取属性:

getFields()----所有可访问的公共字段

getDeclaredFields()----所有字段

getField(String name)----返回一个特定的公共Field对象

获取方法:

getMethods()----所有的公共方法,包括从超类和超接口继承的声明,返回的是方法数组;

getDeclaredMethods()----所有方法,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法,返回的是方法数组;

例如:
Method m[] = c.getDeclaredMethods();

getMethod(String name,Class[] parameterTypes)----返回一个方法对象

获取构造方法

getConstructor();

getDeclaredConstructor();

java.lang.reflect.Method:表示类的方法,可以用来获取类的方法信息或执行方法

getName()

invoke(object)

java.lang.reflect.Constructor:表示类的构造方法

setAccessible(boolean)

newInstance()--创建对象;可以根据传入的参数,调用 任意构造构造函数。在特定的情况下(即setAccessible(true))可以 调用私有的构造函数

java.lang.reflect.Field;表示类的成员变量,可用来获取和设置类的属性值

getName()

java.lang.Modifier.Modifier:(修饰符工具类) 用于判断和获取某个类、变量或方法的修饰符,将各个修饰符表示为相对应的整数,在源码中用16进制进行表示

Java反射机制是Java语言被视为准动态语言的关键特性

Java反射机制有优点也有缺点

可以通过下面代码了解反射机制

package cn.kgc.rfc;

import cn.kgc.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

/**
 * @Author:Adminstrator
 * @Date:2021
 * @Description:演示反射
 * className:类型全类名
 * paramsTypes:构造方法参数类型列表
 * params:构造方法参数值列表
 */
public class TestReflect<T> {
    //获取对象实例,创建新的对象实例方法(抛异常)
     public T getInstance(String className,Class[] paramsTypes,Object... params) throws Exception{
             Class<T> c = (Class<T>) Class.forName(className);
             Constructor<T> cons = c.getDeclaredConstructor(paramsTypes);
             cons.setAccessible(true);
             return(T) cons.newInstance(params);
     }
    //获取对象实例,创建新的对象实例方法(处理异常)
//    public T getInstance(String className,Class[] paramsTypes,Object... params) {
//        T t = null;
//        try {
//            Class<?> c =  Class.forName(className);
//            Constructor<?> cons = c.getDeclaredConstructor(paramsTypes);
//            cons.setAccessible(true);
//            Object o= cons.newInstance(params);
//            t=(T) o;
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        } catch (NoSuchMethodException e) {
//            e.printStackTrace();
//        } catch (InstantiationException e) {
//            e.printStackTrace();
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        } catch (InvocationTargetException e) {
//            e.printStackTrace();
//        }
//        return t;
//    }

    public static void main(String[] args) throws  Exception {
        //1、获取类型Class
        Class<Student> sc =Student.class;//使用.class获取
//        Student s=new Student();//由于s的类型不能确定具体的对象地址(可能是子类)
//        Class<? extends  Student> sc1 =s.getClass();//使用对象.getClass()
//        Class<?> sc2=Class.forName("cn.kgc.Student");
        //2、获取构造方法,并创建对象
//        Constructor<Student> c = sc.getConstructor(int.class,double.class);//获取公共的构造方法
        Constructor<Student> c = sc.getDeclaredConstructor(int.class,double.class,String.class);//获取构造方法
        c.setAccessible(true);//强行获取访问权限
        Student s = c.newInstance(1,1.5,"王思聪");//通过构造方法创建对象
        System.out.println(s);
//        System.out.println(s.getScore());
        System.out.println(s.getName());
        //3、使用对象调用方法
//        Method getStuNo = sc.getDeclaredMethod("getStuNo");//根据方法名获取方法
        Method method = sc.getDeclaredMethod("setStuNo", int.class);
        method.setAccessible(true);//强行获取访问权限
        Object o= method.invoke(s,15);
//        Object o = method.invoke(s);//执行对象方法
        System.out.println(o);
        System.out.println(s);
        //4.使用对象强行对属性赋值
        Field stuNo = sc.getDeclaredField("stuNo");
        stuNo.setAccessible(true);
        stuNo.set(s,18);
        System.out.println(s);
        //5、获取父类
        Class<? super Student> suc = sc.getSuperclass();//获取父类的Class对象
        Constructor<? super Student> cs = suc.getConstructor();//获取父类默认的构造方法
        Object object = cs.newInstance();
        System.out.println(object);
        Method think = suc.getMethod("think");
        think.invoke(object);
        //6.获取接口
        Class<?>[] i = sc.getInterfaces();
        Class<?> inter = i[0];//获取父接口
        TestReflect<Student> t=new TestReflect<>();
//        t.getInstance();
    }
}

总结:

反射优点:

运行期类型的判断,动态类加载;

提高了程序的灵活性、扩展性,降低耦合性;

提高自适应能力,无需提前硬编码目标类;

缺点:

性能问题,安全问题,内部暴露;

基于反射生成类的实例并调用方法步骤:

Class类--getConstructor(Class[] parameterTypes)

Constructor类--newInstance(Object[] initargs)

Method类--invoke(Object obj,Object...args)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值