Suppose I am writing a method foo(int i) in Java.
Since i is passed by value it is safe to change it in foo. For example
void foo(int i) {
i = i + 1; // change i
...
}
Is it considered good or bad practice to change arguments of methods in Java?
It's considered bad practice in general, though some people overlook it as you can see in the other answers.
For parameters like primitives that are directly passed in by value, there is no advantage in overriding the original variable. In this case you should make a copy as suggested by #João.
For parameters whose reference is passed in by value (objects), if you modify the handle to point to a different object, that is downright confusing. It's all the more important because modifying the contents of an object passed as a parameter will modify the original object too.
If you replace the object referred to by the handle, and then modify its contents, the object referred to by the original reference in the caller will not be replaced, but someone reading the code might expect it to be.
Whereas if you don't replace the object, and modify the contents, the method calling your method might not expect this change. This category generally comes under security-related bad practices.
It's merely a personal opinion, but I think it can be confusing for other people that may want to use the original parameter value later in that code, and may not notice that it has already been changed.
Plus, it's cheap to simply create another variable and assign it the modified value (i.e., int j = i + 1).
Since i is passed by value it is safe to change it foo()
It is absolutely safe even when you pass an object reference because they are local: i.e., assigning a new reference to the local reference will not have any impact on the original reference in the calling code
It's your personal choice. However i would not change the argument values as one might loose the track of the actual value passed in to this method.
What is important to note is that i = i + 1; does not really change i. It only changes your local copy of i (in other words, the i in the calling code won't change).
Based on that, it is a matter of readability and avoiding unexpected behaviour in your code by complying with the POLS (Principle Of Least Surprise).
Neutral. But it would be considered a better practice by many people to change the method to:
void foo(final int i) {
int j = i + 1; // not change i
...
}
Feel free to work either way.
Depends on context. I lean towards "bad practice", for two reasons:
Some people may think the original value is being changed.
It may make the code harder to reason about (mitigated with appropriately-short methods).
A third issue pops up when it's a reference value. If you modify the parameter reference to point at something else and change its state, the original won't be modified–this may or may not be what's intended. If you create another reference to the parameter and change the new reference's state, the parameter's reference will be changed–which also may or may not be what's intended.
Related
Programming noob here, so probably a dumb question, but there is no plus-equals (+=) operator for a ThreadLocal variable in Java, is there? This sort of thing works fine:
public static ThreadLocal<Double> tl = new ThreadLocal<>();
public double whatever;
//stuff here
double temp = tl.get()+whatever;
tl.set(temp);
Or replacing the last two lines with:
tl.set(tl.get()+whatever);
Just wanted to make sure there was no other way. It'd be nice if there were something like:
tl.add(whatever);
ThreadLocal can contain and work with object of any provided type, so method "add" just is not "generic" enough. You can set your object, you can get your object, and having reference to it you can do whatever you need, but it is out of ThreadLocal responsibility.
The reason you cannot perform the += operation is because in Java, primitives are passed as value not reference. What ends up happening when you call .get() is it returns a copy of the value being held not a pointer to the actual value. So changing the returned value will have no effect.
You will need to utilize the .set(tl.get()+x) idiom that you describe.
There is no operator overloading in Java. You can not do that. In the other hand in a language like C++ you could do it.
In deed, there is no add-method in class ThreadLocal. Look here.
I tend to think that most of the time that variable returning methods are invoked to assign the return value to a variable, e.g.:
return1 = object.DoSomething();
Nevertheless, Apart from executing the method: What happens when a returning method is invoked and the return value is not assigned to a variable? e.g:
object.DoSomething();
Is this a good practice? Where does the return goes?
JB Nizet made a remarkable comment stating that methods are implemented for most cases. Kind of explains why this situation occurs often.
People do it all the time. If you don't need the variable that the method returns, than you don't have to assign it to anything.
Bear in mind, that sometimes the return variable has some meaning, like whether or not the operation was successful, and you might want to do something with that information
I think this is valid. Unless you have a need to use the return value further down, it is better to ignore (You can save from code review tools flag as un-used variables).
Method execution and flow stays same, only thing is you are ignoring return value.
It is good practice or not depends on situation, for example if you have requirement like how many rows update on executing query, you need to capture return value, but most of the times developers ignore this because they don't need to track how many records were updated.
The method is invoked in the same fashion as it would when the return value is assigned to a variable.
This is a perfectly acceptable practice, and is a necessity when invoking void methods, which do not return values (and therefore cannot be assigned to objects).
- Its always better to use void as a return type where you don't want to assign or use the returned value.
- It won't cause any problem in its efficiency but will be considered as loose programming.
That code will compile and run perfectly normal.
I'm considering creating the following method:
public static MyBigCollection doSomeStuff(MyBigCollection m) { ... return m; }
and then in another method (perhaps in another class), using it like so:
MyBigCollection mbc = new MyBigCollection();
mbc = stuffClass.doSomeStuff(mbc);
Am I going about this the right way -- is this an efficient way to "do some stuff" to an object? I'd like to break off the stuff like so for extensibility. I've been doing c# for so long I'm just not sure with java. In c# the method could return void and I can simply call doSomeStuff(mbc) -- which would effectively pass my object by reference and do some stuff to it. I've been reading that java works differently so I wanted to check with the experts here.
I'd refactor to:
stuffClass.doSomeStuff(mbc);
(i.e., a method that modifies mbc and returns void)
Keep in mind that all Java Objects are stored in heap memory, and passed around with reference pointers.
The way you're doing it is fine, but you don't actually need to return the object at the end of the method. As such, the following would be simpler...
MyBigCollection mbc = new MyBigCollection();
stuffClass.doSomeStuff(mbc);
Objects in Java are passed by reference, so any modification on the mbc Object in the doSomeStuff() method would still be retained in the mbc variable after the end of the method call.
The only reason why you might consider returning the mbc Object is if you want the ability to join multiple methods together, such as this...
MyBigCollection mbc = new MyBigCollection();
mbc.doStuff1().doStuff2().doStuff3();
In this case, because mbc is returned by each of the doStuff() methods, the next method can be called straight back on to the same Object. Without returning the reference, you'd have to do something like this instead...
MyBigCollection mbc = new MyBigCollection();
mbc.doStuff1();
mbc.doStuff2();
mbc.doStuff3();
Which is the same thing, but not quite as compact. How you go about it really depends on how you intend to use the methods and the Object itself.
There's only one way to pass Java objects around. Java passes everything by value. Objects aren't passed; they live on the heap. You pass references around, not objects.
Same as C#, as far as I know.
This kind of micro-optimization is usually meaningless.
I think your question is around how Java passes references to objects. Java passes by value, which can be confusing when first said. For objects, this means that the value of the reference to the object is passed to the method. Interacting with the object referred to by the value will alter the object 'passed in', so you don't need to return it.
Strings are treated differently as they are immutable. Primitives are also pass by value, but as the value passed is not a reference, you will not alter the original variable.
The easiest way to test this is to write some code and observe (you might also consider the Java tutorials)
For example, is this code valid?.
class abc{
int x,y;
abc(int x,int y){
this.x=x;
this.y=y;
while(true)
update();
}
public void update(){
x--;
y--;
if(y==0)
this=null;
}
}
If the above is not valid, then please explain why. I am in need of a class that after certain iterations ceases to exist. Please suggest alternatives to the above approach.
No, this code is not valid.
Furthermore, I don't see what meaningful semantics it could have had if it were valid.
Please suggest alternatives to the above approach.
The object exists for as long as there are references to it. To make the object eligible for garbage collection you simply need to ensure that there are no references pointing to it (in your case, this should happen as soon as y reaches zero).
No. The reason is that you do not make object null. When you say obj = null; You just put null to variable that previously hold reference to object. There are probably a lot of other references to the same object.
I think that what you want to do is to kind of invalidate object and make it garbage collected but take this decision inside the class. If this is the problem I'd recommend you to take a look on weak references.
Other possible solution is to implement kind of "smart reference" in java. You can create your class SmartReference that will hold the real reference to the object. The object should hold callback to this smart reference and call its method invalidate() that is something like your syntactically wrong expression this = null. You have to care not to refer to such objects directly but only via smart reference.
The only question is "why do you want to do this?". Really, this will cause the code to be more complicated and unstable. Imagine: the object decides to invalidate itself, so the reference that "smart reference" is holding becomes null. Now all holders of this smart reference will get NPE when trying to use the object! This is exactly the reason the such mechanism does not exist in java and that application programmer cannot mange the memory directly.
Bottom line: remove all object references and let GC to do its hard job. Trust it. It knows to clean the garbage.
I think this is a good question.
I've had loads of cases where I'd like Objects to validate themselves after/during construction and if it finds reason to, to just return an empty value or go back up the stack and skip over creating that object.
Mostly in the case of where you are creating a list of objects from a list of other values. If a value is garbage and you want your object to recognise this.
Rather then have to code a function outside the Class itself to validate the creation, it would be much neater to allow the object to do it.
It's a shame java doesn't allow for things like this on the assumption the programmer is probably going to mess it up. If you code well it would be a nice feature.
I think you need to rethink why you want to do this, because what you're suggesting doesn't even exist as a concept in Java.
The this variable always refers to the object itself. You can't "nullify" an object, only a reference (since after all, what you're doing is assigning a reference to point to null instead of its previous object). It wouldn't make sense to do that with this, as it's always a pointer to the current object in scope.
Are you trying to force an object to be destroyed/garbage collected? If so, you can't do that while other parts of your code still have references to it (and if they don't have references, it will be garbage collected anyway).
What did you hope/think this would do, anyway?
your code must be get compile time error..
Coz..
The left-hand side of an assignment must be a variable
this is not a variable its a keyword..
this=null;
Under what circumstance would you use field variable instead of local variable? I found it a bit hard to decide when a variable is used in 2 or more methods in a class. I tend to use local variables and pass them to another method.
Thanks,
Sarah
In object-oriented terms, does the variable make sense as an attribute of the object? If so, you should make it a field variable. If not, it can go either way.
Remember the Single Responsibility Principle -- well-designed classes should have only 1 responsibility, and thus only 1 reason to change.
A field denotes some kind of state related to an instance of your class. For instance, a BankAccount could have a balance field.
You should never use a field to simplify passing data from one method to another method. That's simply not its purpose. Doing so also makes your methods intrinsically thread unsafe or require synchronization.
A local variable is just a temporary store of data used to support an operation being done by a method. For example,
public void addInterest(double rate) {
double toAdd = rate * balance;
logTransaction("Interest", toAdd);
balance += toAdd;
}
toAdd here makes no sense as a field since it is temporary to the operation, not a part of the account's state.
I would definitely not pass variables around to other methods unless there's a very specific reason. If the variable is used multiple times in the class, make it a field variable. This almost always makes your code much more flexible too.
In general, you can also think if the variable makes sense as a part of the class. That is, it makes sense to have a Car class have the variable numOfMiles, even if it's only used a few times. However, if one method is int GetAmountOfGasUsed(int milesThisTrip) it makes sense to pass in the miles variable as a local variable because the distance you travel is probably not specific to the car.
If the methods that use the variable need to modify the value as well, then by all means make it a field variable. But, if they only read the value, you can safely pass it around.