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");
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
原文地址:https://www.cnblogs.com/benming/p/11548626.html