Scope of variable instantiated inside a method - Java - java

Is this code safe in Java?
public class HelloWorld {
public static void main (String args[]) {
HelloWorld h = new HelloWorld();
int y = h.getNumber(5);
int z = h.getNumber (6);
if (y == 10)
System.out.println("true");
}
public int getNumber(int x) {
int number = 5;
number = number + x;
return number;
}
}
My co-worker says that int number will be placed on the stack and when getNumber returns it will be popped off and could potentially be overwritten.
Is the same code potentially unsafe in C?

The HelloWorld class has no fields, and is therefore immutable. You can call your getNumber(x) function as many times as you'd like, from any thread, using the same object, and it will always give the same result for the same argument.
Maybe your co-worker is recalling horror stories in C where you can have something like static int number, which "belongs" to the method and which would get overwritten. Or maybe she's thinking about "return by reference"; even if it were, you'd be referencing a brand-new object every time because number is newly instantiated for every method call.

Your coworker is correct, sort of, but they apparently misunderstand what is going on.
public int getNumber(int x) {
int number = 5;
number = number + x;
return number;
}
Yes the value of 5 + 5 or 5 + 6 will be placed on the stack, but there is no danger of them being overwritten, they will properly be placed into y or z.
I suspect the confusion is from C (this type code works fine in C as well), but for pointers instead of primitives. Returning a result of malloc from a function in C can be "challenging" if you don't do it right.

Related

Does the program stop excuting once it returns something?

public int max1020(int a, int b) {
// First make it so the bigger value is in a
if (b > a) {
int temp = a;
a = b;
b = temp;
}
// Knowing a is bigger, just check a first
if (a >= 10 && a <= 20) return a;
if (b >= 10 && b <= 20) return b;
return 0;
}
so if both a and b are within the range [10,20], would it just return a, and stop excuting the next two lines of code?
so if both a and b are within the range [10,20], would it just return a, and stop executing the next two lines of code?
It first checks a, if it matches the first condition then the function is returned with the value of a. The next two lines of code will not be executed as the function has returned.
Does the program stop executing once it returns something?
No, the value is not returned by the whole program it is just returned by the particular function. Let me give you an example.
public class Main {
public static void main(String[] args) {
int result;
// The method max1020 returns the value of 'a' here
result = max1020(11,14);
System.out.println(result);
// The method max1020 returns the value of 'b' here
result = max1020(31,11);
System.out.println(result);
// The method max1020 returns the value of '0' here
result = max1020(50,60);
System.out.println(result);
}
private static int max1020(int a, int b) {
// First make it so the bigger value is in a
if (b > a) {
int temp = a;
a = b;
b = temp;
}
// Knowing a is bigger, just check a first
if (a >= 10 && a <= 20) return a;
if (b >= 10 && b <= 20) return b;
return 0;
}
}
The return keyword just gets you out of the function you are in, it does not get you out of your whole program. When you call the max1020() for the first time it returns a. See it returns the value of a but the program will still execute the other lines. It will print the value of the variable result then it'll again call the max1020() on another pair of values.
If both a and b are within the range [10,20] it will always return a.
You are correct, once a return statement is reached, it will not execute any further code.
You are correct in the assumption that the program checks if a is withing the range, and given that the result of the evaluation is true it will return the value bond to variable a.
In Java the keyword return means that the program will return the value associated with it and stops further execution.
As for your question about the void method. In Java and many other languages you have something called "state" which means that there exists some values outside of the current scope of execution, e.g in pseudocode
int a = 0
public void inc (){
a++
}
Method inc does not take any arguments (it has an arity of 0) but increments the variable a that is defined outside the scope of the function it self. Any method that has other return type than void returns the defined type.
I hope that my answer was helpful.
You seem to be mixing method return and program exit (which can also be called "program return code").
In a method, whenever the line return is reached, the method stops right there and will not execute further instructions.
When that method is the main method, it also is the entry-point of the program. Therefore, when the main calls return, the program will effectively stop, returning code 0 (which means "success").
In Java, you can also stop a program execution by calling System.exit(ret). In that particular case, the JVM process (which is "your program") will stop executing further instructions, even if return is not explicitly called (though some IDE will give you errors or warnings). The return code (seen by the caller process) will be the one you specified with ret.

Java - Why void when I'm storing value in variable

So, the question is. If I'm calling method guess from class - Player and it is a void-type method without return statement in it, how come I'm able to store result of number = (int)(Math.random() * 10) in number variable for 3 different objects (p1, p2, p3)?
I'm little confused about when should I use return statement or void-type methods, because if number = (int)(Math.random() * 10) is giving some results which I want to use, why then I don't need to return this results from a method to pass them to the number variable which I declared in int number = 0;
public class Player {
int number = 0;
public void guess() {
number = (int)(Math.random() * 10);
System.out.println("I'm guessing " + number);
}
}
A void method does not return anything, but it still allows you to do things. (Print to the console, modify variables etc) The void keyword just means that it doesn't return a value. (In void methods you can still use a blank return; to end the method) And because you are modifying your number variable in the GuessGame object the changes you make will stay even though you don't return a variable. Try this simple test to see what I mean:
//In your GuessGame class
int number = 0;
public void foo() {
number++;
}
public static void main(String[] args) {
GuessGames games = new GuessGames();
games.foo();
System.out.println(games.number);
//Outputs 1
}
docs for the return statement
The point is: where is the result of Math.random() * 10 physically stored on your computer when your program is run? You list two options.
Options 1: Instance field
In this case the compiler instructs your operating system to reserve space for a int variable for the whole life of the Player object. The player object may live for microseconds, seconds, minutes, hours, days, months, ... it depends! This storage space is usually find in the RAM of the computer and from Java you can access it with the syntax myPlayer.number as long as you have a Player reference somewhere.
Options 2: Return value
In this case the compiler finds the space to store the result of the computation in a register of the Java virtual machine, that you can mentally map to a register of the physical processor. This value will only at best survive for a couple of processor cycles (there are gazillinos in a GHz CPU, so it's really a tiny little fracion of a second) if you don't store it somewhere else - and if you don't it's lost forever. See the following example:
private int someRandom;
private int gimmeARandom() {
return Math.random() * 10;
}
private int test() {
int someRandom = gimmeARandom(); // --> store the value until end of method
this.someRandom = someRandom; // --> further keep it so we can read it later
gimmeARandom(); // --> what did it returned? We'll never know
}
Void is different than static - void just means the function does not return anything, but it can still be a instance method, i.e. one that is associated with each new instance of a class. I think you're confusing this with the functionality of static, which allows methods to be called without an instance of the class.

Why does this code result in these answers?

I am currently learning Java, and I'm trying to understand the logic behind math in Java. On old tests in this course, there have been problems like the ones below. I am then supposed to write out what this code is going to display. My problem is that I don't understand two of the numbers in both codes.
In the first test class, the integer Tal prints out as 15. Ok, I can follow the logic there.
It goes like this:
c.setNbrOf(4+1) = 5
int tal = c.getNbrOf()+10 = 15
BUT
When I apply the same logic to the second test class I get the wrong answer.
My logic goes:
c.setNbrOf(4+1) = 5
c2.setNbrOf(5) +1 = 6
Since Customer c = c2, this means c also has the value of 6 (?)
So, int tal = 6 + 5 which is 11.
It's not though. When I run it, it's 12.
Why does the ++tal in the method andra affect its value globally? I thought it was only local.
I hope I haven't been to unclear.
The customer class is needed to run the test class.
public class Customer {
private String name;
private int nbrOf;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name=name;
}
public int getNbrOf() {
return this.nbrOf;
}
public void setNbrOf (int nbrOf) {
this.nbrOf=nbrOf;
}
}
The first test class.
public class Test {
public static void main(String[] args) {
Customer c = new Customer();
c.setName("Kund1");
c.setNbrOf(4+1);
int tal = c.getNbrOf()+10;
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf());
foo(c, tal+3);
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf());
System.out.println("Tal: "+tal);
}
public static void foo(Customer p, int x) {
p.setName("Kund2");
p.setNbrOf(x);
x ++;
}
}
The second.
public class Test {
public static void main(String[] args) {
Customer c = new Customer();
c.setName("K1");
Customer c2 = c;
c.setNbrOf(4+1);
c2.setNbrOf(c.getNbrOf()+1);
int tal = c.getNbrOf()+5;
System.out.println("Namn: "+c.getName()+" ålder: "+c2.getNbrOf());
andra(c, ++tal);
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf()+",
"Tal: "+tal);
}
public static void andra(Customer p, int tal) {
p.setName("K2");
tal=9;
p.setNbrOf(tal);
}
}
When you write ++tal, it means tal = tal + 1; then return the new value of tal as a result. Hence, when you pass ++tal to a function, you have run two commands.
Also, you should be aware that setting value of tal inside andra function, is local and not changed the value of tal outside the function. Hence, the final value of tal after calling andra(c, ++tal) would be 12.
[EDIT] Fixed the incorrect part about pass by value and clone()
You are asking two questions so let's attach each one separately.
A) What is the value of c and c2 at specific points in the code.
To answer this you need to realize that just saying 'c = c2' doesn't tell the full story. You first create two instances of the Customer object and store the references to them in c and c2 respectively. When you assign c = c2 you are making both variable store the reference to the same (single) instance of Customer; the other will get garbage collected. Now, it is possible to change the state of the remaining object through method calls to either c OR c2 because they both refer to the same instance.
This means that
c.setNbrOf(4+1); // AAA
c2.setNbrOf(c.getNbrOf()+1); // BBB
changes the value of the same nbrOf member variable twice, it just looks like they are separate because you have made c an alias of c2 (or vice versa depending on how you want to look at it). After line AAA c.nbrOf does equal 5; to calculate what happens in line BBB you need to break the line up into its parts. Calling c2.setNbrOf() with an argument that is actually an expression of the sum of two things, the result of a call to c.getNbrOf() and the numeric literal '1'. The call to c.getNbrOf() returns 5 and the expression adds 1 to it before passing the result, 6, to the call of c2.setNbrOf(). Since c and c2 are aliases of each other you will get a result of '6' when you call getNbrOf using either c or c2 simply because they both point to the same instance.
B) Why does the ++tal in the method andra affect it's value globally?
Well, it doesn't affect the value globally, it only looks that way because again, you have run into an expression used as an argument to a method.
andra(c, ++tal); // CCC
The call to andra() does not pass '++tal' into the method, it evaluates the expression first, which actually increments tal by 1 in the local scope and then evaluates the value of tal to determine the value to be sent to the method call. This means that, yes, tal was 11 before the line CCC but during the evaluation of the arguments the variable's value was changed to 12 before the call is made. So why does the code print '12' when you can clearly see that
public static void andra(Customer p, int tal) {
p.setName("K2");
tal=9; // DDD
p.setNbrOf(tal);
}
line DDD should result in the value of p.nbrOf being 9? Well, yes, the value of p.nbrOf does get changed to '9' in the line following DDD, just as p.name gets changed to "K2". This leads to your question of why the code prints '12' instead of '9'. This is because of another thing you have to consider and that is scope. The method andra() actually creates a new storage location named 'tal' that is not the same location as the variable with the same name in main(), that is andra() is hiding the name 'tal' so that when it changes the value of 'tal' to 9 it is only changing the local variable and not the variable with the same name in the calling code.
I have to say that this sample code is doing several things to trip you up, which also means it's doing its job to help you understand the different ways the language handles its symbol table that can be confusing. The sample code isn't making it any better by using tal as a local variable in the test code AND as a parameter name in the methods, that is a poor practice but was used here to make the exercise more difficult.
Try this code to see what is actually happening.
// actually Test3 would be a better name, but I'll leave that to you
public class Test {
public static void main(String[] args) {
Customer c = new Customer();
c.setName("K1");
Customer c2 = c;
c.setNbrOf(4+1);
c2.setNbrOf(c.getNbrOf()+1);
int tal = c.getNbrOf()+5;
int tal2 = ++tal;
System.out.println("Namn: "+c.getName()+" ålder: "+c2.getNbrOf()+" reference to c:"+ c);
andra(c, tal2);
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf()+",
Tal: "+tal);
}
public static void andra(Customer p, int tal3) {
p.setName("K2");
tal3=9;
System.out.println("BEFORE - reference to p: "+p+" tal: "+tal3+" p.nbrOf:"+p.getNbrOf());
p.setNbrOf(tal3);
System.out.println("AFTER - reference to p: "+p+" tal: "+tal3+" p.nbrOf:"+p.getNbrOf());
}
}
This should show several things, the reference to p should be a different value than the reference held in c, using unique variable and parameter names should make it clearer about which variables are being evaluated or changed, and moving the ++tal expression to outside the method call should show how the variable is not being changed from within andra().
c = c2 - this line means that from now you want c to point to the same space in memory that holds c2. From now all changes in c or c2 will affect in the same change in the value of the other one (two different refferences point to the same object)
andra(c, ++tal);
is:
tal = tal + 1; //12
andra(c, tal);
andra(c, ++tal); is the same as:
tal = tal + 1;
andra(c, tal);
While andra(c, tal++); is similar to:
andra(c, tal);
tal = tal + 1;
The pre-increment and post-increment operators increment the value prior to (pre) or after (post) evaluating the expression. This is not a "local" vs "global" scope. It affects the scope of the variable that is within scope.
Also, in your andra method, you are explicitly setting tal = 9 so it ignores the passed argument.
since we actually only have one object here, we could ignore OO here and write it in plain math:
if c2 = c, then there is only one object, therefore only one NbrOf
c.setNbrOf(4+1);
NbrOf = 4 + 1 = 5
c2.setNbrOf(c.getNbrOf()+1);
NbrOf = NbrOf + 1 = 5 + 1 = 6
int tal = c.getNbrOf()+5;
int tal = NbrOf + 5 = 6 + 5 = 11;
andra(c, ++tal);
this increases tal by 1 and assigns that value to tal, its equivalent to
tal = tal + 1;
andra(c, tal);
however, the tal inside of andra(c, tal); is an copied value (all primitives are passed by copy, not by reference. So assigning tal=9 wont affect the outside tal! Rename it inside andra(c, tal); to make it easier to understand.
conclusion, tal = 12

fibonacci works in python but fails in Java

I have this code for calculating fibonacci number in python. It works and gives the expected result. but when I translated the same to Java, it fails. Any idea of what is going wrong here?
In python:
def fib3(n):
a,b=0,1
while n>0:
a,b=b,a+b
n-=1
return a
fib3(12) --> 144
In Java:
public static int fib2(int n){
int a = 0;
int b =1;
while(n-- >0){
a=b;
b=a+b;
}
return a;
}
fib2(12) --> 2048
In this section:
a=b;
b=a+b;
you're assigning b to a+b, but a is already b. So really you're doubling b
Easiest solution is a temp variable:
public static int fib2(int n){
int a = 0;
int b =1;
while(n-- >0){
int old_a;
old_a = a;
a=b;
b=old_a+b;
}
return a;
}
In python, a, b = b, a + b stores an intermediate tuple automatically before assigning the new values to the variables, while in Java you need to be explicit about it
Breaking down Python's instructions, a, b = b, a + b is executing this disassembly:
5 17 LOAD_FAST 1 (b)
20 LOAD_FAST 0 (a)
23 LOAD_FAST 1 (b)
26 BINARY_ADD
27 ROT_TWO
28 STORE_FAST 0 (a)
31 STORE_FAST 1 (b)
In a simpler sense, staying python, here's the process:
temp_tuple = (b, a + b)
a, b = temp_tuple
The issue is that you've got to one value from b to a at the same time as assigning to b the sum of a and b. Get that simultaneous swap wrong and you get the wrong answer.
In the spirit of the Python code, I present:
public static int fib(int n) {
int a = 0, b = 1;
while (n-->0)
b = a + (a = b);
return a;
}
This does the swap effectively at the same time as the add (strictly not, but it's good enough). Note that this is well-defined Java, as the language defines the evaluation order of operators precisely, unlike in C and C++ (where the equivalent of the above code is permitted to make demons fly out of your nose due to being Undefined Behavior).
OK, if it did make you experience problems with nasal demons, I'd suggest not using that compiler in future. But you wouldn't have any assurance of getting a correct fib() function…
a = b;
b = a+b;
This computes b = 2*b because a's value is overwritten by the time you compute the new value for b. Replace it with:
t = b;
b = a+b;
a = t
a=b;
b=a+b;
... is the problem. You need to save the old value of a before adding it to b.
The code is not equivalent, and relies on python's ability to assign multiple primitives in one line a,b=b,a+b; you need a temporary variable -
public static int fib2(int n){
int a = 0;
int b =1;
while(n-- >0){
int t = b; // <-- to hold the original value of b.
b = a + b;
a = t;
}
return a;
}
In java - When you write "a=b; b=a+b;" you are essentially saying that a should be equal to be and then that (since 'a' is now equal to 'b') that 'b' should just be twice what it originally was.
There are two ways you can fix this.
1) You can either continue the function you are originally using and then create a int 'temp' to store 'a' before you change 'a'.
2) You can also do what I would rather do ( this will use a lot more time however for a algorithm like fibonacci and would generally be a terrible idea for real world applications) is use a recursive function that will call itself.
It would generally look something like the following.
public static int fib2(int n){
if(n<=0){return 0;}
if(n<2){return 1;}
else{ return fib2(n-1)+fib2(n-2);}
}
That would probably not be the exact code but something very similar. Hope that was helpful!

Custom functions in Processing Language

doing some uni work on 'Processing' Programming language (a form of java).
So my question is 'Write a function called twoNumbers(int a,int b) which takes in two parameters a and b. If a is greater than b, then the two numbers are added together and the string 'the sum of a and b is sum' is displayed in the console window, where a and b and the sum are the values of a, b and their sum. Finally, the function should return the sum.'
..soo here is my attempt at the code, if I put (int a,int b) after the customer function, it just says that my other int a = number, is a duplicate, which is true, but im not sure how I am ment to give a and b a number without it thinking its a duplicate? Should I be putting it out of a void setup tag? as im unsure if this would then cause too many { brackets...
/* Question 1 */
int twoNumbers(){
int a = 30;
int b = 20;
if (a > b) {println(a+b);}
println("The sum of a and b is sum");
int sum;
sum = a+b;
println(sum);
}
Any help would be massively helpful in getting this and the other questions done :)
Thanks!!
Also your function is not returning a value, which will give you an error. It looks like you are confusing things. Either declare it a void or return a value of declared type (that last is what your assignment calls for). Either way a function, or a method, needs to be called to execute, and you are not calling it! So the code inside your the function is not being run!!
The following:
void imAMethod()
{
println("hello");
}
It is a valid method, but will do nothing, you need to call it, like:
imAMethod();// calling your method
void imAMethod()
{
println("hello");
}
But this won't work also, will give you the error "It looks like you're mixing "active" and "static" modes". Thats because to use a function in Processing you need to have at least a setup() method in the sketch, so:
void setup()
{
imAMethod();
}//end of setup
void imAMethod()
{
println("hello");
}
will work as expected.
But you need a function, so as Jesper pointed you will have to do something like:
int a = 30; // those are global variables to pass to your function
int b = 20;
void setup()// this is a builtin basic Processing method
{
//call your function
println("The sum of " + a + " and " + b + " is "+ twoNumbers(a, b));
}
int twoNumbers(int a, int b)
{
//do your math and tests here
return result;
}
There is another thing not clear in the assignment. A function must return something, so it is not clear what the function should return if a is not greater than b. You will have to handle this case, or compiler will complain. You may want to move this test out of the function to make things easier, like:
if (a < b)
println("The sum of " + a + " and " + b + " is "+ twoNumbers(a, b));//call your function
else
println(a + " is smaller than " + b);
and in the function just do the sum. But this may be not what the assignment requires... Anyway you will need to return something even if a is not greater than b. Note that the printing to console can be done inside the function also.
Hummm, re reading the assignment a think what is expected is: Aways return the sum, and just print if a is greater than b, which makes more sense and is easier, something like:
int twoNUmbers(int a, int b)
{
if (a < b){/*print the string*/}
return a + b;
}
Just a note for jlordo. In Processing.org you don't have a main, or better, it is transparent/hidden from user. Processing is like a "dialect" of java. So the code above would run as it is. There are two basic builtin functions: setup() and draw(). If the user do not use none of them the IDE will warps it in a setup() function, that will call the main() somewhere else. It will run once. Draw() instead loops forever.
'Write a function called twoNumbers(int a,int b) which takes in two parameters a and b.
That's not what your code looks like. Your method twoNumbers doesn't take two parameters a and b. Your code should start like this (exactly as mentioned in the assignment):
int twoNumbers(int a, int b) {
Remove the next two lines, int a = 30; and int b = 20;. Those lines declare two local variables named a and b. You should use the a and b that are passed in as parameters instead.
This also looks wrong:
if (a > b) {println(a+b);}
println("The sum of a and b is sum");
Carefully look at what the assignment says:
If a is greater than b, then the two numbers are added together and the string 'the sum of a and b is sum' is displayed in the console window, where a and b and the sum are the values of a, b and their sum.
That's not what your code is doing. Take it step by step, carefully think about what is meant in the assignment.

Categories

Resources