本文只讲述怎么使用反射
java类编译的时候会生成对应的class文件,jvm加载的就是class文件。
Class类就用于表示.class文件(字节码文件)。
反射首先就要获取类的Class对象,就能够知道这个类所有的信息。
利用反射技术可以对一个类进行拆分,成员变量、成员方法、构造方法等都拆成一个个对象。
先编写一个Person类
public class Person {
public String name;
protected String phone;
char sex;
private Integer age;
public Person() {
}
private Person(Integer age) {
}
public void method() {
System.out.println("该方法被调用了");
}
public void method1() {
System.out.println("调用了公有方法");
}
void method2() {
System.out.println("调用了默认方法");
}
protected void method3() {
System.out.println("调用了受保护方法");
}
private void method4(String name) {
System.out.println(name + "调用了私有方法");
}
public static void main(String[] args) {
System.out.println("main方法执行了");
}
}
1. 获取Class对象的三种方法
如下三种方法,第一种都通过new创建了对象就没有必要多此一举了;一般用第二种和第三种
//new一个Person对象
Person person = new Person();
//通过对象调用getClass方法获取Class对象
Class class1 = person.getClass();
System.out.println(class1.getName());
//直接通过类名调用class获取对象,这种需要导入Person包
Class class2 = Person.class;
System.out.println(class1 == class2);
try {
//通过全限定类名获取Class对象
Class class3 = Class.forName("com.yq.ad.entity.Person");
System.out.println(class2 == class3);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2. 获取构造方法对象
Class clazz = Class.forName("com.yq.ad.entity.Person");
//获取所有共有构造方法,只能获取公有的
Constructor[] constructors = clazz.getConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
//获取所有构造方法,四种修饰符修饰的构造方法都可以获取
constructors = clazz.getDeclaredConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
/**
* 获取单个构造方法时,
* clazz.getConstructor() 无参的
* clazz.getConstructor(String.class, Integer.class) 两个参数的,根据构造方法传参
*/
//获取公有、无参的构造方法
Constructor con = clazz.getConstructor();
//调用构造方法获取对象
Object obj = con.newInstance();
System.out.println("obj=" + obj);
Person person = (Person) obj;
//获取私有、受保护、默认、公有构造方法,Integer类型参数
con = clazz.getDeclaredConstructor(Integer.class);
System.out.println(con);
//暴力破解(忽略掉访问修饰符)
con.setAccessible(true);
//调用构造方法
obj = con.newInstance(12);
3. 获取成员变量对象
Class clazz = Class.forName("com.yq.ad.entity.Person");
//获取所有公有的字段,只能获取共有的
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
//能获取所有的字段,任何修饰符修饰的
fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//获取单个公有字段
Field name = clazz.getField("name");
System.out.println(name);
//获取对象
Object obj = clazz.getConstructor().newInstance();
//为obj对象的name字段设置值
name.set(obj, "张三");
Person person = (Person)obj;
System.out.println("名字为:"+person.name);
//可以所有修饰符修饰的字段
Field age = clazz.getDeclaredField("age");
System.out.println(age);
//私有成员变量的话,需要暴力解除
age.setAccessible(true);
//为obj对象的age字段设置值
age.set(obj, 45);
4. 获取成员方法对象
Class clazz = Class.forName("com.yq.ad.entity.Person");
//获取所有的公有方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取所有的方法
methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取对象
Object obj = clazz.getConstructor().newInstance();
//获取一个公有方法对象,如果方法带有参数clazz.getMethod("method1", String.class, Integer.class)
Method method1 = clazz.getMethod("method1");
//调用方法
method1.invoke(obj);
//可以获取所有方法中某一个方法
Method method4 = clazz.getDeclaredMethod("method4", String.class);
//暴力解除私有
method4.setAccessible(true);
//调用方法
method4.invoke(obj, "小明");
5. 反射获取main方法
//创建一个class对象
Class clazz = Class.forName("com.yq.ad.entity.Person");
//获取mian方法
Method main = clazz.getMethod("main", String[].class);
//因为main方法是静态的,所以实例对象为null就可以,这里必须强转为Object
main.invoke(null, (Object)new String[]{"1", "2"});