Use reflection to get rid of the long if/else check

“This is the first day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021”

The introduction

Recently had a business, you need to do to limit, beyond the limit to do special business processing, encapsulates a method for limit of check, because you need to determine the amount of too many fields if/else judgment also will increase, so the thought of using reflection to do processing, reduce the amount of code at the same time, the subsequent also compare strong extensibility.

The business entity

Here is the business entity class, with special treatment for field names.

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ExpendLimit{
    private BigDecimal count1Amt;
	
    private BigDecimal count2Amt;
	
    private BigDecimal count3Amt;
	
    privateBigDecimal count4Amt; .// There are about 12 amount fields to check
}
Copy the code

Code comparison

CurrentResidue indicates the current amount remaining and currentTotal indicates the current payment. The logic is if count? If the Amt is greater than 0 and the value of currentResidue is greater than the value of currentResidue, false is returned.

Before using reflection

private boolean checkResidue(ExpendLimit currentResidue, ExpendLimit currentTotal){
	boolean result = true;
	if (currentTotal.getCount1Amt().compareTo(BigDecimal.ZERO)>0) {if (currentTotal.getCount1Amt().compareTo(currentResidue.getCount1Amt())>0){
			result = false; }}else if (currentTotal.getCount2Amt().compareTo(BigDecimal.ZERO)>0) {if (currentTotal.getCount2Amt().compareTo(currentResidue.getCount2Amt())>0){
			result = false; }}...// More than 40 lines will be needed to write it completely, and more code will be added if the subsequent business increases
	return result;
}
Copy the code

After using reflection

private boolean checkResidue(ExpendLimit currentResidue, ExpendLimit currentTotal) {
	boolean result = true;
	Class<? extends ExpendLimit> clazz = currentResidue.getClass();
	Field[] fields = clazz.getDeclaredFields();
	try {
		for (Field field : fields) {
			// Open private access
			field.setAccessible(true);
			// Get attributes
			String name = field.getName();
			if (name.contains("Amt")) {
				// Get the attribute value
				BigDecimal totalAmt = (BigDecimal) field.get(currentTotal);
				if (totalAmt.compareTo(BigDecimal.ZERO) > 0) {
					BigDecimal residueAmt = (BigDecimal) field.get(currentResidue);
					if (totalAmt.compareTo(residueAmt) > 0) {
						result = false;
						break;
					}
				}
			}
		}
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	}
	return result;
}
Copy the code

The basic principle of reflection

  • Compile phase: Compile phase loads all classes and stores information about each Class into a Class object, one for each Class. (If you don’t understand why there is only one Class object per Class, you can query the parent delegate model yourself.)
  • Get the Class object: call x.class/ x.goetclass ()/ class.forname () to get the CLZ of x’s Class object
  • Work with reflection: Get the Field/Method/Constructor object from the CLZ object for further work.

The API used by reflection

  • Java.lang. Class: Represents a Class
  • Java.lang.reflect. Method: Represents the Method of a class
  • Java.lang.reflect. Field: Represents a class member variable
  • Java. Lang. Reflect. Constructor: on behalf of the Constructor of a class

Function provided by reflection

  • Determine the class to which any object belongs at run time
  • Constructs an object of any class at run time
  • Determine which member variables and methods any class has at run time
  • Get information about generics at runtime
  • Call the member variables and methods of any object at run time
  • Annotations are processed at run time
  • Generating dynamic proxies

conclusion

Too long if/else judgments have been changed by using reflection. In my business, I actually only use the java.lang.Reflect. Field class to get object attributes for business judgment. In fact, reflection is used in many frameworks. Spring’s dynamic proxy also uses reflection. Both CGLAB dynamic proxy and JDK dynamic proxy use reflection at all.