Why is it bad practice to allow to set a collection? - java

Let's say we have a class with a simple collection (a list for instance). The class contains a constructor, getters and setters.
I've been told that it is a bad practice to set the collection directly.
class Example{
private String id;
private List<String> names;
public Example(String id, List<String> names){
this.id = id;
this.names = names;
}
public String getId(){
return id;
}
public List<String> getNames(){
return names;
}
public void setId(String id){
this.id = id;
}
public void setNames(List<String> names){
this.names = names;
}
}
Can anyone point the disadvantages of writing the method setNames()?

The logic behind set and get operations is to allow validation or replacing of inner representation, if you let an external class set the specific implementation, you lose control over the insertion logic (allows duplicates? is ordered?, is mutable?), and you make you object harder to use, as the users of it have to decide that, when is very probable that they don't care.

Since the private variable names is owned by your class you can ensure that you have control over its contents within the class. If you change the reference of that variable to a list that gets passed in then you no longer are certain that your instance won't be changed externally since both your class AND the class that passed the new list instance will both have a reference/access to it. Same is true with getNames() - any class that calls that method now has full access to change the contents of the list externally from the class.

That would give you two ways of changing the contents (getNames().add(...) vs. setNames(Arrays.asList(...))).
This is confusing.
You should pick a single option and make the other option impossible.

A lot of the builtin collections are mutable, so storing such a value may allow an external class to modify the internal state of your Example is a way you did not plan. Consider the following snippet:
List<Stirng> names = new ArrayList<>();
names.add("Stack");
names.add("Overflow");
Example example = new Example();
example.setNames(names);
// example.getNames() returns ["Stack", "Overflow"]
names.add("Exchange");
// example.getNames now returns ["Stack", "Overflow", "Exchange"]!
A safer approach could be to copy the contents of the passed list:
public void setNames(List<String> names){
this.names = new ArrayList<>(names);
}

A slightly different answer to those here already is that setters are a bad practice (*), whether you're setting a collection property or some other type.
To quote Effective Java 2nd Ed Item 15: "Minimize mutability":
There are many good reasons for [making classes immutable]: Immutable classes
are easier to design, implement, and use than mutable classes. They are less prone
to error and are more secure.
There is also a description of immutable classes in the Oracle tutorial.
(*) That's not to say that you should never use them; just that you should design classes to be immutable as a default position, and only make them mutable in the few occasions where it is actually required - and that's less often than you might imagine. To quote the same item in Effective Java:
Classes should be immutable unless there’s a very good reason to make them
mutable

Using get and set methods allows you to perform verification and validation on the input before it can cause problems. It can also be used to transform info going into and out of your system for the convenience of the program and user.
Edit
Just to be clear defensive measures are part of the verification and validation I was talking about.

Related

Create Fields and methods dynamically

I want to add new fields(variables) and encapsulating methods for a given class. For example: A class name Student has no any fields like below:
public class Student implements Serializable{
}
then in my application an instance is created;
Student s=new Student();
I want to add new methods which do not exist for student class at the run time.for example: I want to add a field called studentName, and getStudentName() and setStudentName() methods.
Then at the run time the student object will be like this;
public class Student implements Serializable{
private String studentName;
public void setStudentName(..){}
public String getStudentName(){return ...;}
}
In my application objects are written to a text file and all objects of same type do not have all variables. Therefore, I want to add only the required fields to save memory.
Any way is there a way to do this? Any sample code or link?
EDIT: or else can we create a class either and create instances which does not exists ?
EDIT 2: Thanks all of you answered and got many info and ideas. And changed the way to a better path from your suggestions as well
Why not just create a HashMap of values? Much more efficient, and has all the flexibility you're looking for.
public class Student
{
private HashMap<String, String> values;
public Student()
{
this.values = new HashMap<String, String>();
}
public void addValue(String name, String value)
{
values.put(name, value);
}
public String getValue(String name)
{
return values.get(name);
}
}
Why a HashMap?
You said that all objects may have differing values, and you'll be defining those new methods and attributes by a String. Well.. this will achieve that functionality without any horrible bytecode manipulation. For example:
String attrName = "name";
String attrValue = "jim";
Student stu = new Student();
stu.addValue(attrName, attrValue);
At the moment, you've only got the one value in your HashMap. The only overheard you have to face is the HashMap object itself, and two methods, which frankly is a fair trade off for a far tidier solution.
You can use bytecode instrumentation libraries like Javassist or ASM for this purpose. Here is an example of adding a field or method by using Javassist.
While it is possible with bytecode manipulation and such it wouldn't be wise, especially if you intend to do this to "save memory". It's unlikely that you would have so much data that it would make a difference, and if you did, you would store them in a database anyways.
Instead of writing your own HashMap based solution you can use DynaBean and DynaClass: support not only simple properties but also indexed (Array) and mapped (Map).
DynaBean can be introspected to get properties and values so you can dump to file BUT
with this solution you are only "simulating" a bean, your Student class doesn't really contains fields and accessors (you you call Student.getClass().getDeclaredField() you will get an empty array).
If you need to compose a "real" java java.lang.Class Javassist (my preferred choice, I used to resolve a solution similar to your question) or ASM (or CGLIB) are the best choiches.
I dont believe if this is possible in java but I'm sure it will only add to the memory because if you add them dynamically they must be set up beforehand + the code to add them dynamically.
Practically speaking, not in Java. In other languages like Javascript, this is possible.
Java is not a dynamic programming language and so I would not advice to follow that route even if some advance approaches may allow you to do so.
The Java idiom for that scenario would be to store the field values in a (hash) map instead. So you would have a couple of common accessors to set or get all attribute values and in the accessor you would need to indicate the name of the attribute you want to change.
However this solution won't save memory unless the maximum number of attributes is rather large and most object just have values for a small number of such attributes.
public class Entity {
// 5 is an estimate for the number attrs.
private Map<String,Object> attrs = new HashMap<>(5);
public Object getAttribute(String name) { return attrs.get(name); }
public void setAttribute(String name, Object obj) { attrs.put(name,obj); }
}
You could implement some runtime type-checking if you manage meta-data about possible attributes and their value types.

Are there any plans for Java to add implicit Getters and Setters?

Does anyone know if there is a plan to add in implicit getters and setters for Class variables?
I'm thinking of the current Scala code that allows this already. Something like the following, where if you don't define a getter/setter it uses the value, but if you do define a getter/setter for the value it uses that instead of a direct variable call.
class A{
int value = 3;
}
class B{
int value = 3;
public int value(){
return value;
}
}
// in some method
A a = new A();
System.out.println(a.value);
B b = new B();
System.out.println(b.value); // <-- no () for accessing value even though it uses the getter
not Java per se, but there is this Project Lombok
Foreword: maybe I'm wrong but the question is maybe a better fit for java platform user/devel lists, like those at http://www.oracle.com/technetwork/java/javase/community/index.html
I suppose you'll receive more meaningful answers there, and less speculation.
My own take on the subject is that the JavaBean model is far too established to admit any significant change for backward compatibility, and that java encapsulation model is based on the concept that you hide fields with private access and provide accessors/mutators.
If you only want to expose members you can simply make them public.
Translating fields to automatic accessor/mutator methods is quite a big change to the language, and would probably create much confusion for little gain.
You should also consider that the scala choice implies a radically different approach to member access, for the sake of uniform access principle.
A simple getter returns a field value. However a getter can also return the results of an operation:
public boolean isError()
{
return errorList.size() > 0;
}
Similarly a setter might do other operations:
public void setName(String name)
{
this.name = name;
this.sortName = name.toLowerCase();
}
So other than the bean paradigm, and for the sake of consistency, getters/setters should be used rather than direct field access.
Java 14 (LTS release) has records, but you need to compile with additional options for it to work. Records provide getters for the constructor params and aim to solve a few other problems inherent in earlier versions.

How do the Law of Demeter and composition with collections work together?

I have read nearly all of the questions tagged Law-of-Demeter. My specific question is not answered in any of these other questions, though it is very similar. Mainly my question is when you have an object with layers of composition, but the need to retrieve property values from the various objects, how do you achieve this and why take one approach over another?
Let's say you have a pretty standard object composed of other objects, like this:
public class Customer {
private String name;
private ContactInfo primaryAddress;
private ContactInfo workAddress;
private Interests hobbies;
//Etc...
public getPrimaryAddress() { return primaryAddress; }
public getWorkAddress() { return workAddress; }
public getHobbies() { return hobbies; }
//Etc...
}
private ContactInfo {
private String phoneNumber;
private String emailAddress;
//Etc...
public getPhoneNumber() { return phoneNumber; }
public getEmailAddress() { return emailAddress; }
//Etc...
}
private Interests {
private List listOfInterests;
}
The following would both violate the Law of Demeter:
System.out.println("Phone: " + customer.getPrimaryAddress().getPhoneNumber());
System.out.println("Hobbies: " + customer.getHobbies().getListOfInterests().toString());
This also would violate the Law of Demeter, I think (clarification?):
ContactInfo customerPrimaryAddress = customer.getPrimaryAddress();
System.out.println("Phone: " + customerPrimaryAddress.getPhoneNumber());
So presumably, you would then add a "getPrimaryPhoneNumber()" method to Customer:
public getPrimaryPhoneNumber() {
return primaryAddress.getPhoneNumber();
}
And then simply call:
System.out.println("Phone: " + customer.getPrimaryPhoneNumber());
But doing this over time seems like it would actually provide a lot of problems and work against the intention of the Law of Demeter. It makes the Customer class into a huge bag of getters and setters that has way too much knowledge about its own internal classes. For instance, it seems possible that the Customer object will one day have various addresses (not just a "primary" and a "work" address). Perhaps even the Customer class will simply have a List (or other collection) of ContactInfo objects rather than specific named ContactInfo objects. How do you continue following the Law of Demeter in that case? It would seem to defeat the purpose of the abstraction. For example, this seems reasonable in such a case where a Customer has a List of ContactInfo items:
Customer.getSomeParticularAddress(addressType).getPhoneNumber();
This seems like it can get even crazier when you think about some people having a mobile phone and a landline phone, and then ContactInfo has to have a collection of phone numbers.
Customer.getSomeParticularAddress(addressType).getSomePhoneNumber(phoneType).getPhoneNumber();
In which case, not only are we referring to objects within objects within objects, but we also have to know what the valid addressType's and phoneType's are. I can definitely see a problem with this, but I am not sure how to avoid it. Especially when whatever class is calling this, probably does know that they want to pull the "mobile" phone number for the "primary" address of the customer in question.
How could this be refactored to comply with the Law of Demeter and why would that be good?
In my experience, the Customer example shown is not a “standard object composed of other objects,” because this example takes the added steps of implementing its composing pieces as inner classes, and furthermore making those inner classes private. That’s not a bad thing.
In general the private access modifier increases information hiding, which is the basis for the Law of Demeter. Exposing private classes is contradictory. The NetBeans IDE actually includes a default compiler warning for, “Exporting non-public type through public API”.
I would assert that exposing a private class outside its enclosing class is always bad: it reduces information hiding and violates the Law of Demeter. So to answer the clarification question about returning an instance of ContactInfo outside of Customer: yes, that is a violation.
The proposed solution of adding a getPrimaryPhoneNumber() method to Customer is a valid option. The confusion is here: “Customer... has way too much knowledge about its own internal classes.” That’s not possible; and that’s why it’s important that this example is not a standard composition example.
An enclosing class has 100% knowledge of any nested classes. Always. Regardless of how those nested classes are used in the enclosing class (or anywhere else). That’s why an enclosing class has direct access to private fields and methods of its nested classes: the enclosing class inherently knows everything about them, because they’re implemented inside it.
Given the preposterous example of a class Foo, which has a nested class Bar, which has a nested class Baz, which has a nested class Qux, it would not be a violation of Demeter for Foo (internally) to call bar.baz.qux.method(). Foo already knows everything there is to know about Bar, Baz, and Qux; because their code is inside Foo, so there is no additional knowledge being passed via the long method chain.
The solution then, per the Law of Demeter, is for Customer not to return intermediate objects, regardless of its internal implemention; i.e. whether Customer is implemented using several nested classes or none, it should return only what its client classes ultimately need.
For example the last code snippet might be refactored as,
customer.getPhoneNumber(addressType, phoneType);
or if there are only a small number of options,
customer.getPrimaryMobilePhoneNumber();
Either approach results in users of the Customer class being unaware of its internal implementation, and ensures those users do not have to call through objects they're not directly interested in.
It's important to remember that the Law of Demeter is, despite its name, a guideline and not an actual law. We need to examine its purpose at a slightly deeper level to determine what is the right thing to do here.
The purpose of the Law of Demeter is to prevent outside objects being able to access the internals of another object. Accessing internals has two problems: 1) it gives too much information about the internal structure of the object, and 2)it also allows outside objects to modify the internals of the class.
The correct response to this issue is to separate out the object being returned from the Customer method from the internal representation. In other words, instead of returning a reference to the private internal object of type ContactInfo, we instead define a new class UnmodifiableContactInfo, and have getPrimaryAddress return UnmodifiableContactInfo, creating it and filling it in as necessary.
This gets us both the benefits of the Law of Demeter. The returned object is no longer an internal object of Customer, which means that Customer can modify its internal storage as much as it likes, and that nothing we do to UnmodifiableContactInfo affects the internals of Customer.
(In reality I would rename the internal class and leave the external one as ContactInfo, but that's a minor point)
So this achieves the objectives of the Law of Demeter, but it still looks like we are breaking it. The way i think of this is that the getAddress method is not returning a ContactInfo object, but instantiating it. This means means that under the Demeter rules we can access ContactInfo's methods, and the code you have written above is not a violation.
You have to note of course that although the 'violation of Demeter's Law' occurred in the code accessing Customer, the fix needs to be made in Customer. In general the fix is a good thing - providing access to internal objects is bad, whether or not they are accessed using more than one 'dot'.
A few notes. It's obvious that an over-strict application of Demeter's law leads to idiocies, forbidding for example:
int nameLength = myObject.getName().length()
being a technical violation which most of us do every day. Everybody also does:
mylist.get(0).doSomething();
which is technically a violation. But the reality is that none of these is a problem unless we actually allow outside code to affect the behaviour of the main object (Customer) based on the objects it has retrieved.
Summary
Here is what your code should look like:
public class Customer {
private class InternalContactInfo {
public ContactInfo createContactinfo() {
//creates a ContactInfo based on its own values...
}
//Etc....
}
private String name;
private InternalContactInfo primaryAddress;
//Etc...
public Contactinfo getPrimaryAddress() {
// copies the info from InternalContactInfo to a new object
return primaryAddress.createContactInfo();
}
//Etc...
}
public class ContactInfo {
// Not modifiable
private String phoneNumber;
private String emailAddress;
//Etc...
public getPhoneNumber() { return phoneNumber; }
public getEmailAddress() { return emailAddress; }
//Etc...
}
}
How about making another class with the name like CustomerInformationProvider. You can pass Your Customer object as a constructor parameter to his new class. And then You can write all the specific methods for getting phones, adresses etc inside of this class, meanwhile leaving Customer class clean.

Methods using private members or public accessors

I realize this probably cannot be answered, but I'm looking for whether there is some sort of guidance about whether to use private members directly or public accessors inside class methods.
For example, consider the following code (in Java, but it would look very similar in C++):
public class Matrix {
// Private Members
private int[][] e;
private int numRows;
private int numCols;
// Accessors
public int rows(){ return this.numRows; }
public int cols(){ return this.numCols; }
// Class Methods
// ...
public void printDimensions()
{
// [A] Using private members
System.out.format("Matrix[%d*%d]\n", this.numRows, this.numCols);
// [B] Using accessors
System.out.format("Matrix[%d*%d]\n", this.rows(), this.cols());
}
The printDimensions() function illustrates two ways to get the same information, [A] using private members (this.numRows, this.numCols) or [B] via accessors (this.rows(), this.cols()).
On one hand, you may prefer using the accessors since there is no way you could inadvertently change the value of the private member variables. On the other, you may prefer accessing the private members directly in hopes that it would remove the unnecessary function call.
I guess my question is, is either the de-facto standard or preferred?
It's a style call. I prefer to use accessors, because IMHO the function call overhead is small enough that in most cases it doesn't matter, and this usage preserves the data abstraction. If i later want to change the way the data is stored, i only need to change the accessors, instead of hunting for all the places where i touched the variables.
I don't feel strongly about it, though, and i would break this "rule" if i thought i had a good reason to.
IMHO, accessors are more a matter of structure and data management rather than accessors per se. Sometimes, you need to preprocess some data before returning it. Think about this example:
public class Foo {
private List<Bar> bars = null;
//Methods and stuff
public List<Bar> getBars() {
if(bars == null)
bars = SomeClass.loadBars();
// You can also use
// setBars(SomeClass.loadBars());
return bars;
}
}
In this case, your getter is not only wrapping your field, but returning an initialized field whenever you invoke it. Using the accessors inside a class gives the same benefits that for outsiders, you abstract yourself from the particular details of a field and you can obtain it after processing it.
On the other hand, if your field is returned directly (say, a String) it doesn't matter if you use a get or you don't, but you might want to use a get to respect a standard in your code.
In the end, it all boils down to coding style.
I have other objects, including subclasses of the object, use the accessors, but have the object itself use the fields. That way there is a clear distinction between the internals and the interface with the rest of the world. Hiding the contents of the class from itself seems unnecessary and potentially confusing. If something really benefits from having its implementation hidden from other parts of the object then break it out into a separate object.

Set, Get and Constructors in Java

Despite Java tutorials, Wikipedia searches, stackoverflow trolling, and hours of reading code samples, constructors still confuse the crap out of me. I've got three related questions that I've been trying to answer to help ME understand constructors a little better.
First, I've been under the impression that constructors need to be named the same as their classes. Consider:
public class Money {
public Money(long l) {
this.value = l;
}
public Money(String s) {
this.value = toLong(s);
}
public long getLong() {
return this.value;
}
public String getString() {
return toString(this.value);
}
}
I see this as four constructors...correct? So it appears that constructors not named the same as the class which contains them allowable. Can someone confirm that?
Second, I seem to have a block against understanding the set and get methods. Consider:
public class GetSetSample {
public int getFoo() {
return int Foo;
}
public void setFoo(int fooValue) {
int Foo = fooValue;
}
}
Why can't I just do this:
public class getFoo(int fooValue){
foo=fooValue;
}
and use foo = getFoo(12) from some other class/method?
The third question is a little more esoteric, but will help me conceive of the bigger picture...which is my learning style, and conducive to my ability to trace program flow when debugging. The get and set methods suggest a "to" and "from" relationship to me. e.g., Passing a value "to" a constructor, receiving the result "from" the get method. It seems to me though that the "to" and "from" will change depending on your perspective. I think that any setMethod is setting parameters for an object, even though the variable comes FROM another class or method, and the GetMethod is getting the resulting object (say, this.foo) with the appropriately set parameter. No matter where the get or set is used, in a main method or a standalone class with a single constructor, 'set' is always associated with sending a parameter and get is always associated with receiving an object with that parameter. Is that a good understanding? or am I missing a vital part?
Question 1:
I see this as four constructors...correct?
No, that class has two constructors and two methods. (getLong and getString are the methods.)
Question 2:
Why can't I just do this:
public class getFoo(int fooValue){
foo=fooValue;
}
Well, that's trying to declare a class with parameters, and also you're setting a value in a get method, which would be extremely weird. It's not clear what you're trying to achieve here, but that code is thoroughly invalid.
Question 3:
The get and set methods suggest a "to" and "from" relationship to me.
Well it's not really a relationship IMO. A relationship suggests something longer term than either of these methods. A setter typically changes the state of an object in some way, and a getter typically just returns some aspect of the state of an object. It's not really clear what the rest of your explanation meant, because you're playing somewhat fast and loose with terminology. For example: "get is always associated with receiving an object with that parameter" doesn't really make sense to me. Objects don't have parameters, methods/constructors do - and getters can fetch primitive values or references...
I suspect you would benefit from reading the "Classes" part of the Java tutorial, which talks about constructors and methods.
Regarding the first answer, there's only 2 constructors. The difference is on how they are going to be called (called using a string will use the construction having a string has a parameter and called using a long will use the other one). So to answer, yes a constructor has the same name as the class.
The two constructors :
public Money(long l) {
this.value = l;
}
public Money(String s) {
this.value = toLong(s);
}
Regarding the second answer, getters ans setters are not meant to be classes. They are supposed to be within the class itself.
Consider this example which uses getter and setters to get ans set value for the printer class :
public class Printer {
#Inject #Informal Greeting greeting;
private String name;
private String salutation;
public void createSalutation() {
this.salutation = greeting.greet(name);
}
public String getSalutation() {
return salutation;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
A good read of this link could definitly help you out !
Java oriented-object principles
You've shown 2 constructors, which do need to have the same name as the class.
You've also shown two "getter" methods, which return the value of the class variable in the form requested by the user. You can also create "setter" methods, which are used to transfer values into class variables.
You use a constructor to create an object of a particular class, and optionally to set some or all of its internal state (that is, its member variables).
You use setters and getters to isolate the class variables from the outside world, so you don't need to allow other code to access them directly. Why? Because, before a setter updates a variable, it can verify that the new value is valid, and that the operation doesn't violate any or the rules (the "business logic") that are required for the class to work properly.
So you could add a setter and update the constructor to use it:
public Money(long l) {
setValue(l);
}
public Money(String s) {
setValue(toLong(s));
}
// Example setter that validates `l` by prohibiting negative values
public Money setValue(long l) {
if (l < 0) {
// Warn about negative values
}
this.value = l;
return this; // Return the current object to allow chaining; see below.
}
Note that a setter usually doesn't need to return a value (that is, it can be type void), but it's often helpful to return the object itself. That allows you to write code like this:
Money earnings = new Money().setValue(4).setOtherField("foo");
This creates an object of type Money, sets various attributes, and stores it in the variable earnings. Clearly, this isn't terribly useful for a simple class like this, but it can be very helpful for more complex classes:
Paycheck check = new Paycheck("MyCompany")
.setEmployee("YourName")
.setSalary(50,000)
.setPaySchedule(Schedule.BIWEEKLY)
.setAccountNumber("1234567")
.setDefaultTaxRate();
I would like to try to answer your implied conceptual questions -- you've already got plenty of examples of this and that, so I'm just going to try to explain. I have no doubt you have heard most of this -- maybe all of this -- before, but am not sure and not sure which parts.
Object-oriented programming centers mostly around objects; an object is an amalgamation of code and data. You define objects by writing a class, and you create one or more copies of the object defined by that class with the class constructor (called instantiating the class).
A parallel in other languages: you can have a data structure of related items and a set of subroutines that operate on that data structure. Think of a class as a way of collecting the items in that data structure and the subroutines that operate on it into one unit.
After you have invoked a constructor, you have a copy of the data defined in that class and a way to refer to that copy. By referring to that instance when you invoke a class method, you operate on that copy of the data with the methods defined in that class.
If you were to do this in a non-OO language, you could have a routine that created a copy of the data structure in memory and then only use the methods prescribed for it on that data structure. You could have a pointer to the copy in memory and pass that pointer as a parameter to every subroutine that operated on it, and in fact that's the way some pre-OO systems were programmed.
A constructor is similar to a method call that returns a value; it involves (or can involve) the execution of statements, and it always returns an object of that class. There are also differences between a constructor and a method; until the constructor completes, for instance, the object is not fully created and shouldn't have some methods invoked on it.
So I hope that helped; if there are conceptual things you still have questions about, perhaps something in here will help you form a specific question so we can explain things further.
Many people have found that if they have spent years learning languages such as COBOL and FORTRAN then changing to OO programming involves unlearning the old languages. I certainly found this when I first tackled C++ 20 years ago. From your description you are clearly struggling with the concepts and I sympathize.
I don't think there is a simple recipe. Practice at the simple examples and don't be disheartened. Don't be afraid to ask on SO - if the questions are clearly asked you will get a useful answer.
Get a good IDE (Eclipse, Netbeans, etc.) which allows you to "look inside" objects with the debugger. Hopefully at some stage things will click!
Question 1 - Basic Java Classes:
There's pretty much only 3 things you're going to find in a Java class
Field/attribute (Depending on your language of origin)
Method
Constructor (Which looks like a special kind of method)
Every class is going to have a class name that shares the name of the file it's located in. So to expand Money out a bit:
Money.java
----------
public class Money {
// This is a field/attribute
Long value;
// This is a constructor
public Money() {
this.value = Long(0L);
}
// This is a method
public Long getValue() {
return value;
}
// Another method
public void makeMoney(Long moreMoney) {
this.value = this.value + moreMoney;
}
} // Everything in here is part of the Money class
The only distinction between a constructor and a method is that a constructor has no specified return value, which is declared as a type right before the name of a potential method. Constructors do have to be named the same as the class they are contained in, but why is implied in how they are written.
Another way of looking at it is if you remove all of the non-type related Java keywords (public, private etc., but not things like float and int) from the front of the method you're looking at (A list of which you can find here), is there anything left in front of the method?
With the Money we have at the moment, it would look like this:
Money()
Long getValue()
void makeMoney()
The constructor is the one that has no type for the return value, because it is implied in the declaration.
Question 2/3 - Get/Set methods:
I'm going to say something potentially controversial, but don't worry about these yet. Get/Set are essentially patterns for Object Oriented development, and generally good Java style, but they aren't required (Last I checked, Android development actually discourages their use when possible for optimization reasons). Moreover, not all fields in your objects will be accessible or mutable so writing them isn't mandatory.
If you declare all of your fields as public (Like the 'value' field is implied to be right now), you simple can do this:
Money myMoney = new Money(new Long(40L));
System.out.println(myMoney.value) // 40
myMoney.value = new Long(20L);
System.out.println(myMoney.value) // 20
Aside from that, the notion of get() and set() are just methods. There is nothing special about them at all. The main reason they exist is because for general Object-Oriented programming, you shouldn't have to directly modify the internal workings of an object (This is the principle of Encapsulation). Everything you should need to affect state or get something out of it should be handled by a method.
In a pithy one-liner: If you need to know the fields of an object to use it, you designed it incorrectly.
Big Picture
So what get() and set() really are is a pair of commonly written methods that happen to affect a field in an object in an extremely simple way (get() is a simple access to a field, set() is assignment to that field). It's just that other methods you write will happen to do more complicated stuff than that.

Categories