JAVA打怪升级-反射比较对象属性和属性值

JAVA打怪升级-反射比较对象属性和属性值

       最近开发遇到一个比较相同对象的同一字段的属性值,然后将对象的两次变化数据保存到数据库中的需求,这个对象实体字段比较多,而且包含的实体对象也很多,如果只是简单的写代码把两个对象需要的字段手动比较,那么则会有大量的冗余代码。同时,如果将记录日志写到原来的业务逻辑代码中,那么也会破坏原有的代码结构,而且也不利于后期的需求新增和代码修改。

       我这里只讲解通过工具类比较相同对象的相同属性的值,然后将数据差异展现出来,同时参数还支持特定字段比较,以及忽略某些比较字段。

PropertyModelInfo

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class PropertyModelInfo implements Serializable {

    private String propertyName;

    private Object value;

    private Class<?> returnType;

}

ModifiedPropertyInfo

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ModifiedPropertyInfo implements Serializable {

    private String propertyName;

    private Object oldValue;

    private Object newValue;

}

CompareUtil

/**
 * 对象比较工具类
 *
 * @version 0.1.0
 * @create 2020-12-09 14:32
 * @since 0.1.0
 **/
@Log4j2
public class CompareUtil {

    /**
     * 比较两个对象属性值是否相同,如果不同返回修改过的属性信息集合,包括:字段名,原始数据值,新值
     *
     * @param oldObj       原始对象
     * @param newObj       新对象
     * @param ignoreFields 忽略比较字段,如果忽略比较字段和记录比较字段中都有相同字段,则忽略比较字段优先级较高
     * @param recordFields 记录比较字段
     * @return 变化后的数据集合
     * @version 0.1.0
     * @date 2020/12/9 14:34
     * @since 0.1.0
     */
    public static <T> List<ModifiedPropertyInfo> compareProperty(
            @NonNull T oldObj,
            @NonNull T newObj,
            List<String> ignoreFields,
            List<String> recordFields
    ) {
        // 通过反射获取原始对象的属性名称、getter返回值类型、属性值等信息
        List<PropertyModelInfo> oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreFields, recordFields);
        // 通过反射获取新对象的属性名称、getter返回值类型、属性值等信息
        List<PropertyModelInfo> newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreFields, recordFields);

        // 定义修改属性值接收器集合,包括:字段名,原始数据值,新值
        List<ModifiedPropertyInfo> modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size());

        // 获取新对象所有属性、属性值
        Map<String, Object> newObjectInfoMap = getObjectPropertyAndValue(newObjectPropertyValue);
        // 获取原始对象所有属性、属性值
        Map<String, Object> oldObjectInfoMap = getObjectPropertyAndValue(oldObjectPropertyValue);

        // 处理原始对象数据内容并和新对象的属性、属性值比较
        for (Map.Entry<String, Object> oldInfoMap : oldObjectInfoMap.entrySet()) {
            String oldKey = oldInfoMap.getKey();
            Object oldValue = oldInfoMap.getValue();

            // 比较原始对象和新对象之间的属性和属性值差异
            if (newObjectInfoMap.containsKey(oldKey)) {
                ModifiedPropertyInfo modifiedPropertyInfo = new ModifiedPropertyInfo();
                Object newValue = newObjectInfoMap.get(oldKey);

                if (oldValue != null && newValue != null) {
                    // 初始值和新值不为空比较值
                    if (!oldValue.equals(newValue)) {
                        modifiedPropertyInfo.setPropertyName(oldKey);
                        modifiedPropertyInfo.setOldValue(oldValue);
                        modifiedPropertyInfo.setNewValue(newValue);
                        modifiedPropertyInfos.add(modifiedPropertyInfo);
                    }
                } else if (oldValue == null && newValue == null) {
                    // 如果初始值和新值全部为空不做处理
                } else {
                    // 如果初始值和新值有一个为空
                    modifiedPropertyInfo.setPropertyName(oldKey);
                    modifiedPropertyInfo.setOldValue(oldValue);
                    modifiedPropertyInfo.setNewValue(newValue);
                    modifiedPropertyInfos.add(modifiedPropertyInfo);
                }
            }
        }
        return modifiedPropertyInfos;
    }

    /**
     * 组建对象属性和属性值信息数据
     *
     * @param objectPropertyValue 对象属性和属性值信息
     * @return 对象属性和属性值信息
     * @version 0.1.0
     * @date 2020/12/9 17:25
     * @since 0.1.0
     */
    private static Map<String, Object> getObjectPropertyAndValue(List<PropertyModelInfo> objectPropertyValue) {
        Map<String, Object> objectInfoMap = new HashMap<>(16);
        for (PropertyModelInfo propertyModelInfo : objectPropertyValue) {
            // 对象属性名称
            String propertyName = propertyModelInfo.getPropertyName();
            // 对象属性值
            Object value = propertyModelInfo.getValue();
            objectInfoMap.put(propertyName, value);
        }
        return objectInfoMap;
    }

    /**
     * 通过反射获取对象的属性名称、getter返回值类型、属性值等信息
     *
     * @param obj          对象
     * @param ignoreFields 忽略字段属性集合
     * @param recordFields 比较字段属性集合
     * @return 对象的信息
     * @version 0.1.0
     * @date 2020/12/9 16:49
     * @since 0.1.0
     */
    private static <T> List<PropertyModelInfo> getObjectPropertyValue(
            @NonNull T obj,
            List<String> ignoreFields,
            List<String> recordFields
    ) {
        Class<?> objClass = obj.getClass();
        PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass);
        List<PropertyModelInfo> modelInfos = new ArrayList<>(propertyDescriptors.length);

        // 遍历对象属性信息
        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            String name = propertyDescriptor.getName();
            Method readMethod = propertyDescriptor.getReadMethod();
            // 该字段属性是否被过滤
            boolean isIgnore = ignoreFields == null || !ignoreFields.contains(name);
            // 该字段属性是否必须被比较
            boolean isRecord = recordFields == null || recordFields.contains(name);
            if (readMethod != null && isIgnore && isRecord) {
                try {
                    // 获取数据类型
                    Class<?> returnType = readMethod.getReturnType();
                    // 获取数据值
                    Object invoke = readMethod.invoke(obj);
                    modelInfos.add(new PropertyModelInfo(name, invoke, returnType));
                } catch (IllegalAccessException | InvocationTargetException e) {
                    log.error("反射获取类:" + objClass.getName() + "方法异常:", e);
                }
            }
        }
        return modelInfos;
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A:好的,以下是一个基于Java实现的打怪升级小游戏示例: 首先,我们需要设计游戏中所需的角色和怪物类,以及它们的属性和方法。假设我们的游戏中有玩家角色和怪物角色,它们都有姓名、等级、血量、攻击力和防御力属性。 ``` // 角色类 public abstract class Character { String name; int level; int health; int attack; int defense; public abstract void attack(Character target); public abstract void levelUp() } // 玩家类 public class Player extends Character { int experience; public Player(String name, int level, int health, int attack, int defense) { this.name = name; this.level = level; this.health = health; this.attack = attack; this.defense = defense; this.experience = 0; } public void attack(Character target) { int damage = this.attack - target.defense; target.health -= damage; System.out.println(this.name + "攻击了" + target.name + ", 造成了" + damage + "点伤害!"); if (target.health <= 0) { System.out.println(target.name + "已经不能战斗了!"); this.experience += target.level * 10; levelUp(); } } public void levelUp() { if (this.experience >= this.level * 100) { this.experience -= this.level * 100; this.level++; System.out.println(this.name + "升级了,当前等级为" + this.level + "!") this.health += 10; this.attack += 5; this.defense += 5; } } } // 怪物类 public class Monster extends Character { public Monster(String name, int level, int health, int attack, int defense) { this.name = name; this.level = level; this.health = health; this.attack = attack; this.defense = defense; } public void attack(Character target) { int damage = this.attack - target.defense; target.health -= damage; System.out.println(this.name + "攻击了" + target.name + ", 造成了" + damage + "点伤害!"); if (target.health <= 0) { System.out.println(target.name + "已经不能战斗了!"); } } } ``` 接着,我们设计游戏管理类,负责控制游戏的流程和事件。在游戏初始化时,随机生成若干只怪物,并让玩家与它们进行战斗。当玩家击败所有怪物后,玩家等级提升,再次与新的怪物战斗,直到达到最高等级或失败。 ``` //游戏管理类 public class GameEngine { List<Character> enemies; Player player; public GameEngine(String playerName) { List<Integer> levels = Arrays.asList(1, 2, 3, 4, 5); List<Integer> healths = Arrays.asList(10, 20, 30, 40, 50); List<Integer> attacks = Arrays.asList(5, 10, 15, 20, 25); List<Integer> defenses = Arrays.asList(5, 10, 15, 20, 25); Random random = new Random(); enemies = new ArrayList<Character>(); for (int i = 0; i < 5; i++) { Monster monster = new Monster("怪物" + (i+1), levels.get(random.nextInt(levels.size())), healths.get(random.nextInt(healths.size())), attacks.get(random.nextInt(attacks.size())), defenses.get(random.nextInt(defenses.size()))); enemies.add(monster); } player = new Player(playerName, 1, 50, 20, 10); } public void start() { System.out.println("游戏开始!"); for (Character enemy : enemies) { while (player.health > 0 && enemy.health > 0) { player.attack(enemy); if (enemy.health <= 0) { break; } enemy.attack(player); } } System.out.println("当前等级为" + player.level + ", 经验为" + player.experience + ", 准备下一场战斗!"); while (player.health > 0 && player.level < 5) { Monster monster = new Monster("怪物" + (player.level + 1), player.level + 1, 50 + player.level * 10, 20 + player.level * 5, 10 + player.level * 5); System.out.println("出现新的怪物:" + monster.name + "!"); while (player.health > 0 && monster.health > 0) { player.attack(monster); if (monster.health <= 0) { break; } monster.attack(player); } } if (player.health <= 0) { System.out.println(player.name + "被击败了,游戏结束!"); } else { System.out.println("恭喜" + player.name + "升到了最高等级" + player.level + ",游戏结束!"); } } } ``` 最后,在主函数中创建游戏管理对象并启动游戏: ``` public static void main(String[] args) { String playerName = "玩家1"; GameEngine game = new GameEngine(playerName); game.start(); } ``` 以上是一个简单的打怪升级小游戏示例,您可以根据自己的需求和想法添加更多的游戏元素和玩法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值