• Java复习总结——详细理解Java反射机制


    反射是什么

    反射的作用用一句简单的话来讲就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少。

    能够分析类能力的程序就叫做反射,简单来说就是可以对代码进行操作的代码。反射机制的功能极为强大,可以用来:

    • 在运行时分析类的能力
    • 在运行时查看对象
    • 实现通用的数组操作代码
    • 利用Method对象来实现方法

    从获取Class类开始

    在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。这个类的获取方式有以下三种:

    1. 使用Object类中的getClass()方法来返回一个Class类的实例

      User user;
      Class userClass  = user.getClass();
      
    2. 我们可以使用Class类的getName()方法来获取包含包名在内的类名。同样的,在已知这个名字的情况下,我们可以使用静态方法forName()获得类名对应的Class对象

    Random generator = new Random();
    Class randomClass = generator.getClass();
    //className = "java.util.Random"
    String className = randomClass.getName();
    //第二种方式获取
    Class newRandomClass = Class.forName(className);
    
    1. 获得Class类对象的第三种方法很简单,如果T是任意的Java类型(或者void关键字),T.class将代表匹配的类对象。例如:
    Class randomClass = Random.class;
    Class intClass = int.class;
    Class doubleClass = Double[].class;
    

    如果我们想要创建一个类的实例,可以使用newInstance()方法来动态创建:

    String s = "java.util.Random";
    Object m = Class.forName(s).newInstance();
    

    构造函数的反射

    获得构造函数的方法

        //根据指定参数获得public构造器
        Constructor getConstructor(Class[] params);
        //获得public的所有构造器
        Constructor[] getConstructors();
        //根据指定参数获得public和非public的构造器
        Constructor getDeclaredConstructor(Class[] params);
        //获得public的所有构造器 
        Constructor[] getDeclaredConstructors();
    

    看这些方法如何使用,先来个Student类供我们反射使用

    public class Student {
    
        private static String TAG = Student.class.getSimpleName();
        public int age;
        private String name;
    
        public Student() {
            age = 20;
            name = "小明";
        }
    
        public Student(int age, String name) {
            Log.e(TAG, "Student: " + "age " + age + " name " + name);
        }
    
        public void StudentA() {
            Log.e(TAG, "StudentA: ");
        }
    
        public void StudentA(int age) {
            Log.e(TAG, "StudentA: " + "age " + age);
        }
    
        public void StudentA(int age, String name) {
            Log.e(TAG, "StudentA: " + "age " + age + " name " + name);
        }
    }
    

    利用反射分析类的能力

    在java.lang.reflect包(反射库)中有三各类Field,MethodConstructor分别用于描述类的域,方法和构造器。这三个类都有一个叫做getName()的方法,用于返回项目的名称。Filed类有一个getType()方法,用于返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法。

    这三个类还有一个叫做getModifiers()的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用情况。另外,还可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifiers()返回的整型数值。例如,可以使用Modifier类中的isPublic()isPrivate()isFinal()判断方法或构造器是否是public,private或final。我们需要做的全部工作就是调用Modifier类的相应方法,并对返回的整数数值进行分析,另外,还可以利用Modifier.toString()方法将修饰符打印出来。

    Class类中的getFields()getMethods()getConstructors()方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的公有成员。Class类的getDeclareFieds()getDeclareMethods()getDeclareConstructors()方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。

    下面我们来编写一个程序可以做到输入类名,然后打印出这个类的全部信息的作用:

    package com.reflect.test;
    
    import com.sun.org.apache.xpath.internal.operations.Mod;
    
    import java.io.File;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.Scanner;
    
    public class ReflectionTest {
    
        public static void main(String[] args) {
            String name;
            if(args.length > 0){
                name = args[0];
            }else{
                Scanner in = new Scanner(System.in);
                System.out.println("请输入类名:");
                name = in.next();
            }
    
            try{
                Class c1 = Class.forName(name);
                Class superclass = c1.getSuperclass();
                String modifiers = Modifier.toString(c1.getModifiers());
                if(modifiers.length() > 0){
                    System.out.println(modifiers + " ");
                }
                System.out.println("class"+name);
                if(superclass != null && superclass != Object.class){
                    System.out.println("extends"+superclass.getName());
                }
                System.out.println("
    {
    ");
                printConstructors(c1);
                System.out.println();
                printMethods(c1);
                System.out.println();
                printFields(c1);
                System.out.println("}");
            }catch (ClassNotFoundException e){
                e.printStackTrace();
            }
            System.exit(0);
        }
    
        private static void printFields(Class c1) {
            Field[] fields = c1.getDeclaredFields();
    
            for(Field field : fields){
                Class type = field.getType();
                String name = field.getName();
                System.out.println("   ");
                String modifiers = Modifier.toString(field.getModifiers());
                if(modifiers.length() > 0){
                    System.out.println(modifiers + " ");
                }
                System.out.println(type.getName() + " " + name + ";");
            }
        }
    
        private static void printMethods(Class c1) {
            Method[] methods = c1.getDeclaredMethods();
    
            for(Method method : methods){
                Class returnType = method.getReturnType();
                String name = method.getName();
                System.out.println("  ");
                String modifiers = Modifier.toString(method.getModifiers());
                if(modifiers.length() > 0){
                    System.out.println(modifiers + " ");
                }
                System.out.println(returnType.getName()+" "+name+"(");
                Class[] paramTypes = method.getParameterTypes();
                for(int j = 0; j < paramTypes.length; j++){
                    if(j > 0){
                        System.out.println(",");
                    }
                    System.out.println(paramTypes[j].getName());
                }
                System.out.println(");");
            }
        }
    
        private static void printConstructors(Class c1) {
            Constructor[] constructors = c1.getDeclaredConstructors();
            for(Constructor constructor : constructors){
                String name = constructor.getName();
                System.out.println("  ");
                String modifiers = Modifier.toString(constructor.getModifiers());
                if(modifiers.length() > 0){
                    System.out.println(modifiers + " ");
                }
                System.out.println(name + "(");
                Class[] paramTypes = constructor.getParameterTypes();
                for(int j = 0; j < paramTypes.length; j++){
                    if(j > 0){
                        System.out.println(",");
                    }
                    System.out.println(paramTypes[j].getName());
    
                }
                System.out.println(");");
            }
        }
    }
    
    

    输入java.long.Double

    回显:

    请输入类名:
    java.lang.Double
    public final 
    Disconnected from the target VM, address: '127.0.0.1:51190', transport: 'socket'
    classjava.lang.Double
    extendsjava.lang.Number
    
    {
    
      
    public 
    java.lang.Double(
    double
    );
      
    public 
    java.lang.Double(
    java.lang.String
    );
    
      
    public 
    boolean equals(
    java.lang.Object
    );
      
    public static 
    java.lang.String toString(
    double
    );
      
    public 
    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 
    java.lang.Double valueOf(
    java.lang.String
    );
      
    public static 
    java.lang.Double valueOf(
    double
    );
      
    public static 
    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;
    }
    
    Process finished with exit code 0
    
    

    不积跬步无以至千里

    思维导图

    扩展阅读:

    https://blog.csdn.net/zhangqiluGrubby/article/details/60874013

    https://www.daidingkang.cc/2017/07/18/java-reflection-annotations/

    https://www.javazhiyin.com/17014.html

    https://www.javazhiyin.com/17008.html

  • 相关阅读:
    oracle基本语句
    html页面比较长,如何用js实现网页一打开显示在网页的中部?
    idea拉出Output窗口和还原窗口
    关于idea的目录结构如何变成树状,也就是横向变纵向
    IDEA -- idea无法导入HttpServlet包解决方法
    tomcat启动startup.bat一闪而过
    li标签和checkbox绑定
    利用jQuery对li标签操作
    &#65279导致页面顶部空白一行解决方法
    Myeclipse快速排版的快捷键
  • 原文地址:https://www.cnblogs.com/Tu9oh0st/p/10708859.html
Copyright © 2020-2023  润新知