1

I often have a situation in my Java code when I need to set a boolean flag inside an inner class. It is not possible to use primitive boolean type for that, because inner class could only work with final variables from outside, so I use pattern like this:

// class from gnu.trove is not of big importance, just to have an example
private final TIntIntHashMap team = new TIntIntHashMap();
// ....... code ............
final boolean[] flag = new boolean[]{false};
team.forEachValue(new TIntProcedure() {
    @Override
    public boolean execute(int score) {
        if(score >= VICTORY_SCORE) {
            flag[0] = true;
        } 
        return true; // to continue iteration over hash map values
    }
});
//  ....... code ..............

The pattern of final array instead of non-final variable works well, except it is not look beautiful enough to me. Does someone know better pattern in Java ?

Nulldevice
  • 3,926
  • 3
  • 31
  • 37
  • Instead of using the very generic `forEachValue`, you could use an existing method or write your own method that better fits your use-case. Of course you can keep it very generic, like `exists(Iterator it, Predicate p)` or `count(Iterator it, Predicate p)`. I think a functional approach instead of this imperative approach would be much cleaner here. – Niklas B. Jul 01 '12 at 10:24
  • 1
    After quite a long stint of trying to use FP constructs in Java, I have finally given up. It just doesn't promote readability, correctness, or any other desirable feature of code. With Java 8's closures around the corner now, there's ever less reason not to wait for them. – Marko Topolnik Jul 01 '12 at 10:39

6 Answers6

6

Use AtomicBoolean.

Here's a popular StackOverflow question about this issue: Why are only final variables accessible in anonymous class?

Community
  • 1
  • 1
Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196
  • 1
    As far as aesthetics (conciseness), nothing can beat the final array idiom. This solution has even more boilerplate characters. – Marko Topolnik Jul 01 '12 at 10:36
  • The problem with objects from java.util.concurrent.atomic is that they have performance cost. Synchronization is not free, and I do not need it for my case. – Nulldevice Jul 01 '12 at 13:11
  • @nulldevice: expensive synchronization is a [ten year old urban legend](http://www.ibm.com/developerworks/java/library/j-jtp04223/index.html)... we're not using JDK 1.3 anymore. like the article says, the runtime can even detect superfluous synchronization which means it is very likely to be optimized out in a simple case like this. – Janus Troelsen Jul 02 '12 at 09:07
  • @MarkoTopolnik: trying to avoid boilerplate in Java is futile. – Janus Troelsen Jul 02 '12 at 09:08
  • @JanusTroelsen I second that :) However, I am on a quest to beat it down to the minimum. – Marko Topolnik Jul 02 '12 at 09:12
  • @MarkoTopolnik: it is more readable though, that's why it matters. let's say someone is reading your code and stumbles upon this one-element array. now, since you used a weird idiom like this, you'd need a comment to explain it. the comment is be your boilerplate. if someone sees a reference to a class they don't know, they can just look it up, no comments needed. maybe the unnecessary thread-safety should be commented on then. – Janus Troelsen Jul 02 '12 at 09:15
  • 1
    Janus, there are many, many well-known idioms in Java and no-one feels the need to explain them in a comment. This is one of them, so a dev that doesn't know it will get to learn it very quickly. – Marko Topolnik Jul 02 '12 at 09:19
4

How about having a generic holder class which holds object of any type. In your case, it can hold a Boolean type. Something like:

class Holder<T> {        
    private T genericObj;

    public Holder(T genericObj) {
        this.genericObj = genericObj;
    }

    public T getGenericObj() {
        return genericObj;
    }

    public void setGenericObj(T genericObj) {
        this.genericObj = genericObj;
    }    
}

And use it as:

public class Test {
    public static void main(String[] args) throws Exception {        
        final Holder<Boolean> boolHolder = new Holder<Boolean>(Boolean.TRUE);
        new Runnable() {            
            @Override
            public void run() {
                boolHolder.setGenericObj(Boolean.FALSE);
            }
        };
    }
}

Of course, this has the usual problems that occur with mutable objects that are shared across threads but you get the idea. Plus for applications where memory requirements are tight, this might get crossed off when doing optimizations in case you have a lot of invocations of such methods. Also, using AtomicReference to swap/set references should take care of use from multiple threads though using it across threads would still be a bit questionable.

Sanjay T. Sharma
  • 22,857
  • 4
  • 59
  • 71
3

There are situations where this is the best pattern.

The only improvement I can suggest is return false when you have found a match.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

One problem is that the TIntIntHashMap does not have a fold/reduce method so you have to simulate it using foreach. You could try to write your own class extending TIntIntHashMap adding a reduce method.

Other solution is to just extend TIntProcedure to have a value. Something like:

abstract class TIntProcedureWithValue<T> implements TIntProcedure {
    private T accumulator;
    public T getValue() {return accumulator;}
}

Then you can pass an instance of this class to foreach, set the internal accumulator instead of the external flag array, and get the resulting value afterwards.

src
  • 541
  • 2
  • 6
1

I am not familiar with gnu.trove, but generally it's better for the "algortihm" function to be more specific, leaving less code here.

private final IntIntHashMap team = new IntIntHashMap();

boolean found = team.value().containsMatch(new IntPredicate() {
    public boolean is(int score) {
        return score >= VICTORY_SCORE;
    }
});

(More concise syntax should be available in Java SE 8.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

maybe something like that? (implements or extends... I don't know what is TIntProcedure, unfortunately) :

    class FlagResult implements TIntProcedure {
        boolean flag = false;
        @Override
        public boolean execute(int score) {
            flag = score >= VICTORY_SCORE;
            return !flag;
        }
    };
    FlagResult result = new FlagResult();
    team.forEachValue(result);
    boolean flag = result.flag;
Pavel K.
  • 436
  • 4
  • 11