Accessing class fields from arrayList index?

I need to access lots of very similar objects and everything within them. So far, I have three classes:

"Piece" - Does nothing so far, but is subclassed by LcPawn.

"LcPawn" - This has one line of code, '''public static int ID;''' which is supposed to hold a different number for each instance of the LcPawn.

"Main" - The code in question is as follows:

public static ArrayList<LcPawn> LcPawns = new ArrayList<LcPawn>(256);
for (int i = 0; i < 256; i ++) {
    LcPawns.add(i, new LcPawn());
}
for (int i = 0; i < LcPawns.size(); i ++) {
    LcPawns.get(i).ID = i; 
}
for (int i = 0; i < LcPawns.size(); i ++) {
    System.out.println(LcPawns.get(i).ID);
}

However, nothing comes up on the console. The separate loops are so I can make sure this works without having to reset all the objects over and over again. This is as much as i know.

Upvotes: 0

Views: 309

Answers (1)

cameron1024
cameron1024

Reputation: 10136

Some things to note:

Your LcPawn class has a variable public static int ID; which you say should have a different value for each instance. In Java, the keyword static in this context does the opposite of that, it declares a "class variable", instead of an "instance variable". To provide one instance of ID for each instance of LcPawn, just remove static here and that should be fine.

Second, a convention worth sticking to is to make all fields private, while providing "getters and setters". For example, instead of declaring a class as follows:

public class MyClass {
    public int value;
}

instead declare it as:

public class MyClass {
    private int value;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }
}

This has several advantages:

  • You can add business logic to the functions, e.g. perhaps you want to forbid negative numbers in the value field. You can add a line: if (value < 0) throw new NegativeNumberException();

  • You can change implementation without changing the rest of your code. Perhaps you want to get your value from the internet, or you use a library that wants to lazy-load your variable. This is only possible with a method call, and cannot be done by a raw variable.

  • Many popular libraries expect classes to be in this format (e.g. Jackson Databind, and Spring).

You should also follow standard Java capitalization rules:

  • field names and methods are written likeThis and likeThis()
  • class names are written LikeThis
  • constants are written LIKE_THIS

With that in mind, here is how I would write your code:

public static void main(String[] args) {
    List<LcPawn> pawns = new ArrayList<>(256);  // more generic type and type parameter omitted for brevity

    for (int i = 0; i < 256; i++) {
        pawns.add(new LcPawn());  // no need to specify an index, it gets added to the end by default
    }

    for (int i = 0; i < pawns.size(); i++) {
        pawns.get(i).setId(i);  // using setter method
    }

    for (int i = 0; i < pawns.size(); i++) {
        System.out.println(pawns.get(i).getId());  // using getter method
    }
}

However, this can be compacted into one single for loop:

List<LcPawn> pawns = new ArrayList<>(256);
for (int i = 0; i < 256; i++) {
    LcPawn pawn = new LcPawn();
    pawn.setId(i);
    System.out.println(pawn.getId());
    pawns.add(pawn);
}

Or, with Java 8 streams:

IntStream.range(0, 256)  // generate a stream of integers from 0-255
    .map(i -> {  // map each integer to a pawn with that integer as its id
        LcPawn pawn = new LcPawn();
        pawn.setId(i);
        return pawn;
    })
    .forEach(System.out::println);  // print all of them, using a "method reference"

Upvotes: 1

Related Questions