Java反射总结

Posted ming-szu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射总结相关的知识,希望对你有一定的参考价值。

反射(java.lang.reflect)用于分析类能力

(一)Class类

1.定义

Java运行时为每一个对象都维护的一个类型标识,用于跟踪对象所属的类提供给虚拟机分析调用,而保存这些信息的类就是Class类

(一个Class类对象可以理解为一个类型,这个类型可以是类或基本数据类型int等)

2.作用

通过对象所属的Class类,我们可以获取对象类型的数据域,方法,父类等一切类信息,还可以用它来创建实例对象

获得父类

            //2.获取父类
            Class superc1=c1.getSuperclass();

创建实例

        //利用反射创建一个实例对象
        Class myClass=Class.forName("java.util.Random");
        Random random=(Random)myClass.newInstance();    

3.获得Class类的3种途径

调用Class的静态方法获取:Class.forName(String className)

对象调用getClass()方法获取Class

通过类型名.class获取,如T.class,T可以是基本数据类型int等,也可以是具体的类如Random.class

        Class myClass=Class.forName("java.util.Random");
        myClass=new Random().getClass();
        myClass=Random.class;

 

(二)用于描述一个class的三个类:Field,Method,Constructor

Field类代表一个class中的数据域

Method类代表一个class中的方法

Constructor类代表一个class中的构造器

这三个类都继承Accessible

1.获取一个类中的Field,Method,Constructor

Class类调用getDeclaredFields()方法获得该类的所有数据域

Class类调用getDetclaredMethods()方法获得该类的所有方法

Class类调用getDetclaredConstructors()方法获得该类的构造器

2.获得一个Class|Field|Method|Constructor的修饰符

            //Modifier.toString()能够获取c1的修饰符public final
            String modifiers=Modifier.toString(c1.getModifiers());        

调用这四个类的getModifiers()方法可以返回一个int,作为参数传入Modifier.toString(),该方法会根据int判断出修饰符

3.获得Field数据域的类型(Class)与Field的名臣

            Class classType=f.getType();
            String name=f.getName();

4.获取Method的返回类型,Method名称,Method参数类型

            String returnType=methods[j].getReturnType().getName();
            String methodName=methods[j].getName();
            Class[] paraTypes=methods[j].getParameterTypes();

5.打印一个类的具体信息

package Reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @ClassName ReFlectionTest
 * @Description 利用反射打印Double类的所有方法
 * @Author cherry
 * @Date 2018/6/9 21:22
 * @Update 2018/6/9 21:22
 **/
public class ReFlectionTest{
    public static void main(String[] argv){
        String className="java.lang.Double";
        try{
            //1.获取Class
            Class c1=Class.forName(className);
            //2.获取父类
            Class superc1=c1.getSuperclass();
            //3.Modifier.toString()能够获取c1的属性public final
            String modifiers=Modifier.toString(c1.getModifiers());
            //4.打印c1的属性
            if(modifiers.length()>0)System.out.print(modifiers+" ");
            //5.打印c1的类名
            System.out.print("class "+className);
            //6.若有继承则打印
            if(superc1!=null&&superc1!=Object.class)System.out.print("extends "
                    +superc1.getName());
            //7.打印中括号
            System.out.print("
{
");
            //8.打印域
            printFields(c1);
            //9.打印构造器
            printConstructors(c1);
            //10.打印方法
            printMethods(c1);
            //11.打印中括号
            System.out.print("
}
");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }

    /**
     * 打印域
     * @param c1
     */
    public static void printFields(Class c1){
        //1.获得所有域
        Field[] fields=c1.getFields();
        //2.遍历打印
        for(Field f:fields){
            Class classType=f.getType();
            String name=f.getName();
            //3.打印进位符
            System.out.print("   ");
            //4.打印属性
            String modifiers=Modifier.toString(f.getModifiers());
            if(modifiers.length()>0)System.out.print(modifiers+" ");
            System.out.println(classType+" "+name+";");
        }
        System.out.println();
    }

    /**
     * 打印传入类的构造器
     * @param c1
     */
    public static void printConstructors(Class c1){
        //1.获取所有构造器
        Constructor[] constructors=c1.getConstructors();
        //2.遍历打印
        for(Constructor c:constructors){
            //3.打印tab占位符
            System.out.print("   ");
            //4.获取构造器的属性
            String modifier=Modifier.toString(c.getModifiers());
            if(modifier.length()>0)System.out.print(modifier+" ");
            //5.打印构造器名
            String conName=c.getName();
            System.out.print(conName+"(");
            //6.打印参数
            Class[] paraTypes=c.getParameterTypes();
            for(int j=0;j<paraTypes.length;j++){
                if(j>0)System.out.print(", ");
                System.out.print(paraTypes[j].getName());
            }
            System.out.print(");
");
        }
        System.out.print("
");
    }

    /**
     * 打印方法
     * @param c1
     */
    public static void printMethods(Class c1){
        //1.获取所有的方法
        Method[] methods=c1.getMethods();
        //2.遍历打印
        for(int j=0;j<methods.length;j++){
            //3.打印占位符
            System.out.print("   ");
            //4.打印方法属性
            String modifiers=Modifier.toString(methods[j].getModifiers());
            if(modifiers.length()>0)System.out.print(modifiers+" ");
            //5.打印返回类型
            String returnType=methods[j].getReturnType().getName();
            System.out.print(returnType+" ");
            //6.打印方法名
            String methodName=methods[j].getName();
            System.out.print(methodName+"(");
            //7.打印参数名
            Class[] paraTypes=methods[j].getParameterTypes();
            for(int i=0;i<paraTypes.length;i++){
                if(i>0)System.out.print(",");
                System.out.print(paraTypes[i].getName());
            }
            if(j+1!=methods.length) System.out.print(")
");
        }
    }
}

 

(三)运行时获取一个对象的数据域的具体值

        Student student=new Student(18);                        //创建student对象
        Class studentClass=student.getClass();                  //获取Student的Class
        Field field=studentClass.getDeclaredField("age");       //得到age域
        field.setAccessible(true);                              //设置可访问private域
        System.out.println(field.get(student));                 //访问age域的值

 

(四)调用一个对象的方法

        Student student=new Student(18);                                  //创建student对象
        Class studentClass=student.getClass();                          //获取Student的Class
        Method setAgeMethod=studentClass.getMethod("setAge", int.class);     //获取方法
        setAgeMethod.invoke(student,20);                               //访问age域的值
        System.out.println(student.getAge());                            //返回20

 

(五)实现一个泛型数组操作方法

    /**
     * 用于扩展已经填满的数组
     * @param a
     * @param newLength
     * @return
     */
    public static Object goodCopyOf(Object a,int newLength){
        Class c1=a.getClass();                          //获取传入的a的Class
        if(!c1.isArray())return null;                   //若不是数组类型直接返回null
        Class compomentType=c1.getComponentType();      //获取数组元素类型
        int length=Array.getLength(a);                  //获取传入的数组的长度
        Object newArray=Array.newInstance(compomentType,newLength);                         //Array.newInstance()根据元素类型与长度新建一个相同类型数组且长度扩大              
        System.arraycopy(a,0,newArray,0,Math.min(length,newLength));      //将原数组的值赋予新数组
        return newArray;
    }

 

 

 

 

参考《Java核心技术 卷I》p190

以上是关于Java反射总结的主要内容,如果未能解决你的问题,请参考以下文章

反射机制

关于JAVA中的反射机制的总结

Java核心编程总结(十反射)

关于JAVA 反射 基础知识/编码经验的一些总结

关于JAVA 反射 基础知识/编码经验的一些总结

Java反射学习总结五(Annotation(注解)-基础篇)