(1)反射getter And setter

本文介绍了一种通过Java反射机制封装getter和setter方法的技术,旨在提高代码复用性和简化操作过程。作者通过具体示例展示了如何封装这些方法并提供了一种更简洁的调用方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近来封装了很多发射的小方法,使用过程中,发觉发射的好处是:当很多类有共性时,使用发射,可以达到只做一次,到处使用的效果。就像Hibernate一样,save(obj),我并不需要知道obj到底是哪个类,Hibernate自动会正确的把记录保存到数据库!

 

备注:

我使用反射封装一些小方法,是为了对大部分有共性的方法通用,所以要求,

a.类的属性必须有getXXX与setXXX方法;

b.getXXX,setXXX,XXX必须与类的字段名一致,而首字母大写;

c.getXXX是无参的,setXXX参数只能有1个,而且类型必须与属性一致(除了基础数据类型,他们可以自动打包)

d.最好有一个无参构造函数

 

我将有关反射的方法都放入了BeanReflectUtil,作为工具类使用。

 

准备一个简单的类(我的小方法也就只能对简单的类其作用)

public class Person {

	private String name;
	private int age;
	private Date birthday;
	
	public Person() {
	}
	
	public Person(String name, int age, Date birthday) {
		super();
		this.name = name;
		this.age = age;
		this.birthday = birthday;
	}

	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;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}

 

 

1.封装getter

/***
* 组装类中某个属性的get方法名称
* StringUtil.upperFirst(String str)是自己封装的,将首字母变大小的小方法;
* @param c
* @param filedName
* @return
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static Method assembleGetMethod(Class<?> c, String filedName)  throws SecurityException, NoSuchMethodException {
    String methodName = "get" + StringUtil.upperFirst(filedName);
    Class<?>[] nullClasses = null;
    return c.getDeclaredMethod(methodName, nullClasses);
}

 调用方法实例:

Method m = BeanReflectUtil.assembleGetMethod(Person.class, "name");
m.invoke(new Person("jack"), null);

 为了进一步——偷懒,将封装一个小方法:

public static Object invokeGetMethod(Class<?> c, String filedName, Object obj) 
  throws SecurityException, NoSuchMethodException, IllegalArgumentException, 
  IllegalAccessException, InvocationTargetException {
  Method method = assembleGetMethod(c, filedName);
  Object[] nullObjects = null;
  return method.invoke(obj, nullObjects);
 }

 那么,我们使用某个属性的getter方法时,只需要

BeanReflectUtil.invokeGetMethod(Person.class, "name", new Person("jack"));

 就可以了。

 

 2.封装setter方法

与getter方法不一样的地方是:getXXX()是无参的,

所以,封装的时候,需要告诉他参数的类型;调用的时候,要给一个参数!

/***
 * 组装类中某个属性的set方法名称
 * @param c 要封装哪个类
 * @param filed 封装哪个属性
 * @return
 * @throws SecurityException
 * @throws NoSuchMethodException
 */
public static Method assembleSetMethod(Class<?> c, Field field) 
 throws SecurityException, NoSuchMethodException {
 String methodName = "set" + StringUtil.upperFirst(field.getName());
 Class<?>[] parameterClasses = new Class[]{field.getType()}; //告诉Java该set方法的参数类型
 return c.getDeclaredMethod(methodName, parameterClasses);
}

 调用:

Method setMethod = BeanReflectUtil.assembleSetMethod(Person.class, Person.class.getDeclaredField("name"));
Person p = new Person();
setMethod.invoke(p, "jack");
System.out.println(p.getName());

 想进一步偷懒,可以

/**
 * 封装Set方法,并立刻调用
 * @param c 为哪个类封装Set方法
 * @param fieldName 属性名称
 * @param obj 为哪个对象赋值
 * @param fieldValue 赋的值
 */
public static void invokeSetMethod(Class<?> c, String fieldName, Object obj, Object fieldValue) 
	throws SecurityException, NoSuchFieldException, 
		NoSuchMethodException, IllegalArgumentException, 
		IllegalAccessException, InvocationTargetException {
	Field f = c.getDeclaredField(fieldName);
	Method setMethod = assembleSetMethod(c, f);
	setMethod.invoke(obj, fieldValue);
}

 

调用方法:

invokeSetMethod(Person.class, "name", p, "Mike");
System.out.println(p.getName());

 

但,实际使用中,应该不会用到,

我的想象场景是:有一堆Map<Person p, String name>

我获得set方法后,会为很多Map中的Person的name属性赋上Map中的name值,

所以,不会组装好set后就马上调用,这样效率也太低了。

<think>我们正在修复CartSummary类,根据描述有两个问题:1.getCartItems方法的返回类型不匹配:在CartController中,我们期望getCartItems返回的是List<CartItem>,但是问题提到返回类型不匹配,可能是CartSummary类中定义的类型不正确。2.缺失构造器、gettersetter:在CartSummary类中,我们需要为所有字段提供构造器getter/setter方法。根据之前的上下文,CartSummary类应该包含以下字段:privateList<CartItem>cartItems;privatedoubletotalPrice;privatedoublediscount;privatedoublefinalPrice;所以,我们需要:1.确保cartItems字段的类型为List<CartItem>,并且getCartItems方法返回List<CartItem>。2.提供包含这四个字段的构造器。3.为每个字段提供gettersetter方法。另外,我们也可以使用IDE(如IntelliJIDEA)的生成功能快速生成构造器getter/setter,如引用[4]所述。下面修复后的CartSummary类代码:</think> ### 修复后的CartSummary类代码 ```java public class CartSummary { private List<CartItem> cartItems; private double totalPrice; private double discount; private double finalPrice; // 构造器 - 修复缺失问题 public CartSummary(List<CartItem> cartItems, double totalPrice, double discount, double finalPrice) { this.cartItems = cartItems; this.totalPrice = totalPrice; this.discount = discount; this.finalPrice = finalPrice; } // 修复getCartItems返回类型不匹配问题 public List<CartItem> getCartItems() { return cartItems; } // Setter for cartItems public void setCartItems(List<CartItem> cartItems) { this.cartItems = cartItems; } public double getTotalPrice() { return totalPrice; } public void setTotalPrice(double totalPrice) { this.totalPrice = totalPrice; } public double getDiscount() { return discount; } public void setDiscount(double discount) { this.discount = discount; } public double getFinalPrice() { return finalPrice; } public void setFinalPrice(double finalPrice) { this.finalPrice = finalPrice; } } ``` ### 主要修复点说明 1. **修复getCartItems返回类型不匹配** - 将`getCartItems()`的返回类型从原始代码中的`List<String>`或其它错误类型改为`List<CartItem>`[^1] - 正确封装`cartItems`集合属性,保持类型一致性封装性 2. **添加完整构造器** - 增加了包含所有字段的构造器,解决缺失构造器问题 - 确保所有字段都能在对象创建时被正确初始化 3. **补充getter/setter方法** - 为所有属性添加完整的gettersetter方法[^4] - 遵循JavaBean规范,兼容Spring等框架的反射机制[^2] 4. **保持封装性** - 所有字段使用`private`修饰,外部只能通过getter/setter访问 - 有效控制数据操作边界,避免不合理的状态变更 ### 优化建议 1. **使用IDE自动生成** ```java // 在IntelliJ IDEA中: // 右键 > Generate > Constructor > 选择所有字段 // 右键 > Generate > Getter and Setter > 选择所有字段 ``` 2. **添加空安全处理** ```java public List<CartItem> getCartItems() { // 返回不可修改的空集合替代null return cartItems != null ? cartItems : Collections.emptyList(); } ``` 3. **增强不可变性** ```java public List<CartItem> getCartItems() { // 返回不可修改的拷贝集合 return Collections.unmodifiableList(new ArrayList<>(cartItems)); } ``` > **重要原则**:getter/setter方法应保持简单,业务逻辑不应放在getter/setter中[^2]。复杂逻辑应放在业务层的Service类中实现[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值