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.
Related
I want to make a getter that doesn't allow the caller to edit the returned object.
Using a List as an example (though I would like the answer to apply to any other type as well), this is the usual approach for returning and for editing an attribute:
class MyClass {
private List<String> strings;
// to get the whole object
public List<String> getStrings() {
return this.strings;
}
// to alter the object
public void addString(String newStr) {
this.strings.add(newStr);
}
//...
}
However, this doesn't prevent that some other class from doing this
myClassInstance.getStrings().add("that's a dumb implementation, bro");
and that would be kind of rude since I created addString() for that specific purpose.
I would rather if other classes would only use the getStrings() method for reading, because there might be a similar case where I don't want to implement the addString() method. In that situation, other classes are able to edit strings anyway through the getter, but I still want to be able to edit the object privately in the C class.
I know this wouldn't be a problem if the attribute was a primitive type since those are saved directly in the instance, but objects are references to memory, so any class that's able to get its hands on those references can edit it if the object type allows that.
Can I just trust that other classes won't try to edit my object through the getter?
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
Also, should objects provide a method that returns a non-writeable clone of the object to solve this?
You can have getStrings return an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(this.strings);
}
https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)
Can I just trust that other classes won't try to edit my object through the getter?
No.
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
The oracle docs provide a proposed strategy:
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods. (https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html)
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
In this case not (see Micky Loo's answer). However in a more special case yes (if you have to guarantee immutableness and can not copy the object).
Also, should objects provide a method that returns a non-writable clone of the object to solve this?
You can not create a const return value in Java. see: Const return values in 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);
Say I have some class:
public class A {
private int val = 0;
public int getVal() {
return val;
}
public void addFrom(A otherA) {
this.val += otherA.val;
if (otherA.val > 0)
otherA.val = 0;
else
otherA = Math.abs(otherA.val);
}
}
Should I be using getter methods instead to use otherA's val variable? Is it better style to do so?
Edit: This is a very simplified version of a class that takes much too long to read. But assume that there IS lazy initialization going on, that there are other methods that access this class, etc. I have updated the example method so that this may be more clear, but I hope it is clear that my question involves accessing the other object's variables, and want to know if it is faux pas to use a direct variable access for something that is not "this".
No, absolutely not.
You should use the variable directly when you're inside the class' members, and use getters in every other situation (when you would get an error because val is private anyway).
public int getVal() is intended to present your gift(variable) within a box to the outside world (encapsulation). Do you give gifts yourself in a box? It's weird, so use the variable as it is.
You can use variables, but the current code does not compile. Probably, the return should be int instead of boolean.
Probably, your intention is to override the compareTo method from the Comparable interface
Adding an unnecessary getter reveals internal structure and this is an opportunity for increased coupling.
A truly well-encapsulated class has no setters and preferably no getters either. Rather than asking a class for some data and then compute something with it, the class should be responsible to compute something with its data and then return the result.
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. 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. A class should expose larger behavior which happens to use its state, rather than a repository of state to be manipulated by other classes.
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.
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.