What's the best practice for specifying flags in a Java method?
I've seen SWT using int as bitfields, like:
(example partially from "Effective Java, 2nd Ed." page 159):
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
void printText(String text, int flags) {
}
}
and your client call looks like:
printText("hello", Text.STYLE_BOLD | Text.STYLE_ITALIC);
..but this is discouraged as you can mixed flags (int values) from different classes together without any compiler checks.
In the same book ("Effective Java"), I see the use of EnumSet, but then your user call becomes:
printText("hello", EnumSet.of(Style.Bold, Style.ITALIC));
I find this a bit verbose and I prefer the elegance of SWT.
Is there any other alternative or is this basically the two tastes you must pick?
Guess you have hit a wall. I don't see any other option. Java is verbose that's a fact. In situations like this i usually add a local variable to make the code more readable. You can do this,
EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.ITALIC);
printText("hello", styles);
If you want bit style flags, Java wraps them in a BitSet. It's been around for ages, yet few people bother to use it (preferring embedding C style bit handling in ints).
The api for BitSet can be found here.
Coupled with a few well chosen static ints, it does pretty well until you start getting into checking and setting multiple bits in one pass.
I advise that you go with the EnumSet approach.
EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.Italic);
This approach provides better type safety, and Style being an enum will have full-blown OO capabilities.
Late answer for anyone coming across this. Here is one way to do it to reduce memory and have a nice enum like api:
public static class MyFlag {
public static final MyFlag A = new MyFlag(1<<0);
public static final MyFlag B = new MyFlag(1<<1);
public static final MyFlag C = new MyFlag(1<<2);
public static final MyFlag ALL = A.and(B).and(C);
private final int flag;
private MyFlag(int flag){
this.flag = flag;
}
public MyFlag and(MyFlag limit){
return new MyFlag(flag & limit.flag);
}
public MyFlag not(MyFlag limit){
return new MyFlag(flag | ~limit.flag);
}
public boolean isSet(MyFlag limit){
if(limit ==null){
return false;
}
return (this.flag & limit.flag) != 0;
}
}
method:
public void doFoo(MyFlag flag){
if(MyFlag.A.isSet(flag)){
....
}
if(MyFlag.C.isSet(flag)){
....
}
}
call:
x.doFoo(MyFlag.A.and(MyFlag.C));
If you only have a limited number of methods that will be taking a set of styles (like printText, in your example), you can tweak their signature to take a variable number of Style params:
void printText(String text, Style... flags) {
EnumSet<Style> style = logicalOr(flags); // see comment below
...
}
And then your calls are very close to the untyped (int) flag route:
printText("hello", Style.BOLD, Style.ITALIC);
Sadly, there is no EnumSet.of(E... ) factory, just EnumSet.of(E first, E... more), so you'll need a generic logicalOr method to split your array into first + rest chunks. Left as an exercise to the reader =).
Related
I am wondering when should I use builder with static class inside and where classical one?
Implementation from Effective Java book
public class Pizza {
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
public static class Builder {
//required
private final int size;
//optional
private boolean cheese = false;
private boolean pepperoni = false;
private boolean bacon = false;
public Builder(int size) {
this.size = size;
}
public Builder cheese(boolean value) {
cheese = value;
return this;
}
public Builder pepperoni(boolean value) {
pepperoni = value;
return this;
}
public Builder bacon(boolean value) {
bacon = value;
return this;
}
public Pizza build() {
return new Pizza(this);
}
}
private Pizza(Builder builder) {
size = builder.size;
cheese = builder.cheese;
pepperoni = builder.pepperoni;
bacon = builder.bacon;
}
}
Regular implementation
(just diagram)
You should consider using the Builder pattern when 1. you need to prevent the object from getting into an inconsistent state AND 2. using constructor parameters would be difficult to use/read because you have an unwieldy (large) number of properties that need to be set.
Using a normal default constructor + getters/setters could allow consumers to get into an invalid/inconsistent state. I.E. They might forget to set a very important property (like Cheese), but they aren't prevented from doing so and can create a Pizza anyway, even in a "bad" state. The burden is on the consumer to set state on the object appropriately after construction.
You can normally prevent this via Constructor parameters. E.G.
private Pizza() {}
public Pizza(int size, boolean cheese, boolean pepperoni, boolean bacon)
{
...
}
But when you have a large number of parameters this can be difficult to read/write.
So, in summary, when you want to guarantee that your object can't be constructed in an inconsistent state AND you have too many fields to set that using constructor parameters would make it difficult to use and read, you could consider using the Builder pattern.
I'd say when you are prepared to go the extra mile to make the class constructor look natural.
Who can deny that this reads like good code?
Pizza pizza = new Pizza.Builder(10).cheese(true).peperoni(true).bacon(true).build();
I mean ... isn't that just sweet? It's even got bacon!
Second (and more common) option would be:
Pizza pizza = new Pizza(10);
pizza.setCheese(true);
pizza.setPeperoni(true);
pizza.setBacon(true);
This would be easier to work with using reflection and would therefore serialise/deserialise much more easily - but suffers from a more cumbersome and verbose construction.
Third and least flexible would be:
Pizza pizza = new Pizza(10, true, true, true);
but it is possible to provide both 2nd and 3rd mechanism together which can be a plus.
How to choose
There isn't a simple way to choose. If you want to woo your customers into buying your libraries you could offer all three methods but that would then spoil one of the major the benefits of using a Builder (which is hiding the actual constructor).
I would recommend using the 2nd method and perhaps the 3rd unless there is a good reason to take the unusual route of using a Builder.
This is a simplified example. I have this enum declaration as follows:
public enum ELogLevel {
None,
Debug,
Info,
Error
}
I have this code in another class:
if ((CLog._logLevel == ELogLevel.Info) || (CLog._logLevel == ELogLevel.Debug) || (CLog._logLevel == ELogLevel.Error)) {
System.out.println(formatMessage(message));
}
My question is if there is a way to shorten the test. Ideally i would like somethign to the tune of (this is borrowed from Pascal/Delphi):
if (CLog._logLevel in [ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error])
Instead of the long list of comparisons. Is there such a thing in Java, or maybe a way to achieve it? I am using a trivial example, my intention is to find out if there is a pattern so I can do these types of tests with enum value lists of many more elements.
EDIT: It looks like EnumSet is the closest thing to what I want. The Naïve way of implementing it is via something like:
if (EnumSet.of(ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error).contains(CLog._logLevel))
But under benchmarking, this performs two orders of magnitude slower than the long if/then statement, I guess because the EnumSet is being instantiated every time it runs. This is a problem only for code that runs very often, and even then it's a very minor problem, since over 100M iterations we are talking about 7ms vs 450ms on my box; a very minimal amount of time either way.
What I settled on for code that runs very often is to pre-instantiate the EnumSet in a static variable, and use that instance in the loop, which cuts down the runtime back down to a much more palatable 9ms over 100M iterations.
So it looks like we have a winner! Thanks guys for your quick replies.
what you want is an enum set
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumSet.html
put the elements you want to test for in the set, and then use the Set method contains().
import java.util.EnumSet;
public class EnumSetExample
{
enum Level { NONE, DEBUG, INFO, ERROR };
public static void main(String[] args)
{
EnumSet<Level> subset = EnumSet.of(Level.DEBUG, Level.INFO);
for(Level currentLevel : EnumSet.allOf(Level.class))
{
if (subset.contains(currentLevel))
{
System.out.println("we have " + currentLevel.toString());
}
else
{
System.out.println("we don't have " + currentLevel.toString());
}
}
}
}
There's no way to do it concisely in Java. The closest you can come is to dump the values in a set and call contains(). An EnumSet is probably most efficient in your case. You can shorted the set initialization a little using the double brace idiom, though this has the drawback of creating a new inner class each time you use it, and hence increases the memory usage slightly.
In general, logging levels are implemented as integers:
public static int LEVEL_NONE = 0;
public static int LEVEL_DEBUG = 1;
public static int LEVEL_INFO = 2;
public static int LEVEL_ERROR = 3;
and then you can test for severity using simple comparisons:
if (Clog._loglevel >= LEVEL_DEBUG) {
// log
}
You could use a list of required levels, ie:
List<ELogLevel> levels = Lists.newArrayList(ELogLevel.Info,
ELogLevel.Debug, ELogLevel.Error);
if (levels.contains(CLog._logLevel)) {
//
}
I'm using GWT.
When it is compiling the Java code to Javascript code, sometimes it changes some of the members' names.
for example:
private int height;
becomes in the JS:
height_0;
Example:
public class TestClass
{
private int a;
public TestClass()
{
a = 0;
}
public TestClass(int a)
{
this.a = a;
}
public int getMember()
{
return a;
}
public void advance()
{
a++;
}
}
Will result in output like so:
function TestClass_0(){
this.a_0 = 0;
}
function TestClass_1(a){
this.a_0 = a;
}
function TestClass(){
}
_ = TestClass_1.prototype = TestClass_0.prototype = TestClass.prototype = new Object_0;
_.advance_0 = function advance(){
++this.a_0;
}
;
_.getClass$ = function getClass_1(){
return Lcom_autodesk_autocadws_gwt_platform_testExporter_TestClass_2_classLit;
}
;
_.getMember_0 = function getMember(){
return this.a_0;
}
;
_.a_0 = 0;
}
The name of the member a was changed to a_0. In some cases, when using web workers, the code will be compiled differently on the web worker script, and the member's name will not be changed (or will be cjanged to a_1, for example).
My problem with that is when I transfer objects in messages to web workers. When coding the web worker side in Java, I'm expecting to access the member a, and not a_0. Using getters does not solve the issue, since they are simply replaced with direct access when compiled to JS.
My question:
Why are these naming changes occur? In which cases? Is it possible to avoid them?
Thanks a lot.
In most cases, the fields will actually be renamed to something lik a, b, etc. What you're seeing here is due to compiling with -style PRETTY which does not obfuscate the code.
The reason GWT obfuscates the code is to make it smaller.
If you need to pass objects to the outside world, you have to serialize them (or map them to JavaScript objects) to a stable structure.
The easiest way to do it is to use a JavaScriptObject. You can also have a look at gwt-exporter.
Been a while since I used Java and was wondering if this was a decent or even correct way of setting this up.
FYI, userResults refers to a JDBI variable that isn't present in the code below.
Feel free to suggest a better method, thanks.
public class Stat
{
private int current;
private int max;
public int getCurrent() {return current;}
public void setCurrent(int current) {this.current = current;}
public int getMax() {return max;}
public void setMax(int max) {this.max = max;}
}
public class Character
{
Stat hp = new Stat();
Stat mp = new Stat();
}
Character thisCharacter = new Character();
// Set the value of current & max HP according to db data.
thisCharacter.hp.setCurrent((Integer) userResults.get("hpColumn1"));
thisCharacter.hp.setMax((Integer) userResults.get("hpColumn2"));
// Print test values
System.out.println (thisCharacter.hp.Current);
System.out.println (thisCharacter.hp.Max);
Correct? Well, does it work? Then it probably is correct.
Wether or not it is a decent way to do it then the answer is "maybe". It is hard to tell from what context this code is in. But there are some things you could keep in mind though:
In which class (or object rather) are the Stat set in? Do you feel is it the responsibility of the class to do this and know what database values to get them from? If not, consider making some kind of a class that does this.
Making chained calls such as thisCharacter.hp.setCurrent(...) is a violation of principle of least knowledge. Sometimes you can't help it, but usually it leads to kludgy code. Consider having something that handles all the logic surrounding the stats. In your code you may need a HealthStatsHandler that have methods such as loadStats(), saveStats(), and mutator actions such as takeDamage(int dmg) and revive(int health).
If you have trouble figuring things out if it has the correct object design, then study up on the SOLID principles. They provide nice guidelines that any developer should follow if they want to have code that is extensible and "clean".
This is not really a tree. It is not possible two have more than one layer of children.
Usually you define an interface let's call it Node where both Stat and Character implements it and the two children of Character would have the type Node.
I would consider creating the Stat objects seperately and passing them into Character, and making the character attributes private as follows:
public class Character
{
private Stat hp;
private Stat mp;
public Stat getHp() {return hp;}
public void setHp(Stat h) {this.hp = h;}
public Stat getMp() {return mp;}
public void setMp(Stat m) {this.mp = m;}
}
// Set the value of current & max HP according to db data.
Stat hp = new Stat();
hp.setCurrent((Integer) userResults.get("hpColumn1"));
hp.setMax((Integer) userResults.get("hpColumn2"));
Character thisCharacter = new Character();
thisCharacter.setHp(hp);
// do the same for mp
One additional simple step would be to create a Character constructor that would take an hp and an mp
I maintain a large document archive and I often use bit fields to record the status of my documents during processing or when validating them. My legacy code simply uses static int constants such as:
static int DOCUMENT_STATUS_NO_STATE = 0
static int DOCUMENT_STATUS_OK = 1
static int DOCUMENT_STATUS_NO_TIF_FILE = 2
static int DOCUMENT_STATUS_NO_PDF_FILE = 4
This makes it pretty easy to indicate the state a document is in, by setting the appropriate flags. For example:
status = DOCUMENT_STATUS_NO_TIF_FILE | DOCUMENT_STATUS_NO_PDF_FILE;
Since the approach of using static constants is bad practice and because I would like to improve the code, I was looking to use Enums to achieve the same. There are a few requirements, one of them being the need to save the status into a database as a numeric type. So there is a need to transform the enumeration constants to a numeric value. Below is my first approach and I wonder if this is the correct way to go about this?
class DocumentStatus{
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFINED(1<<0),
DOCUMENT_STATUS_OK(1<<1),
DOCUMENT_STATUS_MISSING_TID_DIR(1<<2),
DOCUMENT_STATUS_MISSING_TIF_FILE(1<<3),
DOCUMENT_STATUS_MISSING_PDF_FILE(1<<4),
DOCUMENT_STATUS_MISSING_OCR_FILE(1<<5),
DOCUMENT_STATUS_PAGE_COUNT_TIF(1<<6),
DOCUMENT_STATUS_PAGE_COUNT_PDF(1<<7),
DOCUMENT_STATUS_UNAVAILABLE(1<<8);
private final long statusFlagValue;
StatusFlag(long statusFlagValue) {
this.statusFlagValue = statusFlagValue;
}
public long getStatusFlagValue(){
return statusFlagValue;
}
}
/**
* Translates a numeric status code into a Set of StatusFlag enums
* #param numeric statusValue
* #return EnumSet representing a documents status
*/
public EnumSet<StatusFlag> getStatusFlags(long statusValue) {
EnumSet statusFlags = EnumSet.noneOf(StatusFlag.class);
StatusFlag.each { statusFlag ->
long flagValue = statusFlag.statusFlagValue
if ( (flagValue&statusValue ) == flagValue ) {
statusFlags.add(statusFlag);
}
}
return statusFlags;
}
/**
* Translates a set of StatusFlag enums into a numeric status code
* #param Set if statusFlags
* #return numeric representation of the document status
*/
public long getStatusValue(Set<StatusFlag> flags) {
long value=0;
flags.each { statusFlag ->
value|=statusFlag.getStatusFlagValue()
}
return value;
}
public static void main(String[] args) {
DocumentStatus ds = new DocumentStatus();
Set statusFlags = EnumSet.of(
StatusFlag.DOCUMENT_STATUS_OK,
StatusFlag.DOCUMENT_STATUS_UNAVAILABLE);
assert ds.getStatusValue( statusFlags )==258 // 0000.0001|0000.0010
long numericStatusCode = 56;
statusFlags = ds.getStatusFlags(numericStatusCode);
assert !statusFlags.contains(StatusFlag.DOCUMENT_STATUS_OK);
assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_TIF_FILE);
assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_PDF_FILE);
assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_OCR_FILE);
}
}
Instead of defining constructor parameters, you could simply use the internal ordinal() value to calculate this.
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFINED,
DOCUMENT_STATUS_OK,
DOCUMENT_STATUS_MISSING_TID_DIR,
DOCUMENT_STATUS_MISSING_TIF_FILE,
DOCUMENT_STATUS_MISSING_PDF_FILE,
DOCUMENT_STATUS_MISSING_OCR_FILE,
DOCUMENT_STATUS_PAGE_COUNT_TIF,
DOCUMENT_STATUS_PAGE_COUNT_PDF,
DOCUMENT_STATUS_UNAVAILABLE;
public long getStatusFlagValue(){
return 1 << this.ordinal();
}
}
Please note that now you should abstain from reordering, inserting (other than at the end) or deleting entries, otherwise the flag values will change, and the meaning of your database contents will change.
your approach is exactly the way to do it.
A slightly better way would be to store the result of 1 << this.ordinal() in a field when
the enum values are constructed. This way, you don't have to provide each value manually, and the flag is only computed once.
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFIND,
DOCUMENT_STATUS_OK,
DOCUMENT_STATUS_MISSING_TID_DIR,
DOCUMENT_STATUS_MISSING_TIF_FILE,
DOCUMENT_STATUS_MISSING_PDF_FILE,
DOCUMENT_STATUS_MISSING_OCR_FILE,
DOCUMENT_STATUS_PAGE_COUNT_TIF,
DOCUMENT_STATUS_PAGE_COUNT_PDF,
DOCUMENT_STATUS_UNAVAILABLE;
public final int flag;
StatusFlag() {
this.flag = 1 << this.ordinal();
}
}
**Update:** This is an old answer from back when I did not have much Java experience.
I no longer think my answer is valid, as this approach couples the value of the flag to the ordering or the enum values, which is bad: if the order is changed or enum values are removed, this will affect the flags of other enum values, which can have unforeseen consequences.
These days, I would use the approach used in the question (manually provide the value of the flag via a constructor parameter) as it is more maintainable:
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFINED(0),
DOCUMENT_STATUS_OK(1),
DOCUMENT_STATUS_MISSING_TID_DIR(2),
DOCUMENT_STATUS_MISSING_TIF_FILE(3),
DOCUMENT_STATUS_MISSING_PDF_FILE(4),
DOCUMENT_STATUS_MISSING_OCR_FILE(5),
DOCUMENT_STATUS_PAGE_COUNT_TIF(6),
DOCUMENT_STATUS_PAGE_COUNT_PDF(7),
DOCUMENT_STATUS_UNAVAILABLE(8);
public final int flag;
StatusFlag(int id) {
this.flag = 1 << id;
}
}
Don't give your enums values. Use an EnumSet to combine them, and use Enum.ordinal() when persisting in order to convert to/from a single integer. You might also find Class.getEnumConstants() useful when reconstructing the set from the integer.
I have made a complete library for this problem:
http://claude-martin.ch/enumbitset/
The main goal was to store sets of enum types in bitfields. But it also supports other types.
With this you would not need any extra methods like your "getStatusFlags()". It can be used on any existing enum type simply by adding the interface EnumBitSetHelper (it is used like a "trait").
Each enum constant can then create an "EnumBitSet" which has all methods of Java's EnumSet and BitSet.
Then you can work with these sets of enum constants and convert them to bitfield values.
It supports many formats such as BigInteger and long to easily store the value into a bit field.
But note that this only works with Java version 8 and newer.