Get fieldname of getter by reflection - java

I was never really strong in reflection and I seem to have stumped on a problem that seems trivial but doesn't turn out that way. At least for me. I have a bean with a few getters , then in a service I use Reflextion to loop over said methods and at a certain point I end up with the get method I want. I invoke the method to get the value, and now I like to know the name of the field I just asked the value from. There is it where I get stuck.
get method
public String getTest(){ return test }
invoking method by reflection
Object value = method.invoke(jsonObject, new Object[]{});
Now I like to do something like this
String fieldName = method.findTheNameOfTheField();
I find lots of examples to call the getter from the fieldname but nothing on how to do the reverse. Is this even possible without parsing the name of the method and just cutting is and get from the method ?

I invoke the method to get the value, and now I like to know the name of the field I just asked the value from.
No, you can't do this - at least not without analyzing the bytecode itself. Don't forget that the getter can contain any code. Maybe it doesn't use a field. Maybe it uses more than one field. Maybe all the properties use a map. Maybe it uses a field, but then changes the result (e.g. copies a list).
You should consider whether a change in your design would remove the need for this in the first place - I can't think of many cases where it would be a good idea.

For working with JavaBeans, the Bean Introspector makes life easier.
Tutorial
http://v1.dione.zcu.cz/java/docs/tutorial/javabeans/introspection/index.html
Examples
http://www.java2s.com/Code/Java/Development-Class/IntrospectingaBean.htm
http://www.znetdevelopment.com/blogs/2012/04/11/java-bean-introspector-and-covariantgeneric-returns/
http://www.javablogging.com/inspecting-your-java-beans/
http://softwaresalariman.blogspot.co.uk/2011/11/minimal-javabean-introspection-example.html
This uses reflection but hides much of the details like; Do I want getValue or isFlag for a getter.

The only thing you can do here is to rely on the JavaBean convention, i.e. that the method getFoo() returns the value of the field foo.

A getter may not necesarily return a field; here's a really trivial example
public getAge() {
return currentdate - birthdate;
}
The whole point of getters is that they may return a field, but they may also return something else, abstracting internal logic from those who call the method.

Related

How to run methods before and after Lombok #Setter

I want some of my methods to run before and after the Lombok #Setter.
For example:
#Setter(after="save")
private String name;
This should run method called "save" after the original setter has assigned a value to the field.
So after compilation it should look like this:
public void setName(String name){
this.name = name;
this.save();
}
Maybe there is something I could do with "onMethod" parameter? Sorry, I'm not professional in annotations.
There is currently indeed no way to do this; onMethod isn't going to help either (SOURCE/DISCLAIMER: I'm a core lombok dev).
We do have some plans to add such a thing, but before you go ahead and write a PullRequest to add such a feature, discuss it first. There are various ways to go here. The primary issue is syntax.
You can't put java code in an annotation (you can put it in a string but we veto such a move; your IDE is not going to help you, it's got the wrong syntax highlighting, and so on). You can't, unfortunately, put a method reference in an annotation either. You could put a string in there that mentions a method but we don't like that either (again, wrong colouring, no IDE autocomplete support).
That leaves magic naming (you make a method called afterName), but at that point lombok saves you nearly nothing, so why not just write the setter. A second option is to have a single 'validate' method that is called after any setter and is e.g. marked by an annotation. That's more the direction we're leaning into.
There's more to consider: Sometimes you'd want to mutate the incoming value before assigning it, and the same mutation should be done in case you have a builder, or have a constructor that accepts this param, as well. Thus, we have:
Post-set actions after any setter and construction, such as save().
Pre-"setting", validate and/or mutate, after any setter and construction. For example, let's say you have a setAge() method and you want to throw an exception if someone attempts to pass a negative value. The set shouldn't even happen, so a post-set handler can't do the job (it'd be too late, the object is already in an invalid state and you'd want to avoid this). Complication: Given that we want to do this pre-setting the field, how does this method get the values, then?
Hopefully that illustrates why this feature isn't (yet) in lombok and why it's a matter of a simple PR to add it.

Accessor and Mutator in Java

For instance in main method I havesetFirstName() and call the Contact class to do this.
In the contact class I know I should use:public String getName()
and then public void setFirstName(String name)
I know this is the right way to do that.
But instead, I find that if i do:
public String setFirstName(String name)
{
return this.name=name;
}
this will also work and I don't need to use getName()method.
Can anyone please help me out why is that? Is my accessor/mutator method correct?
It is the very idea of an accessor that it only reads but does not modify. That is a useful convention, because if done consistently it makes reasoning about some code you don't know a lot easier. Normally, you shouldn't have to expect weird side effects from something named getX(). It may be ok to do some lazy initialization, but it is clearer if such "lazy getters" are named getOrCreateX() or similar to give the user a hint that the first use might take a bit longer/involve some expensive operation.
A mutator that returns something may be useful, but it will help users of your class if you name it in a way that gives a hint about what it returns. Is it an error code or the previous value? People don't expect return values from something named setX(), so they will be surprised to see such a signature and have to look at the documentation of your class to see what it does.
Summary: Always code as if someone else will have to take over your code any moment - don't do things that would be surprising. Even if you never hand your code to anyone else, your future self will thank you for picking names that explain what the method does.
Note: Your implementation of the setter is not very useful, as it always returns the new value you just passed in.
Getters and setters are just a convention. The compiler doesn't recognize them specially, or anything like that.
A getter, for example public String getFirstName() {return this.name;}, is just a method that returns the value of a field.
A setter, e.g. public void setFirstName(String name) {this.name=name;}, is just a method that sets the value of a field to its argument.
There is nothing forcing you to create getters and setters, and nothing bad happens if you don't, or if you decide to implement them differently. The reason they're normally written that particular way is that it works well most of the time. But you don't have to.
You have created a method that:
Sets the value of the name field to its argument.
Returns the value of the name field.
Nothing wrong with that, it's a perfectly valid method.
Is it useful as a setter? Sure, it sets the value.
Is it useful as a getter? Nope - tell me, how would you use it to get the person's first name?
But it's a perfectly valid method, and it's not "right" or "wrong", it's just not particularly useful.
The setters and getters must be properly implemented because some frameworks depends on them for proper functioning.
Mocking frameworks such as Mockito ,DI frameworks and some xml serialization techniques depend on set and get methods.

Can I write validation logic in setter methods?

Are setter methods only used to set the value of attributes as it is passed as argument? Can we write some validation logic before assigning the value to the attributes?
Yes, validation logic is definitely acceptable.
It should be noted though that if you have extensive validation you might want to extract this to a specific validator service. But for simple validations you can safely do this.
The entire idea behind using getters & setters is so nobody will have direct access to your fields. If you just wanted to set/get the value, you can make them public.
Instead, we use setters to validate the incoming data and see if it complies with the rules we set.
This concept is also called "Encapsulation", a cornerstone of Object-Oriented Programming.
Yes, you can add validation logic in your setter attributes before assigning the values. In fact, you must do it if it is possible that unwanted values may be sent to the setters.
Sure. You can include a validation. It is acceptable, but not neccessary. You just have to take into account that if you don't validate it then any values will try to get set to the variable (meeting the data type requirements).
Basically if you have
public void setNickname(String nick)
{
this.nickname = nick;
}
and you want to validate it you can either do it inside the setter - for example
public void setNickname(String nick)
{
if(nick.matches("[a-zA-Z]+"){ // only letters
this.nickname = nick;
}else{
// react
}
}
or outside of the setter before using it
if(nick.matches("[a-zA-Z]+"){ // only letters
account.setNickname(nick);
}
or you can use a method to validate it or even a separate validator class. There are a lot of possibilities.
You don't have to be afraid of developers being dazzled by this, like some say here.
It is actually encouraged to validate the input (check whether it fits your data abstraction) to your setter method, so yes you can.
Sure, there's nothing wrong with making setters only accept valid values.
As long as you do not modify other fields of class it is correct to validate.
You should also consider removing setters and using constructor with valitation or builder in Joshua Bloh version
There is absolutely nothing stopping you from doing any kind of other operation inside a setter of a property. You could do anything from validation to setting the value of some other property etc. etc. Thats not to say you should however. Use your good judgement and common sense to decide what to put in there. If the setter is bulked out with innumerable lines of code then you should question your program structure...

Why are private variables with handlers encouraged? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Are Getters and Setters evil?
I can't find a logical reason behind having a private variable with a getter and a setter that does nothing but directly handling the value being preferable to having a public variable.
Am I missing something?
Because,
Validation is one reason. Keeping the field name out of the public API also allows you to change it later without breaking the API. And it allows you to change the class later in other ways as well, e.g. moving the field to some other class (so that the public setter would call a setter in a different class). Having the setter called also allows you to do other things, e.g. notify interested other components of the change of value. None of this would be possible if the field was accessed directly.
They are preferred to future proof the code. In the future if you want to eliminate the variable or use another variable to derive this variables value - the change is simpler. You just need to change the getter/setter, the rest of the code remains unaffected. This is not the case with direct access to the variable.
As #user370305 already mentioned one reason is validation.
Other reason is types conversion. Setter may accept string and parse it to integer.
Yet another reason is data encapsulation. It is not necessarily to have a simple filed stored in the same class. Method setName(String) of class Person may store the name in more complicated data structure. Using simple field does not allow you to change the internal implementation of class Person without affecting code that uses it.
EDIT:
yet another technical reason.
It is much easier to discover and debug code with getters and setters. If some field is changed unexpectedly you can just toggle break point into appropriate setter and find the problem very quickly. If this field is public and you have 1000 references to this field you theoretically have to put 1000 breakpoints in all these places.
1. Encapsulation has different use in different context, In design patterns its like behaviors that keeps changing needs to be encapsulated in abstract class, or interface.
2. Having private instance variable and public getter setter is b
3. Its mainly done to Validate the input from the user... Setting the value to an instance variable directly is dangerous.
Eg:
int dogAge;
System.out.println("My dogs age is :"+dogAge);
Now what if someone gives a negative age... then.......???
So we must do it this way...
int dogAge;
public void setAge(int age){
if (age>0){
dogAge = age;
}
else{
System.out.println("Not a valid age");
}
}
public int getAge(){
return dogAge;
}
System.out.println("My dog age is :"+ getAge());
Its simple .. if you make those variable public then you give rights for ading any values to them .
But if you do that via getter or setter ... you can put checks over it and control the input or conversion without letting the end user know that
eg :
getName(){
return firstName+lastName;
}
or
getData(){
// code to convert byte to Mb or whatever you like to represent
}
Use of accessors to restrict direct access to field variable is preferred over the use of public fields, however, making getters and setter for each and every field is overkill and considerd as not a good practice. It also depends on the situation though, sometimes you just want a dumb data object. Accessors should be added for field where they're really required. See this link to know more about it Getter Setter: To Use or Not to Use.
I can't find a logical reason behind having a private variable with a getter and a setter that does nothing but directly handling the value being preferable to having a public variable.
Consider that any additional code that you put into getters and setters adds to complexity and also needs to be tested. For a small system which is fully controlled by you, there may be little benefit in using getters and setters. Use your professional judgement. You may not need the future proofing and added complexity. Or it may be more important to you to have the efficiency and simplicity of direct access.
Personally, I think that getters and setters are over-used. For a small system which is fully controlled by you, direct access may be the way to go.

A more generic return

Looking at some code cleanup and I was wondering the best way to deal with this:
Have a class with some private variables like:
myBool1, myBool2, myBool3
myInt1, myInt2, myInt3
myString1, myString2, myString3
What's the best way to do a getter function that is generic to the return value? So if I do a call to the getter with something like:
myNewBool=<blah>.get("myBool1")
myNewString=<blah>.get("myString2")
myNewInt=<blah>.get("myInt3")
Anyone have any suggestions?
You can't really have a generic getter if you don't know what you want to get, for example :
boolean myNewBool= get("myString1");
If get returns something, but you don't really know if this something is compatible with a boolean, and terrible things could happen.
You could try this:
public <T> get(String element){
return (T) elementToGet;
}
But you would have to specify the return type when you call the get method.
String element = myObject.<String>get("element");
Here are the bad sides :
You can't work directly with primitives
You can have a lot of ClassCastException
If you misspell an attribute name you won't see it until you run it
You don't expose a nice public API, people would have to know evert possible attribute to use it, and as said above, a misspelled attribute (or an inexistant one) wouldn't be seen until runtime.
You have to know the return time and type it each time you use your method
You would have to type a really long (and smelly) code in your get method either to use each possible attribute (if you still want have some private and not accessible) or worse, use reflection to find the right attribute.
So definitively not a good idea.
What you can do instead is using the good old getters//setters and if there is a lot of them, generate them with your IDE.
Another way would be to use the project lombok.
Resources :
Project Lombok
On the same topic :
Create automatically only getters in Eclipse
Eclipse Generate All getters setters in package
Java Getters and Setters
First you should ask what would be the pros and cons of such a solution.
Pros:
One method instead of many
Cons:
Non-intuitive to the users of your class (classical getters are more common)
You cannot have an overload that only differs by a return type, therefore you will have to have methods like getBool, getInt etc.
It's slower - you have to pass the string, check for validity, do a lookup in a map...
The only advantage of your proposed solution would be not repeating the get()/set() code. However, as these methods are usually generated by your IDE and contain only a single-line command, I wouldn't see that as a big problem.
To answer your actual question - you can create a HashMap with name-attribute mapping. Alternatively, you may use Java reflection to access the attributes. The second solution is more general but also harder to write.
This is really a terrible idea. I'm not sure why creating a getter/setter for each private variable is a problem, but passing around strings that map to a variable's symbolic name would be hard to maintain and confusing. You don't need this to be generic; each variable represents a different quantity and they should be accessed as such.
It wouldn't be clean up but mess up. I'd either created 3 getter methods for the fields or redesign it completely. But calling a function, with a name of a field to return, as an argument can bring nothing good.
When you code, you must be refactoring your code for all the time you are coding. But not like this. Solution is delegating logic to another class, wrapping code into more utilizable methods or changing and simplifying domain objects...

Categories

Resources