We have an exception Class A with a few fault codes defined as public static final and it is referenced in many files (more than 100) in our source code.
We want all these fault codes in Class B for some processing.
Currently we have implemented a method called getFaultCodes() in Class A to build a list of fault codes and return the same. The problem with this approach is that whenever an fault code is introduced, it has to be added in getFaultCode method as well. This is error prone, as a user may forget to add the new code to the method.
Moving these fault codes under an enum requires changes in many files all over the source code, so we don't want do this.
class ExceptionA {
public static final String faultCode1 = "CODE1";
public static final String faultCode2 = "CODE1";
public static final String faultCode3 = "CODE1";
List<String> getFaultCodes(){
list.add(faultCode1);
......
return list;
}
}
We are thinking about using reflection, but I'm posting in this forum just to check if there is a better solution. Please provide your suggestion to solve this problem.
Maybe you can go through an interface:
public interface FaultCodeProvider
{
String getFaultCode();
}
Then have your enums implement it:
public enum DefaultFaultCodes
implements FaultCodeProvider
{
FAULT1("text for fault 1"),
// etc
;
private final String value;
DefaultFaultCodes(final String value)
{
this.value = value;
}
#Override
public String getFaultCode()
{
return value;
}
}
Collecting them from the enum is then as easy as cycling through the enum's values().
I have modified code code like below:
class ExceptionA {
public enum codes {
CODE1("CODE1"),
CODE2("CODE2"),
CODE3("CODE3"),
private String code;
codes(String code){
this.code = code;
}
public String getCode() {
return this.code;
}
}
public static final String faultCode1 = code.CODE1;
public static final String faultCode2 = code.CODE2;
public static final String faultCode3 = code.CODE3;
}
So that I need not to change the variables occurrences "faultCode" in the source code, I can access the list of fault codes from other class.
Related
Error:
...
Caused by: java.lang.ExceptionInInitializerError
...
Caused by: java.lang.ClassCastException:
class com.evopulse.ds2150.TechTrees$BuildingTechTree
not an enum
at java.util.EnumSet.noneOf(Unknown Source)
at java.util.EnumSet.of(Unknown Source)
at com.evopulse.ds2150.TechTrees$BuildingTechTree.<clinit>(TechTrees.java:38)
Here is a snippet of my enumeration
public enum BuildingTechTree {
//Name SoftName Requirements
NONE ("NULL", null),
--> This next line is where it crashes
BARRACKS ("Barracks", EnumSet.of(NONE),
WALLS_SANDBAGS ("Sandbag wall", EnumSet.of(NONE),
POWERPLANT ("Power plant", EnumSet.of(BARRACKS)),
GUARDTOWER ("Guard Tower", EnumSet.of(BARRACKS));
Replacing EnumSet.of(NONE) and EnumSet.of(BARRACKS) with null, lets initialization work, but breaks my code, due to missing data structure... obviously, but I did it to test the rest of my code wasn't somehow the cause.
Removing EnumSet.of(NONE) and replacing with just NONE, and the same for BARRACKS, and changing all related variables, constructor, and methods, that didn't work either... (and even couldn't use the contains.all, since is wasn't "applicable to my changed variable"... )
I extended this example, using the second implementation:
https://gamedev.stackexchange.com/a/25652/48573
I also tried retracing my steps by copying the example verbatim. added
private static Set<BuildingTechTree> techsKnown;
techsKnown = (BuildingTechTree.BIODOME);
test = TechTrees.researchTech(techsKnown);
to another class to be called from for testing initialization. and had to change
public boolean researchTech(BuildingTechTree tech) {
to static
This resulted in the same "in not an enum" error. I don't have any rep, to comment on his answer to point out the initialization error...
Added info for both current answers, as both solutions cause the same new error:
public class TechTrees {
private static Set<BuildingTechTree> techsKnown;
public TechTrees() {
techsKnown = EnumSet.of(BuildingTechTree.NONE); //Using this
techsKnown = EnumSet.noneOf(BuildingTechTree.class); //Or this
}
public static boolean researchTech(BuildingTechTree tech) {
if (techsKnown.containsAll(tech.requirements)) { //Causes null pointer
return true; //exception # techsKnown
}
return false;
}
Your declaration structure is so clever it's a shame it doesn't work. But EnumSet apparently needs the enum to be fully initialized first. It tries to fetch the array of constants from the enum so that, among other things, it knows how much space is needed for its internal bitset.
Here's one workaround. It uses a helper method that creates an ordinary set (HashSet) first, and then, in a static initialization block, it iterates the enum constants and replaces all the sets with EnumSets.
public enum BuildingTechTree {
// Named constants
//Name SoftName Requirements
NONE ("NULL", null),
BARRACKS ("Barracks", setOf(NONE)),
WALLS_SANDBAGS ("Sandbag wall", setOf(NONE)),
POWERPLANT ("Power plant", setOf(BARRACKS)),
GUARDTOWER ("Guard Tower", setOf(BARRACKS));
private final String softName;
private Set<BuildingTechTree> requirements;
private BuildingTechTree(String softName, Set<BuildingTechTree> requirements) {
this.softName = softName;
this.requirements = requirements;
}
private static Set<BuildingTechTree> setOf(BuildingTechTree... values) {
return new HashSet<>(Arrays.asList(values));
}
static {
for (BuildingTechTree v : values()) {
if (v.requirements == null) {
v.requirements = EnumSet.noneOf(BuildingTechTree.class);
} else {
v.requirements = EnumSet.copyOf(v.requirements);
}
}
}
}
You have a chicken and egg problem. You could refactor your enum to something like this:
public enum BuildingTechTree {
NONE("NULL"),
BARRACKS("Barracks"),
WALLS_SANDBAGS("Sandbag wall"),
POWERPLANT("Power plant"),
GUARDTOWER("Guard Tower");
static {
NONE.trees = EnumSet.noneOf(BuildingTechTree.class);
BARRACKS.trees = EnumSet.of(NONE);
WALLS_SANDBAGS.trees = EnumSet.of(NONE);
POWERPLANT.trees = EnumSet.of(BARRACKS);
GUARDTOWER.trees = EnumSet.of(BARRACKS);
}
private String name;
private Set<BuildingTechTree> trees;
private BuildingTechTree(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Set<BuildingTechTree> getTrees() {
return Collections.unmodifiableSet(trees);
}
}
EDIT:
regarding your second problem: you're accessing a static variable, from a static method. But this variable is initialized when the constructor of the class has been called (which is a huge design problem). Don't use non-final static fields. And don't initialize static fields from instance methods or constructors. That doesn't make sense. You don't set the color that all cars should have when constructing a car. Initialize your static fields statically:
public class TechTrees {
private static final Set<BuildingTechTree> TECHS_KNOWN =
EnumSet.of(BuildingTechTree.NONE);
public static boolean researchTech(BuildingTechTree tech) {
return TECHS_KNOWN.containsAll(tech.requirements));
}
}
I have few constant values which I refer across my application. I am creating a class something like below snippet.
public class Styles {
public static final String tableStyle = "TableGrid";
public static final String fontFamily = "Calibri";
public static final String headerStyle = "Heading2";
public static final String footerStyle = "Heading3";
public static final String tableHeaderStyle = "Heading1";
public static final String tableDataFontFamily = "Cambria";
public static final int tableHeaderFontSize = 16;
public static final int tableDataFontSize = 12;
}
I am assigning the values in it and I am referring them like Styles.headerStyle . My doubt is, is this the good way or is there any better approach to achieve this? something like Enum ?
Thanks in advance.
It depends on the nature of your application, in most cases it is not a good practice to have a collection of constants in that way, but it is difficult to tell without knowing the context of your application. BTW, are sure that you'll never (or almost never) change things like "fontFamily"?
Of course an enum would be a little less verbose and more functional:
public enum Styles {
TABLE_STYLE("TableGrid"),
FONT_FAMILY("Calibri"),
HEADER_STYLE("Heading2"),
FOOTER_STYLE("Heading3"),
TABLE_HEADER_STYLE("Heading1"),
TABLE_DATA_FONT_FAMILY("Cambria"),
TABLE_HEADER_FONT_SIZE("16"),
TABLE_DATA_FONT_SIZE("12");
private String value;
private Styles(String value) {
this.value = value;
}
public String getStringValue() {
return value;
}
public int getIntValue() {
return Integer.valueOf(value);
}
}
1) You can use an external file as a Property File.
2) You can use an enum as #morgano answer
3) I would change your class declaration to
public final class Styles { // final class can't have childs
private Styles(){} // you cannot instanciate
public static final String tableStyle = "TableGrid";
.
.
.
}
I have encountered a weird problem in my app (java).
I have an enum. Something like that
public enum myEnum implement myIntrface{
valueA(1),valueb(2),valuec(3),valued(4)
private int i;
// and then - a constructor
public MyEnum(int number){
i = number;
}
private MyObj obj = new MyObj;
// getter and setter for obj
}
and in another class I have this
MyEnum.valueA.setObj(new Obj(...))
in briefe - I have an enum with a private instance member that has a set and a get.
So far so good -
The only thing that amazes me is that later on I look at the value of the MyEnum.valueA().obj is null.
there is nothing that updates the value to null, I have even gave it a default value in the constructor and I still see it null later.
any suggestions?
Enums should be un-modifiable classes so you shouldn't really be doing this. If your looking to modify the state of a type based object like an enum you should use an final class approach with embedded constants. Below is an example of a class based approach with a modifiable name an a un-modifiable name...
public final class Connection {
public static final Connection EMAIL = new Connection("email");
public static final Connection PHONE = new Connection("phone");
public static final Connection FAX = new Connection("fax");
/**/
private final String unmodifiableName; //<-- it's final
private String modifiableName;
/*
* The constructor is private so no new connections can be created outside.
*/
private Connection(String name) {
this.unmodifiableName = name;
}
public String getUnmodifiableName() {
return unmodifiableName;
}
public String getModifiableName() {
return modifiableName;
}
public void setModifiableName(String modifiableName) {
this.modifiableName = modifiableName;
}
}
The purpose of enums is to represent constant values. It does not make any sense to set the fields of a constant value.
You should declare your fields as final, and use the constructor to initialize all of them.
For reference, the following code works as expected:
public class Test {
public static enum MyEnum {
valueA(1),valueb(2),valuec(3),valued(4);
private int i;
private Object o;
private MyEnum(int number) {
i = number;
}
public void set(Object o) {
this.o = o;
}
public Object get() {
return o;
}
}
public static void main(String[] args) {
System.out.println(MyEnum.valueA.get()); // prints "null"
MyEnum.valueA.set(new Integer(42));
System.out.println(MyEnum.valueA.get()); // prints "42"
}
}
the cause of this problem is the db40 framework . It loads an enum from the db using reflection. This is well documented .
http://developer.db4o.com/Forums/tabid/98/aft/5439/Default.aspx
Given an enum where each instance is associated with some value:
public enum SQLState
{
SUCCESSFUL_COMPLETION("00000"),
WARNING("01000");
private final String code;
SQLState(String code)
{
this.code = code;
}
}
How can I construct a Map for efficient reverse look-ups? I tried the following:
public enum SQLState
{
SUCCESSFUL_COMPLETION("00000"),
WARNING("01000");
private final String code;
private static final Map<String, SQLState> codeToValue = Maps.newHashMap();
SQLState(String code)
{
this.code = code;
codeToValue.put(code, this); // problematic line
}
}
but Java complains: Illegal reference to static field from initializer. That is, the static Map is being initialized after all enum values so you cannot reference it from the constructor. Any ideas?
use:
static {
for (SQLState sqlState : values()){
codeToValue.put(sqlState.code, sqlState);
}
}
As you are using Guava, i recommend using the following code:
public enum SQLState {
SUCCESSFUL_COMPLETION("00000"),
WARNING("01000"),
;
private final String code;
private SQLState(String code) {
this.code = code;
}
public static final Function<SQLState,String> EXTRACT_CODE = new Function<SQLState,String>() {
#Override
public String apply(SQLState input) {
return input.code;
}
};
public static final Map<String, SQLState> CODE_TO_VALUE = ImmutableMap.copyOf( Maps.uniqueIndex(EnumSet.allOf(SQLState.class), EXTRACT_CODE) );
public static void main(String[] args) {
System.out.println( SQLState.CODE_TO_VALUE.get("00000") );
}
}
This produces as expected: "SUCCESSFUL_COMPLETION"
Using static initializer is nice when you can't init the final variables inline, but in this case, with Guava, you really can, in a functionnal approach with Guava functions.
Furthermode, you make your list immutable in the same time which is nice if you need to expose it publicly
You can also make your list immutable with a static block but you need to fill a temporary list before initializing the final list.
Check the
Maps uniqueIndex documentation which is a really cool function of Guava that permits to index any object by any of its attribute.
In case many objects are sharing the same attribute value, you can use Multimaps.index which, for each key, will give you a list of objets having this attribute.
Initialize the static map in static{...} block before the constructor. Look up static initializer blocks.
Right now I have about 60 Message types which are passed to a getStuff(Message) method of a class which implements ContainerOfThings. There are multiple variations of an ContainerOfThings such as BoxOfStuff and BagOfTricks both of which realize the getStuff(Message) method which generates a string based on member variables. The result may also have pre-pended or post-pended data such as labels or concatenated data. See code below.
public class BoxOfStuff implements ContainerOfThings
{
private String var1;
private String var2;
private String varN;
public String getStuff(Message message)
{
if (message.equals(Message.GET_STUFF1))
return var1;
else if (message.equals(Message.GET_STUFF2))
return "Var2 is: " + var2;
else if (message.equals(Message.GET_STUFFN))
return varN + "\n";
// Etc. for each Message.GET_*
}
// getters and setters for each var*
}
public class Message
{
private String id = null;
private Message(String id)
{ this.id = id; }
public final String toString()
{ return this.id; }
public static final Message GET_STUFF1 = new Message("V1");
public static final Message GET_STUFF2 = new Message("V2");
public static final Message GET_STUFFN = new Message("VN");
}
I am trying to find a design that meets the following objectives. (1) The string returned from getStuf() needs to reflect the current state of the implementing class's member fields. (2) Also I would prefer to get away from an incredibly long series of if / else if blocks. One concern is ease of potentially changing to a persistent data-driven configurable object approach which a Map lends well towards. (3) Design should allow for simple maintenance and/or edits.
One design that could work but is a little messy is to create a Map with all key/values initialized in the constructor and also reset any key/value pair inside each setter method. In this way, the response to getStuff(Message) is updated to the new content after changes (ie: in a setVar*() method). Any other thoughts?
I think you'll need two maps. One will be a Map<Message, String> where the value will be a format string (i.e. something that will get passed into String.format()). The second map will be a Map<Message, Field> which should be fairly self explanatory once you take a look at the reflection libs. These will need to be setup at init time but after that the getStuff() method should be fairly clean and your setters won't be affected at all.
BTW, Java doesn't generally prefix interfaces with I.
I'm not 100% sure I understand your problem, but it sounds like you want to memoize the result of your getStuff() call.
One easy way to do this is to use the makeComputingMap() method from the MapMaker class in the Google Guava library.
For example, you could do:
Map<Message, String> map = new MapMaker()
.expireAfterWrite(10, TimeUnit.MINUTES)
.makeComputingMap(
new Function<Message, String>() {
public String apply(Message message) {
// Your getStuff() implementation here
}
});
Does that make sense?
How about this:
public abstract class BaseOfBox implements IContainerOfThings {
protected final Map<Message, String> stuffs =
new HashMap<Message, String>();
public final String getStuff(Message message) {
return stuffs.get(message);
}
}
public class BoxOfStuff extends BaseOfBox {
private String var1;
private String var2;
public BoxOfStuff() {
super();
}
public setVar1(String var1) {
this.var1 = var1;
stuffs.put(Message.GET_STUFF1, var1);
}
public setVar2(String var2) {
this.var2 = var2;
stuffs.put(Message.GET_STUFF2, "Var2 is: " + var2);
}
...
}
Frankly, I think this is a pretty ugly solution, but so are the requirements, IMO. I suspect a more elegant solution can only be found if we review the (real) requirements