'Boolean value remains false after the value of the static field involved changes
In my assignment I have to use an enum
to make an EnumSet
of elements that fit the criteria given. So, the code needs to be as flexible as possible and allow any criteria that could be applied to the object declared in the enum
.
I've been testing things out, my code involves taking the finals of the enum
into the static context, so that a boolean
can be applied to them, and then looping through each declared object in the enum
to see if they fit the criteria. For some reason though, the state of the boolean
doesn't change to true
, when the value of the static fields fit the criteria.
Here is my code:
public class test {
// enumeration of persons by age and sex
enum Name {
Adam("Male", 17),
Amy("Female", 24),
Boris("Male", 12),
Bella("Female", 16);
final String _sex;
final int _age;
// static variants to "turn" values to the static context
volatile static String sex = "";
volatile static int age = 0;
Name(String sex, int age) {
_sex = sex;
_age = age;
}
}
public static void main(String[] args) {
// creating a set of people older than 17
EnumSet<Name> set = makeSet(Name.age >= 17);
System.out.print(set.toString());
}
static EnumSet<Name> makeSet(boolean query) {
EnumSet<Name> set = EnumSet.noneOf(Name.class);
for (Name element : Name.values()) {
// this is the "turning" of the values to the static context
Name.sex = element._sex;
Name.age = element._age;
// PROBLEM LIES HERE
// the query remains false, even when age is above 17
if (query) {
set.addAll(EnumSet.of(element));
}
}
return set;
}
}
Changing the static fields to volatile
doesn't fix the problem either, so I don't think it's a caching issue.
So, why does the boolean not update? Is there a work-around?
Solution 1:[1]
Answered in comments by @Turing85
The problem occurred because the boolean
is being passed by value.
Using a Predicate
instead of just a boolean
fixed the problem, because the object reference would be passed on instead, allowing the value to change after the makeSet()
method was invoked.
Furthermore, this eliminates the need to take the finals of the enum
into the static context.
Here is my code now:
public class test {
// enumeration of persons by age and sex
enum Name {
Adam("Male", 17),
Amy("Female", 24),
Boris("Male", 12),
Bella("Female", 16);
final String sex;
final int age;
Name(String sex, int age) {
this.sex = sex;
this.age = age;
}
}
public static void main(String[] args) {
// creating a set of people older than 17
EnumSet<Name> set = makeSet(query -> query.age >= 17);
System.out.print(set.toString());
}
static EnumSet<Name> makeSet(Predicate<Name> query) {
EnumSet<Name> set = EnumSet.noneOf(Name.class);
for (Name element : Name.values()) {
// PROBLEM FIXED
if (query.test(element)) {
set.addAll(EnumSet.of(element));
}
}
return set;
}
}
Solution 2:[2]
The problem you are facing is that the predicate
(Name.age >= 17
) is checked at the moment of the function call:
When you are calling makeSet(Name.age >= 17)
, what actually happens is, the predicate
returns a boolean, which at the time of checking returns false
, and false
is therefore parsed into the function.
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 | |
Solution 2 | Daan Sneep |