0

I know Java foreach loops are only meant to read values and not assign them, but I was wondering if they can call mutator methods on object. To find out I designed an experiment. Unfortunately the experiment crashes and I'm curious as to why.

public class test {

public static void main(String[] args)
{
    foo[] f = new foo[4];
    /*this would be a foreach loop, once I got the program working normally*/
    for(int i = 0; i < f.length; i++) {
        System.out.println(f[i].get());
        f[i].add();
        System.out.println(f[i].get());
    }
}
private class foo {
    foo() {
        int x = 5;
    }

    void add() {
        x++;
    }

    int get() {
        return x;
    }

    private int x;
}

}

Gives Exception in thread "main" java.lang.NullPointerException when I expected the output to be 5 6. Is it because the constructor to foo isn't being called? If so, how can it be called? Must foo be made a static class?

Koitoer
  • 18,778
  • 7
  • 63
  • 86
Celeritas
  • 14,489
  • 36
  • 113
  • 194

1 Answers1

0

You have an array of null and have not initialized any of the Foo items in the array, meaning it holds nothing but nulls.

Foo[] foos = new Foo[4];

// you need to first do this! You need to fill your array with **objects**!
for (int i = 0; i < foos.length; i++) {
  foos[i] = new Foo();  // ******* add this!!*******
  System.out.println(foos[i].get());  // this will now work
  foos[i].add();
  System.out.println(foos[i].get());
}

// now you can use the array

As an aside, your x will be 0 initially because you shadow the variable in the Foo constructor.

public class Foo {
    private int x;

    Foo() {
        // this **re-declares the x variable**
        int x = 5;
    }

    //....

Instead you want to do:

public class Foo {
    private int x;

    Foo() {
        x = 5;
    }

    //....

Aside #2: you will want to learn and use Java naming conventions. Class names should all begin with an upper-case letter and variable names with a lower-case letter. This is important if you need others (us!!) to understand your code quickly and easily.


An example of a single class. Call it Foo.java and have it hold only one class:

public class Foo {
   private int x;

   public Foo() {
      x = 5;

      // not!
      // int x = 5;
   }
   public void increment() {
      x++;
   }

   public void decrement() {
      x--;
   }

   public int getX() {
      return x;
   }

   public static void main(String[] args) {
      int fooCount = 10;
      Foo[] foos = new Foo[fooCount];
      for (int i = 0; i < foos.length; i++) {
         foos[i] = new Foo();
         System.out.println(foos[i].getX());
         foos[i].increment();
         foos[i].increment();
         System.out.println(foos[i].getX());         
      }

      for (Foo foo : foos) {
         foo.decrement();
         foo.decrement();
         foo.decrement();
         System.out.println(foo.getX());
      }
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I don't think that works. `foos[i] = new Foo();` gives `non-static variables this cannot be referenced from a static context.` – Celeritas Aug 12 '14 at 22:28
  • 1
    @Celeritas: yes of course it works if implemented correctly. Your Foo class should be public and in its own file. You're shooting yourself in the foot with short cuts -- don't do that. – Hovercraft Full Of Eels Aug 12 '14 at 22:29
  • You also need to search on and look up this error, `"non-static variables this cannot be referenced from a static context."` because understanding the meaning of static and instance goes to the core of understanding Java. – Hovercraft Full Of Eels Aug 12 '14 at 22:30
  • Yes it fixed the error when I made Foo static. This was necessary because the main method which was calling it was itself static. – Celeritas Aug 12 '14 at 22:31
  • Re: not shooting myself in the foot by taking shortcuts. This was designed to be a simple experiment and I wanted a new class fast. What would you have done? – Celeritas Aug 12 '14 at 22:31
  • Better to not try to put more than one class in a file. – Hovercraft Full Of Eels Aug 12 '14 at 22:31
  • So in your opinion all of [these](http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html) are bad? Lambda expressions are in a sense another class inside the same file, would you say those are bad too? – Celeritas Aug 12 '14 at 22:33
  • @Celeritas: please see edit to answer showing standard and enhanced for loops with arrays. But most important is that the element held by the array must be created first with a standard for loop usually. – Hovercraft Full Of Eels Aug 12 '14 at 22:35
  • 1
    @Celeritas: there are times when you must use inner classes, including anonymous inner classes, and lambda expressions, which are very similar to anonymous inner classes, but you shouldn't do this until you understand why and when they should be used. – Hovercraft Full Of Eels Aug 12 '14 at 22:36