I have question about one method of InputStream class, because it doesn't seem to me it could ever work.
Let we have something like this:
InputStream is;
byte[] b = new byte[64];
is.read(b);
// and now the byte array b contains data comming through InputStream???
I would understand if usage of the .read() method would look something like this:
b = is.read();
Because the read method would be returning byte array.
But how can the real method write something to its argument and make it visible outside of itself?
It's like I would have this:
String myString = "myText";
public void myMethod(String s) {
s = "abc123";
}
myMethod(myString);
// and now is the content of myString equal to "abc123" instead of "myText" ???
// ANSWER: no!
Thanks for your replies.
Everything except primitives types are objects in java(including array). The objects are passed by copy of reference from one method to another. So if the called method makes changes to the object passed to it, method is eventually making changes to the same object which was passed to it. Hence, changes are reflected to the calling method as well.
You need to learn about objects and how are they passed between method calls to understand this in detail. Please refer this link for better understanding.
Because the read method would be returning byte array.
Eh? Where did you read that? InputStream's .read() method returns an integer.
how can the real method write something to its argument and make it visible outside of itself?
Because you pass in a reference to an array where the .read(byte[]) will write. And the return value of this method is the number of bytes actually written to the byte array passed as an argument.
This code works:
public void writeOneToFirstElement(final int[] array)
{
array[0] = 1;
}
final int[] foo = { 0 };
writeOneToFirstElement(foo);
System.out.println(foo[0]); // prints 1
THe Array is just a reference to the object and cause the adress where the data resides doesnt change on modifications it can work that way
Explained here:
http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html
Edit: Typo
byte array as well as String are reference types..When you pass them as argument there reference are copied and they all refer to the same object..
For example, a remote is like a reference to a TV.When you pass the remote to another person,he's still able to access the TV
The objects are passed by copy of reference from one method to another. So if the called method makes changes to the object passed to it, method is eventually making changes to the same object which was passed to it. Hence, changes are reflected to the calling method as well. For example replace the String in the parameter with String[] and check the output.
public static void main(String[] args)
{
String[] myString = {"myText"};
myMethod(myString);
System.out.println(myString[0]);
}
public void myMethod(String[] s) {
s[0] = "abc123";
}
Related
I'm working on an assignment right now, and am confused by this. The code given is simple:
public class Variables{
public static void main(String[ ] args){
StringBuffer b = "ghi";
f(b);
System.out.println(b):
}
public static void f(StringBuffer p){
p.concat("jkl");
}
}
The question simply asks what the output of the print statement will be. My first thought was simply "ghi", but this was incorrect. If the method f is taking b as a parameter and setting it to p, then how does .concat() modify b? I've read through the StringBuffer documentation and dont understand why this wouldn't end up with b equaling "ghi" while p is "ghijkl".
Basically, how is the .concat() method called on p also modifying b?
First, you need to create a StringBuffer correctly.
StringBuffer foo = new StringBuffer("some string");
You passed an object to a function. Java passes objects as references (the references themselves of course are passed by value). See: Is Java "pass-by-reference" or "pass-by-value"?
Since you have a reference to a StringBuffer and not a copy of it, you are actually modifying the same object as you would as if you were in main.
This is the difference between parsing by reference and parsing by value.
When you create a method taking a primitive, for example, it undergoes what is called parsing by value. The JVM pretty much creates a copy of the value and that is what you get in the method.
int j = 0;
foo(k);
System.out.println(j); //Will still be 0.
public static void foo(int i) {
//i is not j (what you called the method with), it is a copy of it that is only valid within this method
i++;
}
Now when you call the method with an object such as a StringBuffer you are parsing by reference. This means that you are not parsing the value of the StringBuffer(not parsing a StringBuffer` with "ghi" as its contents), but you are rather parsing a pointer to it. Using this pointer you can still operate on the original object within other methods and bodies of code.
First of all, I understand what's so called passing by value in Java.
Also I understand, when you pass an object or an array, it is the array's address that is passed into the method. So modifying the array variable inside the method will affect the outside array variable.
For example,
private void change(int[] a) {
a[0] = 1234;
}
public static void main(String[] args) {
int[] a = new int[2]{1,2};
change(a);
System.out.println(a[0]);
}
The output will be 1234, because the a inside change is actually the array outside.
What I don't understand is the following code:
private void change(int[] a) {
a = new int[3]{1234, 4, 5};
}
public static void main(String[] args) {
int[] a = new int[2]{1,2};
change(a);
System.out.println(a[0]);
}
Why the output is 1, not 1234?
The inside a was the same thing as outside a, right? I also modify the inside a just like the example above did, why two different output?
This is not the same. In your second example, you are changing the local reference a to refer to a completely new array, not changing the existing array. But this does not change the a in main to refer to the new array; it still refers to the old array, so 1 is printed.
If you wanted to re-assign a completely new array to the a in main using a method, then return the new array from change and assign that to a in main.
Let's inspect your function:
private void change(int[] a) {
a = new int[3]{1234, 4, 5};
}
As you stated in your question, a is a reference to an array. If you use it to modify the array (e.g., a[0]=1234), you will be changing the same array that was passed in to the function.
However, if you change the reference itself, a will no longer be pointing to the original array, and changes to it will not affect the original.
This is exactly because the reference is passed by value. We'll represent object pointers with 5-digit numbers like 12345. The process is as follows:
We create an int[]{1,2}, at memory location, say 10000. We assign a the value 10000. a is on the stack frame corresponding to main.
We pass the value 10000 to change.
change executes:
change creates a new array at location 20000 and sets the value of a on its stack frame to 20000. This does not affect the main stack frame.
change returns (void).
We deference the untouched pointer to the original array in order to print the zeroth element, 1.
Note that by the time change returns, we have no live references left to {1234, 4, 5}.
In Java all variables are references to objects.
When you pass a variable into an array, you pass the reference to the object. If you modify the object then the calling method - which also has a variable that refers to the same object - sees the change.
When you write "a = new int..." you are changing the value of the variable a to point to a different object. It is no longer referring to the same object as the one in the method that called it. So the calling method and the called method see different things.
When you pass a parameter by value, it basically means that it's copied from a method's point of view. So, you have a reference a to an array, and when you pass it to some method, inside that method you have another reference, also named a to the same array. Now, when you assign a new value to that reference (a = new int[]...) you are only modifying the local a variable to point to a new array.
The answer has as much to do with passing by reference or value as it does with which variables are in scope when you attempt to make the change.
When you pass "a," or any variable to a method, you pass the value of that variable - in other words a copy of what it represents- and not the actual variable itself. For example:
public static void main(String[] args){
int a = 3;
addTwo(a);
System.out.println(a);
}
private void addTwo(int a){
a += 2;
}
In the above example the value 3 is passed to addTwo. The variable "a" in the main method is outside of its scope (i.e. it is localized to the main method) so the addTwo method acts only on the copy of "a," the value 3, and not the variable. The variable "a" remains unchanged. When the method completes the value of a is discarded and the original "a" in the main method remains unchanged.
This is the same thing that is happening in your case. It does not matter that you use the same name for two variables. The variable in your main method will not be changed.
This question already has answers here:
Changing array in method changes array outside [duplicate]
(2 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
method(arr);
System.out.println(arr[0]);
}
private static void method(int[] array)
{
array[0] = 2;
}
}
After invoking method, arr[0] becomes 2. Why is that!?
You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.
If Java were pass by reference, this would pass:
public class Test {
public static void main(String[] args) {
Test test = new Test();
int j = 0;
test.setToOne(j);
assert j == 1;
}
public void setToOne(int i) {
i = 1;
}
}
Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm
This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.
When you pass an object -- including arrays -- you pass the object itself. A copy is not created.
If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)
Here is the code above, annotated:
public static void main(String[] args)
{
int[] arr = new int[5]; // create an array object. let's call it JIM.
// arr evaluates to the object JIM, so sets JIM[0] = 1
arr[0] = 1;
System.out.println(arr[0]); // 1
method(arr); // fixed typo :-)
// arr still evalutes to JIM
// so this will print 2, as we "mutated" JIM in method called above
System.out.println(arr[0]); // 2
}
private static void method(int[] array)
{
// array evaluates to the object JIM, so sets JIM[0] = 2
// it is the same JIM object
array[0] = 2;
}
Happy coding.
*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.
Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.
Additional:
Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?
Make copy of array Java -- note this only creates a "shallow" copy.
Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.
A quick example for thought:
If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.
Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method
however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place
method(arr[0]);
I think that's supposed to be
method(arr);
But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.
Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.
I read that Java does everything by call by value. I was wondering how to verify this fact? As far as I understand, in case of objects(not primitives) functions get its own copy of reference but points to same object. In that case, reference of that object in callee function and caller function should be different? How can I verify that? In other words, how to print the reference of the object.
System.out.println(object); //does this print reference i.e text following #
EDIT:
I understand that modifying object in callee function does change the value in caller function. I am interested in how to print the references of objects as in what property can I print on console that clearly shows me 2 different reference.
Java passes references by value. This means you'll get a copy of the reference, so once you dereference that you'll get to the same object in the heap as with the original reference.
But if Java was pass by reference:
public static void nullify(Object obj) {
obj = null;
}
public static void main(...) {
String x = "Hello";
nullify(x);
System.out.println(x);
}
The call to S.o.p. would print null if Java was pass by reference. But it isn't, so x is unchanged and you'll get Hello.
Assuming Class A property aa
A a= new A();
a.aa = 1;
// print a.aa here should be 1
method(a);
// here a.aa should be 2
Void method(A a) {
a.aa =2;
a = new A();
a.aa = 3;
}
So this shows reference was passed as value. When you change the object in the method it does not change the reference of caller.
I think the String Object#1ed3af is composed of the class name of your object and it's hashcode, separated by a #. This is a unique string, identifying it.
Read this topic to get a full explanation !
im a bit confused on this and i dont know how to solve this question that i have been asked, id be grateful if you could assist me on this question, maybe try to tell me what needs to be done, and how. the question is:
Write a method called countChars which takes an InputStream as a parameter, reads the stream and returns the number of characters it contains as an int. Any IOExceptions which might occur in the method should be passed back to the method's caller.
Note that the method header should show that it is possible that an exception might occur.
i attempted this question with the following code:
public class countChars
{
public int countChars(int InputStream)
{
return InputStream;
}
}
and i get an error message saying :
Main.java:26: cannot find symbol
symbol : method countChars(java.io.InputStream)
location: class Main
s1 = "" + countChars(f1);
^
1 error
public class CounterUtility
{
public static Integer countChars(InputStream in)
{
Integer counter = 0;
/* your code here */
return counter;
}
}
s1 = CounterUtility.countChars(f1).toString();
You have a couple things mixed up. For one your function is going to take in an InputStream and return an int. You have your function set up to take in an int called InputStream and return an int.
InputStream has a function, read(), which loads the next character of the stream (or -1 if there are no remaining characters). You'll need to define an integer counter and then call read() as many times as it takes to get that response of -1. Once you see a -1 you know that you're at the end of the stream and you can return the counter (which will have a value equal to the number of characters).
//take in an InputStream object and return an int
public int countChars(InputStream input){
int counter = 0; //start counting at zero
while (input.read() != -1){
//as long as there are more characters, keep incrementing the counter
counter++; //add one to the counter
}
return counter; //return the result
}
I never attempted to compile the above code and I haven't written in Java since college, so there may be syntactical errors.
Your countChars method is inside of a class called countChars.
When you call the method, you need an instance of the class.
You need to make the method static, then change the call to countChars.countChars(f1).
The error is probably due to the fact that the countChars method was not successfully compiled. If you review the rest of the output of the compiler you'll probably see it complaining on the return statement. Replace the stub return, with return 0 and it should go through.
Besides, you should not use InputStream as variable name. Use is or something similar.
Furthermore, if the method should take an InputStream as argument, the signature should be
public int countChars(InputStream is) { ...
Seems like you may be compiling the wrong file. The code example you included does not contain the code from the error message. I therfore conclude that the compiler is not acting on the source file that you believe it is (assuming you have accurately copy/pasted the code you are using).
First things first: In Java, class names should always be capitalized.
Second, the code you are running is in the Main class. Your countChars method is in the countChars class. You need to create a countChars object to call it on, or make countChars a static method, which would be called via countChars.countChars(intHere).
Third, int InputStream would be an integer value with the name InputStream, not an InputStream object.
A few points. Generally it is considered good practice to Capitalize all Java Classes. You aren't forced to do so, but when you don't it makes readability much more difficult for the rest of the world.
So public class countChars becomes public class CountChars.
Second, you are attempting to call a method on an object, but you don't specify which object you want to use. Generally you can't use a method all by itself in object oriented programming, you must specify the class and then the method to call on the class. This is done one of two ways:
By creating an Object (instance of the class) and the calling the method on that Object, like so:
CountChars counter = new CountChars();
s1 = "" + counter.countChars(i);
By declaring the method to be static, which means it will be a method on the "Class" Object, CountChars. To call a static method, the class name is used, like so:
s1 = "" + CountChars.countChars(i);