This site requires JavaScript, please enable it in your browser!
Greenfoot back
Phiesel
Phiesel wrote ...

2014/6/24

NullPointerException when calling a method from another class

Phiesel Phiesel

2014/6/24

#
Hi, I'm trying to build a simple vocab-quiz. It's working fine so far, except for one thing and I can't figure out what the problem might be. I have a class 'WordList' that stores my words(vocabs) in a HashMap, each vocab having an English meaning value and a German meaning value:
import greenfoot.*;  
import java.util.HashMap;

public class WordList extends Actor
{    
    HashMap<Integer, Vocab> en_wortliste = new HashMap<Integer, Vocab>(); 
    {
        en_wortliste.put(1, new Vocab("hello", "hallo"));
        en_wortliste.put(2, new Vocab("friend", "der Freund"));
        en_wortliste.put(3, new Vocab("world", "die Welt"));
        en_wortliste.put(4, new Vocab("house", "das Haus"));
        en_wortliste.put(5, new Vocab("dog", "der Hund"));
        en_wortliste.put(6, new Vocab("small", "klein"));
        en_wortliste.put(7, new Vocab("new", "neu"));
        en_wortliste.put(8, new Vocab("grow", "wachsen"));
        en_wortliste.put(9, new Vocab("fast", "schnell"));
        en_wortliste.put(10, new Vocab("flower", "die Blume"));
        en_wortliste.put(11, new Vocab("water", "das Wasser"));
        en_wortliste.put(12, new Vocab("old", "alt"));
        en_wortliste.put(13, new Vocab("table", "der Tisch"));
        en_wortliste.put(14, new Vocab("hour", "die Stunde"));
        en_wortliste.put(15, new Vocab("fresh", "frisch"));
        en_wortliste.put(16, new Vocab("clock", "die Uhr"));
    }
    
    public HashMap<Integer, Vocab> getList()
    {
        return en_wortliste;
    } 
}
Then there is the class 'AufgabenVerteiler'. It is supposed to draw 4 random numbers without repeat and take those 4 numbers to fetch 4 words from the vocab-list. They are put to wordfields to open up a choice for the player. One of those 4 is then again chosen to be the word in question, so the 2nd-language-value of this word is put to the taskfield, which presents the question. That's how it looks in code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.HashMap;

public class AufgabenVerteiler extends Actor
{
    HashMap<Integer, Vocab> wordlist = new HashMap<Integer, Vocab>();
    WordList words = new WordList();
    private String word1;
    private String word2;
    private String word3;
    private String word4;
    private String taskField;

    public AufgabenVerteiler()
    {
        wordlist = words.getList();
    }
    
    public void act()
    {
        if (Greenfoot.mouseClicked(this))
        {
            drawWords();
        }
    }

    public void drawWords()
    { 
        int random1 = getRandomNumber();
        while (random1 == 0)
        {
            random1 = getRandomNumber();
        }
        int random2 = getRandomNumber();
        while (random2 == random1 || random2 == 0)
        {
            random2 = getRandomNumber(); 
        }
        int random3 = getRandomNumber();
        while (random3 == random1 || random3 == random2 || random3 == 0)
        {
            random3 = getRandomNumber();
        }
        int random4 = getRandomNumber();
        while (random4 == random1 || random4 == random2 || random4 == random3 || random4 == 0)
        {
            random4 = getRandomNumber();
        }
       
        int taskRandom = Greenfoot.getRandomNumber(4);
        while (taskRandom == 0)
        { 
            taskRandom = Greenfoot.getRandomNumber(4);
        }
           
        switch(taskRandom)
            {
                case 1: taskField = wordlist.get(random1).getEnglish();
                break;
                case 2: taskField = wordlist.get(random2).getEnglish();
                break;
                case 3: taskField = wordlist.get(random3).getEnglish();
                break;
                case 4: taskField = wordlist.get(random4).getEnglish();
            }

        World myWorld = getWorld();
        EnglishWorld english = (EnglishWorld)myWorld;

        english.getWordField1().updateWordField(wordlist.get(random1).getDeutsch());
        english.getWordField2().updateWordField(wordlist.get(random2).getDeutsch());
        english.getWordField3().updateWordField(wordlist.get(random3).getDeutsch());
        english.getWordField4().updateWordField(wordlist.get(random4).getDeutsch());
        english.getTaskField().updateTask(taskField);

        // System.out.println(word1 + ", " + word2 + ", " + word3 + ", " + word4);
    }

    public int getRandomNumber()
    {
        int random = Greenfoot.getRandomNumber(wordlist.size()+1);
        return random;
    }
}
When I put an object of this class to the Greenfoot-Gaming Area and click on it, it does everything I want it to do. No problems, everything is fine. But I want another class to call the drawWords()-method when clicked on it. There is the OK-class, which is going to check whether the player's choice was right or wrong. And if it is right it shall go and fetch a new set of words. The checkIt()-method isn't coded yet, I first wanted to call the drawWords()-method from the OK-class to see if it works, .... but it doesn't, it just says NPE in AufgabenVerteiler where it should put the random chosen words to the wordfields. And after 2 hours of fiddling around I still have no real idea what's wrong. Maybe someone could point it out to me. The OK-class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.HashMap;

public class OK extends Actor
{
    HashMap<Integer, Vocab> wordlist = new HashMap<Integer, Vocab>();
    AufgabenVerteiler verteiler = new AufgabenVerteiler();
    
    public void act() 
    {
        if (Greenfoot.mouseClicked(this))
        {
            verteiler.drawWords();
        }
    }   
}
danpost danpost

2014/6/24

#
Line 7 of the OK class is creating a new AufgabenVerteiler object which is not in the world and the 'drawWords' method requires the object be in a world with lines 70 through 74 of that class. You probably should be calling 'drawWords' on the AufgabenVerteiler object that is already in the world and not on a 'new' one.
Phiesel Phiesel

2014/6/24

#
That works fine, thank you, danpost. I still don't understand why the drawWords()-method needs the object to be in the world of that class. Most of the time it is enough to create an object of the class that should do something an call the method on it. Why doesn't it work here?
danpost danpost

2014/6/24

#
Lines 70 through 74 of the AufgabenVerteiler class are calling methods on the world that the (newly created) AufgbenVerteiler object is in (from lines 67 and 68). If the object is not in a world, 'getWorld' (line 67) will return a 'null' value and you cannot call any non-static methods ('getWordField1', 'getWordField2', 'getWordField3', 'getWordField4' and 'getTaskField') on a 'null' world.
Phiesel Phiesel

2014/6/24

#
Ah, I understand. Thanks again!
You need to login to post a reply.