Try this. The initial reflection is certainly expensive, but if you're going to use it many many times, which I think you will, this is most certainly a better solution what what you're proposing. I don't like using reflection, but I find myself using it when I don't like the alternative to reflection. I do think that this will save your team a lot of headache, but you must pass the name of the method (in lowercase).
In other words, rather than pass "name", you would pass "fullname" because the name of the get method is "getFullName()".
Map<String, Method> methodMapping = null;
public Object getNode(String name) {
Map<String, Method> methods = getMethodMapping(contact.getClass());
return methods.get(name).invoke(contact);
}
public Map<String, Method> getMethodMapping(Class<?> contact) {
if(methodMapping == null) {
Map<String, Method> mapping = new HashMap<String, Method>();
Method[] methods = contact.getDeclaredMethods();
for(Method method : methods) {
if(method.getParameterTypes().length() == 0) {
if(method.getName().startsWith("get")) {
mapping.put(method.getName().substring(3).toLower(), method);
} else if (method.getName().startsWith("is"))) {
mapping.put(method.getName().substring(2).toLower(), method);
}
}
}
methodMapping = mapping;
}
return methodMapping;
}
If you need to access data contained within members of contact, you might consider building a wrapper class for contact which has all methods to access any information required. This would also be useful for guaranteeing that the names of the access fields will always remain the same (I.e. if wrapper class has getFullName() and you call with fullname, it will always work even if contact's getFullName() has been renamed -- it would cause compilation error before it would let you do that).
public class ContactWrapper {
private Contact contact;
public ContactWrapper(Contact contact) {
this.contact = contact;
}
public String getFullName() {
return contact.getFullName();
}
...
}
This solution has saved me several times, namely when I wanted to have a single data representation to use in jsf datatables and when that data needed to be exported into a report using jasper (which doesn't handle complicated object accessors well in my experience).
It's anyways bad practice to initialie a char array with a string literal.
The author of that comment never really justifies it, and I find the statement puzzling.
In C (and you've tagged this as C), that's pretty much the only way to initialize an array of char
with a string value (initialization is different from assignment). You can write either
char string[] = "october";
or
char string[8] = "october";
or
char string[MAX_MONTH_LENGTH] = "october";
In the first case, the size of the array is taken from the size of the initializer. String literals are stored as arrays of char
with a terminating 0 byte, so the size of the array is 8 ('o', 'c', 't', 'o', 'b', 'e', 'r', 0). In the second two cases, the size of the array is specified as part of the declaration (8 and MAX_MONTH_LENGTH
, whatever that happens to be).
What you cannot do is write something like
char string[];
string = "october";
or
char string[8];
string = "october";
etc. In the first case, the declaration of string
is incomplete because no array size has been specified and there's no initializer to take the size from. In both cases, the =
won't work because a) an array expression such as string
may not be the target of an assignment and b) the =
operator isn't defined to copy the contents of one array to another anyway.
By that same token, you can't write
char string[] = foo;
where foo
is another array of char
. This form of initialization will only work with string literals.
EDIT
I should amend this to say that you can also initialize arrays to hold a string with an array-style initializer, like
char string[] = {'o', 'c', 't', 'o', 'b', 'e', 'r', 0};
or
char string[] = {111, 99, 116, 111, 98, 101, 114, 0}; // assumes ASCII
but it's easier on the eyes to use string literals.
EDIT2
In order to assign the contents of an array outside of a declaration, you would need to use either strcpy/strncpy
(for 0-terminated strings) or memcpy
(for any other type of array):
if (sizeof string > strlen("october"))
strcpy(string, "october");
or
strncpy(string, "october", sizeof string); // only copies as many characters as will
// fit in the target buffer; 0 terminator
// may not be copied, but the buffer is
// uselessly completely zeroed if the
// string is shorter!
Best Answer
I much prefer using Enums to store system wide string constants, makes it easy to create additional functionality and I think it is generally accepted best practice.
then you can call it like so :
or you could also the Command pattern without enums....
then build a Map object and populate it with Cat instances:
then you can replace your if/else if chain with: