Enums as replacement of Constants in Java - java

I heard now a day that We should use Enums instead of Constants .
Is it possible in all cases ? Whether enums are replacement of Constants ?
In Below Example I have Constants defined in Constants file and ConstantsTest uses them
public final class Constants {
private Constants(){
}
public static final String ACCOUNT="Account";
public static final String EVENT_ITEM ="EventItem";
public static final int MULTIPLIER_ONE = 1;
public static final int MULTIPLIER_NEGATIVE_ONE = -1;
public static final String BALANCE_AFTER_MODIFICATION = "BalanceAfterModification";
public static final String COMMA = ",";
public static final String DOTPSV =".psv";
public static final String NEW_LINE = "\n";
}
// Test Class
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ConstantsTest {
private static File rootDir = new File(".");
public static void main(String[] args) throws IOException {
Map<String,Integer> accountBalance = new HashMap<String, Integer>();
accountBalance.put("123",55000);
accountBalance.put("223",15000);
writeToFile(Constants.ACCOUNT, accountBalance, true, 2000);
// do operation
}
/**
*
* #param fileType
* #param inputData
* #param add if true add balance else substract the balance
* #return
* #throws IOException
*/
private static File writeToFile(String fileType , Map<String,Integer>accountBalance ,boolean add, int amount) throws IOException{
File file = null;
FileWriter fw = null;
try{
if(Constants.ACCOUNT.equals(fileType)){
file = new File(rootDir,Constants.ACCOUNT+Constants.DOTPSV);//creating a fileName using constants
fw = new FileWriter(file);
fw.write(Constants.ACCOUNT+Constants.COMMA+Constants.BALANCE_AFTER_MODIFICATION);//Writing Header in file using constant values
updateBalance(accountBalance, add, amount);
for(String key:accountBalance.keySet()){
fw.write(Constants.NEW_LINE);
fw.write(key+Constants.COMMA+accountBalance.get(key));
}
}
else if(Constants.EVENT_ITEM.equals(fileType))
{
// write to EventItem.psv
}
} finally{
if (null!=fw){
fw.close();
}
}
System.out.println("File created successfully");
return file;
}
private static void updateBalance(Map<String, Integer> accountBalance,
boolean add, int amount) {
for(String key:accountBalance.keySet()){
int currentBal = accountBalance.get(key);
if(add){
accountBalance.put(key,currentBal+amount*Constants.MULTIPLIER_ONE); // do lot of calculations
}else{
accountBalance.put(key,currentBal+amount*Constants.MULTIPLIER_NEGATIVE_ONE);// do a lot of calculations
}
}
}
}
Please suggest in my sample example enums would be better or my current approach of using constants is good enough ?

In your particular case the using enums is classic solution.
First, let's re-write your Constants as an enum:
public enum Constants {
ACCOUNT,
EVENT_ITEM,
;
}
public enum Operation {
MULTIPLIER_ONE {
public int action(int value) {
return value;
}
},
MULTIPLIER_NEGATIVE_ONE {
public int action(int value) {
return value * (-1);
}
},
;
private Operation(int coef) {
this.coef = coef;
}
public abstract int action(int value);
}
Now instead of writing:
if(Constants.ACCOUNT.equals(fileType)){
} else if(....)
you can either use switch/case or even better define: define method (let's call it action() into the enum and call it from your code. See example in Operation enum above. In this case you code becomes trivial: no more if/else or switch statements. Everything is simple. Validation is done at compile time: you defined abstract method in enum you cannot add yet another element to enum without implementing this method for it. This does not happen when using if/else structures maintenance of which is a programmer's responsibility.
I know only one limitation of enums: using string contstants in annotations. There are a lot of annotations with string attributes. For example XmlElement(name="foo"). Even if you define enum
enum FooBar {
foo, bar
}
you cannot use it in annotations:
#XmlElement(name=FooBar.foo) // is wrong because String type is required
#XmlElement(name=FooBar.foo.name()) // is wrong because annotations do not support method invocation
In all other cases I prefer enum.

You should use enums this code
enum Constants {
ACCOUNT,
EVENT_ITEM ,
COMMA ,
DOTPSV ,
BALANCE_AFTER_MODIFICATION ;
#Override
public String toString() {
switch(this) {
case ACCOUNT: return "Account";
case EVENT_ITEM : return "EventItem";
case COMMA : return ",";
case DOTPSV : return ".psv";
case BALANCE_AFTER_MODIFICATION : return "BalanceAfterModification";
default: throw new IllegalArgumentException();
}
}
}

Only we can use Enums for the constant values which are in the single group.
Let us suppose: Weeks, Months, Colours, Gender, Process states
It is not the good idea to use single enum for storing all constants. Instead we can use one enum for each group of constants.
Let us suppose you have maintaining some colour codes then better to have Colour enum instead of saving as constants.

An Enum doesn't define a contract for the class using it, an interface does. A class which uses an Enum isn't of the type an Enum. A class which implements an Interface is effectively of the same type as the interface (the Interface is the parent.. and the reference could be changed). Considering these design issues. Tell me, is your approach correct?

You got enum wrong, it's not like you should create an enum instead of constant: an enum is a group of constants that are related, for example:
enum Days {
SUNDAY, MONDAY, TUESDAY, ...
}
From the docs:
An enum type is a special data type that enables for a variable to be
a set of predefined constants.

Constants will be better for the example provided. Interface variables are public static final by default.
public static final String ACCOUNT="Account";
See Why are interface variables static and final by default?

Related

Java enum synthetic arguments for constructors

Please have a look at Synthetic Arguments. Enum constructors have two additional synthetic arguments.
Please look at the section:
Another example: Java enum classes
As you can see, it saves quite some code, but also adds synthetic fields, methods and constructor parameters. If you had defined your own constructor, with its own set of parameters.
Can there be a situation where a enum constructor does not have any synthetic arguments.
Apologies for not providing enough detail.
Having read the article, I would say the answer is no. The article explains that a typical enum such as:
enum Colours {
RED, BLUE;
}
Becomes:
final class Colours extends java.lang.Enum {
public final static Colours RED = new Colours("RED", 0);
public final static Colours BLUE = new Colours("BLUE", 1);
private final static values = new Colours[]{ RED, BLUE };
private Colours(String name, int sequence){
super(name, sequence);
}
public static Colours[] values(){
return values;
}
public static Colours valueOf(String name){
return (Colours)java.lang.Enum.valueOf(Colours.class, name);
}
}
where the arguments to the Colours constructor are considered synthetic (i.e. they've been produced by the compiler to make sure "stuff works"). So it seems the synthetic arguments are unavoidable as they're a necessary part of translating an enum into a real class.
The only possibility is if the enum has no values - does Java still create the synthetic fields? Intuitively, the answer is yes. This is backed up by the article in the OK, but why should I care? section. Here the author shows that an empty enum still has a parameter count of two, when viewed with reflection.
Check the source code of the Concurrent class of TimeUnit. It's an enum with its own methods.
You can have work with enums like if they were class themselves.
http://fuseyism.com/classpath/doc/java/util/concurrent/TimeUnit-source.html
Here is an example of mine:
public enum ExampleEnum {
ENUM_1 ( "ENUM_1", 1, Color.GREEN ) {
#Override
public void doMethingWeird( String stringToEnum ) {
//Implementation goes here;
}
},
ENUM_2 ( "ENUM_2", 2, Color.BLACK ) {
#Override
public void doMethingWeird( String stringToEnum ) {
//Implementation goes here;
}
},
ENUM_3 ( "ENUM_3", 3, Color.WHITE ){
#Override
public void doMethingWeird( String stringToEnum ) {
//Implementation goes here;
}
}; //Don't forget the semicolon ';' after the enums, to separate them from the methods;
//You can have static constants;
private static final Object object = new Object();
private final String enumName;
private final int enumNumber;
private final Color enumColor; //why not?
//CONSTRUCTOR IT MUST BE PRIVATE
private Effect( String enumName, int enumNumber, Color enumColor ){
this.enumName = enumName;
this.enumNumber = enumNumber;
this.enumColor = enumColor;
}
//you can have abstract methods and implement them on the enums.
public abstract void public void doMethingWeird( String stringToEnum );
public String getEnumName() {
return enuName;
}
public int getEnumNumber() {
return enumNumber;
}
public Color getEnumColor() {
return enumColor;
}
}
I hope I have helped.
I was running into the same problem, having an enum with tree constructors and parameters. Doing reflection and getting the constructors parameters, you get a String and an int extra as the first 2 parameters. I was wondering where they were coming from. After debugging I found out that the Enum class has a protected constructor, which is using the first 2 parameters.
I did a test by adding a constructor without parameters, and the 2 extra parameters are added too.
Code from Enum.java with the constructor:
/**
* Sole constructor. Programmers cannot invoke this constructor.
* It is for use by code emitted by the compiler in response to
* enum type declarations.
*
* #param name - The name of this enum constant, which is the identifier
* used to declare it.
* #param ordinal - The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*/
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
To detect this situation, you can use the isEnum() method of the reflected constructor, and skip the 2 parameters.
Constructor<?> constructor;
private boolean isEnum() {
return constructor.getDeclaringClass().isEnum();
}

Are enums less maintainable than public static final constants?

I was recently discussing enums vs public static final constants with a friend. I told him that public static final constants are more maintainable than enums, sometimes faster (android developer docs confirm this), and more convenient as well. I also said that you lose functionality when using enums as well:
You cannot extend an enum.
You cannot instantiate an enum.
He then said you shouldn't be using an enum if you need to instantiate or extend an enum. I then replied that's why we should just use constants because it is more maintainable; What if mid project we need to instantiate an enum or extend it? Then we would have to change everything.
An example demonstrating enums vs constants I made to illustrate my point:
public enum WeekDay {
/*
* We will start at 1 for demonstration
*/
SUNDAY("Sunday", 1), MONDAY("Monday", 2), TUESDAY("Tuesday", 3), WEDNESDAY(
"Wednesday", 4), THURSDAY("Thursday", 5), FRIDAY("Friday", 6), SATURDAY(
"Saturday", 7);
/*
* Notice we cannot do this...This is where enums fail.
*/
// LUNES("lunes",1), MARTES("martes",2);
private String dayName;
private int dayIndex;
private WeekDay(String dayName, int dayIndex) {
this.dayName = dayName;
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
}
What if we need Spanish week days as well? The enum falls short because you cannot extend it (you would have to do some copy and paste action).
Contrast the enum with this:
public class WeekDayClass {
private int dayIndex;
private String dayName;
public WeekDayClass(int dayIndex, String dayName) {
super();
this.dayIndex = dayIndex;
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
abstract static class Constants {
}
public static void main(String[] args) {
WeekDayClass init = new WeekDayClass(10, "I can init new days here");
}
}
And then I can extend it and make AmericanWeekDays:
public class AmericanWeekDay extends WeekDayClass {
public AmericanWeekDay(int dayIndex, String dayName) {
super(dayIndex, dayName);
}
static class AmericanConstants extends Constants {
public static final WeekDayClass SUNDAY = new WeekDayClass(1, "Sunday");
public static final WeekDayClass MONDAY = new WeekDayClass(2, "Monday");
/*
* And so on...
*/
}
}
Or Spanish Week Days:
public class SpanishWeekDays extends WeekDayClass {
public SpanishWeekDays(int dayIndex, String dayName) {
super(dayIndex, dayName);
}
static class SpanishConstants extends Constants {
public static final SpanishWeekDays LUNES = new SpanishWeekDays(2, "lunes");
/*
* And so on...
*/
}
}
Also to go even further:
public class WeekDayClass {
private int dayIndex;
private String dayName;
public WeekDayClass(int dayIndex, String dayName) {
super();
this.dayIndex = dayIndex;
this.dayName = dayName;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public String getDayName() {
return dayName;
}
public void setDayName(String dayName) {
this.dayName = dayName;
}
#Override
public String toString() {
return this.dayName + ": " + this.dayIndex;
}
static class AmericanConstants {
/*
* Insert Constants Here
*/
}
static class SpanishConstants {
/*
* Insert Constants Here
*/
}
}
I understand with an enum you could perhaps make a workaround using data structures (Lists) so you accommodate this shortcoming but why bother? With using public static constants I gain inheritance from the base class, cleaner code, possibly shorter code, and easier maintainability.
I also read that you can use enum's to better design "input parameters" but you could also do the same with the public static final constants as shown above.
Enums have the advantage of being able to be used in switch statements and have the inherited enum methods like values(). These methods can also be replicated if needed in "public static final constant" classes. Aside from the switch I don't see any enum advantages.
In conclusion, is an enum really better than public static final constants? If so, where did I go wrong? Is their something I am missing?
EDIT:
You cannot use generics in enums as well.
Enums get you a lot more than you seem to give them credit for, and while sometimes constants are required, this case is probably a win for enums.
First of all, there is no real difference between an "English weekday" and a "Spanish weekday", they represent the same values. Therefore, the best solution would be to do the conversion to string independently of what the values actually are through some kind of localization method. The values don't change with the language, their representation does.
This is entirely doable quickly and easily with enums. Just write it like this (a little pseudocode-y):
public enum Weekday {
MONDAY,
TUESDAY,
WEDNESDAY,
...;
public String toLocalizedString(Language l) {
// interact with localization files
}
}
You are conflating the ideas of external representation and internal representation. Your data should be as homogenous as possible because there is only ever going to be one Monday. It might be called different things, but it's still the same value.
Enums also get you a lot of niceness for free, though, which makes your code much clearer and more maintainable in the long run. Type checking, == comparison, and usability in switch are a few, with no boilerplate to speak of.
I think you're taking the usage of enums way to far and then come to a conclusion that they are not useful.
Enums are simply telling you that there's a limited and predefined number of options to choose from. Nothing more than that. For example, when you see a parameter that is an enum (let's say State) and it has 3 values (Pending, InProgress, Closed), you know that a state of some object can have one of those and only one of those values.
Enums provide an easy way of validating that a proper value is used as you cannot easily select a value that is not proper when coding. They are also a way of documenting as you can easily see what options are available.
Enumerations wouldn't exist if they weren't useful - the same can be said of constants. Just like a screwdriver can remove a screw while a hammer can remove a nail - different tools in your programmer "toolbox" can be used for unique and important purposes. I suggest reading more about enumerations and constants and I think you will find why they exist and when to use them.

Regarding alternative to interfaces and acessing with static imorts

I was going through a research in which I dont want to store the constants in the interface itself, so I was looking for alternatives like enums but another approach I have found is that ....t instead of using an interface, use a final class with a private constructor. (Making it impossible to instantiate or subclass the class, sending a strong message that it doesn't contain non-static functionality/data. and we can also take the advantage of static import in that case
Public final class KittenConstants
{
private KittenConstants() {}
public static final String KITTEN_SOUND = "meow";
public static final double KITTEN_CUTENESS_FACTOR = 1;
}
two independent things. 1: use static imports instead of abusing inheritance. 2: If you must have a constants repository, make it a final class instead of an interface . Please advise is this approach is correct..!!
To avoid some pitfalls of the constant interface (because you can't prevent people from implementing it), a proper class with a private constructor should be preferred (example borrowed from Wikipedia):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
And to access the constants without having to fully qualify them (i.e. without having to prefix them with the class name), use a static import (since Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
Please show how we can do same ting with enum also..!
You can achieve your "constants" via an enum:
public enum Animal {
Kitten("meow", 1),
Puppy("woof", 2);
private final String sound;
private final double cuteness;
Animal (String sound, double cuteness) {
this.sound = sound;
this.cuteness = cuteness;
}
public String getSound() {
return sound;
}
public double getCuteness() {
return cuteness;
}
}
To use:
String sound = Animal.Kitten.getSound();
double cuteness = Animal.Kitten.getCuteness();
The simple answer is that you can't do that with an enum. An enum defines a set of related constants with the same type.
What you have in the KittenConstants case is a set of constants with fundamentally different types. This doesn't fit the enum model. (If you change the problem a bit; e.g. by generalizing over different kinds of SFA, you can make it fit ... as #Bohemian does ... but if that's not what you are trying to achieve, enum is not the right solution.)
What you have in the Constants case is a bunch of named floating point constants that you want to use as values. (All the same type ... which helps!) Now you could declare them as an enum as follows:
public enum Constants {
PLANCK_CONSTANT(6.62606896e-34),
PI(3.14.59);
public final double value;
Constants(double value) {this.value = value);
}
The snag is that you need to use ".value" to access each named constant's numeric value; e.g.
import static Constants.*;
....
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT.value / (2 * PI.value);
}
.... which is kind of ugly, and I don't think there is any way around the ugliness.
Bottom line - enums are not an ideal replacement for all kinds of constant.

Best way to create the behavior of an extendable Enum in java

I want to create something that resembles an extendable Enum (understanding extending Enums isn't possible in Java 6).
Here is what im trying to do:
I have many "Model" classes and each of these classes have a set of Fields that are to be associated with it. These Fields are used to index into Maps that contain representations of the data.
I need to be able to access the Fields from an Class OR instance obj as follows:
MyModel.Fields.SOME_FIELD #=> has string value of "diff-from-field-name"
or
myModel.Fields.SOME_FIELD #=> has string value of "diff-from-field-name"
I also need to be able to get a list of ALL the fields for Model
MyModel.Fields.getKeys() #=> List<String> of all the string values ("diff-from-field name")
When defining the "Fields" class for each Model, I would like to be able to keep the definition in the same file as the Model.
public class MyModel {
public static final Fields extends BaseFields {
public static final String SOME_FIELD = "diff-from-field-name";
public static final String FOO = "bar";
}
public Fields Fields = new Fields();
// Implement MyModel logic
}
I also want to have OtherModel extends MyModel and beable to inherit the Fields from MyModel.Fields and then add its own Fields on top if it ..
public class OtherModel extends MyModel {
public static final class Fields extends MyModel.Fields {
public static final String CAT = "feline";
....
Which woulds allow
OtherModel.Fields.CAT #=> feline
OtherModel.Fields.SOME_FIELD #=> diff-from-field-name
OtherModel.Fields.FOO #=> bar
OtherModel.Fields.getKeys() #=> 3 ["feline", "diff-from-field-name", "bar"]
I am trying to make the definition of the "Fields" in the models as clean and simple as possible as a variety of developers will be building out these "Model" objects.
Thanks
I need to be able to access the Fields from an Class OR instance obj as follows:
MyModel.Fields.SOME_FIELD #=> has string value of "diff-from-field-name"
That is not possible in Java unless you use a real enum or SOME_FIELD is a real field. In either case, the "enum" is not extensible.
The best you can do in Java 6 is to model the enumeration as mapping from String names to int values. That is extensible, but the mapping from names to values incurs a runtime cost ... and the possibility that your code will use a name that is not a member of the enumeration.
The reason that enum types in Java are not extensible is that the extended enum would break the implicit invariants of the original enum and (as a result) could not be substitutable.
I've just tried out some code trying to do what you've just described and it was really cumbersome.
If you have a Fields static inner class somewhere in a model class like this:
public class Model {
public static class Fields {
public static final String CAT = "cat";
protected static final List<String> KEYS = new ArrayList<String>();
static {
KEYS.add(CAT);
}
protected Fields() {}
public static List<String> getKeys() {
return Collections.unmodifiableList(KEYS);
}
}
}
and you extend this class like this:
public class ExtendedModel extends Model {
public static class ExtendedFields extend Model.Fields {
public static final String DOG = "dog";
static {
KEYS.add(DOG);
}
protected ExtendedFields() {}
}
}
then its just wrong. If you call Model.Fields.getKeys() you'd get what you expect: [cat], but if you call ExtendedModel.ExtendedFields.getKeys() you'd get the same: [cat], no dog. The reason: getKeys() is a static member of Model.Fields calling ExtendedModel.ExtendedFields.getKeys() is wrong because you really call Model.Fields.getKeys() there.
So you either operate with instance methods or create a static getKeys() method in all of your Fields subclasses, which is so wrong I can't even describe.
Maybe you can create a Field interface which your clients can implement and plug into your model(s).
public interface Field {
String value();
}
public class Model {
public static Field CAT = new Field() {
#Override public String value() {
return "cat";
}
};
protected final List<Field> fields = new ArrayList();
public Model() {
fields.add(CAT);
}
public List<Field> fields() {
return Collections.unmodifiableList(fields);
}
}
public class ExtendedModel extends Model {
public static Field DOG= new Field() {
#Override public String value() {
return "dog";
}
};
public ExtendedModel() {
fields.add(DOG);
}
}
I wonder whether you really need a generated enumeration of fields. If you are going to generate a enum of a list the fields based on a model, why not generate a class which lists all the fields and their types? i.e. its not much harder to generate classes than staticly or dynamically generated enums and it much more efficient, flexible, and compiler friendly.
So you could generate from a model something like
class BaseClass { // with BaseField
String field;
int number;
}
class ExtendedClass extends BaseClass { // with OtherFields
String otherField;
long counter;
}
Is there a real benefit to inventing your own type system?
I was able to come up with a solution using reflection that seems to work -- I haven't gone through the full gamut of testing, this was more me just fooling around seeing what possible options I have.
ActiveField : Java Class which all other "Fields" Classes (which will be inner classes in my Model classes) will extend. This has a non-static method "getKeys()" which looks at "this's" class, and pulled a list of all the Fields from it. It then checks a few things like Modifiers, Field Type and Casing, to ensure that it only looks at Fields that match my convention: all "field keys" must be "public static final" of type String, and the field name must be all UPPERCASE.
public class ActiveField {
private final String key;
protected ActiveField() {
this.key = null;
}
public ActiveField(String key) {
System.out.println(key);
if (key == null) {
this.key = "key:unknown";
} else {
this.key = key;
}
}
public String toString() {
return this.key;
}
#SuppressWarnings("unchecked")
public List<String> getKeys() {
ArrayList<String> keys = new ArrayList<String>();
ArrayList<String> names = new ArrayList<String>();
Class cls;
try {
cls = Class.forName(this.getClass().getName());
} catch (ClassNotFoundException e) {
return keys;
}
Field fieldList[] = cls.getFields();
for (Field fld : fieldList) {
int mod = fld.getModifiers();
// Only look at public static final fields
if(!Modifier.isPublic(mod) || !Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
continue;
}
// Only look at String fields
if(!String.class.equals(fld.getType())) {
continue;
}
// Only look at upper case fields
if(!fld.getName().toUpperCase().equals(fld.getName())) {
continue;
}
// Get the value of the field
String value = null;
try {
value = StringUtils.stripToNull((String) fld.get(this));
} catch (IllegalArgumentException e) {
continue;
} catch (IllegalAccessException e) {
continue;
}
// Do not add duplicate or null keys, or previously added named fields
if(value == null || names.contains(fld.getName()) || keys.contains(value)) {
continue;
}
// Success! Add key to key list
keys.add(value);
// Add field named to process field names list
names.add(fld.getName());
}
return keys;
}
public int size() {
return getKeys().size();
}
}
Then in my "Model" classes (which are fancy wrappers around a Map, which can be indexed using the Fields fields)
public class ActiveResource {
/**
* Base fields for modeling ActiveResource objs - All classes that inherit from
* ActiveResource should have these fields/values (unless overridden)
*/
public static class Fields extends ActiveField {
public static final String CREATED_AT = "node:created";
public static final String LAST_MODIFIED_AT = "node:lastModified";
}
public static final Fields Fields = new Fields();
... other model specific stuff ...
}
I can then make a class Foo which extends my ActiveResource class
public class Foo extends ActiveResource {
public static class Fields extends ActiveResource.Fields {
public static final String FILE_REFERENCE = "fileReference";
public static final String TYPE = "type";
}
public static final Fields Fields = new Fields();
... other Foo specific stuff ...
Now, I can do the following:
ActiveResource ar = new ActiveResource().
Foo foo = new Foo();
ar.Fields.size() #=> 2
foo.Fields.size() #=> 4
ar.Fields.getKeys() #=> ["fileReference", "type", "node:created", "node:lastModified"]
foo.Fields.getKeys() #=> ["node:created", "node:lastModified"]
ar.Fields.CREATED_AT #=> "node:created"
foo.Fields.CREATED_AT #=> "node:created"
foo.Fields.TYPE #=> "type"
etc.
I can also access the Fields as a static field off my Model objects
Foo.Fields.size(); Foo.Fields.getKeys(); Foo.Fields.CREATED_AT; Foo.Fields.FILE_REFERENCE;
So far this looks like a pretty nice solution, that will require minimal instruction for building out new Models.
Curses - For some reason my very lengthy response with the solution i came up with did not post.
I will just give a cursory overview and if anyone wants more detail I can re-post when I have more time/patience.
I made a java class (called ActiveField) from which all the inner Fields inherit.
Each of the inner field classes have a series of fields defined:
public static class Fields extends ActiveField {
public static final String KEY = "key_value";
}
In the ActiveRecord class i have a non-static method getKeys() which uses reflection to look at the all the fields on this, iterates through, gets their values and returns them as a List.
It seems to be working quite well - let me know if you are interested in more complete code samples.

Implement an interface with final fields or access fields directly?

Is there any advantage of NOT having a class implement an interface and instead use the final fields directly? For example:
public interface MyInterface {
int CONST_A = 16;
int CONST_B = 45;
}
Approach 1:
public class MyClass implements MyInterface {
MyClass() {
System.out.println("A = " + CONST_A);
System.out.println("B = " + CONST_B);
}
}
Approach 2:
public class MyClass {
MyClass() {
System.out.println("A = " + MyInterface.CONST_A);
System.out.println("B = " + MyInterface.CONST_B);
}
}
I was wondering if any of the approaches above has advantage of any kind over the other. One of the places this situation occurs is in Blackberry where you have your localized texts defined as an interface with keys to the strings and you need to call a system API with the key as the argument in various parts of the code.
It is considered a bad practice to put constants in interfaces and to implements those interfaces to access the constants. The reason is, many classes could implement the interface, thus providing many access points to the same constants.
So, to answer your question, I'd rather use the second solution. Even better, I'd put the constants in a final class, so that there is only a single point of access to the constants. It'd be clearer, and would be easier to refactor.
use enumeration for constants (Effective Java)
For example define like that and call KernelError.KE_UNDEFINED_CALLER
public enum KernelError {
KE_NO_ERROR(0), KE_UNDEFINED_SESSION(1), KE_UNDEFINED_CALLER(2), KE_SESSION_EXPIRED(
3), KE_NULL_VALUE_IN_SESSION(4), KE_N0_SUCH_METHOD(5);
private KernelError(int errorCode) {
setErrorCode(errorCode);
}
private int errorCode;
/**
* #return the errorCode
*/
public int getErrorCode() {
return errorCode;
}
/**
* #param errorCode
* the errorCode to set
*/
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
}
If you defined constants in interfaces and, for example, define MyInterface2 which has a constant CONST_A, they conflict. Personally I think that approach 2 is easier to read.
I prefer approach 2 as it does not pollute the namespace of the using class with all possible constants. This reduces the number of code completion choices. Also, when looking at a use of a constant, the qualified name makes it obvious that it is a constant, and where that constant is defined.
That is, I prefer
interface Constants {
static int A;
static int B;
}
void foo() {
System.out.println(Constants.A);
}
to
interface Constants {
static int Const_A;
static int Const_B;
}
void foo() {
System.out.println(Const_A);
}

Categories

Resources