I want to know the difference between these two codes even though they produce the same output:
CODE 1:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return x;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
CODE 2:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return 0;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
They both output 15 but how come the second code also output's 15 instead of zero?My understanding is that the last call would be add(0) for code 2 and it would return zero.I also want to know is it okay to use multiple return statements or use a single return statement and replace the rest with local variables.I remember reading that single entry single exit model is a good practice.
This is a recursive method, so when x != 0, you will return the result of "x added to calling the method again with (x-1)". The final call will always return x == 0 or constant = 0, so you will return 15 from both versions.
Single return vs. multiple return is a matter of debate. The former should be preferred as a rule. Generally it will be obvious where multiple return statements are acceptable as it will be simpler to understand the method with them than with the alternative code constructs required to engineer a single exit point. Also note you could rewrite add as:
public static int add(int x) {
return x == 0 ? 0 : (x + add(x-1));
}
Version 1:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (x = 0)
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
Version 2:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (constant = 0) // the only difference
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
The use of multiple return statement versus using a single exit point cannot be answered with an easy one-line answer. I guess the best answer you can get is "it depends on your company's standards".
Single exit point is a very good standard, even though I don't personally endorse it. You end up having methods that always have a single return statement at the end, so you never get in a position where you are looking for those many possible return statement while editing someone else's code. I believe that developers that used to code in C tend to follow this standard (see this question).
I, for one, perfer using multiple return statements when it can help simplify the code. One case where I like to use it is to prevent cascading braces in my code. For instance, in the following example:
private int doSomething (int param) {
int returnCode;
if (param >= 0) {
int someValue = param * CONSTANT_VALUE;
if (isWithinExpectedRange (someValue)) {
if (updateSomething (someValue)) {
returnCode = 0;
} else {
returnCode = -3;
}
} else {
returnCode = -2;
}
} else {
returnCode = -1;
}
return returnCode;
}
I find this type of coding to be very confusing when reading it. I tend to change this type of code to:
private int doSomething (int param) {
if (param < 0) {
return -1;
}
int someValue = param * CONSTANT_VALUE;
if (!isWithinExpectedRange (someValue)) {
return -2;
}
if (!updateSomething (someValue)) {
return -3;
}
return 0;
}
The second example looks cleaner, and clearer, to me. Even more when the actual code has some extra coding in the else blocks.
Again, this is personal tastes. Some company might enforce a single exit point, some might not, and some developers prefer single exit point. The bottom line is, if there's a guideline available for you to follow in your environment, then do so. If not, then you can chose your own preference base partly on these arguments.
Related
So Im creating a Helper method in Java to calculate postage based on size, but I can't seem to figure out the return part. Im still new to helper methods and accessors etc. Im using Eclipse and its telling me "Add return statement" but I did.. What am I doing wrong here?
Here is my code:
//Helper Method.
public int calculatePostageCost() {
double postCost;
if(satchelSize.equals("small"))
postCost = 10;
else if(satchelSize.equals("Medium") || satchelSize.equals("medium"))
postCost = 13;
else if(satchelSize.equalsIgnoreCase("Large") || satchelSize.equals("large"))
postCost = 17;
else {
return calculatePostageCost();
}
}
The problem is that you do not have a guaranteed return statement at the end of the function. What would happen if your function does not encounter a satchel size, which is either "small", "medium", etc, you will return the value of what your function calculatePostageCost returns (I will return to that later).
In every other case, however, you do not have a return in your function. When you encounter "small" as satchel size, you enter the first if block of code, where you will set postCost to 10, then you jump over the rest of the code (since it is all else if).
Most likely you are missing a statement like return postCode; below the else block. This would at least eliminate the error message from eclipse. I am not fully sure about your code, but you could have an endless recursion here. Your else block might be a problem:
else {
return calculatePostageCost();
}
You need to check if it is possible, that in the next call of this recursion, the else block will not be reached. When this is not the case, you will have an endless recursion everytime you enter this function while you are in a state where the satchel size is not "small", "medium", etc, because you won't have a chance to change the state and get out of these calls anymore.
Don't use strings to compare your size, create an enum to do that:
public enum Size {
SMALL, MEDIUM, LARGE
}
private Size satchelSize; ....
public int calculatePostageCost() {
switch(satchelSize) {
case SMALL:
return 10;
case MEDIUM:
return 13;
case LARGE:
return 17;
}
}
If you are very keen on keeping the strings you can switch on strings too:
private String stachelSize = ....;
public int calculatePostageCost() {
switch(satchelSize.toUpperCase()) {
case "SMALL":
return 10;
case "MEDIUM":
return 13;
case "LARGE":
return 17;
default:
throw new AssertionError("Don't know satchel size " + satchelSize);
}
}
Note that your original code had
else {
return calculatePostageCost();
}
Which would call the same function again, which would end up in the same else branch, calling the same function again, which would end up in the same else branch, which.... would eventually give a StackOverflowException.
(I understand that strictly it does not answer your question 'why doesn't this compile'.)
The problem is that your return statement is within the scope of the else statement ,it should be outside like this : `
public int calculatePostageCost() {
double postCost;
if(satchelSize.equals("small"))
postCost = 10;
else if (satchelSize.equals("Medium") || satchelSize.equals("medium")){
postCost = 13;
else if(satchelSize.equalsIgnoreCase("Large") || satchelSize.equals("large"))
postCost = 17;
return postCost;
}
If you return calculatePostageCost() you create a recursive loop which causes a stack overflow error.
Do like this,
//Helper Method.
public int calculatePostageCost() {
int postCost = 5; // i don't know about default conndition, i am taking 5
if(satchelSize.equals("small"))
postCost = 10;
else if(satchelSize.equals("Medium") || satchelSize.equals("medium"))
postCost = 13;
else if(satchelSize.equalsIgnoreCase("Large") || satchelSize.equals("large"))
postCost = 17;
}
return postCost ;
}
You have to return value on every possible scenario. Right now you are returning (infinite recursion thus stak overflow will happen) only single in case if package is not small not medium nor large. You have to return value for every of this variants, like that:
public int calculatePostageCost() {
int postCost=1234; // default cost for not small nor medium nor large package
if(satchelSize.equals("small"))
postCost = 10;
else if(satchelSize.equals("Medium") || satchelSize.equals("medium"))
postCost = 13;
else if(satchelSize.equalsIgnoreCase("Large") || satchelSize.equals("large"))
postCost = 17;
return postCode
}
Or even better
public int calculatePostageCost() {
if(satchelSize.equalsIgnoreCase("small"))
return 10;
else if(satchelSize.equalsIgnoreCase("Medium"))
return 13
else if(satchelSize.equalsIgnoreCase("Large"))
return 17;
return 12345; // cos of non small, medium nor large package
}
I am being asked to learn Java very quickly and I am struggling with not only the verbose syntax but also the expected style and approach requirements.
Given a simple FizzBuzz challenge I produced the following code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n <= 30; n++) {
hit = false;
if (n % 3 == 0) {
System.out.print("Fizz");
hit = true;
}
if (n % 5 == 0) {
System.out.print("Buzz");
hit = true;
}
if (hit != true) {
System.out.print(n);
}
System.out.println();
}
}
}
Asked to refactor this code by the lead programmer and to consider possible future requirements and code managability issues I gave it some thought and produced the following refactored code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n < 30; n++) {
hit = false;
hit = (n % 3 == 0) ? writeAction("Fizz") : hit;
hit = (n % 5 == 0) ? writeAction("Buzz") : hit;
if ( ! hit)
System.out.print(n);
System.out.println();
}
}
private static boolean writeAction(String actionWord){
System.out.print(actionWord);
return true;
}
}
However, the guy who set this task has moved on quite quickly and I never got any feedback on this approach. Am I going in the right direction with this or have I regressed?. To me this should scale better and would be easier to modify. I have also considered that maybe he was expecting some sort of TDD approach? I am aware that I have no tests currently.
This site isn't for reviews, but in case your question gets moved, here is some feedback (from the "clean code" perspective):
your "main" code sits in a main() method. Makes re-using it very hard.
talking about re-use - various things in there prevent re-using it
you have some duplicated code in there
you are violating the single layer of abstraction principle
How I would write something along the lines of:
public class FizzBuzz {
private final OutputStream out;
public FizzBuzz(OutputStream out) {
this.out = out;
}
public void runFizzBuzzUpTo(int n) {
for (int i = 1; i < n; i++) {
if ( writeIfTrue(n % 3 == 0, "Fizz") ) {
continue;
}
if ( writeIfTrue(n % 5 == 0, "Buzz") ) {
continue;
}
out.println(n);
}
}
private boolean writeIfTrue(boolean toCheck, String word) {
if (toCheck) {
out.println(word);
}
return toCheck;
}
public static void main(String[] args) {
new FizzBuzz(System.out).runFizzBuzzUpto(30);
}
}
Things I changed:
made the output the "core" thing of a class
provided the possibility to run for arbitrary positive numbers
Stuff still missing:
"single layere of abstraction" is still not good
instead of fixing "30" in main() - one could check for exactly one argument passed to main() - which would then be used as parameter for runFizzBuzzUpTo()
Of course, the second code is more modular and easier to modify that way. I mostly don't prefer to write the if conditions in the short way...
The method writeAction could be void because you don't have to return anything.
But you have good ideas :)
I'm pretty new to java, but I'm trying to make a simulation of the finger game, 'Sticks', using my limited knowledge. This may not be the neatest, but if you're going to make a suggestion on me to do something, link a page explaining what that thing is, and I'll read it.
Ok, so the issue comes up basically when I call a method to decide who's turn it is and trying to return the value for the "count" up to 5, but it's not returning to main()
public static int TurnCalcBB(int PLH, int PRH, int BRH, int BLH, int Death)
{
//Attacking with bot Right hand
Random botAtk = new Random();
if(botAtk.nextInt(2) == 1 && PRH <= 5)
{
PRH = BRH + PRH;
JOptionPane.showMessageDialog(null,"Your right hand is now at " + PRH);
return PRH;
} else if(botAtk.nextInt(2) == 0 && PLH <= 5){
PLH = BRH + PLH;
JOptionPane.showMessageDialog(null, "Your left hand is now at " + PLH);
return PLH;
}
return Death;
}
Death is there because I was getting an error telling me that I always need to return SOMETHING so I'm returning a static value.
Basically, the problem is getting PLH (player left hand) or PRH (player right hand) to return to main. If I'm not wrong, they should return as their initial variable name (PL, and PR) with the returned value correct? If not, what can I do to fix this?
The code is a lot larger than this, and this issue is happening throughout the whole program, so I'm showing just 1 method and assuming they're all the same issue; the methods are almost all the same.
Also, while I'm typing a question already, is nextInt() the best way to do a random number generator? When I had it as nextInt(1) it was exclusively attacking the left hand, and when I switched it to nextInt(2) now it's attacking both, but occasionally the code... "crashes" (what I mean by crashes is that it generates a number outside of what the If statements are looking for). I obviously need to to generate either a 1 or a 2 (or 0 and 1 if 0 counts).
You can change your code to
public static Integer TurnCalcBB(int PLH, int PRH, int BRH, int BLH, int Death)
{
//Attacking with bot Right hand
Random botAtk = new Random();
if(botAtk.nextInt(2) == 1 && PRH <= 5)
{
PRH = BRH + PRH;
JOptionPane.showMessageDialog(null,"Your right hand is now at " + PRH);
return PRH;
} else if(botAtk.nextInt(2) == 0 && PLH <= 5){
PLH = BRH + PLH;
JOptionPane.showMessageDialog(null, "Your left hand is now at " + PLH);
return PLH;
}
return null;
}
NOTE: make sure you first check for null values where you call this function.
You are generating random number twice, this is why you can observe "strange" behvior.
Random botAtk = new Random();
if(botAtk.nextInt(2) == 1 && PRH <= 5) {
...
}
else if(botAtk.nextInt(2) == 0 && PLH <= 5) {
...
}
Try generating random only once:
Random botAtk = new Random();
boolean right = botAtk.nextInt(2) == 1; // flip coin only once
if(right && PRH <= 5) {
...
}
else if(!right && PLH <= 5) {
...
}
I know the answer will not get accepted, because there is an accepted one, but nevertheless:
I suspect that you have a wrong understanding of method parameter passing in Java.
What I read from your question and comments is that you expect this to work:
public static int psInt = 0;
static void main() {
int someNumber = 1;
int someOtherNumber = 5;
method1( someNumber, someOtherNumber );
// You expect "someNumber" to be 6 right now.
// But in fact, the value will be unchanged.
// What WILL work: psInt is 0 now
method3(); // this method will modify the static class var
// psInt is 5 now.
}
static void method1( int numParam, int someothervalue ){
numParam = numParam + someothervalue;
}
static void method2( int someNumber, int someothervalue ){
someNumber = someNumber + someothervalue; // <- same name won't work either!
}
public static void method3(){
psInt = 5;
}
But in Java method arguments are passed by value. That is: a copy!
So no matter how you name the variables and arguments, you will never have an "out" argument here.
What you can do:
In a static method, you can use and modify static class variables.
In a non-static method, you can use and modify non-static and static class variables.
You can pass a State-Object, of which you can modify field values.
You can return a value.
... there are more possibilites. These just to start with.
In your case, 4. does not make so much sense, because you wouldn't know if it is the new right or left hand value.
I want to display an error if more than one of the four variables is set...
In Java..this is what I came up with..
if( (isAset() && isBset()) || (isBset() && isCset()) || (isCset() && isDset()) || (isDset() && isAset()) )
attri.greedySelectionException(..);
I wanted to check if there is a better way of doing this..?
How about you use a counter and then compare it to 1?
Something like...
int i = 0;
if (isAset()) i++;
if (isBset()) i++;
if (isCset()) i++;
if (isDset()) i++;
if (i > 1)
...
Alternatively, if you are checking properties of a certain object, you could use some reflection to iterate through the relevant properties instead of having one if statement per property.
Edit: Take a look at Marius Žilėnas's varargs static method below for some tidier code, i.e. using (changed the oldschool for to a for-each and the ternary expression for an if):
static int trueCount(boolean... booleans) {
int sum = 0;
for (boolean b : booleans) {
if (b) {
sum++;
}
}
return sum;
}
instead of several if statements.
You can simplify this expression with :
if((isAset() || isCset()) && (isBset() || isDset()))
attri.greedySelectionException(..);
Wolfram alpha made the work for you :
Original expression
You can verify with the truth tables :
Original
Final
In Java 8 you can solve this problem with Streams in an elegant way (assuming your values are null if they are not set):
if (Stream.of(valueA, valueB, valueC, valueD).filter(Objects::nonNull).count() != 1) {
/* throw error */
}
If you have control on the implementation of isAset(), isBSet, isCSet, & isDset methods, you can achieve this with much more clarity if you return 1 or 0 instead of true or fales from this functions. These functions are to be created as below...
public int isAset()
{
return (A != null) ? 1 : 0;
}
To verify if more than one variable is set use use something like below...
if( isASet() + isBSet() + isCSet() + isDSet() > 1)
ThrowMoreAreSetException()
If you don't have control on this here is another way of doing it...
int count = isASet() ? 1 : 0;
count+= isBSet() ? 1 : 0;
count+= isCSet() ? 1 : 0;
count+= isDSet() ? 1 : 0;
if(count > 1)
ThrowMoreAreSetException()
By following either of these approches, code will be less clumsy and more readable than doing somany comparision combinations.
I suggest using varargs ... (see Java tutorial) and make a function that calculates how many trues was given. The following code to demonstrates it:
public class Values
{
public static boolean isASet()
{
return false;
}
public static boolean isBSet()
{
return true;
}
public static boolean isCSet()
{
return true;
}
public static boolean isDSet()
{
return true;
}
public static int booleans(boolean... booleans)
{
int sum = 0;
for (int i = 0; i < booleans.length; i++)
{
sum += booleans[i] ? 1 : 0;
}
return sum;
}
public static void main(String[] args)
{
System.out.println(
booleans(isASet(), isBSet(), isCSet(), isDSet()));
if (1 < booleans(isASet(), isBSet(), isCSet(), isDSet()))
{
System.out.println("Condition met.");
}
}
}
Try this:
if (!(isAset ^ isBset ^ isCset ^ isDset))
This will true only is any one is true or else false.
I wrote these two methods to determine if a number is perfect. My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that.
The issue is with my main method. I tested the two test methods. I tried debugging and it gets stuck on the number 5, though I can't figure out why. Here is my code:
public class Lab6
{
public static void main (String[]args)
{
int testNum = 3;
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
}
public static int sum_of_divisors(int numDiv)
{
int count = 1;
int totalDivisors = 0;
while (count < numDiv)
if (numDiv%count == 0)
{
totalDivisors = totalDivisors + count;
count++;
}
else
count++;
return totalDivisors;
}
public static boolean is_perfect(int numPerfect)
{
int count = 1;
int totalPerfect = 0;
while (totalPerfect < numPerfect)
{
totalPerfect = totalPerfect + count;
count++;
}
if (numPerfect == totalPerfect)
return true;
else
return false;
}
}
Make
testNum%2 != 2
as
testNum%2 != 0
testNum=3
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
You may want to do 'testNum+=2' since you are concerned about only odd numbers and replace the testNum %2!=2 with testNum>0 or other stopping condition. Eventually your integers will overflow.
"My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that."
Do you mean between 3 & 2^32-1? It is not known that there are no odd perfect numbers.