public final class Templates {
public static class NewDeviceDetailsConsts {
public static final String AAA = "aaaa";
public static final String BBB = "bbbb";
public static final String CCC = "cccc";
}
}
for using AAA, I have to write Templates.NewDeviceDetailsConsts.AAA and thats a long string to use 10-20 times in every class I use it.
Will it be efficient to use it like,
I define a field in classes I need it , Templates.NewDeviceDetailsConsts DeviceConst; and use DeviceConst.___ in the class.
Is it fine or can I do it better than that.
There a a few ways you can solve this problem.
create a static import:
Where your import statements are, add this import static path.to.Templates.NewDeviceDetailsConsts.AAA;. This will allow you to reference your AAA object just by typing AAA.
Unfortunately, you will have to add this line at the top of all your classes.
Create a getter your Templates class.
public static NewDeviceDetailsConsts getAAA(){
return NewDeviceDetailsConsts.AAA;
}
Then use Templates.getAAA() to get the AAA object.
Save a reference to the AAA object inside the working class.
private static NewDeviceDetailsConsts AAA = Templates.NewDeviceDetailsConsts.AAA;
I would use enum's for such purpose:
public final class Templates {
public enum NewDeviceDetailsConsts {
AAA("aaaa"), BBB("bbbb"), CCC("cccc");
private String value;
private NewDeviceDetailsConsts(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
Then you can use the constants as follows:
NewDeviceDetailsConsts aaa = NewDeviceDetailsConsts.AAA;
You can also use AAA, BBB, ... without param if you need as follows:
public final class Templates {
public enum NewDeviceDetailsConsts {
AAAA, BBBB, CCCC;
}
}
And lastly, you should not define them inside a class. An enum can also be a top level class as follows unless they have to be part of a class:
public enum NewDeviceDetailsConsts {
AAAA, BBBB, CCCC;
}
Related
How can I set or get a field in a class whose name is dynamic and stored in a string variable?
public class Test {
public String a1;
public String a2;
public Test(String key) {
this.key = 'found'; <--- error
}
}
You have to use reflection:
Use Class.getField() to get a Field reference. If it's not public you'll need to call Class.getDeclaredField() instead
Use AccessibleObject.setAccessible to gain access to the field if it's not public
Use Field.set() to set the value, or one of the similarly-named methods if it's a primitive
Here's an example which deals with the simple case of a public field. A nicer alternative would be to use properties, if possible.
import java.lang.reflect.Field;
class DataObject
{
// I don't like public fields; this is *solely*
// to make it easier to demonstrate
public String foo;
}
public class Test
{
public static void main(String[] args)
// Declaring that a method throws Exception is
// likewise usually a bad idea; consider the
// various failure cases carefully
throws Exception
{
Field field = DataObject.class.getField("foo");
DataObject o = new DataObject();
field.set(o, "new value");
System.out.println(o.foo);
}
}
Class<?> actualClass=actual.getClass();
Field f=actualClass.getDeclaredField("name");
The above code would suffice .
object.class.getField("foo");
Unfortunately the above code didn't work for me , since the class had empty field array.
I have a REST API test suite where certain URIs are used repeatedly. Thus, I created a separate class with public static final members. Something like:
public class RestURI {
public RestURI(){}
public static final String getAllShipsURI = "/ship/manager/ships";
public static final String getAllPortsURI = "/port/manager/ports";
}
However, is there a way to deal with URIs like this:
/infrastructure/ships/docked/" + shipId + "/capacity
I am looking for a way such that I can declare the URL like above in the RestURI class and still specify values in the test when I use them.
You can use a constant format, rather than a String and use a static getter:
public static String getShipUri(int shipId) {
return String.format("/infrastructure/ships/docked/%d/capacity", shipId);
}
You could use String.format. Like this:
public class RestURI {
public RestURI(){}
public xxx() {
int shipId = 219001000;
... String.format(dockedShipURIFormat, shipId) ...;
}
public static final String dockedShipURIFormat = "/infrastructure/ships/docked/%d/capacity";
}
I've used ANTLR StringTemplate for exactly this on multiple occasions. The ability to have inline macro parsing and a little if..else logic in the templates is pretty powerful, and it maintains good readability.
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?
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.
I have a question about the following code:
public Class Settings{
public static final String WelcomeMessage= "helloworld";
public static final String ByeMessage= "yo";
public static String[] widgets = {WelcomeMessage,ByeMessage};
}
The compiler complains about duplicat variables. Can I delete the 2 separate variables and still acces WelcomeMessage by Settings.WelcomeMessage? I don't need to acces it by Settings.widget[0]? And is it possible to add another variable to the WelcomeMessage variable (by for instance using a static hashtable)?
Edit: I know this code doesn't look right but it's just an example because I wondered why the compiler thinks WelcomeMessage (as a separata variable) is the same as the variable in the Widgets array.
I would consider java-enums in your case:
public enum Settings {
WelcomeMessage ("helloworld"),
ByeMessage ("yo");
public final String value;
Settings(String value) {
this.value = value;
}
}
You can access now the values via Settings.WelcomeMessage.value. Also you get a List of the enums with Settings.values().
You've marked the fields as public static which means that yes you'll be able to access them via:
Settings.WelcomeMessage
or if you you use a static import in your class, just:
WelcomeMessage
You haven't actually used these constants in the widgets array, you've just created two new strings in there "WelcomeMessage" and "ByeMessage"
public static String[] widgets = {"WelcomeMessage","ByeMessage"};
No, if you delete the WelcomeMessage and ByeMessage constants you can't access them in that way, you'd have to go through the widgets array and access them as:
Settings.widgets[0]
I think you meant to use this instead:
public Class Settings
{
public static final String WelcomeMessage= "helloworld";
public static final String ByeMessage= "yo";
public static String[] widgets = {WelcomeMessage,ByeMessage};
}
But this is better:
public Class Settings
{
public static String[] widgets = {"WelcomeMessage","ByeMessage"};
}
And yes you can access WelcomeMessage via Settings.widgets[0].
Edit: Oops - yep - of course you cannot access them by name, only index into the array.
Edit 2: If you make the field protected or private and provide 'getter' methods, then it doesn't matter to any user classes how they are implemented:
public Class Settings
{
private static final String welcomeMessage= "helloworld";
private static final String byeMessage= "yo";
public static String getWelcomeMessage()
{
return welcomeMessage;
}
public static String getByeMessage()
{
return byeMessage;
}
}