Java - should I use new() in Setters or not? - java

I see that a default setX function just uses X = _x, but in Java wouldn't it be just a reference to the _x object?
Shouldn't I use X = new X(_x) instead?
I truly looked for an answer, and haven't found one.

To be semantically correct, _x isn't an object, it's a parameter, and it's referring to an object. And yes, afterwards your X will be a copy of that reference, so it will point to the same object.
But usually that is exactly what you want to achieve. You don't want to spawn new objects whenever you set a value. And often you explicitly want it to be exactly the same object.
It's only if the calling site considers its version of the object as private property, that it's its responsability to produce and set a copy instead.

The name setter implies: setting a field.
That method isn't called storeCopyOf(), is it?
Of course you can use new (in case the corresponding class offers a copy constructor), but doing so in a setter is not common practice. And as shown, doing so is very misleading given the meaning that the name setX() communicates.

Shouldn't I use X = new X(_x) instead?
No, you shouldn't. A user of your API expects to set exactly the given instance, not a copy of it.
You could validate this incoming instance by throwing an exception if it doesn't fit your needs, but it's really unclear to set a copy.
Probably, you may want to return a value from a getter by using this approach. Returning a copy of an inner field (of a reference type) is a good technique to maintain immutability.

We use setter (and getter) method to implement encapsulation.
Example :
private String myField; //"private" means access to this is restricted
public String getMyField()
{
//include validation, logic, logging or whatever you like here
return this.myField;
}
public void setMyField(String value)
{
//include more logic
this.myField = value;
}
Someone who is using your APIs, will pass these value according to need, like :
obj.setMyField("myvalue");

If x is a primitive type, then there is no need to recreate the value with a copy constructor as changes to its value elsewhere won't affect the local copy.
If you are setting a mutable (changeable) object, but you don't want your copy changed, then yes you should use a copy constructor in your setter. However I'd hesitate to call that setting, it's more like a saveCopy(_x);

Related

Can I use setter method for a replacement of final variable In the following way

Most of us understand the consequences of shared mutability, and it is said that always prefer immutability(final modifier, set once and you can't change it) if you have a chance. I have seen few coding examples where People are actually making fields final or setters as private or even removing setters for a class (which can be DTO, Model or Entity class) and another class (a builder class which can set values once to that immutable class) is used to create and set fields of the Immutable class To ensure no other class is able to modify the state. Which seems a burden to me. SO I have come-up with this thought (below I am giving an example)
public class TestDataClass {
private String name;
public String getName() {
return name;
}
public void setName(Supplier<String> supplier) throws Exception {
if(Objects.isNull(name))
{this.name = supplier.get();return;}
throw new Exception("This field is immutable and already has a value "+this.name);
}
}
In this way either you can set values through setter like this objectOfTestDataClass.setName(() -> {return Perform_Desired_Logic;});
or
objectOfTestDataClass.setName(() ->"My Name"); if it is plain setter. Then also you dont have to create a bulder class or make setters private or omit setter method
In this way, I can get rid of variable initialization during Instantiation also once you set fields to become Immutable(I am not considering reflection).
I want your expert opinion to validate how legitimate is my thought, Can I consider this as Immutability? Am I missing something? in that case please correct me.
There are several things to note
Using a Supplier<String> instead of a String does not improve the code. There are only two cases, the intended case where the method is only executed once and the code of the supplier gets executed immediately and the erroneous case, where the supplier does not get executed, but where’s the sense in optimizing the erroneous case?
If a particular property supports being null, that approach fails to handle the case when it should be fixed to `null.
The API signature does not indicate that the class should be treated like immutable. Most readers will assume that it is mutable. So they may try to modify the object and not even notice the error if you’re going to remove the exception throwing statement, as said in a comment.
Immutable objects created by a builder are definitely completed and truly immutable once build. In contrast, your class allows the creator to forget setting some properties to fixed values, producing an actually mutable object.
Since instances of this class are not guaranteed to be immutable, they also do not have the guaranty to be thread safe that is usually associated with immutable objects.
What you wrote allows to not set more than one time a field of an object.
But it is not a way to create object with a fully initialized state as a constructor or a builder can provide.
So, if the client manipulates the object with a not complete or corrupted state, it could not work as expected.
Besides, providing setters that may be invoked by the clients at compile time but which the misuses would be known only at runtime (by throwing an exception) is not a friendly and good designed API.
Example of issue with an object that has a not complete state.
Take a Rectangle class.
It is composed of 4 mandatory information (height, weight, x and y coordinates).
These are represented by 4 instance fields :
int x, int y, int width, int height
Suppose the class provides an instance method boolean contains(Point p) to determinate if a Point (x, y coordinates) is included in it.
If you apply your method to value fields of this class, you may create Rectangle instances with incomplete/partial state.
The contains() method could not work. It should perform different checks and if a field is missing in Rectangle, it should may be even throw an exception.
Example of issue with an object which the state may be corrupted
If your object may be manipulated by multiple threads, using your way to value the fields of the object may set the object in an unexpected and inconsistent state.
Two threads may manipulate the object at the same time and changing two fields that should not be changed in this way.
To avoid it, you are forced to use explicit synchronization mechanisms for both reading and writing of fields.
Ii you use a constructor or a builder, you have not these problems as you get out of the box a complete, unmodifiable (de facto thread-safe) object with a clear API.

Const function arguments in java?

Is there a way to achive something similar to C++'s const in Java? Specifically, I have a function like
private static Vector2 sum(Vector2 vec1, Vector2 vec2) {
return vec1.cpy().add(vec2);
}
and I want to
make clear in the signature that it doesn't modify it's arguments,
and
enforce that it doesn't modify it's arguments (preferably at compile time, but inserting runtime assertions would also be OK).
Now I know that java is strictly pass-by-reference (I'm just teasing, I know it is pass-by-value or rather pass-by-copying-a-reference of course). What I mean is that in Java, when you call a method, the reference is copied, but that reference points to the same object contents. If a class has public fields or setters, a called method can always modify the contents of a passed object. Is there any e.g. annotation like #NotNull or tool to prevent this? I just found the JetBrains annotations like #Contract(pure = true), but I don't think they provide any checking.
You can not guarantee that method won't change the parameters. If you want to avoid changing the object, you should make it immutable. You can use some wrapper classes to be passed inside, without provided setters. Or you can make your setters package-local and use some access helper classes in the same package if you need to call some package-local method.
In Java the only way to do this is to have a read only interface as well as a mutable one. This isn't easy to maintain and a const would be much nicer, but it's not available. You can write
interface ReadOnlyVector<T> {
int size();
// getter methods
T get(int n);
default ReadOnlyVector<T> add(ReadOnlyVector<T> v) {
// add two vectors and create a new one.
}
}
interface Vector<T> extends ReadOnlyVector<T> {
// mutating methods.
void add(T t);
}
You can add final to the parameter, but this will only prevent a initialisation of those, you still can call method and setter modifying the content of your Vector.
If you need the restrict the access to those, you might need to create a immutable class hiding the Vector, a wrapper. Basicly it will redirect only the methods that prevent any update by hiding the setter and limit the getter to primitive values, returning an instance give a possibility to change a value in it.
Of course, there is also some drastic solution, you could clone the Vector and his content. Keeping the instances safe even if someone try to update some values. This will only be a problem during this call, using wrong values but will keep the original instances unchanged.
Or you could use both solution, creating a wrapper that return cloned instance (just need to provide a get(int index) that return a clone). This solution is a compromise between memory consumption (cloning only needed instance) and restrictive getter.

No arg constructor or arg constructor

In my program I read a fixed length file, stored each string in a local variable, and then stored every value into a class type array list. For creating the object of an array list, I used argument constructor with all the variables. The below code demonstrates this.
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel(a,b);
ArrayList<SampleModel> sampleList = new ArrayList<>();
sampleList.add(sm);
I find this absolutely right but my colleague asked me to change it to a no arg constructor and call getters and setters instead. That would be like below.
SampleModel sm = new SampleModel();
ArrayList<SampleModel> sampleList = new ArrayList<>();
String a = "text1";
String b = "text2";
sm.setA(a);
sm.setB(b);
sampleList.add(sm);
Is there any reason to prefer a no arg constructor over argument constructor? (My program has around 15 variables)
It depends on how the class will be used.
For example, an immutable class will need a constructor that takes arguments, and no setters.
But a Java Bean will need a no-argument constructor, and setters.
Some things to consider:
Encapsulation can be valuable. Other than special cases like JavaBeans, usually the interface of the class can be designed based on the desired interactions, not on the current set of data members.
Methods have names. Java does not support named arguments. Method names communicate how an actual parameter is being used, in the calling code. If your class has more than a handful of parameters, passing them via methods can result in more readable calling code.
Immutable classes have value. If you're adding named setters directly in your class, it won't be immutable. The builder pattern allows you to accept construction parameters even for immutable classes.
Whether I use accessors and mutators for a class variable depends on two things:
Whether the variable is essential or optional to the object.
Whether it might ever change in the course of using the object, or whether it is final.
Variables that are necessary and final should be in the constructor, in my opinion, and should not have mutators. Variables that are optional should have accessors and mutators. Variables that are essential but might change are up to your discretion. I would probably put them in the constructor, but use a Builder design pattern to avoid having a long list of arguments for the constructor.
A constructor that takes arguments is essentially for convenience (although that's not always the case if the object requires arguments in order to be constructed properly, it is here without seeing anymore context); it's doing the exact same thing as the set methods are doing.
There is no reason to not have a constructor take arguments, as long as those arguments "make sense" in the context of the object. In other words, it's more of a semantics thing to consider than a correctness thing.
If the constructor is:
public SampleModel(String a, String b)
{
this.a = a;
this.b = b;
}
It probably doesn't make a difference.
It might just be that it's easier to see whats going on than having a large comma separated list. This might also be a nice place to use Double Brace Initialization:
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel() {{
setA(a);
setB(b);
}};
ArrayList<SampleModel> sampleList = new ArrayList<>() {{
add(sm);
}};
Quotation from Fowler and Beck book: "Refactoring"
Long Parameter List
In our early programming days we were taught to pass in as parameters everything needed by a routine. This was understandable because the alternative was global data, and global data is evil and usually painful. Objects change this situation because if you don't have something you need, you can always ask another object to get it for you. Thus with objects you don't pass in everything the method needs; instead you pass enough so that the method can get to everything it needs. A lot of what a method needs is available on the method's host class. In object-oriented programs parameter lists tend to be much smaller than in traditional programs. This is good because long parameter lists are hard to understand, because they become inconsistent and difficult to use, and because you are forever changing them as you need more data. Most changes are removed by passing objects because you are much more likely to need to make only a couple of requests to get at a new piece of data. Use Replace Parameter with Method when you can get the data in one parameter by making a request of an object you already know about. This object might be a field or it might be another parameter. Use Preserve Whole Object to take a bunch of data gleaned from an object and replace it with the object itself. If you have several data items with no logical object, use Introduce Parameter Object. There is one important exception to making these changes. This is when you explicitly do not want to create a dependency from the called object to the larger object. In those cases unpacking data and sending it along as parameters is reasonable, but pay attention to the pain involved. If the parameter list is too long or changes too often, you need to rethink your dependency structure.

right way to pass objects in another object

Good morning, i'm learning java and i have a question.
I have a class "table" with a constructor, that accept a "fields", and put it in PRIVATE variable.
the question is: it is right to pass the object and use a "=" to put in the PRIVATE variable, or it's better to clone it?
if i use a "=", the variable inside my class are still editable from the method that used the constructor of the class, and eventually put NULL inside it.
for example:
class Table{
private Field field;
table (Field field)
{this.field=field;}
public String getValue()
{return field.toString(); }
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
and the result is "VALUE2".
So in the table passed a value, and then i alter it.
but for the "good programming art", it is acceptable, or is better
class Table{
private Field field;
table (Field field)
{this.field=field.clone();}
public String getValue()
{return field.toString();}
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
prints VALUE1
so if i pass a value to a Table, i can't modify it without using the Table methods?
what is the right way to to this?
This is a good question and points to a real problem. The recommended way to do this would be to have your classes immutable.
So the problem is not in the Table class, but in the Field class - it should only allow the modification of the value through the constructor, not through direct changes or with setters. Doing that you won't have this issue.
Declaring a variable private has nothing to do with its immutability. If the object passed to you is not immutable then I would suggest making a (deep) copy, otherwise you cannot rely on it not being changed elsewhere.
Other way would be making the Field class immutable, then you wouldn't have to make a copy, you would just save the reference in a private field.
There is no right or wrong way to do this in Java. Java passes objects by reference, and you need to understand that objects passed by reference are usually mutable, meaning they can change state. In Java, this is the expected behavior, but it can be confusing at first. It can also be very difficult to manage in a multi-threaded environment.
You do have the option, as #eis has indicated, to use immutable objects. There are many advantages to this, especially in multi-threaded code, but also some disadvantages. That discussion is too long and involved to get into here.
If you are concerned specifically with Java collections, the collections framework allows you to make a collection immutable. See the java.util.Collections.unmodifiable* methods for details on how to do that. Those methods can make an unmodifiable view of a collection without the overhead of cloning the data.
When you want the second object to see your original object over its lifetime, no matter how you change it, clone it before you pass it, or use an immutable object in the first place. When you want to ensure the second object cannot change your object, make it either immutable or use a read-only view as the Java collections do.
Good morning to you too.
I guess that you already know that Java is pass by reference value, so in the first case, table.field and field are "pointers" to the same object. Thus, modifying one will modify the other and viceversa. If that is what you want in this case then your first implementation would be correct.
On the other hand, if you just want to pass an object and you wouldn't be using the object field that you created, the following would be better suited:
Table table(new Field("Value 1"));
Lastly, if you just want to pass the value and you field and table.field referencing different objects that happen to have the same value. Modifying one won't modify the other. The clone() method is a valid solution, but not all classes implement this method. If the class Field didn't support the method clone(), your best bet is to implement a method similar to this in the Field class:
class Field {
//...Your code...
//First possibility
public void copyField(Field originalField) {
this.atribute1 = originalField.attribute1;
this.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
//Second possibility (a static method)
public static void copyField(Field newField, Field originalField) {
newField.atribute1 = originalField.attribute1;
newField.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
}
//**Using each method to make a copy of field1 in field2**
Field field1 = new Field(...);
Field field2 = new Field();
field2.copyField(field1); //Non-static method
Field.copyField(field1, field2); //Static method
Yet another solution would be to make a copy constructor which would be almost exactly the same as the non-static method:
public Field(Field fieldToCopy) {
this.atribute1 = fieldToCopy.attribute1;
this.atribute2 = fieldToCopy.attribute2;
//...
}
As you can see there are several correct ways to do this. You need to be able to chose and implement any of them depending on the particular problem you are solving.

making a class immutable in java

To make a class immutable what I can do is:
1)Make class final
2)do not provide setters
3)mark all variables as final
But if my class has another object of some other class then , somone can change value of that object
class MyClass{
final int a;
final OtherClass other
MyClass(int a ,OtherClass other){
this.a = a;
this.other = other;
}
int getA(){
return a;
}
OtherClass getOther(){
return other;
}
public static void main(String ags[]){
MyClass m = new Myclass(1,new OtherClass);
Other o = m.getOther();
o.setSomething(xyz) ; //This is the problem ,How to prevent this?
}
}
A) Make the OtherClass immutable as well
or
B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.
Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.
Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:
No way for an external user to change the value of the object
A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result
Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).
So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:
Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.
All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)
I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.
If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.
Return deep clones from your getters. You may find this to be no easy task.
All the objects referenced in the immutable class should be immutable, or at least be encapsulated as private and making sure that they are not modified (not inside the methods of your class and definitely not from the outside). For instance, if you have this situation:
public class MyImmutable {
private MutableClass mutableObject;
}
... You can not provide the getMutableObject() method, because doing so will open the door for outside modifications, like this:
myImmutable.getMutableObject().setSomeAttribute(newValue);
As a special case of the above, all collections and/or maps should be made immutable, with the ummodifiableXXX() methods in the Collections class.
you cannot (reasonably) stop that in java. if you don't have control over the other class, there are ways to effectively get immutable behavior, but it can be very expensive in practice. basically, you must always return a copy of that class in any public method return values. (the jdk actually has this problem with the TimeZone class).
But If my class has another object of some other class then , somone
can change value of that object...
Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.
One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.
It is possible to create the immutable class in java by following ways
1.Don't Provide setter methods.
2.Make all fields are as final and private.
3.Make Class as final.

Categories