写一个函数,传入任意的对象,可以将对象里面String类型的属性中的a改成b。
field.getClass()
private void changeField(Object object) throws IllegalAccessException {
//1.获得对应的字节码
Class clazz = object.getClass();//对象.getClass。 类.class
//2.获取所有的fields
Field[] fields = clazz.getDeclaredFields();//所有的 包括私有的
//3.遍历所有的field,如果是String类型,将包含a改为b
for (Field field : fields) {
//3.1 是String类型才修改
if (field.getType() == String.class) {
//属性是私有的
field.setAccessible(true);
//person.getName()
//3.2 获得field原来的值
String oldValue = (String) field.get(object);
if (oldValue == null || "".equals(oldValue)) {
continue;
}
String newValue = oldValue.replace("a", "b");
//3.3 将修改后的值设置到field
//person.setName("11");
field.set(object, newValue);
}
}
}
1 能不能用field.class == String.class来判断类型是否相等?
在 Java 中,使用 field.getType() == String.class
来判断字段的类型是否为 String
是正确的做法,而 field.class == String.class
则是错误的。原因在于 field
是一个 Field
对象,而不是一个类。field.class
指向的是 Field
类的字节码对象,而不是字段本身的类型。
正确的类型判断方法
要判断字段的类型是否为 String
,应该使用 field.getType()
方法。field.getType()
返回的是一个 Class
对象(压根不能这样写),表示该字段的类型。
正确的代码示例
private void changeField(Object object) throws IllegalAccessException {
// 1.获得对应的字节码
Class<?> clazz = object.getClass(); // 使用对象.getClass 获取类对象
// 2.获取所有的 fields
Field[] fields = clazz.getDeclaredFields(); // 获取所有的字段,包括私有字段
// 3.遍历所有的 field,如果是 String 类型,将包含 a 改为 b
for (Field field : fields) {
// 3.1 是 String 类型才修改
if (field.getType() == String.class) { // 正确的类型判断方法
// 属性是私有的
field.setAccessible(true);
// 获取字段的当前值
String oldValue = (String) field.get(object);
if (oldValue != null) { // 确保旧值不是 null
String newValue = oldValue.replace("a", "b");
// 将修改后的值设置到字段
field.set(object, newValue);
}
}
}
}
解释
field.getType() == String.class
:这是正确的判断方法。field.getType()
返回字段的类型Class
对象,通过比较它与String.class
,可以判断该字段是否是String
类型。field.class == String.class
:这是错误的,因为field
是一个Field
对象,而field.class
指向的是Field
类的字节码对象,而不是字段的类型。
其他注意事项
-
检查旧值是否为
null
:
在使用oldValue.replace("a", "b")
之前,应该检查oldValue
是否为null
,以避免NullPointerException
。 -
设置字段的可访问性:
使用field.setAccessible(true)
来访问私有字段。完成后,最好将其恢复为不可访问状态(可选)。 -
异常处理:
确保捕获和处理所有可能的异常,尤其是在反射操作中。
总结
在反射操作中,判断字段类型应该使用 field.getType() == String.class
。直接比较 field.class
与 String.class
是不正确的,因为 field
是 Field
类的实例,而不是表示字段的类型。通过正确的方法,可以有效地操作对象的字段,实现所需的功能。
2 field.getClass行不行?
field.getClass()
不能用于判断字段的类型是否为 String
。让我们更详细地解释原因并提供适当的方法。
详细解释
-
field.getClass()
:field
是一个Field
对象,因此field.getClass()
返回的是Field
类的Class
对象。这并不是字段的类型,而是Field
类本身的类型。- 换句话说,
field.getClass()
始终返回的是Field.class
,无论该Field
对象表示的是String
类型的字段还是其他类型的字段。
-
field.getType()
:field.getType()
返回的是这个字段的类型。例如,如果字段是String
类型,则field.getType()
返回String.class
。
示例代码和比较
错误的用法
if (field.getClass() == String.class) {
// 这段代码永远不会为 true,因为 field.getClass() 返回的是 Field.class
}
正确的用法
if (field.getType() == String.class) {
// 这段代码会在字段类型为 String 时为 true
}
完整示例
以下是如何正确判断字段是否为 String
类型的完整代码示例:
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[] args) throws IllegalAccessException {
Student student = new Student();
student.setName("aName");
student.setAge(20);
changeField(student);
System.out.println("Updated student: " + student);
}
private static void changeField(Object object) throws IllegalAccessException {
// 1.获得对应的字节码
Class<?> clazz = object.getClass();
// 2.获取所有的 fields
Field[] fields = clazz.getDeclaredFields();
// 3.遍历所有的 field,如果是 String 类型,将包含 a 改为 b
for (Field field : fields) {
// 3.1 是 String 类型才修改
if (field.getType() == String.class) { // 正确的类型判断方法
// 属性是私有的
field.setAccessible(true);
// 获取字段的当前值
String oldValue = (String) field.get(object);
if (oldValue != null) { // 确保旧值不是 null
String newValue = oldValue.replace("a", "b");
// 将修改后的值设置到字段
field.set(object, newValue);
}
}
}
}
static class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + '}';
}
}
}
关键点
field.getClass()
:返回Field
对象的类,即Field.class
,无法用于判断字段的类型。field.getType()
:返回字段的实际类型,可以用于判断字段是否为String
类型。
通过使用 field.getType()
,可以正确地判断字段的类型并实现所需的逻辑操作。
3 .class和.getClass()的测试
package com.sdust.day37;
public class Teacher {
private String name = "android";
private int age = 18;
private String address = "qingdao";
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + ", address="
+ address + "]";
}
}
@Test
public void testPointClass() {
System.out.println(String.class);
System.out.println("----------------------");
Class clazz = Teacher.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getClass());
System.out.println(field.getType());
}
}
class java.lang.String
----------------------
class java.lang.reflect.Field
class java.lang.String
class java.lang.reflect.Field
int
class java.lang.reflect.Field
class java.lang.String