#|头歌Educoder——Java高级特性 - Java反射
文章目录
- 第1关:了解 Class 对象
-
- 任务描述
- 相关知识
-
- Class 对象
- 三种获取Class类型的实例的方法
- 三种方法获取的 Class 对象之间的区别
- 编程要求
- 测试说明
- 代码样例
-
- Reflect_stu.java
- Reflect_run.java
- Person.java
- 第2关:利用反射分析类的能力
-
- 任务描述
- 相关知识
-
- 反射的基本概念
- Class 对象与反射之间的关系
- Class 的类结构
- 利用反射分析类的能力
- 编程要求
- 测试说明
- 代码样例
-
- Reflect_stu.java
- Reflect_run.java
- Person.java
- 第3关:在运行时使用反射分析对象
-
- 任务描述
- 相关知识
-
- 如何通过 `Field` 类的 `get` 方法获取对象域
- 如何绕过 `Java` 安全访问控制获取私有对象域
- 获取对象域时数值类型如何处理
- 编程要求
- 测试说明
- 代码示例
-
- Reflect_stu.java
- Reflect_run.java
- 第4关:利用反射进行方法调用
-
- 任务描述
- 相关知识
-
- 如何通过反射创建对象
- 如何通过反射调用对象方法
- 编程要求
- 测试说明
- 代码示例
-
- Reflect_stu.java
- Reflect_run.java
第1关:了解 Class 对象 任务描述 本关任务:实现获取
Class
对象的三种方式相关知识 为了完成本关任务,你需要掌握:
Class
对象;- 三种获取
Class
类型的实例的方法;- 通过
Object
类中的getClass()
方法; - 通过静态方法
Class.forName("全类名")
; - 通过类字面常量
Class.class
。
- 通过
- 三种方法获取的
Class
对象之间的区别。
- 在程序运行期间,
Java
运行时系统始终为所有的对象维护一个被称为运行时的类型标识(RTTI
)。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。保存这些信息的类被称为Class
,可以通过专门的Java
类访问这些信息。 Class
类的实例表示正在运行的Java
应用程序中的类和接口。其中枚举是一种特殊的类,注释是一种特殊的接口。每个数组属于被映射为Class
对象的一个类,所有具有相同元素类型和维数的数组都共享该Class
对象基本的Java
类型(boolean
、byte
、char
、short
、int
、long
、float
和double
)和关键字void
也表示为Class
对象。Class
对象就是用来创建类的所有的”常规”对象的。每个类都有一个Class
对象,每当编写一个并且编译了一个新类,就会产生一个Class
对象(保存在体同名的.class
文件中)。Class
没有公共构造方法。Class
对象是在加载类时由Java
虚拟机以及通过调用类加载器中的defineClass
方法自动构造的。
方法1:通过
Object
类中的getClass()
方法返回一个Class
类型的实例示例如下:
Person person = new Person();
Class clazz = person.getClass();
【#|头歌Educoder——Java高级特性 - Java反射】方法2:通过静态方法
Class.forName("全类名")
获取类名对应的Class
对象Class.forName()
方法原型:public static Class forName(String className) throws ClassNotFoundException
若无法根据类路径
className
找到对应的 .class
文件会抛出 ClassNotFoundException
异常,因此使用forName()
方法需要捕获异常或向上抛出异常。示例如下:
Class clazz = null;
String className = "step1.Person";
try {
clazz = Class.forName(className);
} catch(ClassNotFoundException e) {
}
方法3:通过类字面常量
Class.class
获取示例如下:
Class clazz = Person.class;
该方法不仅更简单,而且更安全,因为它在编译时就会受到检查(因此不需要置于
try
语句块中)。并且它根除了对forName()
方法的调用,所以更高效。三种方法获取的 Class 对象之间的区别
每个类都有一个
Class
对象,因此对于某个类使用三种方式获取的 Class
对象都是相等。编程要求 请仔细阅读右侧代码,结合相关知识,在
Begin-End
区域内进行代码补充,完成三个方法getPersonClass1()
、getPersonClass2()
、getPersonClass3()
的代码编写,要求分别使用三种方式获取Person
类的Class
对象并返回。 注意:无需修改main()
方法的输出内容。测试说明 平台会对你编写的代码进行测试:
预期输出:
通过Object 类中的 getClass() 获取的 Class 对象为:class step1.Person
通过静态方法 Class.forName() 获取的 Class 对象为:class step1.Person
通过类字面常量获取 Class 的对象为:class step1.Person
开始你的任务吧,祝你成功!
代码样例 Reflect_stu.java
package step1;
/**
* 学员任务文件
*/
public class Reflect_stu { public static void main(String[] args) {
System.out.println("通过Object 类中的 getClass() 获取的 Class 对象为:" + getPersonClass1());
System.out.println("通过静态方法 Class.forName() 获取的 Class 对象为:" + getPersonClass2());
System.out.println("通过类字面常量获取 Class 的对象为:" + getPersonClass3());
} /**
* 通过 Object 类中的 getClass() 获取的 Class 对象
*
* @return
*/
public static Class getPersonClass1() {
/********** Begin *********/
Person person = new Person();
Class clazz1 = person.getClass();
return clazz1;
/********** End *********/
} /**
* 通过静态方法 Class.forName() 获取的 Class 对象
* * 注意:Person 类的全路径为: step1.Person
*
* @return
*/
public static Class getPersonClass2() {
/********** Begin *********/
String className = "step1.Person";
Class clazz2 = null;
try {
clazz2 = Class.forName(className);
} catch (ClassNotFoundException e) {
}return clazz2;
/********** End *********/
} /**
* 通过类字面常量获取 Class 的对象
*
* @return
*/
public static Class getPersonClass3() {
/********** Begin *********/
Class clazz3 = Person.class;
return clazz3;
/********** End *********/
}
}
Reflect_run.java
package step1;
/**
* 评测执行文件
*/public class Reflect_run {public static void main(String[] args) {
//Class clazz1 = Person.class;
2、通过对象的getClass()方法返回一个Class类型的实例
//Person person = new Person();
//Class clazz2 = person.getClass();
3、通过静态方法Class.forName()获取类名对应的Class对象
//Class clazz3 = null;
//try {
//clazz3 = Class.forName("step1.Person");
//} catch (ClassNotFoundException e) {
//e.printStackTrace();
//}
//
//// 使用 "==" 进行比较 clazz1 与 clazz2 的关系
//System.out.println(clazz1 == clazz2);
//// 使用 "==" 进行比较 clazz2 与 clazz3 的关系
//System.out.println(clazz2 == clazz3);
System.out.println("通过Object 类中的 getClass() 获取的 Class 对象为:" + getPersonClass1());
System.out.println("通过静态方法 Class.forName() 获取的 Class 对象为:" + getPersonClass2());
System.out.println("通过类字面常量获取 Class 的对象为:" + getPersonClass3());
}/**
* 通过 Object 类中的 getClass() 获取的 Class 对象
*
* @return
*/
public static Class getPersonClass1() {
return new Person().getClass();
}/**
* 通过静态方法 Class.forName() 获取的 Class 对象
*
* @return
*/
public static Class getPersonClass2() {
Class clazz = null;
try {
clazz = Class.forName("step1.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return clazz;
}/**
* 通过类字面常量获取 Class 的对象
*
* @return
*/
public static Class getPersonClass3() {
return Person.class;
}
}
Person.java
package step1;
public class Person {}
第2关:利用反射分析类的能力 任务描述 本关任务:利用反射获取
Apple
类的的所有的方法和构造器签名,以及全部域名。相关知识 为了完成本关任务,你需要回顾上节所学
Class
对象的相关知识, 以及需要掌握以下知识:- 反射的基本概念;
Class
对象与反射之间的关系;Class
的类结构;- 利用反射分析类的能力。
反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
Class 对象与反射之间的关系
Java
反射机制允许程序在运行时取得任何一个已知名称的Class
的内部信息,包括其 modifiers
(修饰符)、fields
(属性),methods
(方法)等,并可于运行时改变 fields
内容或调用 methods
。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!Class 的类结构
在
java.lang.reflect
包中有三个类Field
、Method
和Constructor
分别用于描述类的域、方法和构造器。Class
类中的getFields()
、getMethods()
和getConstructors()
方法将分别返回类提供的 public
域、方法和构造器,其中包括超类的共有成员。Class
类中的getDeclareFields()
、getDeclareMethods()
和getDeclareConstructors()
方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。如:
public Field[] getFields() throws SecurityException
public Method[] getMethods() throws SecurityException
public Constructor[] getConstructors() throws SecurityException
利用反射分析类的能力
通过获取某个类的
Class
对象,并通过Class
类的 getFields()
、getMethods()
和getConstructors()
获得所有域、方法和构造器。示例:
class Person {
public String name;
String sex;
protected String height;
private int age;
public Person() {
}
private Person(String name) {
this.name = name;
}
public Person(String name, String sex, String height, int age) {
...省略
}
}
public static void main(String[] args) {
Person person = new Person();
printConstructors(person.getClass());
}
public static void printConstructors(Class clazz) {
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
String name = constructor.getName();
System.out.print("");
String modifiers = Modifier.toString(constructor.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
System.out.print(name + "(");
Class[] paramTypes = constructor.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 Person();
public Person(java.lang.String,java.lang.String,java.lang.String,int);
编程要求 请仔细阅读右侧代码,结合相关知识,在
Begin-End
区域内进行代码补充,打印Apple
类的所有public
域、方法和构造器。已分别提供了方法声明printConstructors
、printFields
、printMethods
,请将代码补充完整,且按照打印格式要求输出。提示:
Method.getReturnType()
可以获得方法的返回类型。- 打印方法或域的修饰符可以调用提供的
printModifiers()
方法 - 打印方法的参数可以调用提供的
printParamTypes()
方法 Field
的getType
方法可以获得域类型、getName
方法可以获得域的名称
private java.lang.String name;
public step2.Apple();
public step2.Apple(java.lang.String);
public void setName(java.lang.String);
平台会对你编写的代码进行测试。
开始你的任务吧,祝你成功!
代码样例 Reflect_stu.java
package step2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
class Apple {
private String name;
public Apple() {
} public Apple(String name) {
} public void setName(String name) {
this.name = name;
}
}public class Reflect_stu { public static void main(String[] args) {
// 请根据提供的 classPath 获取 step2.Apple 的 Class 对象, 请使用 Class.forName() 方法, 注意捕获异常
// 通关之后,你也可以修改 clasapath 为其他类路径,分析某个类的能力, 例如: java.util.Date
String classPath = "step2.Apple";
Class clazz = null;
/********** Begin *********/
try {
clazz = Class.forName(classPath);
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}/********** End *********/
printFields(clazz);
printConstructors(clazz);
printMethods(clazz);
} /**
* 请打印类的每个域,输出格式为:修饰符 类型 变量名;
*
* @param clazz
*/
public static void printFields(Class clazz) {
/********** Begin *********/
try {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.print(Modifier.toString(field.getModifiers()) + " ");
System.out.print(field.getType().getTypeName() + " ");
System.out.println(field.getName() + ";
");
}
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}/********** End *********/
} /**
* 打印构造函数,输出格式为:修饰符 方法名称(参数)
*
* @param clazz
*/
public static void printConstructors(Class clazz) {
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
Class[] paramTypes = null;
/********** Begin *********/paramTypes = constructor.getParameterTypes();
System.out.print(Modifier.toString(constructor.getModifiers()) + " ");
System.out.print(constructor.getName() + "(");
/********** End *********/
printParamTypes(paramTypes);
}
} /**
* 请针对每个方法打印其签名,格式为:修饰符 返回值类型 方法名称(参数);
*
* @param clazz
*/
public static void printMethods(Class clazz) {
Method[] methos = clazz.getDeclaredMethods();
for (Method method : methos) {
Class[] paramTypes = null;
/********** Begin *********/paramTypes = method.getParameterTypes();
System.out.print(Modifier.toString(method.getModifiers()) + " " + method.getReturnType().getName() + " "
+ method.getName() + "(");
/********** End *********/
printParamTypes(paramTypes);
}
} /**
* 打印方法参数
*
* @param paramTypes
*/
private static void printParamTypes(Class[] paramTypes) {
for (int j = 0;
j < paramTypes.length;
++j) {
if (j > 0) {
System.out.print(",");
}
System.out.print(paramTypes[j].getName());
}
System.out.println(");
");
}}
Reflect_run.java
package step2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Reflect_run {public static void main(String[] args) {
// 请根据提供的 classPath 获取 step2.Apple 的 Class 对象
String classPath = "step2.Apple";
Class clazz = null;
try {
clazz = Class.forName(classPath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
printConstructors(clazz);
printFields(clazz);
printMethods(clazz);
}public static void printConstructors(Class clazz) {
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
String name = constructor.getName();
printModifiers(clazz);
System.out.print(name + "(");
Class[] paramTypes = constructor.getParameterTypes();
printParamTypes(paramTypes);
}
}private static void printModifiers(Class clazz) {
System.out.print("");
String modifiers = Modifier.toString(clazz.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
}public static void printMethods(Class clazz) {
Method[] methos = clazz.getDeclaredMethods();
for (Method method : methos) {
Class returnType = method.getReturnType();
String name = method.getName();
printModifiers(clazz);
System.out.print(returnType.getName() + " " + name + "(");
Class[] paramTypes = method.getParameterTypes();
printParamTypes(paramTypes);
}
}private static void printParamTypes(Class[] paramTypes) {
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 clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Class type = field.getType();
String name = field.getName();
printModifiers(clazz);
System.out.println(type.getName() + " " + name + ";
");
}
}
}
Person.java
package step2;
public class Person {public String name;
protected String height;
String sex;
private int age;
public Person() {}public Person(String name) {
this.name = name;
}public Person(String name, String sex, String height, int age) {
this.name = name;
this.sex = sex;
this.height = height;
this.age = age;
}public String getSex() {
return sex;
}public void setSex(String sex) {
this.sex = sex;
}public String getHeight() {
return height;
}public void setHeight(String height) {
this.height = height;
}public int getAge() {
return age;
}public void setAge(int age) {
this.age = age;
}
}
第3关:在运行时使用反射分析对象 任务描述 本关任务:完成一个可供任意类使用的通用
toString(Object)
方法。相关知识 为了完成本任务,你需要掌握:
- 如何通过
Field
类的get
方法获取对象域; - 如何绕过
Java
安全访问控制获取私有对象域; - 获取对象域时数值类型如何处理。
Field
类的 get
方法获取对象域利用反射机制可以查看在编译时还不清楚的对象域。而查看对象域的关键方法就是
Field
类中的get
方法。Object | get(Object obj) 返回指定对象上此Field表示字段的值。 |
f
是一个Field
类型的对象(例如,通过getDeclaredFields()
得到的对象),obj
是一个包含f
域的类的对象, 那么f.get(obj)
将返回一个对象,其值为obj
域的当前值。如此就可以在运行时获得对象的域。示例:
class Person {
public Integer weight;
private Integer age;
private double height;
// 省略构造器、setter 和 getter 方法
}
public void test() {
Person person = new Person(123, 19);
Class clazz = person.getClass();
Field field = clazz.getDeclaredField("weight");
Object name = field.get(person);
System.out.println(name);
// 其打印结果为: "123"
}
如何绕过
Java
安全访问控制获取私有对象域那如果要获取对象的私有域呢,例如,要获取
Perso
小明的年龄呢,直接修改上面示例为getDeclaredField("age")
可以吗。答案是,不行,因为age
是一个私有域,所以get
方法会抛出一个 IllegalAccessException
异常。只有利用
get
方法才能得到可访问域的值。除非拥有访问权限,Java
安全机制只允许查看任意对象有哪些域,而不允许读取它们的值。反射机制的默认行为受限于
Java
的访问控制。然而,如果一个 Java
程序没有收到安全管理器的控制,就可以覆盖访问控制。调用 Field
、Method
或Constructor
对象的setAccessible
方法可以突破这种限制。示例:
public void test() {
Person person = new Person(123, 19, 175);
Class clazz = person.getClass();
Field field = clazz.getDeclaredField("age");
// 获取私有域的访问权限
field.setAccessible(true);
Object name = field.get(person);
System.out.println(name);
// 其打印结果为: "19"
}
获取对象域时数值类型如何处理
Object | get(Object obj) 返回指定对象上此Field表示字段的值。 |
get
方法还有一个要解决的问题。name
域是一个String
,因此可以作为Object
返回。但是,如果要查看height
域,它属于double
类型,而 Java
中数值类型不是对象。因此要使用Field
的其他 getXXX()
方法。反射机制会自动的将这个域值打包到相应的对象包装器中。double | getDouble(Object obj) 获取double类型或另一个通过扩展转换可以转换为double类型的基本类型的静态或实例字段的值。 |
---|---|
float | getFloat(Object obj) 获取float类型或另一个通过扩展转换可以转换为float类型的基本类型的静态或实例字段的值。 |
Type | getGenericType() 返回一个Tpye对象,它表示此Field对象所表示字段的声明类型。 |
int | getInt(Object obj) 获取int类型或另一个通过扩展转换可以转换为int类型的基本类型的静态或实例字段的值。 |
long | getLong(Object obj) 获取long类型或另一个通过扩展转换可以转换为long类型的基本类型的静态或实例字段的值。 |
Begin-End
区域内进行代码补充,完成通用toString()
方法。提示:
快速设置访问权限: ``AccessibleObject.setAccessible(fields, true);
``
获得所有域:``Class.getDeclaredFields()``
测试说明 平台会对你编写的代码进行测试。
示例:
public static void toString(Object obj) {
// 请完成代码
}
public static void main(String[] args) {
Person person = new Person(123, 19, 175);
toString(person);
}
预期输出:
[weight=[value=https://www.it610.com/article/123],age=[value=19],height=[value=175.0]]
开始你的任务吧,祝你成功!
代码示例 Reflect_stu.java
package step3;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Reflect_stu { public static String toString(Object obj) {
Class cl = obj.getClass();
String r = "";
r += "[";
// 请获取所有 Field 并设置访问权限为 true
/********** Begin *********/
Field[] fields = null;
fields = cl.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
/********** End *********/
for (Field f : fields) {
// 此处 if,逻辑为判断 Field 域是否为非静态域
if (!Modifier.isStatic(f.getModifiers())) {
if (!r.endsWith("["))
r += ",";
r += f.getName() + "=";
try {
// 请获取域的类型及值
/********** Begin *********/Class t = null;
Object val = null;
t = f.getType();
val = f.get(obj);
/********** End *********/
// isPrimitive() 用于判断是否为基本数据类型,若为基础数据类型直接拼接,否则递归调用 toString 方法
if (t.isPrimitive())
r += val;
else
r += toString(val);
} catch (Exception e) {
e.printStackTrace();
}
}
}
r += "]";
return r;
} public static void main(String[] args) {
Person person = new Person(88, 19, 175);
System.out.println(toString(person));
}
}class Person {
public Integer weight;
private Integer age;
private Double height;
public Person(Integer weight, Integer age, double height) {
this.weight = weight;
this.age = age;
this.height = height;
}
}
Reflect_run.java
package step3;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Reflect_run {public static String toString(Object obj) {
Class cl = obj.getClass();
String r = "";
r += "[";
Field[] fields = cl.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
if (!r.endsWith("[")) r += ",";
r += f.getName() + "=";
try {
Class t = f.getType();
Object val = f.get(obj);
if (t.isPrimitive()) r += val;
else r += toString(val);
} catch (Exception e) {
e.printStackTrace();
}
}
}
r += "]";
return r;
}public static void main(String[] args) {
Person person = new Person(88, 19, 175);
System.out.println(toString(person));
}}
第4关:利用反射进行方法调用 任务描述 本关任务:利用反射创建对象并调用其方法。
相关知识 为了完成本关任务,你需要掌握:
- 如何通过反射创建对象;
- 如何通过反射调用对象方法。
反射创建类对象主要有两种方式,通过
Class
对象的newInstance()
方法、通过Constructor
对象的 newInstance()
方法。- 第一种:通过
Class
对象的newInstance()
方法。
Class clazz = Apple.class; Apple apple = (Apple)clazz.newInstance();
- 第二种:通过
Constructor
对象的newInstance()
方法
Class clazz = Apple.class; Constructor constructor = clazz.getConstructor(); Apple apple = (Apple)constructor.newInstance();
Constructor
对象创建类对象可以选择特定构造方法,而通过 Class
对象则只能使用默认的无参数构造方法。示例:(调用有参构造方法进行类对象的初始化)
Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("红富士", 15);
如何通过反射调用对象方法
利用
Method
的invoke
方法可以调用执行对象obj
的方法More ActionsObjectinvoke(Object obj,Object… args) 对带有指定参数的指定对象调用由此Method对象表示的底层方法。 |
obj
表示要调用的Method
方法对象。 args
表示要调用的方法的参数,是可变长参数类型。示例:
// 获取类的 Class 对象实例
Class clz = Class.forName("Apple");
// 根据 Class 对象实例获取 Constructor 对象
Constructor appleConstructor = clz.getConstructor();
// 使用 Constructor 对象的 newInstance 方法获取反射类对象
Object appleObj = appleConstructor.newInstance();
// 而如果要调用某一个方法,则需要经过下面的步骤:
// 1、获取方法的 Method 对象
Method setPriceMethod = clz.getMethod("setPrice", int.class);
// 2、用 invoke 方法调用方法
setPriceMethod.invoke(appleObj, 14);
class Apple {
public void setPrice(int price) {
//省略
}
// 省略
}
编程要求 请仔细阅读右侧代码,结合相关知识,在
Begin-End
区域内进行代码补充,使用反射调用 Apple
类的 setPrice()
方法,设置苹果价格为 14
,并打印价格。接着还要用反射去调用getTotal
方法获取单价为 20
,数量 24
的总金额并打印。测试说明 预期输出:
14.0
480.0
平台会对你编写的代码进行测试。
开始你的任务吧,祝你成功!
代码示例 Reflect_stu.java
package step4;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflect_stu {
public static void main(String[] args) throws InvocationTargetException {
// 使用反射调用
Class clazz = null;
try {
clazz = Class.forName("step4.Apple");
/********** Begin *********/
Constructor cons = clazz.getConstructor();
Apple apple = (Apple) cons.newInstance();
Method method = clazz.getMethod("setPrice", double.class);
method.invoke(apple, 14);
Method getPrice = clazz.getMethod("getPrice");
System.out.println(getPrice.invoke(apple));
Method getTotal = clazz.getMethod("getTotal", double.class, int.class);
System.out.println(getTotal.invoke(apple, 20, 24));
/********** End *********/
} catch (Exception e) {
e.printStackTrace();
}
}}class Apple {
private double price;
private int count;
public Apple() {
} public double getPrice() {
return price;
} public void setPrice(double price) {
this.price = price;
} public int getCount() {
return count;
} public void setCount(int count) {
this.count = count;
} public double getTotal(double price, int count) {
return price * count;
}
}
Reflect_run.java
package step4;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflect_run {
public static void main(String[] args) throws InvocationTargetException {
//使用反射调用
Class clazz = null;
try {
clazz = Class.forName("step4.Apple");
Method setPriceMethod = clazz.getMethod("setPrice", double.class);
Constructor appleConstructor = clazz.getConstructor();
Object apple = appleConstructor.newInstance();
setPriceMethod.invoke(apple, 20);
Method getPriceMethod = clazz.getMethod("getPrice");
System.out.println(getPriceMethod.invoke(apple));
Method getTotal = clazz.getMethod("getTotal", double.class, int.class);
System.out.println(getTotal.invoke(apple, 20, 24));
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
推荐阅读
- 程序人生|95后阿里P7晒出工资单(狠补了这个,真香...)
- 比赛wp|[VNCTF2022]部分wp
- 程序人生|外包干了五年,废了...
- 数据库|TiDB Online DDL 在 TiCDC 中的应用丨TiDB 工具分享
- Java|几种常见的注册中心以及区别
- 大数据|最全的产品经理分类
- 前端|面试官(为什么Vue中的v-if和v-for不建议一起用)
- java|跳槽进字节跳动了,面试真简单。
- 发现Spring事务的一个实锤bug,官方还拒不承认(你来评评理...)