/* package whatever; // don't place package name! */

import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone {
    public static void main(String[] args) {
        ValueSwitcher<Integer> valueSwitcher = ValueSwitcher.getInstance();
        valueSwitcher.setValue1(1);
        valueSwitcher.setValue2(2);
        valueSwitcher.switchValues();
        System.out.println(String.format("value1: %s, value2: %s", valueSwitcher.getValue1(), valueSwitcher.getValue2()));
    }
}


class ValueSwitcher<T1> {
    private final static Logger LOGGER = Logger.getLogger("Value switcher");
    private T1 value1;
    private T1 value2;


    public static <T> ValueSwitcher<T> getInstance() {
        return new ValueSwitcher<>();
    }

    protected ValueSwitcher() {
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "ctor");
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "ctor");
    }

    public T1 getValue1() {
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "getValue1");
        return value1;
    }

    public void setValue1(T1 value1) {
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "setValue1", value1);
        this.value1 = value1;
        LOGGER.exiting(ValueSwitcher.class.getCanonicalName(), "setValue1", value1);
    }

    public T1 getValue2() {
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "getValue2");
        return value2;
    }

    public void setValue2(T1 value2) {
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "setValue2", value2);
        this.value2 = value2;
        LOGGER.exiting(ValueSwitcher.class.getCanonicalName(), "setValue2", value2);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ValueSwitcher<?> that = (ValueSwitcher<?>) o;
        return Objects.equals(getValue1(), that.getValue1()) &&
                Objects.equals(getValue2(), that.getValue2());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getValue1(), getValue2());
    }

    public void switchValues() {
        LOGGER.entering(ValueSwitcher.class.getCanonicalName(), "switchValues");
        T1 tmpValue = getValue1();
        setValue1(getValue2());
        setValue2(tmpValue);
        if (shouldLogInfo()) {
            LOGGER.log(Level.INFO, String.format("Values %s and %s has been switched", value1, value2));
        }
        LOGGER.exiting(ValueSwitcher.class.getCanonicalName(), "switchValues");
    }

    private static boolean shouldLogInfo() {
        Level level = Logger.getGlobal().getLevel();
        return level != null && level.intValue() > Level.INFO.intValue();
    }

}