简体   繁体   中英

What to do with fields that can only be assigned non-null values after the object is created (Java)

Suppose I'm making a game:

public class Game {

    Board board;
    public ArrayDeque<Player> players;

    //Players can have 'knights' and the one with the largest number
    //is referenced by the game.
    public Player playerWithLargestArmy;

    ...

}

At the beginning, when a game like this is initialised, no player can have the largest army (a player only has an 'army' once they have a certain number of knights). I want to assign the playerWithLargestArmy a value, but I'm not sure what. I also don't want to use null since I could just leave the implicit assignment to do that (and using null is bad practice anyway).

I am looking for someone to explain to me how I can resolve this issue. I looked up factories and builders but I'm not sure they handle this kind of delayed assignment. For context, each player has an int field specifying how many knights they have.

I could resolve this with a boolean for each player saying whether or not they have the largest army, but then you'd need to iterate through the players to find that player, which isn't ideal. Even if, in my case, that isn't a huge sacrifice, I'd still like to know for future reference.

There is java.util.Optional<T> class for such case.

It have isPresent() and get() (and several other) methods which give you ability to check that object is present and get instance of underlying object.

Examples

Declaration

 Optional<Player> playerWithLargestArmy = Optional.empty();

Assignment of value

playerWithLargestArmy = Optional.of(newValue);

Usage of value

if(playerWithLargestArmy.isPresent()) {
    Player p = playerWithLargestArmy.get();
}

or even better

playerWithLargestArmy.map(p -> doSomethingWithIt(p));

which will invoke doSomethingWithIt only if value is present.

Null Object Pattern https://en.wikipedia.org/wiki/Null_Object_pattern

public class Army {
    public static final Army NullArmy = new Army(0);
    private int size;

    public Army(int size) {
        this.size = size;
    }
}

Now when you create a new Army, just set the initial value to Army.NullArmy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM