Outside of the context of beans, reflection, introspection or any other often referenced nonsense, is there an important reason that Java Getter/Setter are always notated as Type getAttribute() and void setAttribute(Type a)?
I read and wrote a lot of C++ code in recent times and when coming back to Java, I suddenly felt the urge to use Type attribute() and void attribute(Type a) as signatures for getters and setters as they somehow feel more comfortable to use all of a sudden. It reminds me of functional programming, having the attribute as a method of the object instead of having a method explicitly change or access the attribute.
The shorter style is the one I use. AFAIK Those in low level Java programming tend to use it possibly because it's more like C++, or because it's less like EJB's.
The problem with the JavaBean getter/setter style is it assumes an implementation of just setting and getting the variable, however this is not always the case.
You can use the methods the way you are comfortable with;
Type attribute() and void attribute(Type a)
The reason it is as you first example
Type getAttribute() and void setAttribute(Type a)
is used is to make it obvious what the method is to be used for. For example and new developer to a project can pick up and understand the flow of code without moving between different classes to see what that method does.
Getters & Setters are usually only one line functions. If a function is to do some data manipluation, it with usually use a descriptive name rather have a get or a set.
Summary:
Getters & Setters are mainly used for entity objects, where no data manipluation should be done, NOT saying that it can't be done.
The Java Naming Conventions state that "Methods should be verbs", which is commonly generalized by the community to "Methods should start with a verb". It is a question of consistency. You may very well use attribute, but I can guarantee you that people will confuse it. So if you expect other people to read and change you code, I strongly suggest to go for getAttribute and setAttribute. This argument is supported by Robert C. Martin in his book Clean Code (Section "Method Names"). It explicitly deals with your case.
That being said, the Java-API itself violates this rule sometimes (for example with the method size() in Collections). This is a known problem but shouldn't stop you from doing it better.
Related
I come from a C++ background and I am currently learning Java. One question arose when I have tried using some third party libraries. How do I determine if the call to a method taking an object reference as parameter modifies the object?
In C++ this is clear thanks to the use of the const keyword. If the method signature is:
void foo(Boo& boo);
I know that the referenced object might be modified, while if the method signature is:
void foo(const Boo& boo);
The compiler guarantees that the referenced object is not modified.
I haven't seen something analogous in Java, as only the reference itself can be declared final, not the referenced object, and a final argument doesn't make much sense in the first place since it is passed by value anyway. Therefore, when I see a method such as:
void foo(Boo boo) {...}
How do I determine if the object referenced by boo is modified inside the body of the function (maybe using annotations)? If there is no way to know, is there some widely used convention or some best practices to avoid confusion and bugs?
how do I determine if the object referenced by boo is modified inside the body of the function (maybe using annotations)?
The only way is to read the code unfortunately.
If there is no way to know, is there some widely used convention or some best practices to avoid confusion and bugs?
The common convention is to pass an object which cannot be modified, using a wrapper if needed. This ensure the class cannot modify the object.
List<String> readOnly = Collections.unmodifiableList(list);
If the object is Cloneable, you can also use clone() but another common approach is to use a copy.
List<String> readOnly = new ArrayList<>(list);
If you care about such behaviour, unit tests can show whether a method modifies an object or not. If you have unit tests already, it is usually one or two lines extra to check for this.
There's no such facility built in to the language, unfortunately. A good defensive practice is to define the data objects you pass around as immutable (i.e., without any public method that allows modifying their state). If you are really concerned about this, you could copy/clone an object before passing it to a method you don't trust, but this is usually a redundant precaution.
NOTE: this answer is a more detailed version of
You can also write purity or side-effect annotations in your code — mernst
There exists the Checker Framework among the various things it can check at compile-time via annotations is the IJG Immutablity checker. This checker allows you to annotate object references with #Immutable or #ReadOnly.
The problem is that you often would have to annotate the library yourself. To ease your task the Checker Framework can automatically infer part of the annotations; you will still have to do much yourself.
A side effect analysis is not built into the Java language.
You can perform side effect analysis via manual inspection, but several tools exist to automate the process.
You can use an inference tool (1, 2, 3) to detect whether your code side-effects a parameter.
You can also write purity or side-effect annotations in your code and then use a checking/verification tool (1, 2) to ensure that your code conforms to the annotations you have written.
All of the above-linked tools have limitations, but you might find them useful. If you know of other tools, mention them in comments.
How do I determine if the object referenced by boo is modified inside
the body of the function (maybe using annotations)?
I must agree with other answers that there is no direct way to determine that method will modify your object or not and yes to make sure that method can not modify your Object you all have to do it is from your side.
If there is no way to know, is there some widely used convention or
some best practices to avoid confusion and bugs?
Here the method name comes to the scene. Moving ahead with the naming convention of method we have to take a look at some method declarations which clearly convince you that your Object will not be changed at all.
For example, You know that Arrays.copyOf will not change your actual array, System.out.println(boo) will not change your boo
Method names are real weapons to provide as much information as possible to the method user.(Yes! it's always not possible but quite a good practice to follow.)
Let's consider it in your case that say printBoo will only print, copyBoo will only copy, clearBoo will reset all attributes, checkAndCreateNewBoo will check your boo Object and create new if required.
So, ultimately if we can use them in a proper way caller can be assured with the fact that Object will remain the same after calling the method.
As everyone says, prefer using immutable objects and also avoid void methods
The available purposes of methods like this
void foo(Boo boo) {...}
are to change the state of the object itself or change the object passed as a parameter
void completOrder(Order order) { ... }
//or
void parserTokenEnded(String str) { ... }
There is a way , that the method developer should mark parameter as final , if it is not going to modify the parameter.
public void test(final Object param)
However very few people follow this , so it is difficult to know. However good programmer follow this rule , especially writing the api. If you want to write method and expose it. Make param final to indicate that passed object is not going to be modified.
Through the Java API you see numerous occurrences of conflicting naming and practices which are really confusing to me.
For example:
The String class has a private variable (Integer) by the name of count which keeps track of the size of the string, however this is returned by a getter by the name of length().
If you move over to any type of arrays, instead of having a getter method for length, they just pass the variable through with a public accessor, and it can be obtained through arrayInstance.length.
Moving back to the String class we have the String#getBytes() method which is a getter, similar to the length() getter, however performs slightly more logic to get and return the value.
To me, personally, creating a getter with the prefix of get seems redundant, for example I rather type GamePacket#data() versus GamePacket#getData() however I feel like there may be a deeper meaning behind this naming instead of just inconsistency.
Also, why doesn't the Array[] use a getter for length?
Would anybody be kind enough to shed some light on this for me?
Getters (and setters) come from the Java Bean specification. The reasons to use them are multiple:
most Java developers expect accessors to be named like that
an API respecting these conventions is easier to discover. For example, in my IDE, I'll often press get CtrlSpace to discover all the information available in an object.
many APIs and frameworks rely on these conventions to work: the JSP EL, MVC frameworks populating beans from request parameters, JPA, dependency injection frameworks like Spring, etc.
You usually name the getter the same way as the private variable that holds the information, but what matters is encapsulation and the public API, so nothing prevents you from computing a value in a getter, or to name the private field a different way.
This is not going to be a full answer, as a real answer would probably require interviewing the original developers of Java or otherwise researching historical records. But here are a few notes:
As you were told in the comments, the length field of an array is final, therefore it cannot be set.
Both arrays and the String class were designed in the earliest versions of Java, before the conventions for getters and setters were settled upon. The get... is... and set... conventions have only really been settled upon at the introduction of JavaBeans. Changing the API would make old code stop working, and so the old names persist.
In general (e.g. classes which are not JavaBeans), there is actually no rule that says the getter and setter methods have to reflect the name of any particular field in the class. The whole idea of accessor methods is that they hide implementation, so whatever is behind them can be a field, a combination of fields, or something else altogether.
Naming conventions appear to vary throughout the Java codebase, but one early standard was the JavaBeans naming convention; this basically formed an nomenclature solution to Java's lack of true properties.
Object/primitive getters had the form getXXX(), except for booleans, which had the preferred form isXXX(). Setters were always in the form setXXX().
From this single point, millions of lines of reflective code were written.
This convention pre-dated annotations, which would have been a trade-off between increased intent and increased verbosity when writing something like this pseudo-ish code
#Setter
void data(Data data) {
this.data = data;
};
#Getter
Data data() {
return data;
};
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...
I'm looking for the official naming convention in Java regarding accessors.
I've seen that, for instance, the JPanel class deprecated the size() method in favor of getSize().
But in the ArrayList class, the method is size().
So I'm wondering if accessors should be named getXXX() or xXX() ?
It's usually a bad idea to not use the JavaBeans convention (getters and setters).
They're used through reflection by many frameworks, in particular with EL where sometimes you can't access your fields without the rights getters (depending on the EL flavour).
So your accessors should always be named getXxx() or isXxx() and setXxx().
size() in the collection framework is an example of "flaw" which can annoy developers (see link below). The choice made by Josh Bloch and Neal Gafter to make it more readable now makes it difficult to obtain in some contexts (EL).
But remember the JavaBeans convention isn't the Java naming convention.
Resources :
How to Access the Size of a Collection in a JSP Page Using JSTL-EL
Java conventions
JavaBeans
JavaBeans specification
On the same topic :
Getters on an immutable type
With query methods, I always look at getXXX as something that is provided versus something that is calculated. The size() method returns the size of the collection which is a derived value, so it makes sense. If you had getSize() my assumption would be that I could somehow set the size (through a constructor or setter method).
For anything trying to look like a JavaBean, it should be getXXX or isXXX. (I can't remember whether hasXXX is valid for Boolean properties as well... not sure.)
It makes sense to treat a JPanel in a bean kind of way - for designers etc - but not an ArrayList.
Personally I tend to use the getXXX form just for consistency, but I believe the above is the reasoning involved in ArrayList's naming.
This is only a formative addentum to Colin HERBERT's answer which, in my opinion, is enough:
Accessor method signatures should always look like public Type getProperty(). Additionally, accessors should always return a copy of the property's value, not the value itself.
Mutator method signatures should always look like public void setProperty(Type value)
Combining an accessor and a mutator gives you a JavaBean property. JavaBeans are not considered to be immutable by nature, but if you want to make it immutable, you should use the following signature for the mutator method: public YourJavaBean withProperty(Type value). Note that this should always return a completely new YourJavaBean instance with copied property values.
In Eclipse the convention is definitely to use the getpattern. The automisation tools create and handle getters by checking for and writing get and set style accessors.
I prefer the get/is/set-Convention (especially for ValueObjects/DataObjects) not only because it's the JavaBeans specification but because of the following two points.
The clear prefix of the method seperates property related methods from 'logic' methods.
You can use it out of the box with JSP and other frameworks that assume this naming.
It is always better to follow setXXX and getXXX pattern as per JavaBeans specification. The size() method named so, may be as it is just querying the state.
I’m a huge believer in consistency, and hence conventions.
However, I’m currently developing a framework in Java where these conventions (specifically the get/set prefix convention) seem to get in the way of readability. For example, some classes will have id and name properties and using o.getId() instead of o.id() seems utterly pointless for a number of reasons:
The classes are immutable so there will (generally) be no corresponding setter,
there is no chance of confusion,
the get in this case conveys no additional semantics, and
I use this get-less naming schema quite consistently throughout the library.
I am getting some reassurance from the Java Collection classes (and other classes from the Java Platform library) which also violate JavaBean conventions (e.g. they use size instead of getSize etc.).
To get this concern out of the way: the component will never be used as a JavaBean since they cannot be meaningfully used that way.
On the other hand, I am not a seasoned Java user and I don’t know what other Java developers expect of a library. Can I follow the example of the Java Platform classes in this or is it considered bad style? Is the violation of the get/set convention in Java library classes deemed a mistake in retrospect? Or is it completely normal to ignore the JavaBean conventions when not applicable?
(The Sun code conventions for Java don’t mention this at all.)
If you follow the appropriate naming conventions, then 3rd-party tools can easily integrate with and use your library. They will expect getX(), isX() etc. and try to find these through reflection.
Although you say that these won't be exposed as JavaBeans currently, I would still follow the conventions. Who knows what you may want to do further down the line ? Or perhaps at a later stage you'll want to extract an interface to this object and create a proxy that can be accessed via other tools ?
I actually hate this convention. I would be very happen if it was replaced by a real java tool that would provide the accessor/modifier methods.
But I do follow this convention in all my code. We don't program alone, and even if the whole team agrees on a special convention right now, you can be assured that future newcomers, or a future team that will maintain your project, will have a hard time at the beginning... I believe the inconvenience for get/set is not as big as the inconvenience from being non-standard.
I would like to raise another concern : often, java software uses too many accessors and modifiers (get/set). We should apply much more the "Tell, don't ask" advice. For example, replace the getters on B by a "real" method:
class A {
B b;
String c;
void a() {
String c = b.getC();
String d = b.getD();
// algorithm with b, c, d
}
}
by
class A {
B b;
String c;
void a() {
b.a(c); // Class B has the algorithm.
}
}
Many good properties are obtained by this refactor:
B can be made immutable (excellent for thread-safe)
Subclasses of B can modify the computation, so B might not require another property for that purpose.
The implementation is simpler in B it would have been in A, because you don't have to use the getter and external access to the data, you are inside B and can take advantage of implementation details (checking for errors, special cases, using cached values...).
Being located in B to which it has more coupling (two properties instead of one for A), chances are that refactoring A will not impact the algorithm. For a B refactoring, it may be an opportunity to improve the algorithm. So maintenance is less.
The violation of the get/set convention in the Java library classes is most certainly a mistake. I'd actually recommend that you follow the convention, to avoid the complexity of knowing why/when the convention isn't followed.
Josh Bloch actually sides with you in this matter in Effective Java, where he advocates the get-less variant for things which aren't meant to be used as beans, for readability's sake. Of course, not everyone agrees with Bloch, but it shows there are cases for and against dumping the get. (I think it's easier to read, and so if YAGNI, ditch the get.)
Concerning the size() method from the collections framework; it seems unlikely it's just a "bad" legacy name when you look at, say, the more recent Enum class which has name() and ordinal(). (Which probably can be explained by Bloch being one of Enum's two attributed authors. ☺)
The get-less schema is used in a language like scala (and other languages), with the Uniform Access Principle:
Scala keeps field and method names in the same namespace, which means we can’t name the field count if a method is named count. Many languages, like Java, don’t have this restriction, because they keep field and method names in separate namespaces.
Since Java is not meant to offer UAP for "properties", it is best to refer to those properties with the get/set conventions.
UAP means:
Foo.bar and Foo.bar() are the same and refer to reading property, or to a read method for the property.
Foo.bar = 5 and Foo.bar(5) are the same and refer to setting the property, or to a write method for the property.
In Java, you cannot achieve UAP because Foo.bar and Foo.bar() are in two different namespaces.
That means to access the read method, you will have to call Foo.bar(), which is no different than calling any other method.
So this get-set convention can help to differentiate that call from the others (not related to properties), since "All services (here "just reading/setting a value, or computing it") offered by a module cannot be available through a uniform notation".
It is not mandatory, but is a way to recognize a service related to get/set or compute a property value, from the other services.
If UAP were available in Java, that convention would not be needed at all.
Note: the size() instead of getSize() is probably a legacy bad naming preserved for the sake of Java's mantra is 'Backwardly compatible: always'.
Consider this: Lots of frameworks can be told to reference a property in object's field such as "name". Under the hood the framework understands to first turn "name" into "setName", figure out from its singular parameter what is the return type and then form either "getName" or "isName".
If you don't provide such well-documented, sensible accessor/mutator mechanism, your framework/library just won't work with the majority of other libraries/frameworks out there.