Java - pass by value [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
I was trying something with Integer, and output is freaking me out.
public class CountB
{
public static boolean returnBool(String w, Integer count)
{
for (int i = 0; i < w.length(); i++)
{
if (w.charAt(i) == 'B' || w.charAt(i) == 'b')
{
count++;
}
}
if (count > 0)
return true;
return false;
}
// write the static method “isThisB” here
public static void main(String[] args)
{
// Scanner keyboard = new Scanner(System.in);
// System.out.println("Enter a string: ");
String w = "fgsfbhggbB";//keyboard.nextLine();
Integer count = new Integer(0);
System.out.println(returnBool(w, count));
System.out.println("Number of B and b: " + count);
}
}
Now, Integer being a wrapper class of int, and count being its object, when I pass count from main to returnBool, value of count becomes 3, so it returns true, as java is pass by value count object value should change in main method also, but in main count prints 0.
I want to understand why this is happening?

count++ is just a convenience for
count = Integer.valueOf(count.intValue()+1)
After this operation, your local variable count (in returnBool) refers to another object, and the local variable in your main method keeps pointing to the initial object. You haven't achieved pass-by-reference.
As for Java semantics, there are two similar concepts which are easy to confuse: Java's pass-by-value of object references (in essence, pointers), and true pass-by-reference. Your example stresses this difference.

Java passes the class Integer by Value and not by Reference. If you want to pass it by Reference you'll need an other class like org.apache.commons.lang.mutable.MutableInt from Apache Commons library

There is no pass-by-reference in java. Method parameters are passed by value but that value may be a reference to an object. If the passed object is mutable the changes on it will affect the object outside the method since the object is the same in and out. Integer objects are immutable.
You can pass int[1] or AtomicReference or AtomicInteger or any other object that contains a mutable integer value.
This is your code adapted to AtomicInteger
public class CountB
{
public static boolean returnBool(String w, AtomicInteger count)
{
for (int i = 0; i < w.length(); i++)
{
if (w.charAt(i) == 'B' || w.charAt(i) == 'b')
{
count.incrementAndGet();
}
}
if (count.intValue() > 0)
return true;
return false;
}
// write the static method “isThisB” here
public static void main(String[] args)
{
// Scanner keyboard = new Scanner(System.in);
// System.out.println("Enter a string: ");
String w = "fgsfbhggbB";//keyboard.nextLine();
AtomicInteger count = new AtomicInteger(0);
System.out.println(returnBool(w, count));
System.out.println("Number of B and b: " + count);
}
}

Related

Why does this insertion sort method gives me wrong output?

Why is this insertion sort giving me the wrong answer, whereas i'm getting the right answer when I do it the way the comment lines specify?What is the difference?
public class Solution
{
public static void main(String[] args)
{
Scanner s=new Scanner(System.in);
int i,j,n,sk=0; //consider another variable k
int a[]=new int[20];
n=s.nextInt();
for(i=0;i<n;i++)
a[i]=s.nextInt();
for(i=1;i<n;i++)
{ j=i-1;
//adding k=a[i]
while((j>=0)&&a[j]>a[i]) //a[j]>k instead of the condition a[j]>a[i]
{ sk++;
a[j+1]=a[j];
j--;
}
a[j+1]=a[i];
//a[j+1]=k instead of the previous line.
}
for(i=0;i<n;i++)
System.out.println(a[i]);
}
}
this line a[j+1]=a[j];
Consider the array = {5,2,3} when i = 1, j = 0,
while((j>=0)&&a[j]>a[i]) //a[j]>k instead of the condition a[j]>a[i]
{ sk++;
a[j+1]=a[j]; // a[1] = a[0]
j--; // j becomes -1 out of the loop
}
// Array becomes {5,5,3} after while loop, we lost 2
a[j+1]=a[i]; // again a[0] is just getting initialized to a[1]
//which are same
//a[j+1]=k instead of the previous line. **// K will have previous
a[1]**
}
You already updated a[1] when you did a[j+1]=a[j] and then outside the while loop you are again assigning a[1] = a[1], however, k will store previous a[1] value, not the updated one
To make it simple, in your solution, you are editing your variables by reference whereas the correct solution is to pass them by value.
When you pass your variables by reference, editing one value would be the same as editing the second.
Here is a simple code which should help you to understand:
public class Main {
public static void main(String[] args) {
Foo foo = new Foo();
int valueToAdd = 5;
// foo.a will not be modified because we set the parameter by value
editTestByValue(foo.a, valueToAdd);
System.out.println(foo.a); // prints 1
editTestByReference(foo, valueToAdd);
// foo.a will be modified because we set the parameter by reference
System.out.println(foo.a); // prints 6
}
public static void editTestByValue(int a, int valueToAdd){
a += valueToAdd;
}
public static void editTestByReference(Foo foo, int valueToAdd){
foo.a += valueToAdd;
}
}
class Foo {
public int a = 1;
}
You use the same thing by using an array instead of a class.
For more information, you can check this
What's the difference between passing by reference vs. passing by value?
Hope it helped !

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()

java : return multiple values from a method [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to return multiple objects from a Java method?
lets say N= a+b;
for a number N i want to generate the all possible values a and b. like
if N =7 a and b are (1+6),(2+5),(3+4).
i have coded this logic in a method.
static void sumofNum(int N){
for(int a=1; a<N; a++){
//a+b=N
int b = N-a;
System.out.println(a+","+b);
int next =a+1;
if(next==b | a==b)
return;
}
}
i want to return (1,6),(2,5),(3,4) from this method. next for any N there can be more (a,b) combinations to be returned from this method.
Return a List<String> (assuming "(1,6)" is to be stored as a String). Use one of the implementations of List, such as ArrayList, to construct the list:
static List<String> sumofNum(int N)
{
List<String> result = new ArrayList<String>();
for(int a=1; a<N; a++)
{
int b = N-a;
result.add("(" + a + "," + b + ")");
int next =a+1;
if(next==b || a==b)
return result;
}
return result;
}
If you want to return them as ints, define a object that contains two ints (or abuse points as I have done below) and return a list of those objects. If you define your own object, just replace point with that.
static ArrayList<Point> sumofNum(int N){
ArrayList<Point> result = new ArrayList<Point>();
for(int a=1; a<N; a++){
//a+b=N
int b = N-a;
System.out.println(a+","+b);
int next =a+1;
if(next==b | a==b)
result.add(new Point(a,b));
}
return result;
}
You can get your results from the list with:
results = sumofNum(7);
int a = results.get(0).x; //a = 1
int b = results.get(0).y; //b = 6
In an object oriented (and also functional) style of programming you can pass the result to a consumer an avoid the overhead of storing results in collections or lists.
Example:
static void sumofNum(int N){
for (int a=1; a<N; a++){
//a+b=N
int b = N-a;
consumer.consume(a,b);
int next =a+1;
if (next==b || a==b)
return;
}
}
[ Further improvements of the code are possible (e.g. avoid the inner if and return), ... ]
Consider the nos as (1,6),(2,5),(3,4)
- Now return an ArrayList<String> which contains each value in String form as "1,6" , "2,5", "3,4".
- When you receive the returned ArrayList, then use split() method "," as delimiter to get the 1 and 6 out of "1,6" and so on....

How can I pass an Integer class correctly by reference?

I am hoping that someone can clarify what is happening here for me. I dug around in the integer class for a bit but because integer is overriding the + operator I could not figure out what was going wrong. My problem is with this line:
Integer i = 0;
i = i + 1; // ← I think that this is somehow creating a new object!
Here is my reasoning:
I know that java is pass by value (or pass by value of reference), so I think that in the following example the integer object should be incremented each time.
public class PassByReference {
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
public static void main(String[] args) {
Integer integer = new Integer(0);
for (int i =0; i<10; i++){
inc(integer);
System.out.println("main: "+integer);
}
}
}
This is my expected output:
Inc: 1
main: 1
Inc: 2
main: 2
Inc: 3
main: 3
Inc: 4
main: 4
Inc: 5
main: 5
Inc: 6
main: 6
...
This is the actual output.
Inc: 1
main: 0
Inc: 1
main: 0
Inc: 1
main: 0
...
Why is it behaving like this?
There are two problems:
Integer is pass by value, not by reference. Changing the reference inside a method won't be reflected into the passed-in reference in the calling method.
Integer is immutable. There's no such method like Integer#set(i). You could otherwise just make use of it.
To get it to work, you need to reassign the return value of the inc() method.
integer = inc(integer);
To learn a bit more about passing by value, here's another example:
public static void main(String... args) {
String[] strings = new String[] { "foo", "bar" };
changeReference(strings);
System.out.println(Arrays.toString(strings)); // still [foo, bar]
changeValue(strings);
System.out.println(Arrays.toString(strings)); // [foo, foo]
}
public static void changeReference(String[] strings) {
strings = new String[] { "foo", "foo" };
}
public static void changeValue(String[] strings) {
strings[1] = "foo";
}
The Integer is immutable. You can wrap int in your custom wrapper class.
class WrapInt{
int value;
}
WrapInt theInt = new WrapInt();
inc(theInt);
System.out.println("main: "+theInt.value);
Good answers above explaining the actual question from the OP.
If anyone needs to pass around a number that needs to be globally updated, use the AtomicInteger() instead of creating the various wrapper classes suggested or relying on 3rd party libs.
The AtomicInteger() is of course mostly used for thread safe access but if the performance hit is no issue, why not use this built-in class. The added bonus is of course the obvious thread safety.
import java.util.concurrent.atomic.AtomicInteger
There are 2 ways to pass by reference
Use org.apache.commons.lang.mutable.MutableInt from Apache Commons library.
Create custom class as shown below
Here's a sample code to do it:
public class Test {
public static void main(String args[]) {
Integer a = new Integer(1);
Integer b = a;
Test.modify(a);
System.out.println(a);
System.out.println(b);
IntegerObj ao = new IntegerObj(1);
IntegerObj bo = ao;
Test.modify(ao);
System.out.println(ao.value);
System.out.println(bo.value);
}
static void modify(Integer x) {
x=7;
}
static void modify(IntegerObj x) {
x.value=7;
}
}
class IntegerObj {
int value;
IntegerObj(int val) {
this.value = val;
}
}
Output:
1
1
7
7
What you are seeing here is not an overloaded + oparator, but autoboxing behaviour. The Integer class is immutable and your code:
Integer i = 0;
i = i + 1;
is seen by the compiler (after the autoboxing) as:
Integer i = Integer.valueOf(0);
i = Integer.valueOf(i.intValue() + 1);
so you are correct in your conclusion that the Integer instance is changed, but not sneakily - it is consistent with the Java language definition :-)
You are correct here:
Integer i = 0;
i = i + 1; // <- I think that this is somehow creating a new object!
First: Integer is immutable.
Second: the Integer class is not overriding the + operator, there is autounboxing and autoboxing involved at that line (In older versions of Java you would get an error on the above line).
When you write i + 1 the compiler first converts the Integer to an (primitive) int for performing the addition: autounboxing. Next, doing i = <some int> the compiler converts from int to an (new) Integer: autoboxing.
So + is actually being applied to primitive ints.
I think it is the autoboxing that is throwing you off.
This part of your code:
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
Really boils down to code that looks like:
public static Integer inc(Integer i) {
i = new Integer(i) + new Integer(1);
System.out.println("Inc: "+i);
return i;
}
Which of course.. will not changes the reference passed in.
You could fix it with something like this
public static void main(String[] args) {
Integer integer = new Integer(0);
for (int i =0; i<10; i++){
integer = inc(integer);
System.out.println("main: "+integer);
}
}
If you change your inc() function to this
public static Integer inc(Integer i) {
Integer iParam = i;
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println(i == iParam);
return i;
}
then you will see that it always prints "false".
That means that the addition creates a new instance of Integer and stores it in the local variable i ("local", because i is actually a copy of the reference that was passed), leaving the variable of the calling method untouched.
Integer is an immutable class, meaning that you cannot change it's value but must obtain a new instance. In this case you don't have to do it manually like this:
i = new Integer(i+1); //actually, you would use Integer.valueOf(i.intValue()+1);
instead, it is done by autoboxing.
1 ) Only the copy of reference is sent as a value to the formal parameter. When the formal parameter variable is assigned other value ,the formal parameter's reference changes but the actual parameter's reference remain the same incase of this integer object.
public class UnderstandingObjects {
public static void main(String[] args) {
Integer actualParam = new Integer(10);
changeValue(actualParam);
System.out.println("Output " + actualParam); // o/p =10
IntObj obj = new IntObj();
obj.setVal(20);
changeValue(obj);
System.out.println(obj.a); // o/p =200
}
private static void changeValue(Integer formalParam) {
formalParam = 100;
// Only the copy of reference is set to the formal parameter
// this is something like => Integer formalParam =new Integer(100);
// Here we are changing the reference of formalParam itself not just the
// reference value
}
private static void changeValue(IntObj obj) {
obj.setVal(200);
/*
* obj = new IntObj(); obj.setVal(200);
*/
// Here we are not changing the reference of obj. we are just changing the
// reference obj's value
// we are not doing obj = new IntObj() ; obj.setValue(200); which has happend
// with the Integer
}
}
class IntObj {
Integer a;
public void setVal(int a) {
this.a = a;
}
}
We can do this using Apache Commons Mutable Int
public static Integer inc(MutableInt i) {
i.increment();
System.out.println("Inc: "+i.getValue());
return i;
}
public static void main(String[] args) {
MutableInt integer = new MutableInt(0);
for (int i =0; i<10; i++){
inc(integer);
System.out.println("main: "+integer.getValue());
}
}
This produces output:
Inc: 1
main: 1
Inc: 2
main: 2
Inc: 3
main: 3
Inc: 4
main: 4
Inc: 5
main: 5
Inc: 6
main: 6
Inc: 7
main: 7
Inc: 8
main: 8
Inc: 9
main: 9
Inc: 10
main: 10

== vs equals method for Doubles [duplicate]

This question already has answers here:
Why can't we use '==' to compare two float or double numbers [duplicate]
(3 answers)
Closed 6 years ago.
I have this class
public class Point {
private Double[] coordinates;
private int dimension;
public Point(Double[] coordinates) {
dimension = coordinates.length;
this.coordinates = new Double[dimension];
for(int i = 0; i < dimension; i++)
this.coordinates[i] = coordinates[i];
}
public Double getCoord(int n) {
if(n < 0 || n > dimension -1 ){
throw new RuntimeException("error de coordenadas");
}
return coordinates[n];
}
public int getDim() {
return dimension;
}
public boolean equals(Object p1){
if( (p1 instanceof Point) ){
Point p = (Point) p1;
int n = p.getDim();
if(getDim() == n)
{
for(; n > 0; n--)
{
if( Double.valueOf(this.getCoord(n-1)) != Double.valueOf(p.getCoord(n-1)) ) // <------- BAD LINE!
{
System.out.println("Checking coord " + (n-1));
System.out.println("Coord " + (n-1) + " p = " + Double.valueOf(this.getCoord(n-1)));
System.out.println("Coord " + (n-1) + " p2 = " + Double.valueOf(p.getCoord(n-1)));
return false;
}
}
}
return true;
}
return false;
}
}
And this main
public class FigureTest {
public static void main(String[] args){
Double[] coord1 = {2.0,3.3};
Double[] coord2 = {2.0,3.3};
Point p = new Point(coord1);
Point q = new Point(coord2);
System.out.println(p.equals(q));
}
}
I can't understand why this p.equals(q) returns false! It goes inside the if( Double.valueOf(... but then prints that both coordinates are equal. It's the same if I remove the Double.valueOf. The only way it worked was when I put ! if(this.getCoord(n-1).equal(p.getCoord(n-1)), but I don't understand why the others don't work.
Double.valueOf returns a Double object, not a primitive double.
You perform a reference check (!=). So even if Double.valueOf(getCoords(n-1)) returned the same numeric value for both calls, different objects would be wrapping the numbers, so the != check would be true, causing your equals to return false.
Here's a quick example:
public static void main(String[] args){
System.out.println(Double.valueOf(5) == Double.valueOf(5));
}
Notice how it returns false. That's because == is a reference check, and a different object is being returned each time you call Double.valueOf. So when you do
Double.valueOf(...) != Double.valueOf(...)
That check will return true, since the valueOf calls didn't return the same object. This is why the check in your code returns true, resulting in equals returning false.
To fix this, you could...
Change your != check into a .equals check, which will compare the numeric values rather than the references.
Double.valueOf(...).equals(Double.valueOf(...));
This returns true if both share the same numeric value.
Or you could use doubleValue() when you call getCoord:
getCoord(n-1).doubleValue() != other.getCoord(n-1).doubleValue()
This will avoid the excess creation of Double objects.
In order to this to work;:
p.equals(q)
you need to keep the contract between Hashcode and equals and override properly both of them: equals AND hashcode in the class Point, and when I write properly I mean specifically this:
Please refer to this question if you dont know why or that you dont need it
Double.valueOf(this.getCoord(n-1)) != Double.valueOf(p.getCoord(n-1))
if the members of the class Point are doubles, then you are right when you compare those doubles as criteria to decide if p1.equals(p2)
but according to the documentation of the class Double, the static method Double.compare(this.getCoord(n-1)),p.getCoord(n-1) must be use in order to compare 2 doubles content.
hence I recommend to do in the equals method some similar to this
if( Double.compare(this.getCoord(n-1)),p.getCoord(n-1)!=0) )

Categories

Resources