ITPub博客

首页 > 应用开发 > > Java中的反射该如何使用?

Java中的反射该如何使用?

作者:u_509a2a8fdb46 时间:2019-10-24 17:42:14 0 删除 编辑

1. 什么是反射

反射是一种功能强大且复杂的机制。Java 反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。

2. 反射可以用来做什么

反射能够分析类的能力,反射的机制十分强大,主要可以用来:

在运行时分析类的能力

在运行时查看对象

实现通用的数组操作代码

利用Method 对象,实现 C++ 中函数指针的功能

3. Class 类

所谓的反射其实是获取类的字节码文件,也就是.class 文件,而获取 Class 这个对象主要有三种方式:

getClass() 函数、 .class 、 forName() 方法,代码如下:

package core.java;

import java.util.ArrayList;

public class Test {

    public static void main(String[] args) throws ClassNotFoundException {

        ArrayList<Integer> test = new ArrayList<>();

// 第一种方法

        Class a = test.getClass();

        System.out.println(a);

// 第二种方法

        Class b = Test.class;

        System.out.println(b);

// 第三种方法

        Class c = Class.forName("java.lang.Math");

        System.out.println(c);

    }

}

4. 利用反射分析类

在reflect 包中有三个类: Field 、 Method 和 Constructor 分别用于描述类的域、方法和构造器。这三个类都有一个叫做 getName() 的方法,用来返回项目的名称。 Field 类有一个 getType 方法,用来返回描述域所属类型的 Class 对象。这三个类共同有一个 getModifiers 的方法,他将返回一个整型数值,来描述修饰符的情况。可以使用 Modifier 类的静态方法分析其返回的整型数值,也可以使用其 toString() 方法将对应的修饰符打印出来。

Class 类中的 getFields 、 getMethods 和 getConstructors 方法将分别返回类提供的 public 域、方法和构造器数组,其中包括超类的共有成员。

Class 类中的 getDeclareFields 、 getDeclareMethods 和 getDeclaredConstructors 方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。

实例代码:

package core.java.reflect;

import java.util.*;

import java.lang.reflect.*;

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("Enter class name (e.g. java.util.Date): ");

            name = in.next();

        }

        try

        {

            Class cl = Class.forName(name);

            Class supercl = cl.getSuperclass();

String modifiers = Modifier.toString(cl.getModifiers()); // 打印修饰符

            if (modifiers.length() > 0) System.out.print(modifiers + " ");

            System.out.print("class " + name);

            if (supercl != null && supercl != Object.class) System.out.print(" extends "

+ supercl.getName());// 输出超类

            System.out.print("\n{\n");

printConstructors(cl); // 输出构造器数组

            System.out.println();

printMethods(cl); // 输出方法

            System.out.println();

printFields(cl);  // 输出域

            System.out.println("}");

        }

        catch (ClassNotFoundException e)

        {

            e.printStackTrace();

        }

        System.exit(0);

    }

    public static void printConstructors(Class cl)

    {

Constructor[] constructors = cl.getDeclaredConstructors(); // 获取构造器数组

        for (Constructor c : constructors)

        {

            String name = c.getName();

            System.out.print("   ");

String modifiers = Modifier.toString(c.getModifiers()); // 输出修饰符

            if (modifiers.length() > 0) System.out.print(modifiers + " ");

System.out.print(name + "("); // 构造器签名

            // print parameter types

Class[] paramTypes = c.getParameterTypes(); // 获取构造器参数数组

            for (int j = 0; j < paramTypes.length; j++)

            {

                if (j > 0) System.out.print(", ");

                System.out.print(paramTypes[j].getName());

            }

            System.out.println(");");

        }

    }

    public static void printMethods(Class cl)

    {

        Method[] methods = cl.getDeclaredMethods();

        for (Method m : methods)

        {

Class retType = m.getReturnType(); // 获取返回类型

String name = m.getName(); // 方法名

            System.out.print("   ");

String modifiers = Modifier.toString(m.getModifiers()); // 输出修饰符

            if (modifiers.length() > 0) System.out.print(modifiers + " ");

            System.out.print(retType.getName() + " " + name + "(");

            // print parameter types

Class[] paramTypes = m.getParameterTypes(); // 获取参数数组

            for (int j = 0; j < paramTypes.length; j++)

            {

                if (j > 0) System.out.print(", ");

                System.out.print(paramTypes[j].getName());

            }

            System.out.println(");");

        }

    }

    public static void printFields(Class cl)

    {

Field[] fields = cl.getDeclaredFields(); // 获取域数组

        for (Field f : fields)

        {

Class type = f.getType(); // 获取参数类型

String name = f.getName(); // 获取域名称

            System.out.print("   ");

String modifiers = Modifier.toString(f.getModifiers()); // 输出修饰符

            if (modifiers.length() > 0) System.out.print(modifiers + " ");

            System.out.println(type.getName() + " " + name + ";");

        }

    }

}

5 、 利用反射技术得到所有的构造函数

public class Test02 {

public static void main(String[] args) {

try {

Class clazz = Student.class;// 获取 class 对象

String name = clazz.getName();// 获得类的名称 ( 全限定名 )

Constructor[] constructors = clazz.getDeclaredConstructors();// 返回指定参数类型的所有构造器

for (Constructor constructor : constructors) {

System.out.println(constructor);

}

} catch (SecurityException e) {

e.printStackTrace();

}

}

}

输出结果:

public com.etime2.Student()

public com.etime2.Student(java.lang.String,java.lang.Integer,java.lang.String)

备注:

getDeclaredConstructor() 与 getConstructor 的区别

getDeclaredConstructor(Class … parameterTypes)

这个方法会返回指定参数类型的所有构造器,包括public 的和非 public 的,其中当然也包括 private 私有的。

getDeclaredConstructors() 的返回结果就没有参数类型的过滤了。

getConstructor(Class … parameterTypes)

这个方法返回的是上面方法返回结果的子集,只返回指定参数类型访问权限是public 的构造器。

getConstructors() 的返回结果同样也没有参数类型的过滤。

6 、 利用反射技术得到类的所有方法

public class Test03 {

public static void main(String[] args) {

try {

Class clazz = Class.forName("com.etime2.Student");// 获取类的 class 对象 ( 加载和解析类的字节码 , 返回相应的 class 对象 )

Method[] Methods = clazz.getDeclaredMethods();// 获取所有的方法 , 包括私有方法

for (Method method : Methods) {

String name = method.getName();// 获得类的名称 ( 全限定名 )

System.out.println(name);

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

输出结果:

getName

setName

sleep

getGender

getAge

setAge

setGender

7 、 利用反射技术得到类的所有字段

public class Test04 {

public static void main(String[] args) {

try {

Class clazz = Class.forName("com.etime2.Student");

function(){   //外汇返佣:http://www.kaifx.cn/

Field[] fields = clazz.getDeclaredFields();// 获取所有的字段

for (Field field : fields) {

System.out.println(" 字段 :" + field);

String name = field.getName();// 获得类的名称 ( 全限定名 )

System.out.println(" 名称 :" + name);

Class type = field.getType();// 获取变量的类型

System.out.println(" 类型 :" + type);

int modifiers = field.getModifiers();// 获得类的修饰符

boolean public1 = Modifier.isPublic(modifiers);

boolean static1 = Modifier.isStatic(modifiers);

boolean final1 = Modifier.isFinal(modifiers);

System.out.println("public1=" + public1 + "  static1=" + static1 + "  final1=" + final1);

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

输出结果:

字段:private java.lang.String com.etime2.Student.name

名称:name

类型:class java.lang.String

public1=false  static1=false  final1=false

字段:private java.lang.Integer com.etime2.Student.age

名称:age

类型:class java.lang.Integer

public1=false  static1=false  final1=false

字段:private java.lang.String com.etime2.Student.gender

名称:gender

类型:class java.lang.String

public1=false  static1=false  final1=false

利用反射调用对象的私有方法(不完整)

public class Test05 {

public static void main(String[] args) {

try {

Class<?> clazz = Class.forName("com.etime2.Student");

Method method = clazz.getDeclaredMethod("sleep");

method.setAccessible(true);// 允许访问私有

Object newInstance = clazz.newInstance();// 调用无参构造函数创建对象

Student student = (Student) newInstance;

Object invoke = method.invoke(student);

System.out.println(invoke);

} catch (Exception e) {

e.printStackTrace();

}

}

}

运行结果:

上课时间打盹!

null

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69927062/viewspace-3153999/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-08

  • 博文量
    210
  • 访问量
    38