简体   繁体   中英

The pattern of final array instead of non-final variable for boolean flag in inner class

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 ?

Use AtomicBoolean .

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

There are situations where this is the best pattern.

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

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.

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.

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.)

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM