Java considering List argument as reference - java

I was doing some RnD I came across this this difference
my java code is as below
public class Main {
public static void main(String[] args) {
Integer x = 10;
increment(x);
System.out.println("print x" + x);
List<String> strList = new ArrayList<String>();
strList.add("one");
strList.add("two");
strList.add("three");
strList.add("four");
strList.add("five");
strList.add("six");
System.out.println("Before removing");
for (String string : strList) {
System.out.println("item " + string);
}
removeSomeItem(strList);
System.out.println("After removing");
for (String string : strList) {
System.out.println("item " + string);
}
}
private static void removeSomeItem(List<String> strList) {
strList.remove(0);
strList.remove(4);
}
private static void increment(Integer x) {
x++;
}
}
I got out for the above code as below
print x10
Before removing
item one
item two
item three
item four
item five
item six
After removing
item two
item three
item four
item five
my question is when I had sent Integer to function it behaved like value same way when I had sent List<String> its behaving like reference why is this difference ?
can any one explain

The main difference is that the Integer class is immutable, hence why you do not see the change in your main method.
x++; // this will simply return a new Integer
To see the difference, try this from your main method:
x = increment(x);
and in the increment method, change it to this:
return x++;
However, with your list example, you are simply passing a copy of the reference to the list. As long as that reference is not set to a new object (which it isn't), it is able to update the original list you passed.

This is exactly what happened
private static Integer b;
public static void main(String[] args) {
Integer x0 = 10;
b = x0;
increment(x0);
}
private static void increment(Integer x1) {
//x1 == b is true
x1++; //implies x1 = x1 + 1;
//x1 == b is now false
//at the end of the day, you've done nothing to x0 or b
}
EDIT: This code will fail because apparently, the JVM is caching Integer values between -128 and 127, see here, set x0 = 150 and test.
public class Main {
static Integer b;
public static void main(String[] args) {
Integer x = 150;
b = x;
increment(x);
}
private static void increment(Integer x) {
System.out.println(x == b); //true
x++;
System.out.println(x == b); //false
b++;
System.out.println(x == b); //false
}
}

Well in case of,
removeSomeItem(strList);
you are passing the address of original ArrayList to the method so when it remove some value using that reference the original ArrayList change too (actually they are single object with two access point , I mean the reference ).
But in case of Integer you also pass the reference and the increment(Integer x) method receive the original reference. But as Integer immutable when I do something like,
x++;
In the background its work like
x=new Integer(x+1);
That’s why the original Integer remain unchanged when the ArrayList change.

Related

Using stacks to solve tower of Hanoi (java)

public static enum Action {
No, LToM, MToL, MToR, RToM
}
public static int hanoiProblem2(int num, String left, String mid, String right) {
Stack<Integer> lS = new Stack<Integer>();
Stack<Integer> mS = new Stack<Integer>();
Stack<Integer> rS = new Stack<Integer>();
lS.push(Integer.MAX_VALUE);
mS.push(Integer.MAX_VALUE);
rS.push(Integer.MAX_VALUE);
for (int i = num; i > 0; i--) {
lS.push(i);
}
Action[] record = { Action.No };
int step = 0;
while (rS.size() != num + 1) {
step += fStackTotStack(record, Action.MToL, Action.LToM, lS, mS, left, mid);
step += fStackTotStack(record, Action.LToM, Action.MToL, mS, lS, mid, left);
step += fStackTotStack(record, Action.RToM, Action.MToR, mS, rS, mid, right);
step += fStackTotStack(record, Action.MToR, Action.RToM, rS, mS, right, mid);
}
return step;
}
public static int fStackTotStack(Action[] record, Action preNoAct,
Action nowAct, Stack<Integer> fStack, Stack<Integer> tStack,
String from, String to) {
if (record[0] != preNoAct && fStack.peek() < tStack.peek()) {
tStack.push(fStack.pop());
System.out.println("Move " + tStack.peek() + " from " + from + " to " + to);
record[0] = nowAct;
return 1;
}
return 0;
}
public static void main(String[] args) {
int num = 4;
// solution 2
int steps2 = hanoiProblem2(num, "left", "mid", "right");
System.out.println("It will move " + steps2 + " steps.");
System.out.println("===================================");
}
This is a code for solving tower of Hanoi. It uses three stacks to simulate 3 towers.
My question is that why does it define the record variable as an array?
Action[] record = { Action.No };
record[0] = nowAct;
I tried to change them to
Action record = Action.No;
record = nowAct;
then the code is failed to run.
I don't know the reason. I really appreciate it if someone could explain the reason.
Thanks.
In your example, record is being defined as an array because its value is being changed within the fStackTotStack method.
The simplest explanation for this is because Java passes variables by value, not by reference. It passes Object references by value as well.
Take, for example, the following code:
public void foo(int bar) {
bar += 4;
System.out.println("Foo's bar: " + bar);
}
public static void main(String[] args) {
int bar = 5;
new Foo().foo(bar);
System.out.println("Main's bar: " + bar);
}
This will print out:
Foo's bar: 9
Main's bar: 5
This is because the bar variable inside the foo function is a different variable than the one inside the main function. The value is just copied over when the method is called.
When you pass an array, the variables themselves are still different:
public void foo(int[] bar) {
bar = new int[]{9};
System.out.println("Foo's bar: " + bar[0]);
}
public static void main(String[] args) {
int[] bar = {5};
new Foo().foo(bar);
System.out.println("Main's bar: " + bar[0]);
}
This will yield the same results as before, because foo's bar is different than main's bar.
However, Object references are passed by value. This means that while the variables are different, the values they represent are the same. Therefore this:
public void foo(int[] bar) {
bar[0] += 4;
System.out.println("Foo's bar: " + bar[0]);
}
public static void main(String[] args) {
int[] bar = {5};
new Foo().foo(bar);
System.out.println("Main's bar: " + bar[0]);
}
Will print out something different than before:
Foo's bar: 9
Main's bar: 9
This is because while foo's bar variable and main's bar variable are different variables, they point to the same underlying object. So, changes to the object itself, and not just the variable, will persist.
In your example above, the line Action[] record = { Action.No }; is creating an array that gets passed into the fStackTotStack method. Since the variable record is not being changed itself (there is no record = new Action[] {} anywhere), the array it points to is still the same one that was passed. This means that you can make changes to the object itself (in this case, an array).
Here is an article that can explain it better than I can.

Quick sort not sorting array [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
I have the following code:
public class Main {
static void swap (Integer x, Integer y) {
Integer t = x;
x = y;
y = t;
}
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
swap(a, b);
System.out.println("a=" + a + " b=" + b);
}
}
I expect it to print a=2 b=1, but it prints the opposite. So obviously the swap method doesn't swap a and b values. Why?
This doesn't have anything to do with immutability of integers; it has to do with the fact that Java is Pass-by-Value, Dammit! (Not annoyed, just the title of the article :p )
To sum up: You can't really make a swap method in Java. You just have to do the swap yourself, wherever you need it; which is just three lines of code anyways, so shouldn't be that much of a problem :)
Thing tmp = a;
a = b;
b = tmp;
Everything in Java is passed by value and the values of variables are always primitives or references to object.
If you want to implement a swap method for Integer objects, you have to wrap the values into an array (or ArrayList) and swap inside the array. Here's an adaptation of your code:
public class Main {
static void swap (Integer[] values) {
if ((values == null) || (values.length != 2)) {
throw new IllegalArgumentException("Requires an array with exact two values");
}
Integer t = values[0];
values[0] = values[1];
values[1] = t;
}
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer[] integers= new Integer[]{a,b};
swap(integers);
System.out.println("a=" + integers[0] + " b=" + integers[1]);
}
}
(Just added this answer because Svish mentioned, that "You can't really make a swap method in Java" fg)
As Svish and others pointed out it it's call by value, not by reference in Java. Since you have no pointers in Java you need some kind of holder object to really swap values this way. For example:
static void swap(AtomicReference<Integer> a, AtomicReference<Integer> b) {
Integer c = a.get();
a.set(b.get());
b.set(c);
}
public static void main(String[] args) {
AtomicReference<Integer> a = new AtomicReference<Integer>(1);
AtomicReference<Integer> b = new AtomicReference<Integer>(2);
System.out.println("a = " + a);
System.out.println("b = " + b);
swap(a, b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
You would need to pass the parameters by reference, which it's not possible in java. Also Integers are inmutables, so you cannot exchange the values as you don't have a setValue method.
Integer are immutable - you can't change their values. The swapping that occurs inside the swap function is to the references, not the values.
You would need to return both references in an array to achieve what you want
static Integer[] swap(Integer a, Integer b) {
return new Integer[]{b, a};
}
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer[] intArray = swap(a, b);
a = intArray[0];
b = intArray[1];
System.out.println("a=" + a + " b=" + b);
}
If Integer had a setValue method, you could do something like this.
static void swap(Integer a, Integer b) {
int temp = a.intValue();
a.setValue(b.intValue());
b.setValue(temp);
}
But it doesn't - so to achieve what you want, return an array.
Using the XOR operator is a very bad idea:
First, it is far less readable. Second, there were times when this was faster but nowadays the opposite is the case. See
Wikipedia
for reference.
As all the guys mentioned its a Pass-By-Value thing.
Just liked to add: you can use this method of swapping GLOBAL integers.
private void swap (){
a ^= b;
b ^= a;
a ^= b;
}
It eliminates the use of another variable, and its just cooler :)
Java code:
class swap {
int n1;
int n2;
int n3;
void valueSwap() {
n3 = n1;
n1 = n2;
n2 = n3;
}
public static void main(String[] arguments) {
Swap trial = new Swap();
trial.n1 = 2;
trial.n2 = 3;
System.out.println("trial.n1 = " + trial.n1);
System.out.println("trial.n2 = " + trial.n2);
trial.valueSwap();
System.out.println("trial.n1 = " + trial.n1);
System.out.println("trial.n2 = " + trial.n2);
}
}
Output:
trial.n1 = 2
trial.n2 = 3
trial.n1 = 3
trial.n2 = 2
Using Scanner:
import java.util.*;
public class Swap {
public static void main(String[] args){
int i,temp,Num1,Num2;
Scanner sc=new Scanner(System.in);
System.out.println("Enter Number1 and Number2");
Num1=sc.nextInt();
Num2=sc.nextInt();
System.out.println("Before Swapping Num1="+Num1+" Num2="+Num2);
temp=Num1;
Num1=Num2;
Num2=temp;
System.out.println("After Swapping Num1="+Num1+" Num2="+Num2);
}
}

Returning String Methods in Java?

I'm in a beginning programming class, and a lot of this had made sense to me up until this point, where we've started working with methods and I'm not entirely sure I understand the "static," "void," and "return" statements.
For this assignment in particular, I thought I had it all figured out, but it says it "can not find symbol histogram" on the line in the main method, although I'm clearly returning it from another method. Anyone able to help me out?
Assignment: "You see that you may need histograms often in writing your programs so you decide for this program to use your program 310a2 Histograms. You may add to this program or use it as a class. You will also write a class (or method) that will generate random number in various ranges. You may want to have the asterisks represent different values (1, 100, or 1000 units). You may also wish to use a character other than the asterisk such as the $ to represent the units of your graph. Run the program sufficient number of times to illustrate the programs various abilities.
Statements Required: output, loop control, decision making, class (optional), methods.
Sample Output:
Sales for October
Day Daily Sales Graph
2 37081 *************************************
3 28355 ****************************
4 39158 ***************************************
5 24904 ************************
6 28879 ****************************
7 13348 *************
"
Here's what I have:
import java.util.Random;
public class prog310t
{
public static int randInt(int randomNum) //determines the random value for the day
{
Random rand = new Random();
randomNum = rand.nextInt((40000 - 1000) + 1) + 10000;
return randomNum;
}
public String histogram (int randomNum) //creates the histogram string
{
String histogram = "";
int roundedRandom = (randomNum/1000);
int ceiling = roundedRandom;
for (int k = 1; k < ceiling; k++)
{
histogram = histogram + "*";
}
return histogram;
}
public void main(String[] Args)
{
System.out.println("Sales for October\n");
System.out.println("Day Daily Sales Graph");
for (int k = 2; k < 31; k++)
{
if (k == 8 || k == 15 || k == 22 || k == 29)
{
k++;
}
System.out.print(k + " ");
int randomNum = 0;
randInt(randomNum);
System.out.print(randomNum + " ");
histogram (randomNum);
System.out.print(histogram + "\n");
}
}
}
Edit: Thanks to you guys, now I've figured out what static means. Now I have a new problem; the program runs, but histogram is returning as empty. Can someone help me understand why? New Code:
import java.util.Random;
public class prog310t
{
public static int randInt(int randomNum) //determines the random value for the day
{
Random rand = new Random();
randomNum = rand.nextInt((40000 - 1000) + 1) + 10000;
return randomNum;
}
public static String histogram (int marketValue) //creates the histogram string
{
String histogram = "";
int roundedRandom = (marketValue/1000);
int ceiling = roundedRandom;
for (int k = 1; k < ceiling; k++)
{
histogram = histogram + "*";
}
return histogram;
}
public static void main(String[] Args)
{
System.out.println("Sales for October\n");
System.out.println("Day Daily Sales Graph");
for (int k = 2; k < 31; k++)
{
if (k == 8 || k == 15 || k == 22 || k == 29)
{
k++;
}
System.out.print(k + " ");
int randomNum = 0;
int marketValue = randInt(randomNum);
System.out.print(marketValue + " ");
String newHistogram = histogram (randomNum);
System.out.print(newHistogram + "\n");
}
}
}
You're correct that your issues are rooted in not understanding static. There are many resources on this, but suffice to say here that something static belongs to a Class whereas something that isn't static belogns to a specific instance. That means that
public class A{
public static int b;
public int x;
public int doStuff(){
return x;
}
public static void main(String[] args){
System.out.println(b); //Valid. Who's b? A (the class we are in)'s b.
System.out.println(x); //Error. Who's x? no instance provided, so we don't know.
doStuff(); //Error. Who are we calling doStuff() on? Which instance?
A a = new A();
System.out.println(a.x); //Valid. Who's x? a (an instance of A)'s x.
}
}
So related to that your method histogram isn't static, so you need an instance to call it. You shouldn't need an instance though; just make the method static:
Change public String histogram(int randomNum) to public static String histogram(int randomNum).
With that done, the line histogram(randomNum); becomes valid. However, you'll still get an error on System.out.print(histogram + "\n");, because histogram as defined here is a function, not a variable. This is related to the return statement. When something says return x (for any value of x), it is saying to terminate the current method call and yield the value x to whoever called the method.
For example, consider the expression 2 + 3. If you were to say int x = 2 + 3, you would expect x to have value 5 afterwards. Now consider a method:
public static int plus(int a, int b){
return a + b;
}
And the statement: int x = plus(2, 3);. Same here, we would expect x to have value 5 afterwards. The computation is done, and whoever is waiting on that value (of type int) receives and uses the value however a single value of that type would be used in place of it. For example:
int x = plus(plus(1,2),plus(3,plus(4,1)); -> x has value 11.
Back to your example: you need to assign a variable to the String value returned from histogram(randomNum);, as such:
Change histogram(randomNum) to String s = histogram(randomNum).
This will make it all compile, but you'll hit one final roadblock: The thing won't run! This is because a runnable main method needs to be static. So change your main method to have the signature:
public static void main(String[] args){...}
Then hit the green button!
For starters your main method should be static:
public static void main(String[] Args)
Instance methods can not be called without an instance of the class they belong to where static methods can be called without an instance. So if you want to call your other methods inside the main method they must also be static unless you create an object of type prog310t then use the object to call the methods example:
public static void main(String[] Args)
{
prog310t test = new prog310t();
test.histogram(1);
}
But in your case you probably want to do:
public static String histogram (int randomNum)
public static void main(String[] Args)
{
histogram(1);
}
Also you are not catching the return of histogram() method in your main method you should do like this:
System.out.print(histogram(randomNum) + "\n");
Or
String test = histogram(randomNum);
System.out.print(test + "\n");
Static methods are part of a class and can be called without an instance but instance methods can only be called from an instance example:
public class Test
{
public static void main(String[] args)
{
getNothingStatic();// this is ok
getNothing(); // THIS IS NOT OK IT WON'T WORK NEEDS AN INSTANCE
Test test = new Test();
test.getNothing(); // this is ok
getString(); // this is ok but you are not capturing the return value
String myString = getString(); // now the return string is stored in myString for later use
}
public void getNothing()
{
}
public static void getNothingStatic()
{
}
public static String getString()
{
return "hello";
}
}
Void means the method is not returning anything it is just doing some processing. You can return primitive or Object types in place of void but in your method you must specify a return if you don't use void.
Before calling histogrom (randomNum) you need to either make histogram static or declare the object that has histogram as a method
e.g
prog310t myClass = new prog310t();
myClass.histogram()

Why it is not possible to create object of a reference in another method in java?

Possible Duplicate : Is Java “pass-by-reference” or “pass-by-value”?
i am trying to do initialization of an array in this way -
class Main {
public static void main(String[] args) {
int n = 4;
int[] s = null;
int[] f = null;
init(n, s, f);
System.out.println(s.length);
}
public static void init(int n, int[] s, int[] f) {
s = new int[n];
f = new int[n];
}
}
but i am getting NullPointerException for the s.length. so this clear passing the parameter to another method is pass by value. therefor objects are not initialize.
but when i do swap in to value in a different method then this is working. like -
class Main {
public static void main(String[] args) {
int n = 4;
int[] s = new int[n];
int[] f = new int[n];
s[0] = 10;
f[0] = 20;
System.out.println(s[0] + " " + f[0]);
swap(s, f);
System.out.println(s[0] + " " + f[0]);
}
public static void swap(int[] s, int[] f) {
int t = s[0];
s[0] = f[0];
f[0] = t;
}
}
on the other hand this isn't swap values.
class Main {
public static void main(String[] args) {
Integer a = 10;
Integer b = 20;
swap(a , b);
System.out.println(a + " " + b);
}
public static void swap(Integer a, Integer b) {
int t = a;
a = b;
b = t;
}
}
therefor i need some explanation whether java “pass-by-reference” or “pass-by-value”? this explanation could help me to understand why it is not possible to create object in another method.
sorry for my bad English. thanks in advance.
This won't work because Java has pass by value, not pass by reference.
When you declare
int[] s = null;
then you have a (null) reference to an int[]. But when you pass s to another method, what happens is that a new variable (let's call it x) is created, and the reference s is copied into it. Any changes to what x references will also change what s references, because they're the same thing; but changes to x itself won't change s, because x and s are two different references to the same thing.
Think of it like this. Your s is an entry on a clipboard, and the clipboard entry tells you the number of the box to look in to find the int[]. When you pass s to a method, you get a new entry x on the clipboard, with the same box number as was under the s reference. That means that any operation that looks in the box and changes its contents will affect what you get when you look at what s refers to: they both look at the same box number. But if you change the entry on the clipboard for x, it won't change the entry on the clipboard for s, because they're two different entries.
As another example, think of s and x as being road signs pointing to the same town. If you change the town that x points to, e.g. by introducing a one way system in the town centre, then of course what s points to will also have changed. But if you change the road sign x, and write a different town's name on it, that won't automatically change the road sign s too. They're different signs, but signifying the same thing.

Object Creation in java and finalize

class FDemo {
int x;
FDemo(int i) {
x = i;
}
protected void finalize() {
System.out.println("Finalizing " + x);
}
void generator(int i) {
FDemo o = new FDemo(i);
System.out.println("Creat obj No: " + x); // this line
}
}
class Finalize {
public static void main(String args[]) {
int count;
FDemo ob = new FDemo(0);
for(count=1; count < 100000; count++)
ob.generator(count);
}
}
}
In the line i have commented, the value of x always shows 0(value of x in object ob), why isnt showing the value of object o?? i know if i use o.x i ll be getting the value of x in object o. But still in this code why does it show the value of abject ob rather than object o??
If you want to reference the x in the FDemo you've just created, you should add a getX() function and call that instead of x, like David Wallace said. (I prefer using getters instead of .variable).
Add this to your class:
public int getX(){
return x;
}
And change your problematic line to this:
System.out.println("Creat obj No: " + o.getX());
That should fix it. As a side note, it's considered good practice to explicitly declare whether your variables and methods are private, public or protected.

Categories

Resources