2013-06-23 75 views
4

錯誤:無法修復的NPE

Caused by: java.lang.NullPointerException 
    at com.mcvigor.RunePlayer.getSkillLevel(RunePlayer.java:90) 
    at com.mcvigor.utils.SkillUtils.getChances(SkillUtils.java:12) 
    at com.mcvigor.listeners.MiningListener.breakBlocks(MiningListener.java:118) 

我想打電話給SkillUtils.getChances及其導致的NPE。我試着通過檢查我的代碼來發現錯誤,我似乎無法找出爲什麼我會得到錯誤。

RunePlayer.java:

package com.mcvigor; 

import java.util.HashMap; 

public class RunePlayer { 

    private HashMap<Skills, Integer> skills = new HashMap<Skills, Integer>(); 
    private HashMap<Skills, Integer> skillXP = new HashMap<Skills, Integer>(); 
    private String name; 

    public RunePlayer(String name) { 
     new RunePlayer(name, 1, 1, 3, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 
    } 


    public RunePlayer(String name, int agility, int attack, int combat, int constitution, 
      int construction, int cooking, int crafting, int defence, int dungeoneering, 
      int farming, int firemaking, int fishing, int fletching, int herblore, int hunter, int magic, int mining, 
      int prayer, int ranged, int runecrafting, int slayer, int smithing, int strength, 
      int summoning, int thieving, int woodcutting, int agilityXP, int attackXP, int combatXP, int constitutionXP, 
      int constructionXP, int cookingXP, int craftingXP, int defenceXP, int dungeoneeringXP, 
      int farmingXP, int firemakingXP, int fishingXP, int fletchingXP, int herbloreXP, int hunterXP, int magicXP, int miningXP, 
      int prayerXP, int rangedXP, int runecraftingXP, int slayerXP, int smithingXP, int strengthXP, 
      int summoningXP, int thievingXP, int woodcuttingXP) { 
     setName(name); 
     skills.put(Skills.AGILITY, agility); 
     skills.put(Skills.ATTACK, attack); 
     skills.put(Skills.COMBAT, combat); 
     skills.put(Skills.CONSTITUTION, constitution); 
     skills.put(Skills.CONSTRUCTION, construction); 
     skills.put(Skills.COOKING, cooking); 
     skills.put(Skills.CRAFTING, crafting); 
     skills.put(Skills.DEFENCE, defence); 
     skills.put(Skills.DUNGEONEERING, dungeoneering); 
     skills.put(Skills.FARMING, farming); 
     skills.put(Skills.FIREMAKING, firemaking); 
     skills.put(Skills.FISHING, fishing); 
     skills.put(Skills.FLETCHING, fletching); 
     skills.put(Skills.HERBLORE, herblore); 
     skills.put(Skills.HUNTER, hunter); 
     skills.put(Skills.MAGIC, magic); 
     skills.put(Skills.MINING, mining); 
     skills.put(Skills.PRAYER, prayer); 
     skills.put(Skills.RANGED, ranged); 
     skills.put(Skills.RUNECRAFTING, runecrafting); 
     skills.put(Skills.SLAYER, slayer); 
     skills.put(Skills.SMITHING, smithing); 
     skills.put(Skills.STRENGTH, strength); 
     skills.put(Skills.SUMMONING, summoning); 
     skills.put(Skills.THIEVING, thieving); 
     skills.put(Skills.WOODCUTTING, woodcutting); 
     skillXP.put(Skills.AGILITY, agilityXP); 
     skillXP.put(Skills.ATTACK, attackXP); 
     skillXP.put(Skills.COMBAT, combatXP); 
     skillXP.put(Skills.CONSTITUTION, constitutionXP); 
     skillXP.put(Skills.CONSTRUCTION, constructionXP); 
     skillXP.put(Skills.COOKING, cookingXP); 
     skillXP.put(Skills.CRAFTING, craftingXP); 
     skillXP.put(Skills.DEFENCE, defenceXP); 
     skillXP.put(Skills.DUNGEONEERING, dungeoneeringXP); 
     skillXP.put(Skills.FARMING, farmingXP); 
     skillXP.put(Skills.FIREMAKING, firemakingXP); 
     skillXP.put(Skills.FISHING, fishingXP); 
     skillXP.put(Skills.FLETCHING, fletchingXP); 
     skillXP.put(Skills.HERBLORE, herbloreXP); 
     skillXP.put(Skills.HUNTER, hunterXP); 
     skillXP.put(Skills.MAGIC, magicXP); 
     skillXP.put(Skills.MINING, miningXP); 
     skillXP.put(Skills.PRAYER, prayerXP); 
     skillXP.put(Skills.RANGED, rangedXP); 
     skillXP.put(Skills.RUNECRAFTING, runecraftingXP); 
     skillXP.put(Skills.SLAYER, slayerXP); 
     skillXP.put(Skills.SMITHING, smithingXP); 
     skillXP.put(Skills.STRENGTH, strengthXP); 
     skillXP.put(Skills.SUMMONING, summoningXP); 
     skillXP.put(Skills.THIEVING, thievingXP); 
     skillXP.put(Skills.WOODCUTTING, woodcuttingXP); 

    } 


    private void setName(String s) { 
     name = s; 
    } 
    public String getName() { 
     return name; 
    } 

    public int getSkillLevel(Skills skill) { 
     return skills.get(skill); // LINE 90 <--------------------- 
    } 

    public void setSkillLevel(Skills skill, int level) { 
     skills.put(skill, level); 
    } 

    public int getSkillXP(Skills skill) { 
     return skills.get(skill); 
    } 

    public void setSkillXP(Skills skill, int level) { 
     skills.put(skill, level); 
    } 

} 

SkillUtils.java:

​​

MiningListener.java:

package com.mcvigor.listeners; 

import org.bukkit.Bukkit; 
import org.bukkit.ChatColor; 
import org.bukkit.Material; 
import org.bukkit.entity.Player; 
import org.bukkit.event.EventHandler; 
import org.bukkit.event.EventPriority; 
import org.bukkit.event.Listener; 
import org.bukkit.event.block.Action; 
import org.bukkit.event.block.BlockBreakEvent; 
import org.bukkit.event.block.BlockPlaceEvent; 
import org.bukkit.event.player.PlayerInteractEvent; 
import org.bukkit.inventory.ItemStack; 
import org.bukkit.inventory.PlayerInventory; 

import com.mcvigor.RuneCraft; 
import com.mcvigor.Skills; 
import com.mcvigor.utils.SkillUtils; 

public class MiningListener implements Listener { 

    RuneCraft plugin; 

    public MiningListener(RuneCraft instance) { 
     plugin = instance; 
    } 

    public boolean hasPickaxe(Player p) { 
     final PlayerInventory i = p.getInventory(); 
     if(i.contains(Material.WOOD_PICKAXE) || i.contains(Material.STONE_PICKAXE) || i.contains(Material.GOLD_PICKAXE) || i.contains(Material.IRON_PICKAXE) || i.contains(Material.DIAMOND_PICKAXE)) { 
      return true; 
     } 
     return false; 
    } 

    public boolean clickedBlockIsMineral(PlayerInteractEvent event) { 
     if(event.getClickedBlock() != null && event.getClickedBlock().getType() != null) { 
      Material b = event.getClickedBlock().getType(); 
      if(b.equals(Material.CLAY) || b.equals(Material.GLOWING_REDSTONE_ORE) || b.equals(Material.REDSTONE_ORE) || b.equals(Material.LAPIS_ORE) || b.equals(Material.IRON_ORE) || b.equals(Material.BEDROCK) || b.equals(Material.COAL_ORE) || b.equals(Material.GOLD_ORE) || b.equals(Material.SPONGE) || b.equals(Material.EMERALD_ORE) || b.equals(Material.DIAMOND_ORE)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    public boolean blockIsMineral(BlockBreakEvent event) { 
     if(event.getBlock() != null && event.getBlock().getType() != null) {  
      Material m = event.getBlock().getType(); 
      if(event.getBlock() != null && m != null || m.equals(Material.CLAY) || m.equals(Material.GLOWING_REDSTONE_ORE) || m.equals(Material.REDSTONE_ORE) || m.equals(Material.LAPIS_ORE) || m.equals(Material.IRON_ORE) || m.equals(Material.BEDROCK) || m.equals(Material.COAL_ORE) || m.equals(Material.GOLD_ORE) || m.equals(Material.SPONGE) || m.equals(Material.EMERALD_ORE) || m.equals(Material.DIAMOND_ORE)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    public boolean hasInventorySpace(Player p) { 
     for(ItemStack i : p.getInventory().getContents()) { 
      if(i == null || i.getType() == null || i.getType().equals(Material.AIR)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    @EventHandler(ignoreCancelled = true) 
    public void placeBlocks(BlockPlaceEvent event) { 
     if(event.getPlayer().isOp()) return; 
     event.setCancelled(true); 
    } 

    @EventHandler(priority=EventPriority.MONITOR) 
    public void playerRClickOre(final PlayerInteractEvent event) throws InterruptedException { //Ore Interactions 

     final Player p = event.getPlayer(); 

     if(event.getPlayer().isOp() || RuneCraft.busyPlayers.contains(p.getName())) return; 

     if(!hasInventorySpace(p) && clickedBlockIsMineral(event) && event.getAction() == Action.LEFT_CLICK_BLOCK) { 
      event.setCancelled(true); 
      p.sendMessage(ChatColor.GRAY + "You do not have enough space in your inventory to mine this rock."); 
     } 

     if(clickedBlockIsMineral(event) && event.getAction() == Action.LEFT_CLICK_BLOCK && !hasPickaxe(p) && hasInventorySpace(p)) { 
      event.setCancelled(true); 
      RuneCraft.busyPlayers.add(p.getName()); 
      p.sendMessage(ChatColor.GRAY + "You need a " + ChatColor.DARK_RED + "pickaxe " + ChatColor.GRAY + "to mine this rock."); // ADD CHECKS FOR PICKAXE REQUIRED LEVEL TO USE 
      RuneCraft.busyPlayers.remove(p.getName()); 
     } 

     if(clickedBlockIsMineral(event) && event.getAction() == Action.RIGHT_CLICK_BLOCK) { 

      final String clickedOreTypeNames = event.getClickedBlock().getType().toString().toLowerCase().replaceAll("_", " ").replaceAll("glowing redstone ore", "copper ore").replaceAll("redstone ore", "copper ore").replaceAll("lapis ore", "tin ore").replaceAll("bedrock", "silver ore").replaceAll("sponge", "mithril ore").replaceAll("emerald ore", "adamant ore").replaceAll("diamond ore", "runite ore"); 

      RuneCraft.busyPlayers.add(p.getName()); 
      p.sendMessage(ChatColor.GRAY + "You examine the rock for ores..."); 
      Bukkit.getScheduler().runTaskLater(plugin, new Runnable(){ 
       public void run() { 
        p.sendMessage(ChatColor.GRAY + "This rock contains " + ChatColor.DARK_RED + clickedOreTypeNames + ChatColor.GRAY + "."); 
        RuneCraft.busyPlayers.remove(p.getName()); 
       } 
      }, 3*20L); // TODO: Change time 

     } 

    } 

    @EventHandler(ignoreCancelled = true, priority=EventPriority.MONITOR) 
    public void breakBlocks(final BlockBreakEvent event) { //MINING 

     Player p = event.getPlayer(); 
     final String oreTypeNames = event.getBlock().getType().toString().toLowerCase().replaceAll("_", " ").replaceAll("glowing redstone ore", "copper ore").replaceAll("redstone ore", "copper ore").replaceAll("lapis ore", "tin ore").replaceAll("bedrock", "silver ore").replaceAll("sponge", "mithril ore").replaceAll("emerald ore", "adamant ore").replaceAll("diamond ore", "runite ore"); 
     final Material originalOre = event.getBlock().getType(); 

     if(p.isOp() || RuneCraft.busyPlayers.contains(p.getName())) return; 

     //RequiredLevels 
     int clayChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 1)) + 1); 
     int copperChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 1)) + 1); 
     int tinChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 1)) + 1); 
     int ironChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 15)) + 1); 
     int silverChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 20)) + 1); 
     int coalChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 30)) + 1); 
     int goldChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 40)) + 1); 
     int mithrilChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 55)) + 1); 
     int adamantChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 70)) + 1); 
     int runiteChance = (RuneCraft.rand.nextInt(SkillUtils.getChances(Skills.MINING, event.getPlayer().getName(), 85)) + 1); 

     if(!hasPickaxe(p) || !hasInventorySpace(p) || !blockIsMineral(event)) event.setCancelled(true); 

     if(hasPickaxe(p) && blockIsMineral(event)) { 

      if(!SkillUtils.shouldBreakBlock(clayChance, 1)) { 
       event.setCancelled(true); 
       p.sendMessage(ChatColor.DARK_RED + "Your mining level is not high enough to mine this rock."); 
      } 
      event.setCancelled(true); 
      p.sendMessage(ChatColor.GRAY + "You swing your pick at the rock."); 
      //ADD TIMER WITH PICKAXE TYPE + LEVEL + ORE TYPE MODIFIER HERE 
      event.getBlock().setType(Material.COBBLESTONE); 
      p.sendMessage(ChatColor.GRAY + "You manage to mine some " + ChatColor.DARK_RED + oreTypeNames + ChatColor.GRAY + "."); 
      event.getBlock().getDrops().clear(); 
      Bukkit.getScheduler().runTaskLater(plugin, new Runnable(){ 
       public void run() { 
        event.getBlock().setType(originalOre); 
       } 
      }, 5*20L); // TODO: Change time 

     } 

    } 

} 

任何人都知道如何解決這個NPE?

+0

_at com.mcvigor.RunePlayer.getSkillLevel(RunePlayer.java:90)_和線路90是什麼?請將它標記爲我們可以看到錯誤的位置 – BackSlash

+0

好吧我在RunePlayer上標記了第90行,並在SkillUtils上標記了第12行 – user2510422

+0

請提供一個* short *代碼來重現問題。 –

回答

9

您的RunePlayer.getSkillLevel(Skills)方法(和getSkillXP())應該返回Integer而不是int

如果您的skills HashMap沒有指定的技能,則返回null。但是返回類型爲intintInteger之間的自動裝箱不能將null轉換爲int,因爲null對於int不是有效值。因此你得到NPE。

(編輯以可讀性)

+1

請使用反引號來突出顯示答案中的關鍵字,如「int」和「null」以及諸如「RunePlayer.getSkillLevel(Skills)」之類的代碼。否則很難閱讀。除此之外絕對正確。 –

+0

感謝提示鮑里斯! – Sandro