-3

If I have a simple class like this:

public class Example{
    int y = 2;
    String z = "textExample";
}

Why is it that inside a Listener I can change a member of a variable of that class but now the variable itself? Or for that matter even a primitive such as an int.

Imagine this function in another class:

public class newClass {

protected void doActivate() {
    ItemCreation model = new Itemcreation(); //A class with visible moving parts
    Example ex = new Example();
    int i = 2;

    model.getSourceProperty().addListener((o, oldVal, newVal) -> {
           //do stuff
           ex.z = "sss"; //THIS I CAN DO and Works


           Example exTmp = new Example();
           ex = exTmp; //This complains with message: Local variable ex defined in an enclosing scope must be final or effectively final

          i= 4;//This also complains with message: Local variable i defined in an enclosing scope must be final or effectively final

    });
}

I looked online a lot and I didn't find any answer for this. All I found was that "Java language has a feature in which local variables accessed from within (anonymous) inner classes must be (effectively) final". But if that is the case, why can I change the members of the Example class, which isn't final?

João Pereira
  • 673
  • 1
  • 9
  • 29
  • 2
    Because a reference to a class instance being final (or effectively final) doesn't affect you're ability to change its members. A final variable can't be reassigned. That doesn't mean that the object it refers to can't have stuff changed inside it. – khelwood Aug 21 '18 at 14:48
  • 1
    A `final` variable is not necessarily immutable. Within context, it simply means the reference needs to be assigned a value before referencing, and that it cannot be reassigned a different value. – Mena Aug 21 '18 at 14:48
  • Because one is a field, one a local parameter. **local** parameters aren't allowed to be changed (because they get **copied**), but fields can be changed. – GhostCat Aug 21 '18 at 14:48
  • The key term is **local**. What does it mean to you when it says "local variable"? – Bhesh Gurung Aug 21 '18 at 14:49
  • I'm sorry guys but the question "Problems with local variable scope. How to solve it? " does not fully address my question. It never states what answered this for me, which is what @khelwood said `Because a reference to a class instance being final (or effectively final) doesn't affect you're ability to change its members.` I think the downvotes are unfair. – João Pereira Aug 21 '18 at 14:59
  • Extra question: What will happen to `ex.z`if 2 listeners try to change it? Or what happens if 1 listener changes it and other reads it? Will the second listener see the changes done by the 1st listener in the variable? – João Pereira Aug 21 '18 at 15:07

1 Answers1

0

You need a final flagged object wrapper for this.

Checkout the atomic package which provide the features you need: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html

excample:

protected void doActivate() {
    ItemCreation model = new Itemcreation(); //A class with visible moving parts
    final AtomicReference<Example> ex = new AtomicReference<>(new Example());
    final AtomicInteger i = new AtomicInteger(2);

    model.getSourceProperty().addListener((o, oldVal, newVal) -> {
        ex.get().z = "sss";
        Example exTmp = new Example();
        ex.set(exTmp);
        i.set(4);
    });
}
Jan S.
  • 994
  • 1
  • 9
  • 21