How can I wrap existing static constants into an enumeration? - java

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.

Related

Java enums insert values

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.

How to create Record class in Java?

I have the following class Type:
class Type{
String type;
public Type(String type){
this.type = type;
}
}
I have few types initialised here:
Type cor = new Type("cor");
Type name = new Type("name")
and Now I want to have a class called Record,
class Record{
String name;
Type[] types;
public Record(String name, Type[] types){
this.name = name;
this.types = types;
}
}
Well I got stuck here. What I want to do is when initialise an instance of the class Record, like this:
Record rec = new Record("Position", ...);
it should be something like this, I will give an example of the position record here:
Record Position = [cor x, cor y, name z];
So is using Type[] a good choice here? I find it hard to both record the type and the variable name such as x, y;
Or should I use a HashMap?
It's hard to answer the question without more information about what you are trying to model. Your 'position' example is fairly confusing as it implies that a single record has several 'variables' of different types. However I'm assuming that a record can have several types. It's unclear whether the types can change and whether there are a fixed set of types.
Ideally the set of types are static and you could use an enumeration of types:
enum RecordType {
COR, NAME, ...;
}
class Record {
public Record(String name, EnumSet<RecordType> types) {
...
}
}
Then creating a new record would look like:
Record record = new Record("My record", EnumSet.of(RecordType.NAME));
If the set of types aren't static then you will need to define a class. In that case I would recommend you use Set<RecordType> rather than RecordType[] as the constructor argument. This makes it clear that it is a set of types (i.e. no duplicates) and avoids all the error checking you'll need to do with an array.
If a single record can have several values for different types then you will need to have a Map<RecordType,String> member variable. In that case I would recommend against trying to define the values in the constructor. Instead have a addTypeValue method for adding values to the map.

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/

(no) Properties in Java?

So, I have willfully kept myself a Java n00b until recently, and my first real exposure brought about a minor shock: Java does not have C# style properties!
Ok, I can live with that. However, I can also swear that I have seen property getter/setter code in Java in one codebase, but I cannot remember where. How was that achieved? Is there a language extension for that? Is it related to NetBeans or something?
There is a "standard" pattern for getters and setters in Java, called Bean properties. Basically any method starting with get, taking no arguments and returning a value, is a property getter for a property named as the rest of the method name (with a lowercased start letter). Likewise set creates a setter of a void method with a single argument.
For example:
// Getter for "awesomeString"
public String getAwesomeString() {
return awesomeString;
}
// Setter for "awesomeString"
public void setAwesomeString( String awesomeString ) {
this.awesomeString = awesomeString;
}
Most Java IDEs will generate these methods for you if you ask them (in Eclipse it's as simple as moving the cursor to a field and hitting Ctrl-1, then selecting the option from the list).
For what it's worth, for readability you can actually use is and has in place of get for boolean-type properties too, as in:
public boolean isAwesome();
public boolean hasAwesomeStuff();
I am surprised that no one mentioned project lombok
Yes, currently there are no properties in java. There are some other missing features as well.
But luckily we have project lombok that is trying to improve the situation. It is also getting more and more popular every day.
So, if you're using lombok:
#Getter #Setter int awesomeInteger = 5;
This code is going to generate getAwesomeInteger and setAwesomeInteger as well. So it is quite similar to C# auto-implemented properties.
You can get more info about lombok getters and setters here.
You should definitely check out other features as well.
My favorites are:
val
NoArgsConstructor, RequiredArgsConstructor, AllArgsConstructor
Logs!
Lombok is well-integrated with IDEs, so it is going to show generated methods like if they existed (suggestions, class contents, go to declaration and refactoring).
The only problem with lombok is that other programmers might not know about it. You can always delombok the code but that is rather a workaround than a solution.
"Java Property Support" was proposed for Java 7, but did not make it into the language.
See http://tech.puredanger.com/java7#property for more links and info, if interested.
The bean convention is to write code like this:
private int foo;
public int getFoo() {
return foo;
}
public void setFoo(int newFoo) {
foo = newFoo;
}
In some of the other languages on the JVM, e.g., Groovy, you get overridable properties similar to C#, e.g.,
int foo
which is accessed with a simple .foo and leverages default getFoo and setFoo implementations that you can override as necessary.
public class Animal {
#Getter #Setter private String name;
#Getter #Setter private String gender;
#Getter #Setter private String species;
}
This is something like C# properties. It's http://projectlombok.org/
You may not need for "get" and "set" prefixes, to make it look more like properties, you may do it like this:
public class Person {
private String firstName = "";
private Integer age = 0;
public String firstName() { return firstName; } // getter
public void firstName(String val) { firstName = val; } // setter
public Integer age() { return age; } // getter
public void age(Integer val) { age = val; } //setter
public static void main(String[] args) {
Person p = new Person();
//set
p.firstName("Lemuel");
p.age(40);
//get
System.out.println(String.format("I'm %s, %d yearsold",
p.firstName(),
p.age());
}
}
Most IDEs for Java will automatically generate getter and setter code for you if you want them to. There are a number of different conventions, and an IDE like Eclipse will allow you to choose which one you want to use, and even let you define your own.
Eclipse even includes automated refactoring that will allow you to wrap a property up in a getter and setter and it will modify all the code that accesses the property directly, to make it use the getter and/or setter.
Of course, Eclipse can only modify code that it knows about - any external dependencies you have could be broken by such a refactoring.
My Java experience is not that high either, so anyone feel free to correct me. But AFAIK, the general convention is to write two methods like so:
public string getMyString() {
// return it here
}
public void setMyString(string myString) {
// set it here
}
From Jeffrey Richter's book CLR via C#: (I think these might be the reasons why properties are still not added in JAVA)
A property method may throw an exception; field access never throws an exception.
A property cannot be passed as an out or ref parameter to a method; a field can.
A property method can take a long time to execute; field access always completes
immediately. A common reason to use properties is to perform thread synchronization,
which can stop the thread forever, and therefore, a property should not be
used if thread synchronization is required. In that situation, a method is preferred.
Also, if your class can be accessed remotely (for example, your class is derived from
System.MarshalByRefObject), calling the property method will be very slow, and
therefore, a method is preferred to a property. In my opinion, classes derived from
MarshalByRefObject should never use properties.
If called multiple times in a row, a property method may return a different value each
time; a field returns the same value each time. The System.DateTime class has a readonly
Now property that returns the current date and time. Each time you query this
property, it will return a different value. This is a mistake, and Microsoft wishes that
they could fix the class by making Now a method instead of a property. Environment’s
TickCount property is another example of this mistake.
A property method may cause observable side effects; field access never does. In other
words, a user of a type should be able to set various properties defined by a type in
any order he or she chooses without noticing any different behavior in the type.
A property method may require additional memory or return a reference to something
that is not actually part of the object’s state, so modifying the returned object has no
effect on the original object; querying a field always returns a reference to an object
that is guaranteed to be part of the original object’s state. Working with a property
that returns a copy can be very confusing to developers, and this characteristic is frequently
not documented.
If you're using eclipse then it has the capabilities to auto generate the getter and setter method for the internal attributes, it can be a usefull and timesaving tool.
I'm just releasing Java 5/6 annotations and an annotation processor to help this.
Check out http://code.google.com/p/javadude/wiki/Annotations
The documentation is a bit light right now, but the quickref should get the idea across.
Basically it generates a superclass with the getters/setters (and many other code generation options).
A sample class might look like
#Bean(properties = {
#Property(name="name", bound=true),
#Property(name="age,type=int.class)
})
public class Person extends PersonGen {
}
There are many more samples available, and there are no runtime dependencies in the generated code.
Send me an email if you try it out and find it useful!
-- Scott
There is no property keyword in java (like you could find it in C#) the nearest way to have 1 word getter/setter is to do like in C++:
public class MyClass
{
private int aMyAttribute;
public MyClass()
{
this.aMyAttribute = 0;
}
public void mMyAttribute(int pMyAttributeParameter)
{
this.aMyAttribute = pMyAttributeParameter;
}
public int mMyAttribute()
{
return this.aMyAttribute;
}
}
//usage :
int vIndex = 1;
MyClass vClass = new MyClass();
vClass.mMyAttribute(vIndex);
vIndex = 0;
vIndex = vClass.mMyAttribute();
// vIndex == 1
As previously mentioned for eclipse, integrated development environment (IDE) often can create accessor methods automatically.
You can also do it using NetBeans.
To create accessor methods for your class, open a class file, then Right-click anywhere in the source code editor and choose the menu command Refactor, Encapsulate Fields.
A dialog opens. Click Select All, then click Refactor.
Voilà,
Good luck,
For me the problem is two fold:
All these extra methods {get*/set*} cluttering up the class code.
NOT being able to treat them like properties:
public class Test {
private String _testField;
public String testProperty {
get {
return _testField;
}
set {
_testField = value;
}
}
}
public class TestUser {
private Test test;
public TestUser() {
test = new Test();
test.testProperty = "Just something to store";
System.out.printLn(test.testProperty);
}
}
This is the sort of easy assignment I would like to get back to using. NOT having to use 'method' calling syntax. Can anyone provide some answers as to what happened to Java?
I think that the issue is also about the unnecessary clutter in the code, and not the 'difficulty' of creating the setters/getters. I consider them as ugly-code. I like what C# has. I don't understand the resistance to adding that capability to Java.
My current solution is to use 'public' members when protection is not required:
public class IntReturn {
public int val;
}
public class StringReturn {
public String val;
}
These would be used to return value from say a Lambda:
StringReturn sRtn = new StringReturn()
if(add(2, 3, sRtn)){
System.out.println("Value greater than zero");
}
public boolean add(final int a, final int b, final StringReturn sRtn){
int rtn = a + b;
sRtn.val = "" + rtn;
return rtn > 0; // Just something to use the return for.
}
I also really don't like using a method call to set or get an internal value from a class.
If your information is being transferred as 'immutable', then the new Java record could be a solution. However, it still uses the setter/getter methodology, just without the set/get prefixes.

Categories