Java8 - "effectively final" - java

I'm using RxVertx which is a sort of RxJava along with Java8 and I have a compilation error.
Here is my code:
public rx.Observable<Game> findGame(long templateId, GameModelType game_model, GameStateType state) {
return context.findGame(templateId, state)
.flatMap(new Func1<RxMessage<byte[]>, rx.Observable<Game>>() {
#Override
public Observable<Game> call(RxMessage<byte[]> gameRawReply) {
Game game = null;
switch(game_model) {
case SINGLE: {
ebs.subscribe(new Action1<RxMessage<byte[]>>() {
#Override
public void call(RxMessage<byte[]> t1) {
if(!singleGame.contains(0) {
game = new Game(); // ERROR is at this line
singleGames.put(0, game);
} else {
game = singleGames.get(0); // ERROR is at this line
}
}
});
}
}
return rx.Observable.from(game);
}
});
}
The compilation error is:
"Local variable game defined in an enclosing scope must be final or effectively final"
I cannot define 'game' as final since I do allocation\set and return it at the end of the function.
How can I make this code compile??
Thanks.

I have a Holder class that I use for situations like this.
/**
* Make a final one of these to hold non-final things in.
*
* #param <T>
*/
public class Holder<T> {
private T held = null;
public Holder() {
}
public Holder(T it) {
held = it;
}
public void hold(T it) {
held = it;
}
public T held() {
return held;
}
public boolean isEmpty() {
return held == null;
}
#Override
public String toString() {
return String.valueOf(held);
}
}
You can then do stuff like:
final Holder<Game> theGame = new Holder<>();
...
theGame.hold(myGame);
...
{
// Access the game through the `final Holder`
theGame.held() ....

Since you need to not modify the reference of the object you can wrap the Game in something else.
The quickest (but ugly) fix is to use an array of size 1, then set the content of the array later. This works because the the array is effectively final, what is contained in the array doesn't have to be.
#Override
public Observable<Game> call(RxMessage<byte[]> gameRawReply) {
Game[] game = new Game[1];
switch(game_model) {
case SINGLE: {
ebs.subscribe(new Action1<RxMessage<byte[]>>() {
#Override
public void call(RxMessage<byte[]> t1) {
if(!singleGame.contains(0) {
game[0] = new Game();
singleGames.put(0, game[0]);
} else {
game[0] = singleGames.get(0);
}
}
});
}
}
return rx.Observable.from(game[0]);
}
Another similar option is to make a new class that has a Game field and you then set that field later.

Cyclops has Mutable, and LazyImmutable objects for handling this use case. Mutable is fully mutable, and LazyImmutable is set once.
Mutable<Game> game = Mutable.of(null);
public void call(RxMessage<byte[]> t1) {
if(!singleGame.contains(0) {
game.mutate(g -> new Game());
singleGames.put(0, game.get());
} else {
game[0] = game.mutate(g->singleGames.get(0));
}
}
LazyImmutable can be used to set a value, lazily, once :
LazyImmutable<Game> game = LazyImmutable.def();
public void call(RxMessage<byte[]> t1) {
//new Game() is only ever called once
Game g = game.computeIfAbsent(()->new Game());
}

You cant. At least not directly. U can use a wrapper class however: just define a class "GameContainer" with game as its property and foward a final reference to this container instead.

#dkatzel's suggestion is a good one, but there's another option: extract everything about retrieving/creating the Game into a helper method, and then declare final Game game = getOrCreateGame();. I think that's cleaner than the final array approach, though the final array approach will certainly work.

Although the other approaches look acceptable, I'd like to mention that you can't be sure subscribing to ebs will be synchronous and you may end up always returning null from the inner function. Since you depend on another Observable, you could just simply compose it through:
public rx.Observable<Game> findGame(
long templateId,
GameModelType game_model,
GameStateType state) {
return context.findGame(templateId, state)
.flatMap(gameRawReply -> {
switch(game_model) {
case SINGLE: {
return ebs.map(t1 -> {
Game game;
if (!singleGame.contains(0) {
game = new Game();
singleGames.put(0, game);
} else {
game = singleGames.get(0);
}
return game;
});
}
}
return rx.Observable.just(null);
});
}

Related

Java Array of InnerClass throwing java.lang.NoSuchFieldError

I am trying to brushup java after a long time.
Any help is much appreciated.
For demonstration I have Animal Class that has an array of innerclass of Organs.
public class Animal
{
String nameOfAnimal;
Organs [] vitalOrgans = new Organs[3];
public Animal()
{
}
public String getNameOfAnimal() {
return nameOfAnimal;
}
public void setNameOfAnimal(String nameOfAnimal) {
this.nameOfAnimal = nameOfAnimal;
}
#Override
public String toString() {
return "Animal{" + "nameOfAnimal=" + nameOfAnimal + "}";
}
class Organs{
String nameOfOrgan;
public String getNameOfOrgan() {
return nameOfOrgan;
}
public void setNameOfOrgan(String nameOfOrgan) {
this.nameOfOrgan = nameOfOrgan;
}
#Override
public String toString() {
return "Organs{" + "nameOfOrgan=" + nameOfOrgan + '}';
}
}
}
Now in driver file when I make call there is no syntactical error but I get "Exception in thread "main" java.lang.NoSuchFieldError: vitalOrgans"
Animal mamal = new Animal();
mamal.setNameOfAnimal("Chimp");
mamal.vitalOrgans[0].setNameOfOrgan("Heart");
System.out.println(mamal.vitalOrgans[0].getNameOfOrgan());
What would be the way to make this (or similar idea) to work.
Thanks.
You would need to initialize the vitalOrgrans with new Organs(). Like:
public Animal() {
for (int i = 0; i < vitalOrgans.length; i++) {
vitalOrgans[i] = new Organs();
}
}
Because when you say :
Organs[] vitalOrgans = new Organs[3];
You are creating an array of 3 null Organs. Hence the null pointer exception, when accessing "vitalOrgans[i].".
Taking the relevant bit of code:
public class Animal
{
//...
Organs [] vitalOrgans = new Organs[3];
//...
}
Since your declaration of vitalOrgans was never given an access modifier (i.e. one of private, public, protected) it took on default access, which means only other classes in the same package can see it. Since your other block of code is not in the same package, it cannot see the field.
A minimally viable modification to just make it work would be to set the access to public:
public class Animal
{
//...
public Organs [] vitalOrgans = new Organs[3];
//...
}
While this works, it's not necessarily the best solution, as if you ever change how vitalOrgans is represented, or need to perform any validation, those edits would have to be done throughout the application. Thus, a better solution (and also, a major stylistic convention in Java for those exact reasons) is to make it (and all your fields, in fact) private and access via methods:
public class Animal {
private String nameOfAnimal;
private Organs[] vitalOrgans = new Organs[3];
//...
public Organs[] getVitalOrgans() {
return vitalOrgans;
}
//Alternative accessor that fetches only one organ.
public Organs getVitalOrgan(int index) {
if(index >= 0 && index < vitalOrgans.length)
return vitalOrgans[index];
else
return null;
}
public void setVitalOrgans(Organs[] vitalOrgans) {
this.vitalOrgans = vitalOrgans
}
//...
}
Your caller could then access Organs via either form of the get method (note, you probably want Organs to be public):
Animal.Organs futureMammalHeart = mamal.getVitalOrgan(0); //Animal.Organs due to Organs being an inner class.
if(futureMammalHeart != null) //Demonstration of null check. Safety first!
futureMammalHeart.setNameOfOrgan("Heart");
Animal.Organs[] mammalianVitalOrgans = mamal.getVitalOrgans();
if(mammalianVitalOrgans != null) //Just in case...
System.out.println(mamal.mammalianVitalOrgans[0].getNameOfOrgan());
Also, as Ari mentioned in his answer, don't forget to initialize the organs in your array, otherwise you will get a NullPointerException!

Waiting for Sub Tasks to Finish in JavaFX

I am trying to create a simple game using JavaFX. The game consists in a main game and sub-games, which the player may have to play, depending on the result of the main game. In the end, the main game has to update it's state (p.e.: score) depending on the sub-games result.
I made a simplified and generalized version of how I have implemented the game logic:
Result play(Player p) {
Result r = p.play(this);
for(SubGame game : r.getSubGames())
{
p.play(game);
}
update(r);
return r;
}
This game works perfectly in the terminal, since it has a linear execution.
But using JavaFX (implemented in the Player), I cannot control the flow of the program properly, because of the game loop.
I have followed this tutorial to handle multiple screens for the main game and sub-games. The Player class can successfully change the screen to a sub-game, using the handler. But the update no longer waits for the sub-games to be played, and this function returns while the player is mid-game.
I am trying to keep the game logic separate from UI, so changes to the code showed above shouldn't be dependent on the interface framework.
Any help?
Use an event-driven approach, setting the values of observable properties, and responding when they change.
For example, you might encapsulate the state of the game with
public class GameState {
private ObservableList<SubGame> currentGames = FXCollections.observableArrayList();
public ObservableList<SubGame> getCurrentGames() {
return currentGames();
}
private ReadOnlyObjectWrapper<SubGame> currentGame = new ReadOnlyObjectProperty<>();
public ReadOnlyObjectProperty<SubGame> currentGameProperty() {
return currentGame.getReadOnlyProperty() ;
}
public final SubGame getCurrentGame() {
return currentGameProperty().get();
}
public GameState() {
// initialize sub game list...
}
public void nextGame() {
int index = currentGames.indexOf(currentGame.get());
if (index < currentGames.size() - 1) {
currentGame.set(currentGames.get(index + 1));
}
}
public void start() {
currentGame.set(currentGames().get(0));
}
public boolean hasMoreGames() {
return currentGames.indexOf(currentGame.get()) < currentGames.size() - 1 ;
}
}
And similarly you might have some observable state in your SubGame class:
public class SubGame {
private final BooleanProperty finished = new SimpleBooleanProperty();
public BooleanProperty finishedProperty() {
return finished ;
}
public final boolean isFinished() {
return finishedProperty().get();
}
public final void setFinished(boolean finished) {
finishedProperty().set(finished) ;
}
// ...
}
Now your game logic is just implemented with listeners:
void play(Player p) {
Result r = p.play(this);
GameState gameState = new GameState();
gameState.currentGameProperty().addListener((obs, oldGame, newGame) -> {
newGame.finishedProperty().addListener((obs, wasFinished, isNowFinished) -> {
if (isNowFinished) {
// maybe update score etc based on state of newGame...
if (gameState.hasMoreGames()) {
gameState.nextGame();
} else {
// logic here for "all games are finished...
}
}
});
});
gameState.start();
}
Obviously the details of how you implement this depend on your requirements etc, but this general approach should work for anything you need.

Java: message system needs to be able to pass various objects

I'm writing a messaging system to queue actions for my program to execute. I need to be able to pass various objects by the messages. I currently have a Msg object that accepts (Action enum, Data<?>...object). The Data object is intended to be a wrapper for any object I might pass.
Currently the Data object uses this code, with generics:
public class Data<T> {
private T data;
public Data(T data){
this.data = data;
}
public T getData(){
return data;
}
}
The Msg object takes Data<?>... type, so Msg has a Data<?>[] field.
If getData() is called on a Data<?> object, it returns the Object type. Obviously not ideal.
I need to be able to pass, say, Image objects as well as String objects. I'm certain there's a better way of passing arbitrary data.
The reason you're having trouble is that you're trying to get the static typing system of Java to do something that it can't. Once you convert from a Data<T> to a Data<?>, whatever T was is effectively lost. There's no clean way to get it back.
The quickest way to get it to work (from what you have right now) is to start throwing casts everywhere, like this:
Data<?> d = new Data("Hello");
String contents = (String)d.getData();
This is kind of a terrible idea, so let's go back to the drawing board.
If (ideally), you have all of the types you could ever need ahead of time (i.e. every Data is either a String or an Image or an Integer), then you can pretty easily (though it's a bit tedious) define a Sum type (aka a union if you're coming from C) of the different types of data you'll have to handle. As a class invariant, we assume that exactly one of the fields is non-null, and the rest are null. For this example I'll assume it can be either a String, an Image, or an Integer, but it's fairly simple to add or remove types from Data as necessary.
public class Data {
private Image imgData;
private String stringData;
private Integer intData;
public Data(Image img) {
this.imgData = img;
}
public Data(String stringData) {
this.stringData = stringData;
}
public Data(Integer intData) {
this.intData = intData;
}
public boolean isImage() {
return imageData != null;
}
public boolean isInteger() {
return intData != null;
}
public boolean isString() {
return stringData != null;
}
public Image asImage() {
if(! isImage()) throw new RuntimeException();
return imgData;
}
public Image asString() {
if(! isString()) throw new RuntimeException();
return stringData;
}
public Image asInt() {
if(! isInt()) throw new RuntimeException();
return intData;
}
}
One necessary side effect is that we cannot wrap null without causing exceptional behavior. Is this is desired, it isn't too difficult to modify the class to allow for it.
With this Data class, it's pretty easy to do if-else logic to parse it.
Data d = ....... //Get a data from somewhere
if(d.isImage()) {
Image img = d.asImage();
//...
} else if (d.isString()) {
String string = d.asString();
//...
} else if (d.isInteger()) {
Integer i = d.asInt();
//...
} else {
throw new RuntimeException("Illegal data " + d + " received");
}
If you call getData().getClass() you will get the class or type that was passed, which doesn't seem to me to be the same as an Object. You might not know what you are getting, but you can either find out or define a common interface for everything you might pass. You could for example, call toString() or getClass() on anything passed. Your question is that you are passing any conceivable object, so my question is what are you going to do with it? If you are going to serialize it into a database you don't need know anything about what type it is, otherwise you can test it or call a common interface.
public class PlayData {
class Msg {
private List<Data<?>> message = new ArrayList<Data<?>>();
public void addData(Data<?> datum) { message.add(datum); }
public void printTypes() { for ( Data<?> datum: message ) { System.out.println(datum.getData().getClass()); } }
}
class Data<T> {
private T value;
public Data(T value) { this.value = value; }
public T getData() { return value; }
}
class Listener {
public void receive(Msg msg) { msg.printTypes(); }
}
class Sender {
private Listener listener;
public Sender(Listener listener) { this.listener = listener; }
public void send(Msg msg) { listener.receive(msg); }
}
class MyPacket {
int i;
public MyPacket(int i) { this.i = i; }
}
public static void main(String[] args) throws Exception { new PlayData().run(); }
public void run() throws Exception {
Sender sender = new Sender(new Listener());
Msg msg = new Msg();
msg.addData(new Data<String>("testing") );
msg.addData(new Data<MyPacket>(new MyPacket(42)) );
sender.send(msg);
}
}

Use the command line to make new objects

In my program, the user needs to input what type of players the game will have. The players are "human", "good" (for a good AI), "bad" (for a bad AI) and "random" (for a random AI). Each of these players have their own class that extend one abstract class called PlayerType.
My struggle is mapping a String to the object so I can A) create a new object using the String as sort of a key and B) get the related String from an object of its subclass
Ultimately, I just want the implicit String to only appear once in the code so I can change it later if needed without refactoring.
I've tried using just a plain HashMap, but that seems clunky with searching the keys via the values. Also, I'm guessing that I'll have to use the getInstance() method of Class, which is a little less clunky, which is okay if it's the only way.
What I would do is create an enum which essentially functions as a factory for the given type.
public enum PlayerTypes {
GOOD {
#Override
protected PlayerType newPlayer() {
return new GoodPlayer();
}
},
BAD {
#Override
protected PlayerType newPlayer() {
return new BadPlayer();
}
},
RANDOM {
#Override
protected PlayerType newPlayer() {
return new RandomPlayer();
}
};
protected abstract PlayerType newPlayer();
public static PlayerType create(String input) {
for(PlayerTypes player : PlayerTypes.values()) {
if(player.name().equalsIgnoreCase(input)) {
return player.newPlayer();
}
}
throw new IllegalArgumentException("Invalid player type [" + input + "]");
}
)
Because then you can just call it like so:
String input = getInput();
PlayerTypes.create(input);
Of course, you'll get an IllegalArgumentException which you should probably handle by trying to get the input again.
EDIT: Apparently in this particular case, you can replace that loop with just merely
return PlayerTypes.valueOf(input).newPlayer();
And it'll do the same thing. I tend to match for additional constructor parameters in the enum, so I didn't think of using valueOf(), but it's definitely cleaner.
EDIT2: Only way to get that information back is to define an abstract method in your PlayerType class that returns the PlayerTypes enum for that given type.
public class PlayerType {
public abstract PlayerTypes getType();
}
public class GoodPlayer extends PlayerType {
#Override
public PlayerTypes getType() {
return PlayerTypes.GOOD;
}
}
I like the answer provided by Epic but I don't find maps to be clunky. So it's possible to keep a map and get the constructor call directly.
Map<String, Supplier<PlayerType> map = new HashMap<>();
map.put("human", Human::new);
Human h = map.get("human").get();
The two main options I can think of:
Using Class.newInstance(), as you mentioned (not sure if you had this exact way in mind):
// Set up your map
Map<String, Class> classes = new HashMap<String, Class>();
classes.put("int", Integer.class);
classes.put("string", String.class);
// Get your data
Object s = classes.get("string").newInstance();
You could use Class.getDeclaredConstructor.newInstance if you want to use a constructor with arguments (example).
Another option is using switch:
Object getObject(String identifier) {
switch (identifier) {
case "string": return new String();
case "int": return new Integer(4);
}
return null; // or throw an exception or return a default object
}
One potential solution:
public class ForFunFactory {
private ForFunFactory() {
}
public static AThing getTheAppropriateThing(final String thingIdentifier) {
switch (thingIdentifier) {
case ThingImplApple.id:
return new ThingImplApple();
case ThingImplBanana.id:
return new ThingImplBanana();
default:
throw new RuntimeException("AThing with identifier "
+ thingIdentifier + " not found.");
}
}
}
public interface AThing {
void doStuff();
}
class ThingImplApple implements AThing {
static final String id = "Apple";
#Override
public void doStuff() {
System.out.println("I'm an Apple.");
}
}
class ThingImplBanana implements AThing {
static final String id = "Banana";
#Override
public void doStuff() {
System.out.println("I'm a Banana.");
}
}

How to navigate in a circle

the title might be not very descriptive but i couldn't think of a better one.
The problem is as follows:
I have one screen (ScreenOne) with a link to another screen (ScreenTwo).
On the ScreenTwo is a link back to ScreenOne.
I implemented this via custom RichTextFields and a custom ChangeListener.
Now the problem is that i keep getting a StackOverflowError!
Is there any way to navigate back and forth in that way?
regards matt
public class MyApp extends UiApplication
{
public static void main(String[] args)
{
MyApp theApp = new MyApp();
theApp.enterEventDispatcher();
}
public MyApp()
{
ScreenOne so = ScreenProvider.getInstance().getScreenOne();
so.initialize();
ScreenProvider.getInstance().getScreenTwo().initialize();
pushScreen(so);
}
}
public class ScreenOne extends MainScreen {
MyTextField link;
public ScreenOne() {
link = new MyTextField("FirstScreen");
add(link);
}
public void initialize(){
link.setChangeListener((FieldChangeListener) new MyFieldChangeListener(ScreenProvider.getInstance().getScreenTwo()));
}
}
public class ScreenTwo extends MainScreen {
MyTextField link;
public ScreenTwo() {
link = new MyTextField("SecondScreen");
add(link);
}
public void initialize(){
link.setChangeListener((FieldChangeListener) new MyFieldChangeListener(ScreenProvider.getInstance().getScreenOne()));
}
}
public class MyFieldChangeListener implements FieldChangeListener {
private Screen nextScreen;
public MyFieldChangeListener(Screen nextScreen) {
this.nextScreen = nextScreen;
}
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().pushScreen(nextScreen);
}
}
public class MyTextField extends RichTextField {
public MyTextField() {
super();
}
public MyTextField(String text) {
super(text);
}
protected boolean touchEvent(TouchEvent message) {
if (TouchEvent.CLICK == message.getEvent()) {
FieldChangeListener listener = getChangeListener();
if (null != listener)
listener.fieldChanged(this, 1);
}
return super.touchEvent(message);
}
}
public class ScreenProvider {
private static ScreenProvider instance = null;
private ScreenProvider(){}
public static ScreenProvider getInstance() {
if (instance == null) {
instance = new ScreenProvider();
}
return instance;
}
private ScreenOne screenOne = new ScreenOne();
private ScreenTwo screenTwo = new ScreenTwo();
public ScreenOne getScreenOne() {
return screenOne;
}
public ScreenTwo getScreenTwo() {
return screenTwo;
}
}
The constructor of ScreenOne creates a ScreenTwo instance, and the constructor of ScreenTwo creates a ScreenOne instance. You have an infinite loop here.
Regarding revision 5 of this question:
new ScreenProvider() -> new ScreenOne() -> ScreenProvider.getInstance() -> new ScreenProvider() -> ...
still infinite. Again, the problem is that you're trying to setup a cycle via object constructors. You need to create the objects first, then assign the next and previous.
Regarding revision 4 of this question:
getScreenOne() -> new ScreenOne() -> getScreenTwo() -> new ScreenTwo() -> getScreenOne() -> newScreenOne() -> ...
you still have an infinite loop, because the constructors are trying to store an instance of each other. You need to construct the objects first, then add the cyclic references.
In your ScreenProvider you don't need to make screen1/screen2 static -- they're members of the singleton instance.
Outside of that the other problem I see in this current version is that you're going to be pushing a screen onto the stack -- that's already on the stack. Try popping the prior screen first.
That overflow error is likely the result of an infinite loop caused by constantly jumping from ScreenOne and ScreenTwo. Could you describe what you actually would want to accomplish and/or show a snippet of code?

Categories

Resources