Java enums insert values - java

I have an enum created as below
public enum CustomData {
SHOW_VAL("","");
private final String valCode;
private final String valD;
CustomData(String valCode, String valD){
this.valCode = valCode;
this.valD = valD;
}
public String getvalCode() {
return this.valCode;
}
public String getvalD() {
return this.valD;
}
}
I am throwing exception using the enum Custom Data. Right now, I can create multiple static types like SHOW_VAL("TEXT","DESC"), but I want to put the text in it at runtime when any error occurs.
In the above, code how can I insert the values via the constructor defined above in other class?

Enums are a compile time constant, you can't create new ones in the runtime using regular language features. As per Enum Type docs:
You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile timeā€”for example, the choices on a menu, command line flags, and so on.
Use a regular class for runtime values.

Related

How can I wrap existing static constants into an enumeration?

I'm porting my Minecraft block protections plugin from Bukkit to Sponge so I can add mods with SpongeForge. Bukkit uses a Material enum to identify all the valid block types in the game. All my protections are specified in the config.yml file like this:
CHEST:
Price: 0.75
InteractMember: R
...
With an enum it was very easy to take the keyname in the config file, CHEST, and get the actual enum value with Bukkit.getMaterial(String name). Unfortunately, Sponge refuses to use enums anywhere in their code, so their list of block types is a class containing nothing but static final int constants, which I cannot iterate through or retrieve by name. I tried reflection..
HashMap<String,Integer> blockTypes = new HashMap<String,Integer>();
for(Field field, BlockTypes.class.getFields())
blockMap.put(field.getName(), field.getInt(null));
But I can only get the int values for the constants. I need the constants themselves to use in the code, and I can't find any way to do that without making my own enum wrapper for the static constants:
public enum Blocks {
ACACIA_FENCE(BlockTypes.ACACIA_FENCE),
ACACIA_STEPS(BlockTypes.ACACIA_STEPS),
...
YELLOW_FLOWER(BlockTypes.YELLOW_FLOWER);
private final BlockTypes type;
Blocks(BlockTypes type) {
this.type = type;
}
public BlockTypes getType() { return type; }
public static BlockTypes getByName(String name) {
// retrieve enum by name
}
}
Am I really stuck doing this or is there another way I'm missing?
Sponge doesn't use enums for a reason: since you can add other mods, constants would have to be dynamically added (which isn't possible), and assuming blocks in the vanilla game are the only blocks isn't valid. Support for other mods is one of the main goals of the sponge API.
If your goal is to get a list of all valid BlockTypes in the game, you should use the GameRegistry:
// Getting a list of all types
Collection<BlockType> types = Sponge.getRegistry().getAllOf(BlockType.class)
for (BlockType type : types) {
System.out.println(type.getName());
}
// Getting a single type by name
Optional<BlockType> type = Sponge.getRegistry().getType(BlockType.class, "minecraft:chest");
if (!type.isPresent()) {
// show some error, as the given type doesn't exist
} else {
return type.get();
}
You should be able to use BlockType as a key in a map, or alternatively the String id. You shouldn't need to make an enum for it (and can't do it automatically).
Worth noting that you're using reflection wrong in your example as well, but I don't think it's too important to explain how it needs to be used right now as that's the wrong approach.

Enum-getter vs. Getter for each stat

I am currently processing a huge data input, including a lot of values, which I want to receive in getters for later use.
After writing a few methodes, I wondered if it might be a better idea to just use one get Method, with an enum-class containing all possible values, e.g.
public double getStat(StatType st) {
if(st != null)
return st.getValue();
}
instead of
public double getAvgReflection() {
return ...
}
public double getMaxLifesteal() {
return ...
}
Is there any convention for using either of the two possibilities?
Any dis/advantages?
Thanks in advance!
Using an Enum maxes it easier to add new stats, just add a constant in the Enum.
But all stats need to behave the same way, i.e. be doubles in your example. What happens if you want to add an int stat?
The "convention" you are asking about really boils down to the use and definition of your values. When you make the values Enums, then you must handle them as that type. Meaning, the fields in your class would have to be defined as such:
private MyEnum avgReflection;
private MyEnum maxLifesteal;
...
public MyEnum getAvgReflection {
return this.avgReflection;
}
And so forth.
Now, you could have your Enums return double values, but these values are static. I don't think you are concerned about static values, but, instead, perhaps a static set of values.
You then have two possible options: declare all possible parameters as fields, or create one aggregate field to hold all values and then use an Enum as an index:
public enum MyEnum {
averageReflection(0),
maximumLifeSteal(1);
private int value;
private MyEnum(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
...
private double[] attributes = new double[100]; // arbitrary initialization
public double getAttribute(MyEnum attribute) {
return this.attributes[attribute.getValue()];
}
The two restrictions on using an array (assuming you want primitive values and you are concerned about performance) is that all the values must be the same type, and the number of attributes will be set at compile time.
Additionally, you may just want to use a Map<String,double> or Map<MyEnum,double>, or even Map<MyEnum, Object>. A Map type will give you the ability to maintain a dynamically-sized set and possibly holding multiple types as well (with the costly overhead of converting your values).
You should base your decision on the amount of attributes you need to keep, the kind of overhead you are willing to tolerate, and your style.

create variables dynamically, Data Types of java Variables

As we know variables are of different data types, but which data type are their names of?
As it seems they are String, but if they are String then this should be allowed:
int i=6;
String [] arr+i;
...as we can add an int to a String.
So if these are not String then what are they?
And if we want to create variable names dynamically how can we create it?
By dynamically I mean whenever the user clicks on a specific JComponent, a new variable is created, like:
int i=0;
//on first click
String str+i; ///str0
i++;
///on 2nd click
String str+i; ////str1
///i++;
How can I do it?
You can not create dynamic variables in Java because Java isn't a scripting language. YOu need to create variables in source code. But Java provides other ways to do this.
You can use arrays or Map<String, String> etc for this purpose.
Map<String, String> map= new HashMap<>();
int i=0;
while(true) {
// you can use whatever condition you need
details.put("key" + i, "val: "+i);
i++
// some condition to break the loop
}
Java identifiers are not of any type and definitely not String. You can't do this in java, instead, you use a data structure to use these values like ArrayList<String>and store the nth String in the nth index of the data structure like so:
ArrayList<String> strings= new ArrayList<String>(); // Create a new empty List
strings.add(index, string); //add string at index position of the List; can be replaced with strings.add(string) if the strings are being sequentially added
CONSIDER THIS:
public class Test {
public Test() {
}
public static void main(String[] args) {
// GenericType<Integer> intObj;//creates a generic type for integers
//String type
GenericType<String> strObj=new GenericType<String>("My data");
System.out.println("Value is " +strObj.getValue());
}
}
class GenericType<GT>{
GT obT;
GenericType(GT o){
obT=o;
}
GT getValue(){
return obT;
}
void showType(){
System.out.println("Type of GT is " +obT.getClass().getName());
}
}
GT is the name of a type parameter. This name is used as a placeholder for the actual type that will be passed to GenericType when an object is created. Thus, GT is used within GenericType whenever the type parameter is needed. Notice that GT is contained within
< >. This syntax can be generalized. Whenever a type parameter is being declared, it is specified within angle brackets. Because Gen uses a type parameter, Gen is a generic class, which is also called a parameterized type.
as mentioned above JAVA provide you with advanced generic classes such as ArrayList, Vectors, Hashmaps to cater for such scenarios .
previous thread similar: How to create new variable in java dynamically
Variable names do not have data types. They are merely references. They are not a String, they are not an int, they are just names. You can't dynamically declare a variable with a name derived from the name of another variable, Java does not work this way.
Java does not work this way. Other languages do but Java isn't one of them. You can't dynamically manipulate the names of variables because they are fixed at compile time. However, in some interpreted scripting languages such a thing is possible.
To be more accurate if they are fixed to be anything at all they are fixed at compile time. If java is not compiled in debug mode the names of the variables cease to be at all. They just become addresses of memory locations.
See this for details: Can I get information about the local variables using Java reflection?
Firstly variables can be categorized into two. primitives (standard ) types such as int, float,double, char,boolean, byte... and non-primitives(user defined)types such as String, Integer, Float, Double. String type fall under non primitive , its a class provided by java.lang Api such that when you create a string variable you are indeed creating an object EX String str; str is an object it can as well be declared as String str=new String();
hence the string class consist of helper methods that may help to achieve your objective, you can as well use concatenation/joining of strings as follows:
class Demo{
String str;
static int i;
JButton but=new JButton("click me!");
.....
public static void actionPeaformed(ActionEvent e){
Object source=e.getSource();
str="msg";
if(source==but){
String newStr;
newStr=str+i;
System.out.println(newStr);
}
}
}
where str may contain some message/text eg from label/elsewhere for every click

Enum relating to a string array that was read from file

I've received a working code (in Java, 1.7) that does the following:
load an array of strings (a list of blood test names) from a file into a string array member (using Properties and FileInputStream). The file can change the strings but the meaning stays the same (for example: a test can be called "abc" and in another run it is called "zzz"). I've got an enum class that enumerates the test names. The enum strings aren't the same as the inputted strings (since the latter can change).
file bloodtest.names contains:
bloodTestNames=abc;def;123;
code:
public enum BloodTestNames {
AAA,BBB,CCC;
}
Properties props = new Properties();
FileInputStream fis = new FileInputStream("bloodtest.names");
props.load(fis);
String testName[]=props.getProperty("bloodTestNames").toString().split(";");
Now to the questions:
Question 1:
I need to return the string that was set in the file when I know the test name (for instance: return "def" for value BBB). What's the best of doing that?
the best way I've come up with is:
return testName[BloodTestNames.BBB.ordinal()]
Question 2: if BBB is not known in compile time - how do I accomplish the same target?
Three points:
* I'm a veteran at C but a newbie with Java. Any Do's and Don't are welcome. Assume my Java knowledge is zero.
* I don't total re-factoring is that's what's needed here.
* I've probably forgot to mention important details, please ask and I'll feel the missing gaps
I'll first assume you do need enum constants for modeling this use-case because you have some sort of specific code to be executed for each kind of blood test (otherwise, a simple set of strings would be enough and more flexible, since you don't need to know the number of tests upfront or care about their names).
Q1: Since Java enums are a little more than a sequence of values, you can make full use of their object oriented nature.
public enum BloodTest {
AAA, BBB, CCC;
private static String[] names;
public static void setNames(String[] names) {
if (BloodTest.names != null)
throw new IllegalStateException("You can only set the names once");
if (names.length != values().length)
throw new IllegalArgumentException("Wrong number of names");
BloodTest.names = names;
}
#Override
public String toString() {
return names[ordinal()];
}
}
Now all you need to do is to initialize your enum by calling BloodTest.setNames(namesFromConfiguration) and then you can get the string representation of each constant by calling the standard toString() method on it: BloodTest.BBB.toString().
Since the initial assumption was that you have some specific logic for each of the test types, I would suggest that logic (as well as the required properties) will also be encapsulated in the enum itself or the enum constants; e.g.:
public enum BloodTest {
AAA(10) {
#Override
public boolean isRequired(MedicalRecord medicalRecord) {
return medicalRecord.includes("someDisease");
}
},
BBB(15) {
#Override
public boolean isRequired(MedicalRecord medicalRecord) {
return ! medicalRecord.hasTakenBloodTestsLately();
}
},
CCC(20) { // ... also implements the abstract method and so on
private final int threshold;
private BloodTest(int threshold) {
this.threshold = threshold;
}
public boolean hasPassed(int value) {
return value <= threshold;
}
public abstract boolean isRequired(MedicalRecord medicalRecord);
// ... same as above
}
Now, once you get a reference to some BloodTest, you can check whether that specific test passed by invoking the corresponding method without switching and having the logic spread around the client code:
BloodTest bloodTest = BloodTest.valueOf(someString); // someString can be "AAA", "BBB" or "CCC"
// no matter which constant this is, you use it as an object and rely on polymorphism
if (bloodTest.hasPassed(someValue)) { // ... do something
Q2: Your question 2 kind of "questions" my initial assumption regarding your actual need for an enum. If there's a chance you'll need to dynamically handle blood tests that you don't know about yet, then you can't use an enum.
In other words, if your code does not have any switch or if/else if blocks to handle each blood test, an enum is a really bad choice for your use case.
However, if it does, than I'd recommend refactoring the code to include the logic in the enum itself as in the above example, rather than in switch/if blocks; moreover, if your switch has a default case (or your if has a final else block), this can still be modeled in the enum itself, for instance by adding a DEFAULT constant as a fallback.
Make the whole thing settings driven: Add a statuc method to load in settings of what string maps to what enum and add a factory method that uses these settings:
public enum BloodTestNames {
AAA,BBB,CCC;
private static Map<String, BloodTestNames> map = new HashMap<String, BloodTestNames>();
public static void addAlias(String alias, String name) {
map.put(alias, valueOf(name));
}
public static BloodTestNames getByAluas(String alias) {
if (map.containsKey(alias))
return map.get(alias);
// own name assumed to be mapped
return valueOf(alias);
}
}
On startup, repeatedly call BloodTestNames.addAlias() based on some settings file to load the mappings.
When you're reading the saved file, use BloodTestNames.getByAlias() to return the enum for a given string value.
You would do well to name your class in the singular, and drop "Name", ie BloodTest - name the class for what each enum is (all enums have a "name" which is the coded instance name).
A short extract from one of my enum class :
public enum TypesStructurelsE {
SOURCE("SRC"),
COLONNE("COL");
private String code;
TypesStructurelsE(final String code1) {
code = code1;
}
/** #return String */
public String getCode() {
return code;
}
public void setCode(final String newCode) {
code = newCode;
}
}
. . In other class
if(TypesStructurelsE.SOURCE.getCode().equal(testName[i])){ // can be "COL" or "SRC"
//
;
}
... changing value :
TypesStructurelsE.SOURCE.setCode("SOURCE_NEW");
So, if your properties file change, you have just to compile with the new symbole (SRC --> SOURCE) no more

How can I simulate Enums that can be expanded at Runtime in Java?

I am writing a program to simulate cities from a game called Civilization 4. In order to do this I have several Enums to represent types of terrain, resources, improvements etc for each plot owned by said city.
The problem is I want to program to be compatible with Fan made mods which may add things to the Game that need to be accepted into my independant utility. So I thought of creating a Enum style class to hold the new types defined by the loaded mods (as Enums cannot be changed at runtime) which is created during runtime when the user enters in a mod to be loaded (which is a txt file that is parsed to read the new additions)
So is there a way to simulate Enums that are created and added to at runtime? I take it static member variables cannot be used as they are done before runtime...
You can make a enum implement an interface.
This way you can have your defined values in the enum, but new values can be any class which implements the interface.
An alternative is that you generate or load the enum at runtime using a byte code generator or the Compiler API. I wrote a library to make it easier to take a String and compile&load it.
http://vanillajava.blogspot.co.uk/2010_11_01_archive.html
Well, enums in Java are simply classes where the language guarantees that the set of known objects is known and limited at compile-time. If you want to add new enum literals at runtime, you end up with regular classes.
The beauty of enums is that you can write human readable names in code that are compiled as numbers behind the scenes, because computers like numbers better. Take for example this enum:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Behind the scenes WINTER might be 0 (zero), SPRING is 1 etc.
To replicate this behaviour in runtime code you could create a list of strings, like this:
List<String> seasons;
seasons = new ArrayList<String>();
seasons.add("Winter");
seasons.add("Spring");
...
That way you can reference the items as numbers, such as seasons[1] would equal "Spring".
This answer is just one of many ways to approach this question.
By default, enum types have only a set number of values. The values in an enum type are actually declared as static final, and there's no way to add more on runtime.
That being said, there are other patterns you can use to implement what you want. Let's take a look at using an interface and a registration system. We'll start with the Terrain interface:
public interface Terrain {
int getId();
String getName();
int getSightBonus();
}
Now an enum, DefaultTerrain:
public enum DefaultTerrain implements Terrain {
PLAINS(0, "Plains", 1),
HILLS(1, "Hills", -1),
MOUNTAINS(2, "Mountains", -2);
private int id;
private String name;
private int sightBonus;
private DefaultTerrain(int id, String name, int sightBonus) {
this.id = id;
this.name = name;
this.sightBonus = sightBonus;
}
public int getId() {return id;}
public String getName() {return name;}
public int getSightBonus() {return sightBonus;}
}
And a registration class, which can be either a static utility class or a singleton.
public class TerrainManager {
private static Map<Integer, Terrain> terrainsById = new HashMap<>();
static {
for (DefaultTerrain terrain : DefaultTerrain.values())
register(terrain);
}
public static void register(Terrain terrain) {
Integer id = terrain.getId();
if (terrainsById.contains(terrain.getId()))
throw new IllegalArgumentException("Terrain with id already exists: " + id);
terrainsById.put(id, terrain);
}
public static Terrain getTerrainById(int id) {
return terrainsById.get(id);
}
public static Set<Terrain> getAllTerrains() {
return new HashSet<Terrain>(terrainsById.values());
}
}
This last class is where the magic happens. Presumably the modders will have some kind of identifier in the game's world definition to say "use this tile," right? In this case, I've called it an integer, id, but really it could be any type, just modify the Map accordingly. In the map-loading code, just use the ID in the world definition to look up the Terrain. When a modder adds a new Terrain, they just need to implement Terrain and register it with TerrainManager.
The static initializer makes sure that your DefaultTerrain objects are added before anything else is added. If you use a singleton, this could be put into the class constructor instead.
Use this pattern for your different enum types that you want users to add to. You could also use it for pretty much any other type as well besides enum.
You will need CGLIB, http://cglib.sourceforge.net/

Categories