'How do I dynamically update a java property when the value of another property within the same class is updated

I have a Java class called Project. It has three properties (among others): goal, amountRaised and percentageRaised.

goal is the amount of money the project aims to raise; amountRaised is as the name implies amount raised so far; and percentageRaised is the percentage of money raised relative to the goal.

I want percentageRaised to be updated anytime either goal or amountRaised changes.

My question is, if I declare a setter method (private) for percentageRaised, is it going to be calculated automatically or do I need to call it somewhere?

Alternatively, would it be bad practice to add the logic on initialisation like so:

public class Project {

    @JsonProperty
    private String id;

    @NotBlank(message = "Please specify the amount of money you intend to raise")
    @JsonProperty
    private double goal;

    @JsonProperty
    private double amountRaised = 0;

    @JsonProperty
    private int percentageRaised = (int) ((amountRaised/goal) * 100);
}


Solution 1:[1]

the easiest way is to execute a calculation method in the setter of both attributes.

public class Project {

    @JsonProperty
    private String id;

    @NotBlank(message = "Please specify the amount of money you intend to raise")
    @JsonProperty
    private double goal;

    @JsonProperty
    private double amountRaised = 0;

    @JsonProperty
    private int percentageRaised = (int) ((amountRaised/goal) * 100);

    public void setGoal(double goal) {
        this.goal = goal;
        this.calculatePercentageRaised();
    }

    public void setAmountRaised(double amountRaised) {
        this.amountRaised = amountRaised;
        this.calculatePercentageRaised();
    }
    
    private void calculatePercentageRaised() {
      //check not null
      if (amountRaised!=null && goal!=null && goal != 0) {
        this.percentageRaised = (int) ((amountRaised/goal) * 100);
      }
    }
}

Solution 2:[2]

This can be achieved with help of basic java beans PropertyChangeListener

package p1;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;

public class Project implements PropertyChangeListener, Serializable {

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private String id;
    private double goal = 1;
    private double amountRaised = 0;
    private double percentageRaised = 0;

    public Project() {
        pcs.addPropertyChangeListener(this);
    }

    public static void main(String[] args) {
        Project project = new Project();
        project.setAmountRaised(20);
        System.out.printf("\n1: now, amountraised= is %f, goal is %f, percent is %f",
            project.amountRaised, project.goal, project.percentageRaised);
        project.setGoal(50);

        System.out.printf("\n2: now, amountraised= is %f, goal is %f, percent is %f",
            project.amountRaised, project.goal, project.percentageRaised);
        project.setGoal(100);
        System.out.printf("\n3: now, amountraised= is %f, goal is %f, percent is %f",
            project.amountRaised, project.goal, project.percentageRaised);
    }

    public void setGoal(double goal) {
        var old = this.goal;
        this.goal = goal;
        pcs.firePropertyChange("goal", old, goal);
    }

    public void setAmountRaised(double amountRaised) {
        var old = this.amountRaised;
        this.amountRaised = amountRaised;
        pcs.firePropertyChange("amountRaised", old, amountRaised);
    }

    public void updatePercentageRaised() {
        this.percentageRaised = ((amountRaised / goal) * 100);
        ;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        updatePercentageRaised();
    }
}

Output:

1: now, amountraised= is 20.000000, goal is 1.000000, percent is 2000.000000
2: now, amountraised= is 20.000000, goal is 50.000000, percent is 40.000000
3: now, amountraised= is 20.000000, goal is 100.000000, percent is 20.000000

Ref: https://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html.

https://kodejava.org/how-do-i-listen-for-beans-property-change-event/

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 braian azcune
Solution 2 swapyonubuntu