使用 newInstance() 实例化 class 时出现 NoSuchMethodException
NoSuchMethodException when instantiating a class using newInstance()
我正在使用以下代码实例化包中的每个 class:
for (Class listenerClass : ClassGetter.getClassesForPackage(this, "cullan.listener")) {
Bukkit.getLogger().info(listenerClass.getSimpleName());
if (!listenerClass.getSimpleName().equals("EnchantmentListener")) {
try {
listenerClass.newInstance();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
这工作得很好,但是,当 classes 之一被实例化时我收到这个错误:
[07:07:58] [Server thread/WARN]: java.lang.InstantiationException: cullan.listener.AgilityListener
[07:07:58] [Server thread/WARN]: at java.lang.Class.newInstance(Unknown Source)
[07:07:58] [Server thread/WARN]: at cullan.main.DCEnchants.loadEnchants(DCEnchants.java:62)
[07:07:58] [Server thread/WARN]: at cullan.main.DCEnchants.onEnable(DCEnchants.java:24)
[07:07:58] [Server thread/WARN]: at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321)
[07:07:58] [Server thread/WARN]: at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340)
[07:07:58] [Server thread/WARN]: at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405)
[07:07:58] [Server thread/WARN]: at net.skycraftmc.PluginManager.PluginManagerPlugin.onCommand(PluginManagerPlugin.java:287)
[07:07:58] [Server thread/WARN]: at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
[07:07:58] [Server thread/WARN]: at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
[07:07:58] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:646)
[07:07:58] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchServerCommand(CraftServer.java:632)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.DedicatedServer.aO(DedicatedServer.java:409)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:373)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:709)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:612)
[07:07:58] [Server thread/WARN]: at java.lang.Thread.run(Unknown Source)
[07:07:58] [Server thread/WARN]: Caused by: java.lang.NoSuchMethodException: cullan.listener.AgilityListener.<init>()
[07:07:58] [Server thread/WARN]: at java.lang.Class.getConstructor0(Unknown Source)
这是抛出错误的 class:
package cullan.listener;
import cullan.type.EnchantmentRarity;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList;
import java.util.List;
public class AgilityListener extends EnchantmentListener{
private List<Player> players = new ArrayList<>();
public AgilityListener() {
super(Enchantment.getByName("Agility"), EnchantmentRarity.VERY_RARE);
startTimer();
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
if (players.contains(player)) {
players.remove(player);
}
}
private void startTimer() {
final PotionEffect effect = mainConfig.getAgilityEffect();
instance.getServer().getScheduler().scheduleSyncRepeatingTask(instance, new Runnable() {
@Override
public void run() {
for (Player player : instance.getServer().getOnlinePlayers()) {
ItemStack boots = player.getInventory().getBoots();
if (boots != null && boots.containsEnchantment(enchantment)) {
player.addPotionEffect(effect);
players.add(player);
} else if (players.contains(player)) {
player.removePotionEffect(effect.getType());
players.remove(player);
}
}
}
}, 10L, 10L);
}
}
如果我删除 startTimer() 方法,则不会发生错误。为什么会这样?
问题是您不是在尝试构建 AgilityListener
的实例 - 您是在尝试构建在 AgilityListener.startTimer
中创建的匿名内部 class 的实例。这就是为什么堆栈跟踪具有:
Caused by: java.lang.NoSuchMethodException: cullan.listener.AgilityListener.<init>()
“$1”表明它是一个匿名内部 class。
如果您只想过滤掉所有 nested/inner class,您可以扩大对 class 名称的检查:
if (!listenerClass.getSimpleName().equals("EnchantmentListener") &&
!listenerClass.getSimpleName().contains("$"))
或:
!listenerClass.isAnonymousClass()
等您还可以检查 class 是否具有 public 无参数构造函数,以及它是否可分配给 EnchantmentListener
.
我正在使用以下代码实例化包中的每个 class:
for (Class listenerClass : ClassGetter.getClassesForPackage(this, "cullan.listener")) {
Bukkit.getLogger().info(listenerClass.getSimpleName());
if (!listenerClass.getSimpleName().equals("EnchantmentListener")) {
try {
listenerClass.newInstance();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
这工作得很好,但是,当 classes 之一被实例化时我收到这个错误:
[07:07:58] [Server thread/WARN]: java.lang.InstantiationException: cullan.listener.AgilityListener
[07:07:58] [Server thread/WARN]: at java.lang.Class.newInstance(Unknown Source)
[07:07:58] [Server thread/WARN]: at cullan.main.DCEnchants.loadEnchants(DCEnchants.java:62)
[07:07:58] [Server thread/WARN]: at cullan.main.DCEnchants.onEnable(DCEnchants.java:24)
[07:07:58] [Server thread/WARN]: at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321)
[07:07:58] [Server thread/WARN]: at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340)
[07:07:58] [Server thread/WARN]: at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405)
[07:07:58] [Server thread/WARN]: at net.skycraftmc.PluginManager.PluginManagerPlugin.onCommand(PluginManagerPlugin.java:287)
[07:07:58] [Server thread/WARN]: at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
[07:07:58] [Server thread/WARN]: at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
[07:07:58] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:646)
[07:07:58] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchServerCommand(CraftServer.java:632)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.DedicatedServer.aO(DedicatedServer.java:409)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:373)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:709)
[07:07:58] [Server thread/WARN]: at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:612)
[07:07:58] [Server thread/WARN]: at java.lang.Thread.run(Unknown Source)
[07:07:58] [Server thread/WARN]: Caused by: java.lang.NoSuchMethodException: cullan.listener.AgilityListener.<init>()
[07:07:58] [Server thread/WARN]: at java.lang.Class.getConstructor0(Unknown Source)
这是抛出错误的 class:
package cullan.listener;
import cullan.type.EnchantmentRarity;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList;
import java.util.List;
public class AgilityListener extends EnchantmentListener{
private List<Player> players = new ArrayList<>();
public AgilityListener() {
super(Enchantment.getByName("Agility"), EnchantmentRarity.VERY_RARE);
startTimer();
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
if (players.contains(player)) {
players.remove(player);
}
}
private void startTimer() {
final PotionEffect effect = mainConfig.getAgilityEffect();
instance.getServer().getScheduler().scheduleSyncRepeatingTask(instance, new Runnable() {
@Override
public void run() {
for (Player player : instance.getServer().getOnlinePlayers()) {
ItemStack boots = player.getInventory().getBoots();
if (boots != null && boots.containsEnchantment(enchantment)) {
player.addPotionEffect(effect);
players.add(player);
} else if (players.contains(player)) {
player.removePotionEffect(effect.getType());
players.remove(player);
}
}
}
}, 10L, 10L);
}
}
如果我删除 startTimer() 方法,则不会发生错误。为什么会这样?
问题是您不是在尝试构建 AgilityListener
的实例 - 您是在尝试构建在 AgilityListener.startTimer
中创建的匿名内部 class 的实例。这就是为什么堆栈跟踪具有:
Caused by: java.lang.NoSuchMethodException: cullan.listener.AgilityListener.<init>()
“$1”表明它是一个匿名内部 class。
如果您只想过滤掉所有 nested/inner class,您可以扩大对 class 名称的检查:
if (!listenerClass.getSimpleName().equals("EnchantmentListener") &&
!listenerClass.getSimpleName().contains("$"))
或:
!listenerClass.isAnonymousClass()
等您还可以检查 class 是否具有 public 无参数构造函数,以及它是否可分配给 EnchantmentListener
.