反射---Java

目录

反射是什么

作用一:检查类的结构:通过反射可以看到,某个类的内部字段(field)、方法(method)、构造方法(constructor)

作用二:运行时分析对象:可以查看在编译时还不知道的值,在debug时可以使用到

作用三:调用任意的方法和构造器:类似的实现了C/C++的指针的功能

作用四:编写泛型数组代码

在Spring设计中用到反射

在mybatis中使用到的反射


反射是什么

Java核心技术卷Ⅰ:能够分析类能力的程序称之为反射,个人理解包括检查类的结构覆盖类的字段值或方法

作用:在运行时分析类的能力、在运行时检查对象、实现泛型数组操作代码、利用method对象

理解class类:Java运行时系统始终为所有的对象维护一个运行时类型标识,这个信息会跟踪每个对象所属的类,虚拟机利用这个信息选择要执行的正确方法

作用一:检查类的结构:通过反射可以看到,某个类的内部字段(field)、方法(method)、构造方法(constructor)
此处使用的方法解释
getField()返回值(class数组),作用(返回类的及其超类的公共字段)
getDeclaredFields()返回值(class数组),作用(返回这个类的全部字段,如果没有或者类描述的是一个基本类型或数组类型,那么其长度为0)
getMethods()返回值(Method数组),作用(返回类的及其超类继承过来的方法)
getDeclaredMethods()返回值(Method数组),作用(返回这个类/接口的全部方法,不包括继承过来的方法)
getConstructor()返回值(Constructor数组),作用(返回这个类的全部公共构造器)
getDeclaredConstructor()返回值(Constructor数组),作用(返回这个类的全部构造器)
getPackageName()返回数组类型,返回元素所属的包
getModifiers()返回值(int) 描述构造器、方法、字段的修饰符
getParameterTypes()返回值(class数组)作用(方法/构造器参数的类型)
getReturnType()返回值(class对象)作用(方法的返回值类型)
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
​
/**
 * @author Rui
 * @description 反射检查某个类的结构
 * @create 2024/8/11 0:28
 */
public class ReflectionTest {
    private static final int PI = 3;
    public static void main(String[] args) throws ReflectiveOperationException {
        String name;
        name = "java.lang.Double";
        Class clazz = Class.forName(name);
        //构造器
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            //打印构造器方法
            String modifiers = Modifier.toString(constructor.getModifiers());
            System.out.print("\n构造器名字:" + modifiers + " " + name + "  参数 (");
            //打印参数
            Class[] parameterTypes = constructor.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + ",");
            }
            System.out.print(")");
        }
        System.out.println("\n----------------------");
​
        //方法
        Method[] methods = clazz.getDeclaredMethods();
        System.out.println("方法:");
        for (Method method : methods) {
            //返回值类型
            Class retType = method.getReturnType();
            //方法的权限
            String modifiers = Modifier.toString(method.getModifiers());
            //打印参数
            Class[] parameterTypes = method.getParameterTypes();
            System.out.print(modifiers + " " + retType + " " + method.getName()+"(");
            for (Class parameterType : parameterTypes) {
                System.out.print(parameterType.getName() + ",");
            }
            System.out.println(")");
        }
        System.out.println("----------------------");
​
        //字段
        Field[] fields = clazz.getDeclaredFields();
        System.out.println("字段:");
        for (Field field : fields) {
            //字段的权限
            String modifiers = Modifier.toString(field.getModifiers());
            //字段的类型
            Class type = field.getType();
            //字段的名字
            String name1 = field.getName();
            System.out.println(modifiers + " " + type.getName() + " " + name1);
        }
​
    }
}
构造器名字:public java.lang.Double  参数 (double,)
构造器名字:public java.lang.Double  参数 (java.lang.String,)
----------------------
方法:
public boolean equals(java.lang.Object,)
public static class java.lang.String toString(double,)
public class java.lang.String toString()
public int hashCode()
public static int hashCode(double,)
public static double min(double,double,)
public static double max(double,double,)
public static native long doubleToRawLongBits(double,)
public static long doubleToLongBits(double,)
public static native double longBitsToDouble(long,)
public volatile int compareTo(java.lang.Object,)
public int compareTo(java.lang.Double,)
public byte byteValue()
public short shortValue()
public int intValue()
public long longValue()
public float floatValue()
public double doubleValue()
public static class java.lang.Double valueOf(java.lang.String,)
public static class java.lang.Double valueOf(double,)
public static class java.lang.String toHexString(double,)
public static int compare(double,double,)
public static boolean isNaN(double,)
public boolean isNaN()
public static boolean isFinite(double,)
public static boolean isInfinite(double,)
public boolean isInfinite()
public static double sum(double,double,)
public static double parseDouble(java.lang.String,)
----------------------
字段:
public static final double POSITIVE_INFINITY
public static final double NEGATIVE_INFINITY
public static final double NaN
public static final double MAX_VALUE
public static final double MIN_NORMAL
public static final double MIN_VALUE
public static final int MAX_EXPONENT
public static final int MIN_EXPONENT
public static final int SIZE
public static final int BYTES
public static final java.lang.Class TYPE
private final double value
private static final long serialVersionUID
​
进程已结束,退出代码0
作用二:运行时分析对象:可以查看在编译时还不知道的值,在debug时可以使用到
代码解释
Object value = f.get (obj)obj是个类,f66是类里面的某个字段名,通过该方法可以返回该字段值但是是一个对象的形式
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
​
/**
 * @author Rui
 * @description 复写通用的ToString()方法
 * @create 2024/8/11 16:07
 */
public class ObjectAnalyzer {
    private ArrayList<Object> visvit = new ArrayList<>();
​
    public String toString(Object obj) throws ReflectiveOperationException{
        if(obj == null) return "null";
        if(visvit.contains(obj)) return "...";
        visvit.add(obj);
        Class cl = obj.getClass();
        if(cl == String.class) return (String)obj;
        if(cl.isArray()){
            String r = cl.getComponentType() + "[]{";
            for(int i = 0; i < Array.getLength(obj); i++){
                if(i > 0) r += ",";
                Object val = Array.get(obj,i);
                if(cl.getComponentType().isPrimitive()) r += val;
                else r += toString(val);
            }
            return r + "}";
        }
        String r = cl.getName();
        do{
            r += "[";
            Field[] fields = cl.getDeclaredFields();
            AccessibleObject.setAccessible(fields,true);
            for(Field f : fields){
                if(!Modifier.isStatic(f.getModifiers())){
                    if(!r.endsWith("[")) r += ",";
                    r += f.getName() + "=";
                    Class  t = f.getType();
                    Object val = f.get(obj);
                    if(t.isPrimitive()) r += val;
                    else r += toString(val);
                }
            }
            r += "]";
            cl = cl.getSuperclass();
        }while(cl != null);
    return r;
    }
}
​
//测试过程
import java.util.ArrayList;
​
/**
 * @author Rui
 * @description 复写的ToString()方法测试
 * @create 2024/8/11 16:08
 */
public class ObjectAnalyzerTest {
    public static void main(String[] args) throws ReflectiveOperationException{
        ArrayList<Integer> squares = new ArrayList<Integer>();
        for (int i = 1; i <= 5; i++) {
            squares.add(i * i);
        }
        System.out.println("squares: " + squares.toString());
        System.out.println(new ObjectAnalyzer().toString(squares));
    }
}
squares: [1, 4, 9, 16, 25]
java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][][]
​
进程已结束,退出代码0
作用三:调用任意的方法和构造器:类似的实现了C/C++的指针的功能
import java.lang.reflect.Method;
​
/**
 * @author Rui
 * @description 功能上类似实现了C/C++的指针功能
 * @create 2024/8/11 16:42
 */
public class MethodTableTest {
    public static void main(String[] args) throws ReflectiveOperationException {
        Method square = MethodTableTest.class.getMethod("square", double.class);
        Method sqrt = Math.class.getMethod("sqrt", double.class);
​
        printTable(1, 10, 10, square);
        printTable(1, 10, 10, sqrt);
​
    }
​
    public static double square(double x) {
        return x * x;
    }
​
    public static void printTable(double from, double to, int n, Method f) throws ReflectiveOperationException {
        System.out.println(f);
        double dx = (to - from) / (n - 1);
        for (double x = from; x <= to; x += dx){
            double y = (Double) f.invoke(null, x);
            System.out.printf("%10.4f | %10.4f%n", x, y);
        }
    }
}
public static double MethodTableTest.square(double)
    1.0000 |     1.0000
    2.0000 |     4.0000
    3.0000 |     9.0000
    4.0000 |    16.0000
    5.0000 |    25.0000
    6.0000 |    36.0000
    7.0000 |    49.0000
    8.0000 |    64.0000
    9.0000 |    81.0000
   10.0000 |   100.0000
public static double java.lang.Math.sqrt(double)
    1.0000 |     1.0000
    2.0000 |     1.4142
    3.0000 |     1.7321
    4.0000 |     2.0000
    5.0000 |     2.2361
    6.0000 |     2.4495
    7.0000 |     2.6458
    8.0000 |     2.8284
    9.0000 |     3.0000
   10.0000 |     3.1623
​
进程已结束,退出代码0
作用四:编写泛型数组代码
import java.lang.reflect.Array;
import java.util.Arrays;
​
/**
 * @author Rui
 * @description 编写泛型数组代码
 * @create 2024/8/11 17:39
 */
public class CopyOfTest {
    public static void main(String[] args) {
        int[] a = {1,2,3};
        a = (int[]) goodCopyOf(a,10);
        System.out.println(Arrays.toString(a));
​
        String[] b = {"Tom","Dick","Harry"};
        b = (String[]) goodCopyOf(b,10);
        System.out.println(Arrays.toString(b));
​
        System.out.println("下面的调用将生成一个异常。");
        b = (String[]) badCopyOf(b,10);
    }
​
    public static Object[] badCopyOf(Object[] a, int newLength) {
        Object[] newArray = new Object[newLength];
        System.arraycopy(a,0,newArray,0,Math.min(a.length,newLength));
        return newArray;
    }
​
    public static Object goodCopyOf(Object a, int newLength) {
        Class cl = a.getClass();
        if (!cl.isArray()) return null;
        Class componentType = cl.getComponentType();
        int length = Array.getLength(a);
        Object newArray = Array.newInstance(componentType,newLength);
        System.arraycopy(a,0,newArray,0,Math.min(length,newLength));
        return newArray;
    }
}
[1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
[Tom, Dick, Harry, null, null, null, null, null, null, null]
下面的调用将生成一个异常。
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
    at CopyOfTest.main(CopyOfTest.java:20)
​
进程已结束,退出代码1
在Spring设计中用到反射

1.1创建Bean实例的时候使用到了反射

       当容器启动时,他会扫描配置文件或者注解来确定那些类需要类实例化,并使用反射调用构造函数

1.2依赖注入时使用了反射

        开发者通过声明式的管理对象之间的依赖关系,Spring使用反射来访问类的信息,包括字段、方法、构造方法,然后哥们个根据信息自动注入所需的依赖

1.3 AOP面向切面编程

        使用动态代理来实现方法的拦截,Spring使用反射动态的创建一个代理对象,该对象会拦截方法调用,并在方法执行前后添加额外的行为

在mybatis中使用到的反射

1.1使用反射完成动态代理

        mybatis使用JDK动态代理来创建Mapper接口的实现类,不需要程序员创建实现类

1.2结果集映射

        mybatis会将查询结果映射到Java对象中

1.3 SQL语句的处理

        mybatis执行SQL时,会根据配置的参数类型,使用反射设置参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值