Java在名为synthetic
和bridge
的方法上有特殊标记。
JLS 13.1.7,“Java编译器引入的任何构造都没有相应的构造 源代码中的构造必须标记为合成 ...“
因此,合成方法是由编译器生成的任何内容,并且未在源代码中表示,虽然在该规范中没有提及PDF,但 bridge 方法用于类型检查泛型。 (例如Animal.interactWith(Creature c)
获得一个桥接方法interactWith(Object c)
,它转换为生物并调用另一种方法。)
我们有一个名为Bukkit的API,它可以提供稳定的访问权限来改变Minecraft服务器的工作方式。我们几乎无法控制的API(也称为vanilla Minecraft)的底层实现的一个方面是,最近在版本1.6.1
中强制将其从整数值更改为浮点值。为了避免另一次更改的困难,我们选择将所有API方法更改为double
。
所以,例如:
public int getHealth();
public void setHealth(int health);
// Must now be
public double getHealth();
public void setHealth(double health);
然而,与往常一样,我们希望使用以前版本1.5.2
编译的插件尽可能地工作 - 这就是API的重点。
setHealth
是一个已解决的问题,只是引入了一个重载。
目前,我们有一个名为_INVALID_getHealth(V)I
的方法,它在实现编译时重命名(不 API编译)到getHealth(V)I
,这样就可以让老插件继续运行。 / p>
但是,当有人试图扩展这些重命名方法的实现时,它们会从双重命名的方法中获得编译错误并覆盖。
有没有办法使用手动/工具插入合成或桥接方法提供int
和double
返回,不会导致那些尝试更改部分API实现的人会出现编译错误吗?
答案 0 :(得分:2)
答案是是 - 如果您使用不同的返回类型标记方法,但是使用与composite和bridge相同的参数,则可以编译子类。
在这种特定情况下,创建了一个新的Maven实用程序" Overmapper"来执行此任务,尽管您可以在任何可以编辑Java字节码的自动化工具中执行此操作。这是配置文件:
members:
"org/bukkit/entity/Damageable _INVALID_damage (I)V": damage
"org/bukkit/entity/Damageable _INVALID_damage (ILorg/bukkit/entity/Entity;)V": damage
"org/bukkit/entity/Damageable _INVALID_getHealth ()I": getHealth
"org/bukkit/entity/Damageable _INVALID_setHealth (I)V": setHealth
"org/bukkit/entity/Damageable _INVALID_getMaxHealth ()I": getMaxHealth
"org/bukkit/entity/Damageable _INVALID_setMaxHealth (I)V": setMaxHealth
"org/bukkit/entity/LivingEntity _INVALID_getLastDamage ()I": getLastDamage
"org/bukkit/entity/LivingEntity _INVALID_setLastDamage (I)V": setLastDamage
"org/bukkit/event/entity/EntityDamageEvent _INVALID_getDamage ()I": getDamage
"org/bukkit/event/entity/EntityDamageEvent _INVALID_setDamage (I)V": setDamage
"org/bukkit/event/vehicle/VehicleDamageEvent _INVALID_getDamage ()I": getDamage
"org/bukkit/event/vehicle/VehicleDamageEvent _INVALID_setDamage (I)V": setDamage
"org/bukkit/event/entity/EntityRegainHealthEvent _INVALID_getAmount ()I": getAmount
"org/bukkit/event/entity/EntityRegainHealthEvent _INVALID_setAmount (I)V": setAmount
"org/bukkit/entity/Minecart _INVALID_getDamage ()I": getDamage
"org/bukkit/entity/Minecart _INVALID_setDamage (I)V": setDamage
"org/bukkit/entity/Projectile _INVALID_getShooter ()Lorg/bukkit/entity/LivingEntity;": getShooter
"org/bukkit/entity/Projectile _INVALID_setShooter (Lorg/bukkit/entity/LivingEntity;)V": setShooter
"org/bukkit/Bukkit _INVALID_getOnlinePlayers ()[Lorg/bukkit/entity/Player;": getOnlinePlayers
"org/bukkit/Server _INVALID_getOnlinePlayers ()[Lorg/bukkit/entity/Player;": getOnlinePlayers
flags:
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getHealth ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart getHealth ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getMaxHealth ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart getMaxHealth ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setHealth (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart setHealth (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setMaxHealth (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart setMaxHealth (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity damage (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart damage (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity damage (ILorg/bukkit/entity/Entity;)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart damage (ILorg/bukkit/entity/Entity;)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getLastDamage ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setLastDamage (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftMinecart setDamage (I)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftMinecart getDamage ()I": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftProjectile getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftProjectile setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftArrow getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftArrow setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFireball getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFireball setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFish getShooter ()Lorg/bukkit/entity/LivingEntity;": 0x1001
"org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFish setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001
您可以看到所有返回int的方法都被更改为标记为桥接和合成。
答案 1 :(得分:-1)
如果您想对实体运行状况执行某些操作,可以转换为Damageable
,然后就不会出现编译错误。
Entity e = /* some entity */;
double health = ((Damageable) e).getHealth();
这应该有效。 我希望它有所帮助