基本概念
利用Java语言反射机制,可以在运行时对程序进行动态控制,通过反射也可以打破类的包装机制
在Java程序运行过程中,每个类被加载后都在内存中产生一个对应的Class对象,
主要包括构造器,方法,成员变量等
Java中无论一个类生成多少个对象,这些对象都会对应内存中同一个class对象
在JDK中,主要由以下类来实现Java反射机制
Java.lang.Class类
对应类本身
Java.lang.reflect.Field类
对应类中定义的成员变量
Java.lang.reflect.Method类
对应类中定义的方法
Java.lang.reflect.Constructor类
对应类中定义构造方法
Java.lang.reflect.Array类
对应如何创建数组,为数组变量赋值,取数组值
获取Class对象的三种方法
方法一:Class的静态方法传入类的全称
Class<?> classType = Class.forName("com.itlwc.MyReflection");
方法二:Java内置语法
Class<?> classType = MyReflection.class;
方法三:使用对象的getClass()
Class<?> classType = new String("abc").getClass();
Class常用方法
package com.itlwc;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
// 返回指定类对应的Class对象,如果找不到指定类抛出ClassNotFoundException
Class<?> c = Class.forName("com.itlwc.Test");
// 返回Class对象自己定义所有构造器
Constructor<?> c1 = c.getDeclaredConstructor();
// 返回Class对象自己定义所有构造器
Constructor<?>[] c2 = c.getDeclaredConstructors();
// 返回Class对象自己定义public构造器
Constructor<?> c3 = c.getConstructor();
// 返回Class对象自己定义public构造器
Constructor<?>[] c4 = c.getConstructors();
// 返回Class对象自己定义所有成员变量,不包括父类继承来的成员变量
Field f1 = c.getDeclaredField("name");
// 返回Class对象自己定义成员变量数组,不包括父类继承来的成员变量
Field[] f2 = c.getDeclaredFields();
// 返回Class对象自己定义public成员变量,包括父类有访问权限的成员变量
Field f3 = c.getField("age");
// 返回Class对象自己定义public成员变量数组,包括父类有访问权限的成员变量
Field[] f4 = c.getFields();
// 返回Class对象自己定义所有成员方法,不包括父类继承来的成员方法
Method m1 = c.getDeclaredMethod("getName");
// 返回Class对象自己定义成员方法数组,不包括父类继承来的成员方法
Method[] m2 = c.getDeclaredMethods();
// 返回Class对象自己定义public成员方法,包括父类有访问权限的成员方法
Method m3 = c.getMethod("getName");
// 返回Class对象自己定义public成员方法数组,包括父类有访问权限的成员方法
Method[] m4 = c.getMethods();
// Class对象所对应类的名称
String str1 = c.getName();
// Class对象所对应类所在的包
Package p = c.getPackage();
// 返回源代码中给出的基础类的简称
String str2 = c.getSimpleName();
// 返回Class对象表示的实体的超类的Class
Class<?> cc = c.getSuperclass();
// Class对象是否为注解类型
boolean b1 = c.isAnnotation();
// Class对象是否为匿名内部类
boolean b2 = c.isAnonymousClass();
// Class对象是否为数组类型
boolean b3 = c.isArray();
// Class对象是否为枚举类型
boolean b4 = c.isEnum();
// Class对象是否为接口类型
boolean b5 = c.isInterface();
// Class对象是否为成员内部类
boolean b6 = c.isMemberClass();
// 创建加载类的对象
Test t = (Test) c.newInstance();
t.getName();
// Class对象转换为字符串
String str3 = c.toString();
}
private String name;
public String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Test() {
}
public Test(String name) {
this.name = name;
}
private Test(String name, String age) {
this.name = name;
this.age = age;
}
}
Field常用方法
package com.itlwc;
import java.lang.reflect.Field;
class PrivateClass {
public String name;
public String age;
private String password;
}
public class T {
public static void main(String[] args) throws Exception {
// 获取Class对象
Class<?> clazz = PrivateClass.class;
Object obj = clazz.newInstance();
// 返回Class对象自己定义public成员变量数组,包括父类有访问权限的成员变量
Field[] field = clazz.getFields();
for (Field f : field) {
// 成员变量名称
System.out.println(f.getName());
// 成员变量类型
System.out.println(f.getType());
// 成员变量值
System.out.println(f.get(obj));
}
// 返回Class对象自己定义的私有不带参数方法,名称为method1
Field f = clazz.getDeclaredField("password");
f.setAccessible(true);
System.out.println("成员变量名称: " + f.getName() + " 成员变量类型: " + f.getType()
+ " 成员变量值: " + f.get(obj));
}
}
Method常用方法
package com.itlwc;
import java.lang.reflect.Method;
class PrivateClass {
private void method1() {
System.out.println("调用了无参私有方法");
}
private String method2(String str, int a) {
return "调用了有参私有方法: " + str + "今年" + a + "岁";
}
}
public class T {
public static void main(String[] args) {
// 获取Class对象
Class<?> clazz = PrivateClass.class;
try {
//生成PrivateClass类的一个实例
Object obj= clazz.newInstance();
// 返回Class对象自己定义成员方法数组,不包括父类继承来的成员方法
Method method[] = clazz.getDeclaredMethods();
for (Method m : method) {
// 方法名称
m.getName();
// 方法返回值
m.getReturnType();
// 方法参数序列
Class<?>[] c = m.getParameterTypes();
for (Class<?> cc : c) {
System.out.println(cc);
}
}
// 返回Class对象自己定义的私有不带参数方法,名称为method1
Method m = clazz.getDeclaredMethod("method1", new Class[] {});
m.setAccessible(true);
Object object = m.invoke(obj, null);
System.out.println(object);
// 返回Class对象自己定义的私有带参数方法,名称为method2
m = clazz.getDeclaredMethod("method2", new Class[] { String.class,
Integer.TYPE });
m.setAccessible(true);
object = m.invoke(obj, new Object[] { "lwc", 18 });
System.out.println(object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Constructor常用方法
package com.itlwc;
import java.lang.reflect.Constructor;
class PrivateClass {
public PrivateClass() {
}
private PrivateClass(String str) {
System.out.println("私有构造器");
}
}
public class T {
public static void main(String[] args) throws Exception {
PrivateClass pc = new PrivateClass();
// 获取Class对象
Class<?> clazz = pc.getClass();
// 返回Class对象自己定义所有构造器
Constructor<?>[] constructor = clazz.getDeclaredConstructors();
for (Constructor<?> cc : constructor) {
// 构造器名称
System.out.println(cc.getName());
// 构造器参数序列
Class<?>[] c = cc.getParameterTypes();
for (Class<?> ccc : c) {
System.out.print(ccc);
}
}
}
}
利用反射动态创建数组
package com.itlwc;
import java.lang.reflect.Array;
public class Test {
public static void main(String[] args) throws Exception {
// 使用反射动态创建长度为5的一维int型数组
int[] intArray = (int[]) Array.newInstance(Integer.TYPE, 5);
// 使用反射动态创建二维String型数组,一维长度为5,二维长度为4
String[][] stringArray = (String[][]) Array.newInstance(String.class,
new int[] { 5, 4 });
}
}