I've defined the following enum in Groovy, though for the purpose of this question it could be Java code:
enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static Set<String> allSearchTokens = new HashSet<String>();
FestivalType() {
String searchToken = this.name().tokenize('_').first().toLowerCase();
if (searchToken in allSearchTokens) {
throw new RuntimeException("Duplicate search token");
} else {
this.searchToken = searchToken;
allSearchTokens.add(searchToken);
}
}
final String searchToken;
}
What I'm trying to do in the constructor is establish whether the first token in the name of each enum constant is unique, where _ is used as the token separator.
However, this code doesn't work because allSearchTokens is not initialized until after all the constants are instantiated, so I get a NullPointerException here
allSearchTokens.add(searchToken)
You can work around this as follows:
public enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static class SetHolder {
static Set<String> allSearchTokens = new HashSet<String>();
}
final String searchToken;
FestivalType() {
String searchToken = name().split("_")[0].toLowerCase();
if (SetHolder.allSearchTokens.contains(searchToken))
throw new RuntimeException("Duplicate search token");
this.searchToken = searchToken;
SetHolder.allSearchTokens.add(searchToken);
}
}
This compiles because of the java specification that all static initializers must be completed before the class is used. By making the Set a static field of a sttic inner class, you guarantee that it will be initialized before the first enum is constructed.
Also, I took the liberty of changing/fixing a few things in your code:
Use a Set rather than a List: Values are unique
Use split(): There is not such method tokenize() for String in java
Remove else: After a return or throws, else is always redundant because execution of the block is halted by these keywords (there is no "else" to handle)
As an aside, this technique is also great for lazy initialization of singletons:
public class MyLazySingleton() {
private static class InstanceHolder {
static MyLazySingleton INSTANCE = new MyLazySingleton();
}
public static MyLazySingleton getInstance() {
return InstanceHolder.INSTANCE;
}
}
The INSTANCE field is only constructed when the getInstance() method is first called!
Look mom! Lazy initialization without locks, without null checks, without synchronization of any kind and 100% bulletproof! (Object deserialization hacks notwithstanding)
It's magic :)
I have done something similar and the following has worked for me:
enum MyEnum{
Enum1, Enum2;
private static List<String> myList;
private static void addToList(MyEnum enum){
if(myList == null){
myList = new ArrayList<String>();
}
myList.add(enum.name());
}
private MyEnum(){
addToList(this);
}
}
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));
}
}
See this incomplete code fragment:
public class Singleton implements Serializable {
private static class SingletonHolder {
private static final Singleton SINGLETON_INSTANCE;
static {
Singleton tmp = singletonTMP;
if (tmp != null) {
SINGLETON_INSTANCE = tmp;
} else {
// etc.
}
}
}
private static volatile Singleton singletonTMP;
// etc.
}
I get a strange warning in NetBeans at line Singleton tmp = singletonTMP;: "Usage of static non-final variable used during initialization".
So, yes. This is true, of course, but why would this be a problem?
The problem is that the variable :
private static final Singleton SINGLETON_INSTANCE;
might not have been initialized in that static block of yours, you can inititalize it to null(say) in the else clause inside that static block, i.e:
static
{
Singleton tmp = singletonTMP;
if (tmp != null)
{
SINGLETON_INSTANCE = tmp;
} else
{
**SINGLETON_INSTANCE = null;**
}
}
After reading a bit about security I think my previous comment was correct.
I think it is a security issue, an attacker could replace your static field with a new object. This happens when the attribute is also defined as public. I assume netbeans considers it a risk and displays the warning even if you declared it private.
More details here:
https://www.securecoding.cert.org/confluence/display/java/OBJ10-J.+Do+not+use+public+static+nonfinal+variables
I have this Thread inside my Project which runs continously accepting new symbols
public class StreamThread extends Thread {
private Set<String> allSymbolSet = new HashSet<String>(Arrays.asList("USBC", "TCSD", "PCLJ"));
private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
public void addSymbols(String str) {
if (str != null) {
priorityBlocking.add(str);
}
}
public void run() {
while (true) {
try {
while (priorityBlocking.peek() != null) {
String symbol = priorityBlocking.poll();
allSymbolSet.add(symbol);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
my question is , i want to access the variable allSymbolSet from another class
what will be the best approach to get access to this variable named allSymbolSet from anoter class , for this i have two choices
modify the access specifier of allSymbolSet from private to default .
Write a get Method which is supoused to return the Set
Please suggest me , what will be the good approach in this case ??
Best approach would be the getter method AND synchronize the access to the object allSymbolSet, something like this:
public Set<String> getAllSymbolSet() {
synchronized(allSymbolSet) {
return allSymbolSet;
}
}
and also synchronize the access to allSymbolSet inside your thread.
A few comments:
If you make the set non-private, some code could modify it (by mistake or on purpose) which could result in inconsistent behaviour in your StreamThread class. Don't do that.
Providing a simple getter does not solve the issue above. Prefer returning a copy of your set.
Make your variables final whenever you can when in a multi-threading environment - it solves many thread safety issues.
Prefer implementing Runnable than extending Thread
You will need to synchronize ALL accesses to your set (read and write), for example by using a synchronizedSet or even better by wrapping a ConcurrentHashMap which generally provides better performance.
instead of peek+poll you can simply take from your queue
So your final class could look like:
public class StreamTask implements Runnable {
private final Set<String> allSymbolSet;
private final PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
public StreamTask() {
String[] symbols = {"USBC", "TCSD", "PCLJ"};
//use a thread safe set, for example based on ConcurrentHashMap
allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean> ());
Collections.addAll(allSymbolSet, symbols);
}
public void addSymbols(String str) {
if (str != null) {
priorityBlocking.add(str);
}
}
public Set<String> getSymbols() {
return new HashSet<> (allSymbolSet); //return a copy
}
public void run() {
while (true) {
try {
allSymbolSet.add(priorityBlocking.take());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Finally, I might be missing something, but that class looks equivalent to the much simpler:
public class StreamTask {
private final Set<String> allSymbolSet;
public StreamTask() {
String[] symbols = {"USBC", "TCSD", "PCLJ"};
//use a thread safe set, for example based on ConcurrentHashMap
allSymbolSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean> ());
Collections.addAll(allSymbolSet, symbols);
}
public void addSymbols(String str) {
if (str != null) {
allSymbolSet.add(str);
}
}
public Set<String> getSymbols() {
return new HashSet<> (allSymbolSet); //return a copy
}
}
Better way is method 2. Writing a getter method. If you want to allow set the values then use a setter later. Then your data will be encapsulated .
Write a get Method which is supposed to return the Set. by using this your private remains private and you also access it from outside using Object of the same class.
I have what seems to me a basic issue that confuses me.
Right now I have the following bad design (it seems to me it is bad design). I have a util class which looks something like this:
public class Countries
{
public boolean isCountryPresent ( String c )
{
//public static final http://en.wikipedia.org/wiki/ISO_3166-1
Set<String> myStrings = new HashSet<String>();
myStrings.add("us"); // Afghanistan
myStrings.add("af"); // Afghanistan
myStrings.add("dz"); // Algeria
myStrings.add("ao"); // Angola
myStrings.add("az"); // Azerbiajan
...
if ( myStrings.contains(c))
return true;
else
return false;
}
And then I check for the existance of the item like this:
Countries co = new Countries ( );
boolean isPresent = co.isCountryPresent( countryISOCode );
But I am thinking that instantiating the object each time wastes resources, no? Is there a more efficient way for doing this given that the country data does not need to be compiled more than once and does not change?
I usually do something like this:
public class Countries
{
private static Set<String> myStrings = null
public static boolean isCountryPresent ( String c )
{
if (myStrings == null) {
myStrings = initializeSet();
}
if ( myStrings.contains(c))
return true;
else
return false;
}
private static Set<String> initializeSet()
{
//public static final http://en.wikipedia.org/wiki/ISO_3166-1
Set<String> countrySet = new HashSet<String>();
myStrings.add("us"); // Afghanistan
myStrings.add("af"); // Afghanistan
myStrings.add("dz"); // Algeria
myStrings.add("ao"); // Angola
myStrings.add("az"); // Azerbiajan
...
return countrySet;
}
}
This way it initializes the set the first time the method is called, but for all subsequent calls, the old initialization is cached.
You could also declare it in the constructor, but I tend to lean toward the lazy loading approach, so the application isn't waiting for all this stuff to load right when it launches, but is loaded sort of on demand when you actually need it.
Also as mentioned in the comments this should probably all be static, unless you are always reusing the same Countries object throughout the code, otherwise it will be redone for every new Countries object you instantiate.
The simplest transition is to move the set to a class variable, and instantiate it in the constructor:
public class Countries
{
private Set<String myStrings = new HashSet<String();
public Countries() {
//public static final http://en.wikipedia.org/wiki/ISO_3166-1
Set<String> myStrings = new HashSet<String>();
myStrings.add("us"); // Afghanistan
myStrings.add("af"); // Afghanistan
myStrings.add("dz"); // Algeria
myStrings.add("ao"); // Angola
myStrings.add("az"); // Azerbiajan
...
}
public boolean isCountryPresent ( String c )
{
return myStrings.contains(c);
}
}
That way it's just called once, when you first construct the Countries object.
Also note that you don't need to have an if statement: contains returns a boolean, so you can just return that straight.
Edit: just noticed your second code segment. Instead of creating a new Countries object each time, just make it once, and persist it.
Alternatively, you could make this static (private static Set..., static { instead of public Countries() { and public static boolean...)
Then you just call it like Countries.isCountryPresent(SomeCountry); without instantiating a new object.
You can use an enum or declare a single static instance of Countries which is initialized on startup, eg:
class Countries {
public final static Countries instance = new Countries();
private Set<String> myStrings;
private Countries() {
myStrings = new HashSet<String>();
myStrings.add("us");
..
}
}
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.