java反射基本使用
一. 反射的作用
当程序中要定义一个不确定类型的类对象,就可以使用反射来创建类对象,因为反射只有在运行时才会被加载。
二. 反射基本使用示例
Dog类:
package com.reflect.example;
public class Dog {
public void bark() {
System.out.println("小狗汪汪叫");
}
}
Demo类:
package com.reflect.example;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
String classFullPath = "com.reflect.example.Dog";
// 加载类
Class classDog = Class.forName(classFullPath);
// 创建类对象
Object dog = classDog.newInstance();
// 获取bark方法对象
Method method = classDog.getDeclaredMethod("bark");
// 调用方法
method.invoke(dog);
}
}
三. 反射爆破
private修饰的构造器、属性、方法是不允许被访问的,反射提供了一种爆破机制,可以强制访问private修饰的构造器、属性、方法。具体操作见 (四. 反射相关类和对应方法介绍)
四. 反射相关类和对应方法介绍
1. Class
Class类是反射的核心, 每个类都有唯一的一个Class类,Class类中保存了实际类中的成员属性、成员方法、构造方法、静态变量、静态方法。
(1) 常用方法
方法 | 作用 |
---|---|
getName() | 获取全类名(带有包名的类名) |
getSimpleName() | 获取类名 |
getFields() | 获取所有public修饰的属性,包括父类 |
getDeclaredFields() | 获取当前类所有属性 |
getField(String name) | 根据属性名获取public属性,包括父类属性 |
getDeclaredField(String name) | 根据属性名获取本类中任意权限修饰符修饰的属性 |
getMethods() | 获取所有public方法,包括父类 |
getDeclaredMethods() | 获取本类中所有方法 |
getMethod(String name) | 根据方法名获取public方法,包括父类 |
getDeclaredMethod(String name) | 根据方法名获取本类任意权限修饰符修饰的方法 |
getConstructors() | 获取本类所有public构造方法 |
getDeclaredConstructors() | 获取本类所有权限修饰符修饰的构造方法 |
getConstructor(Class<?>... parameterTypes) | 根据参数类型获取public构造方法 |
getDeclaredConstructor(Class<?>... parameterTypes) | 根据参数类型获取所有权限修饰符修饰的构造方法 |
(2) 使用示例
Father类:
package com.reflect.classexample;
public class Father {
public String name = "一个父亲";
private int age = 30;
public Father() {
}
public Father(String name, int age) {
this.name = name;
this.age = age;
}
public void duty() {
System.out.println("赚钱养家");
}
private void attitude() {
System.out.println("提升自己");
}
}
Son类:
package com.reflect.classexample;
public class Son extends Father{
public int height = 20;
private int weight = 7;
public Son() {
}
public Son(String name, int age, int height, int weight) {
super(name, age);
this.height = height;
this.weight = weight;
}
private Son(int height, int weight) {
this.height = height;
this.weight = weight;
}
public void learn() {
System.out.println("好好学习");
}
private void grow() {
System.out.println("健康成长,养成积极向上的世界观");
}
public void addElectiveCourse(String cource) {
System.out.println("选修" + cource + "课程");
}
}
Demo类:
package com.reflect.classexample;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException {
// 加载类
Class classSon = Class.forName("com.reflect.classexample.Son");
/***
* 方法示例
*/
// 1. 获取全类名
System.out.println("全类名: " + classSon.getName());
System.out.println();
// 2. 获取类名
System.out.println("类名: " + classSon.getSimpleName());
System.out.println();
// 3. 获取所有public修饰的属性,包括父类
Field[] fields = classSon.getFields();
for (Field field : fields) {
System.out.println("public属性: " + field);
}
System.out.println();
// 4. 获取当前类所有属性
Field[] fields2 = classSon.getDeclaredFields();
for (Field field : fields2) {
System.out.println("所有属性: " + field);
}
System.out.println();
// 5. 根据属性名获取public属性,包括父类属性
Field field = classSon.getField("height");
System.out.println(field);
Field field2 = classSon.getField("name");
System.out.println(field2);
System.out.println();
// 6.根据属性名获取本类中任意权限修饰符修饰的属性
Field field3 = classSon.getDeclaredField("weight");
System.out.println(field3);
System.out.println();
// 7. 获取所有public方法,包括父类
Method[] methods = classSon.getMethods();
for (Method method : methods) {
System.out.println("public方法:" + method);
}
System.out.println();
// 8. 获取本类中所有方法
Method[] methods2 = classSon.getDeclaredMethods();
for (Method method : methods2) {
System.out.println("本类中方法:" + method);
}
System.out.println();
// 9. 根据方法名获取public方法,包括父类
Method dutyMethod = classSon.getMethod("duty");
System.out.println(dutyMethod);
Method addElectiveCourceMethod = classSon.getMethod("addElectiveCourse", String.class);
System.out.println(addElectiveCourceMethod);
System.out.println();
// 10. 根据方法名获取本类任意权限修饰符修饰的方法
Method growMethod = classSon.getDeclaredMethod("grow");
System.out.println(growMethod);
Method learnMethod = classSon.getDeclaredMethod("learn");
System.out.println(learnMethod);
System.out.println();
// 11. 获取本类所有public构造方法
Constructor[] constructors = classSon.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("public构造方法:" + constructor);
}
System.out.println();
// 12. 获取本类所有权限修饰符修饰的构造方法
Constructor[] declaredConstructors = classSon.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("所有构造方法:" + declaredConstructor);
}
System.out.println();
// 13. 根据参数类型获取public构造方法
Constructor constructor = classSon.getConstructor();
System.out.println("public构造方法:" + constructor);
Constructor constructor2 = classSon.getConstructor(String.class, int.class, int.class, int.class);
System.out.println("public构造方法:" + constructor2);
System.out.println();
//14. 根据参数类型获取所有权限修饰符修饰的构造方法
Constructor declaredConstructor = classSon.getDeclaredConstructor(int.class, int.class);
System.out.println("所有权限修饰符修饰的构造方法:" + declaredConstructor);
Constructor declaredConstructor2 = classSon.getDeclaredConstructor();
System.out.println("所有权限修饰符修饰的构造方法:" + declaredConstructor2);
System.out.println();
}
}
2. Field
(1) 常用方法
方法 | 作用 |
---|---|
get(Object obj) | 获取obj对象的属性值,静态属性obj可以为nul |
set(Object obj, Object value) | 为obj对象属性赋值为value,静态属性obj可以为null |
setAccessible(booleab flag) | 设置是否允许访问private属性,true表示允许,false表示不允许 |
getType() | 获取属性类型 |
(2) 使用示例
Person类:
package com.reflect.fieldexample;
public class Person {
public int numOfEye = 2;
private double money = 1;
public Person() {
}
public Person(int numOfEye, double money) {
this.numOfEye = numOfEye;
this.money = money;
}
}
AsianPerson类:
package com.reflect.fieldexample;
public class AsianPerson extends Person{
private float height = 170;
public float weight = 134;
private static int IQ = 200;
public AsianPerson() {
}
public AsianPerson(int numOfEye, double money, float height, float weight) {
super(numOfEye, money);
this.height = height;
this.weight = weight;
}
}
Demo类:
package com.reflect.fieldexample;
import java.lang.reflect.Field;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 加载类
Class<?> classAsianPerson = Class.forName("com.reflect.fieldexample.AsianPerson");
// 创建类实例
Object person = classAsianPerson.newInstance();
// 获取public属性对象
Field field = classAsianPerson.getField("weight");
System.out.println("修改前weight:" + field.get(person));
field.set(person, 120);
System.out.println("修改后weight:" + field.get(person));
System.out.println();
// 获取属性类型
System.out.println("weight变量类型:" + field.getType());
System.out.println();
// 获取private属性对象
Field field2 = classAsianPerson.getDeclaredField("height");
// 设置允许访问field2
field2.setAccessible(true);
System.out.println("修改前height:" + field2.get(person));
field2.set(person, 175);
System.out.println("修改后height:" + field2.get(person));
System.out.println();
// 获取静态属性对象
Field field3 = classAsianPerson.getDeclaredField("IQ");
// 设置允许访问field3
field3.setAccessible(true);
System.out.println("修改前IQ:" + field3.get(person));
field3.set(person, 201);
System.out.println("修改后IQ:" + field3.get(person));
// 静态属性可以使用null
field3.set(null, 250);
System.out.println("修改后IQ:" + field3.get(null));
System.out.println();
}
}
3. Method
(1) 常用方法
方法 | 作用 |
---|---|
invoke(Object obj, Object... args) | 通过obj对象传入args参数调用方法,静态方法obj可以为null |
getParameterTypes() | 获取方法参数类型 |
setAccessible(boolean flag) | 设置是否可以访问private方法, true表示允许访问,false表示不允许访问 |
(2) 使用示例
Phone类:
package com.reflect.methodexample;
public class Phone {
public void call(String phoneNumber) {
System.out.println("拨打电话" + phoneNumber);
}
private void fixedPosition() {
System.out.println("移动不方便,通常放在固定地点");
}
}
MobilePhone类:
package com.reflect.methodexample;
public class MobilePhone extends Phone{
public void listenMusic(String name) {
System.out.println("播放音乐<" + name + ">");
}
private void movedPosition() {
System.out.println("携带方便,随时随地可以使用");
}
private static void sendMessage() {
System.out.println("发短信");
}
}
Demo类:
package com.reflect.methodexample;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class classMobilePhone = Class.forName("com.reflect.methodexample.MobilePhone");
Object phone = classMobilePhone.newInstance();
// 获取public方法
Method method = classMobilePhone.getMethod("listenMusic", String.class);
// 调用方法
method.invoke(phone, "男儿当自强");
Method method2 = classMobilePhone.getMethod("call", String.class);
method2.invoke(phone, "11111111");
// 获取方法参数类型
Class<?>[] parameterTypes = method2.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("参数类型:" + parameterType);
}
// 获取private方法
Method method3 = classMobilePhone.getDeclaredMethod("movedPosition");
// 设置可以访问private方法
method3.setAccessible(true);
method3.invoke(phone);
Method method4 = classMobilePhone.getDeclaredMethod("sendMessage");
method4.setAccessible(true);
method4.invoke(phone);
method4.invoke(null);
}
}
4. Constructor
(1) 常用方法
方法 | 作用 |
---|---|
newInstance(Object... initArgs) | 根据参数调用构造器实例化对象 |
getParameterTypes() | 获取构造器参数类型 |
setAccessible(boolean flag) | 设置是否可以访问构造器,flag为true表示允许访问,flag为false表示不允许访问 |
(2) 使用示例
Apple类:
package com.reflect.construtorexample;
public class Apple {
public double price = 10;
public String name = "苹果";
public Apple() {
}
private Apple(double price) {
this.price = price;
}
public Apple(double price, String name) {
this.price = price;
this.name = name;
}
@Override
public String toString() {
return "Apple{" +
"price=" + price +
", name='" + name + '\'' +
'}';
}
}
Demo类:
package com.reflect.construtorexample;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> classApple = Class.forName("com.reflect.construtorexample.Apple");
// 获取无参构造
Constructor<?> declaredConstructor = classApple.getDeclaredConstructor();
Object apple = declaredConstructor.newInstance();
System.out.println(apple);
// 获取public构造
Constructor<?> declaredConstructor2 = classApple.getDeclaredConstructor(double.class, String.class);
Object apple2 = declaredConstructor2.newInstance(14, "黄元帅");
System.out.println(apple2);
// 获取参数列表
Class<?>[] parameterTypes = declaredConstructor2.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("\t\t参数类型:" + parameterType);
}
// 获取private构造
Constructor<?> declaredConstructor3 = classApple.getDeclaredConstructor(double.class);
// 设置可以访问构造器
declaredConstructor3.setAccessible(true);
Object apple3 = declaredConstructor3.newInstance(19);
System.out.println(apple3);
}
}