2

I'm developing a game and I'm currently trying to implement a ChangeListener for the character's Health. I've defined a getter for the healthProperty which is actually an instance of SimpleIntegerProperty

I've already got it working as a lambda expression:

character1.healthProperty().addListener( ((observable, oldValue, newValue) -> {
        System.out.println(observable);
        System.out.println(oldValue);
        System.out.println(newValue);
    }) );

When the character takes damage it prints out:

IntegerProperty [value: 333]

350

333

The thing is that I want to be able to reuse this listener for every character in-game, so I'd like it to be an inner class, but I can't get the types right, so far i've got this:

private class HealthPropertyListener implements ChangeListener<IntegerProperty> {

    @Override
    public void changed(ObservableValue<IntegerProperty> observable, Integer oldValue, Integer newValue) {
        // Do something
    }

It doesn't compile cause it tells me that i'm not overriding the method correctly.

If I do it this other way, it works, but I'll have to cast the Object to Integer in order to use them. Is there a way to escape that ugly cast?

private class HealthPropertyListener implements ChangeListener {

    @Override
    public void changed(ObservableValue observable, Object oldValue, Object newValue) {
        //Do something
    }
DVarga
  • 21,311
  • 6
  • 55
  • 60
Franch
  • 621
  • 4
  • 9
  • 22

3 Answers3

2

SimpleIntegerProperty implements ObservableValue<Number>, so the correct signature should be:

public void changed (ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue)

As an aside, with Java 8 you don't really have to create a class for this - you can use a method:

private void healthChanged (ObservableValue<? extends Number> obs, Number oldValue, Number newValue) {
    ...
}

...
// inside a method in the same class
character1.healthProperty().addListener(this::healthChanged);

See also: Why does LongProperty implement Property but not Property?

Community
  • 1
  • 1
Itai
  • 6,641
  • 6
  • 27
  • 51
2

Note that SimpleIntegerProperty implements ObservableValue<Number>. Therefore you need a ChangeListener<Number>. The correct signature for the changed method in for this type parameter would be

public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)

See javadoc for ChangeListener and javadoc for SimpleIntegerProperty

fabian
  • 80,457
  • 12
  • 86
  • 114
1

Take a look on changed method of public interface ChangeListener<T>:

void changed(ObservableValue<? extends T> observable, T oldValue, T newValue)

Based on this the correct form is:

private class HealthPropertyListener implements ChangeListener<IntegerProperty> {

    @Override
    public void changed(ObservableValue<? extends IntegerProperty> observable, IntegerProperty oldValue,
            IntegerProperty newValue) {
    }
}

The answer on this question can be helpful:

When do Java generics require <? extends T> instead of <T> and is there any downside of switching?

Community
  • 1
  • 1
DVarga
  • 21,311
  • 6
  • 55
  • 60