public class test{
public static void main(String args[]){
int val = 10;
System.out.println(val);
Obj obj = new Obj();
obj.def(val);
System.out.println(val)
}
}
public class OBJ{
public void def(int val){
val = 1;
}
}
that result is same (10 , 10) however..
public class test{
public static void main(String args[]){
double val[] = {0, 1, 2, 3, 4, 5};
Obj obj = new Obj();
for(int i = 0; i < val.length; i++){
System.out.println(val[i];
}
obj.def(val);
for(int i = 0; i < val.length; i++){
System.out.println(val[i];
}
}
}
public class OBJ{
public void def(double[] val){
for(int i = 0; i < val.length; i++){
val[i] = 1;
}
}
that is different, first print is 0 ~ 5, however, second print is 1 , 1, 1....
I don't know what is different,
in java, Array ( it mean likes int []..) use address?? like pointer in C?
P.S : Sorry for indentation.. above code write in web,
In java primitives, like the int are directly passed by value. Object, which arrays belong to aswell, are passed by value aswell, just that in this case the reference is passed as value. This means that you are working on the same instance of the array in your case.
As you can see in your example passing the int[] and changing the values in it are also affecting the original int[] that was passed to it. The true meaning of what is written above, that the reference is passed as value is that changing the reference of the object wont reflect in a change in the original value.
Here is a tiny example with comments demonstrating this.
public class TestObj {
private int val;
public TestObj(int value) {
this.val = value;
}
public static void main(String[] args) {
int value = 1;
int [] values = {1,2,3,4};
TestObj obj = new TestObj(15);
System.out.print("Print single int: ");
print(value);
System.out.println("Print int array:");
print(values);
System.out.print("Print TestObj val: ");
print(obj);
System.out.print("Changing single int value: ");
changeValue(value); // no effect
print(value);
System.out.println("Changing array int values: ");
changeValues(values); // effected
print(values);
System.out.println("Changing array value of reference: ");
changeRefValues(values); // no effect
print(values);
//
System.out.println("Changing val of TestObj");
changeVal(obj); // effected
print(obj);
System.out.println("Changing TestObj value of reference");
changeRef(obj); // not effected
print(obj);
}
static void changeValue(int value){
value *= 2; // Primitives are directly passed as value, so this wont effect the passed value.
}
static void changeValues(int[] values){
for(int i = 0;i<values.length;++i) {
values[i] *= 2; //You are working on the value of the reference that is passed. The passed int[] is effected
}
}
static void changeRefValues(int[] values){
values = new int[]{0,0,0,0}; // you change the value of the reference that is passed. The passed int[] is not effected
}
static void changeVal(TestObj obj) {
obj.val *= 2; // You are working on the value of the reference that is passed. The passed TestObj is effected
}
static void changeRef(TestObj obj) {
obj = new TestObj(30); // You change the reference, but since it is passed as value it has no effect on the passed TestObj
}
// Only used to print values from here
static void print(int[] values) {
for (int i : values) {
print(i);
}
}
static void print(int i) {
System.out.println(i);
}
static void print(TestObj obj) {
System.out.println(obj.val);
}
}
output :/
Print single int: 1
Print int array:
1
2
3
4
Print TestObj val: 15
Changing single int value: 1
Changing array int values:
2
4
6
8
Changing array value of reference:
2
4
6
8
Changing val of TestObj
30
Changing TestObj value of reference
30
The answere is quite simple looking at the first code snippet:
public class test{
public static void main(String args[]){
int val = 10; //variable var in main method
System.out.println(val); // prints var of main method
Obj obj = new Obj();
obj.def(val);
System.out.println(val) // prints var of main method
}
}
public class OBJ{
public void def(int val){
val = 1; // variable val in OBJ method
}
}
As you might see. both variables are called "var" but only one is printed out. The var variable in your OBJ method is never used.
now the other Case:
public class test{
public static void main(String args[]){
double val[] = {0, 1, 2, 3, 4, 5}; //array is an object, variable var is a pointer to the location of that object in your heap
Obj obj = new Obj();
for(int i = 0; i < val.length; i++){
System.out.println(val[i]; // you print out every number located at the space in your heap your pointer is pointing at
}
obj.def(val);
for(int i = 0; i < val.length; i++){
System.out.println(val[i]; //prints out the overwritten values
}
}
}
public class OBJ{
public void def(double[] val){ //you give the method the pointer to the location of your numbers in heap
for(int i = 0; i < val.length; i++
val = 1; //you have the exact pointer to the exact objects in your heap therefore you overwrite them
}
}
Now to this part. Your var variable is a pointer to your var[] object in your heap (yeah arrays are objects). You give your def method the pointer to your object. Therefore the object can be accessed and overwritten.
To put it in a nutshell. In your first snippet you create two int variables with no connection to each other. In your second snipped you ceate an object and a variable that is pointing to it. In that case the object can be accessed via the pointer. You could also do something like this:
int[] sameArray = var;
In this case "sameArray" would NOT be another object, but a pointer to your var[] object.
I am sorry for my terrible english, I'll correct it as soon as possible
Related
I'm new to this site so let me know if this sort of question is welcome here.
I'm currently coding a class in java to store a set of integers in an array stored in an object and i'm having trouble reassigning the array variable store in the objects created. its not compiling as is(I'm a new programmer so i'm pretty sure i'm missing something simple here).
public class Set
{
// constructor
Set()
{
int array[] = {};
}
//adds a value to the set
public static void addValue(int [] array, int element)
{
int i;
int n = array.length;
int newArray[] = new int[n + 1];
//copy original array into new array
for (i = 0; i < n; i++)
newArray[i] = array[i];
//add element to the new array
newArray[n] = element;
//the issue is this line here
this.array = newArray;
}
//print the set
public static void printSet(int [] array)
{
int i;
int n = array.length;
System.out.print("{");
for (i = 0; i < n; i++)
{
System.out.print(array[i]);
}
System.out.println("}");
}
}
edit - error message returned is:
Set.java:23: error: non-static variable this cannot be referenced from a static context
this.array = newArray;
^
Set.java:23: error: cannot find symbol
this.array = newArray;
^
symbol: variable array
2 errors
First of all, you forgot to put the array inside the class, you can handle it privately like this before the constructor in this way:
private int [] array;
Constructor is used to initialize objects. If you create an empty constructor, you won't be able to pass it any parameters to initialize the array. You can create the constructor this way:
Set (int [] array){
this.array = array;
}
At line you indicated the compiler tells you that you cannot handle the method statically because you are working on an instance method. The "this" keyword is used as a reference to an instance. Since the static methods doesn't have (belong to) any instance you cannot use the "this" reference within a static method. So, you have to remove the static handling from the method. Also, since you want to return the array with the entered value, your method cannot be of type void. So, your method will be:
//adds a value to the set
public int [] addValue(int [] array, int element){
int newArray[] = new int[array.length + 1];
for (int i = 0; i < array.length; i++)
newArray[i] = array[i];
newArray[array.length] = element;
return newArray;
}
Since the length of the array was already available (array.length), it was not necessary to create the variable n, so I took the liberty of making some improvements to your code, to make it less redundant. Similarly, the method you created to print the array would be:
//print the set
public void printSet(int [] array){
System.out.print("{ ");
for (int i = 0; i < array.length; i++){
System.out.print(array[i] + " ");
}
System.out.println("} ");
}
However, once you've made these small changes your code should work fine. You can try to create a testing class like this, to check that everything works right:
public class TestingSet {
public static void main (String [] args){
//creating array
int [] array = {1, 2, 3};
//creating an instance of Set class
Set s = new Set(array);
//printing array
s.printSet(array);
//printing array with new value
s.printSet(s.addValue(array,4));
}
}
It looks like you are trying to access array however it cannot be seen by the addValue method.
You need to declare the array outside of the Set constructor:
public class Set
{
//New location to declear the array
int array[];
// constructor
Set()
{
//We can still initialize the array here
array[] = {};
}
Secondly, the reason for the error is that you cannot use this inside a static method. Static methods are not tied to an object (The Set class) so you need removed static from the method:
//static removed from this line
public void addValue(int [] array, int element)
{
Then to use the method you would create the Set object and use addValue something like this:
Set exampleSet = new Set();
exampleSet.addValue(yourArray, index);
The other option is to make the array a static value (it will no longer be specific to the object but shared with everything), but this is proberbly not the behaviour you want:
public class Set
{
//New location to declear the array
static int array[];
//And to access the object you could use
Set.array = newArray;
I need to create class that has a setter to assign values to an array, then in the main method take command line arguments and use the method to put that in an array. I have no clue how to do this. Any help would be appreciated.
import java.util.*;
public class Number{
private double [] number = new double[3];
private double value ;
private int i;
public double[] getNumber() {
return sweet;
}
public void printNumber() {
System.out.println("Array " + Arrays.toString(number));
}
public double getValue(int i) {
return this.i;
}
public void setMethod(int i, double value) {
this.value = value;
this.i = i;
}
public class Score {
public static void main (String [] args) {
Number score = new Number();
// code to get values from keyboard into the array
edit: Thank you for your help I managed to create the new array. Now I need to be able to change the array value. In my setMethod I am guessing I need to change it to something like this..,
public void setMethod(int i, double value { //
for ( i = 0; i < this.array.length; i ++){
this.array[this.i] =this. value;
}
this.mark = mark;
this.pos = pos;
}
If you look at main() method's list of arguments, you'll see String[] args - command line arguments are passed to the main() method as arguments. You can simply read them using a for loop:
String[] yourNewArray = new String[args.length]:
for(int i = 0; i< args.length; i++) {
yourNewArray[i] = args[i];
}
Now in yourNewArray you have stored command line arguments.
It is worth to mention that yourNewArray doesn't need to be an array containg Strings. Arguments passed as command line arguments can be parsed and used as, for example integers, doubles and other types of values.
Now, as you edited your question and have new thing to figure out, I will show you an example, how you could implement method to assign new array to an existing one and another method to change single value in this array:
import java.util.*;
// This is your class - there is String[] arr - you want to be able to change whole array or its single value:
class MyClass {
String[] arr;
// To change whole array:
public void setMethod(String[] array) {
this.arr = array;
}
// To change only one value in array:
public void changeSingleValue(int index, String value) {
arr[index] = value;
}
}
public class Test {
public static void main(String[] args) {
String[] arrayFromArgs = new String[args.length];
for(int i = 0; i < args.length; i++) {
arrayFromArgs[i] = args[i];
}
MyClass obj = new MyClass();
// In this method you assign array storing command line arguments to the array in MyClass:
obj.setMethod(arrayFromArgs);
System.out.println("obj.arr: " + Arrays.toString(obj.arr));
// Here is an example of assigning another array to obj.arr:
String[] anotherArray = { "A", "B", "C", "D"};
obj.setMethod(anotherArray);
System.out.println("obj.arr: " + Arrays.toString(obj.arr));
// Here is another way to assign new values to obj.arr:
obj.setMethod(new String[]{"x", "y", "z"});
System.out.println("obj.arr: " + Arrays.toString(obj.arr));
// Simple example how to change single value in obj.arr by passing the index where and value that needs to be changed:
obj.changeSingleValue(1, "Changed");
System.out.println("obj.arr: " + Arrays.toString(obj.arr));
}
}
And the output of the above program:
obj.arr: [] // in this array you will see values passed as the command line arguments
obj.arr: [A, B, C, D]
obj.arr: [x, y, z]
obj.arr: [x, Changed, z]
Try something like the following code to copy your array:
public static void main (String [] args) {
// code to get values from keyboard into the array
String[] myArgs = new String[args.length];
for (int i = 0; i < args.length; i++) {
myArgs[i] = args[i];
}
// ...
}
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 !
Is there a way for objects inside an array to detect what slot they are in? If I had a Object array, could a Object inside the array detect what cell it is in without being explicitly told?
Nope, unfortunately, how arrays work in Java is that the array simply "points" to an object. As a Java array only stores references (to objects), but any number of variables can reference the same object, so an Object has no idea where it lives in an array. In fact, the same object can be pointed to from several indices in the array!
Consider
Object o = new Object(); // The variable o has a "reference" to the Object in memory
Object[] arr = new Object[3]; // empty array to hold Object types
arr[0] = o; // the first index points to the Object we created above
arr[1] = o; // the second index points to that same object!
arr[2] = o; // still the same object! If we modified the original object (assuming it's not immutable) in any way, all the indices in this array would point to the modified object.
Hope this helps!
The fastest (easiest to write) way to iterate through an array of objects is
for (Object o : arr) {
// do something to the local variable o, which you can think of as representing each object in your array
}
No. If you need to do this, you probably have a design flaw. Why does an Object need to know where it appears in the array? If the index is of some semantic meaning or interest to the object, then the object should have an int field containing this information. If you are trying to modify the original array based on one object then you probably have a poorly-factored class somewhere, e.g. if something such as this is happening:
class A {
Object data[];
}
class B {
remove(A a, Object instance) {
// how to remove instance from a.data??
}
}
Then really B.remove should be a method of A and hence have access to data in the first place. And so forth.
Furthermore an array may just not be the right data structure. If the index has much semantic value a Map<Integer, Object> may be more appropriate, although arrays are often used to represent this when the indices are continuous from 1..n and the array is immutable. In my silly example with remove, a List would be more appropriate. Etc.
try
int i = Arrays.asList(arr).indexOf(obj);
As #Aaron_H said, no dice. I'll add that you can work around it with something like this:
public class Test {
public static void main(String[] args) {
ZenArray<IndexedString> z = new ZenArray(10);
for (int i = 0; i < z.size(); i++) {
z.set(i, new IndexedString("String " + i));
}
for (int i = 0; i < z.size(); i++) {
System.out.println("I'm at index " + z.get(i).getIndex());
}
}
}
class ZenArray<T extends ZenArray.IndexedElement> {
private Object [] a;
interface IndexedElement {
void setIndex(int i);
int getIndex();
}
public ZenArray(int size) {
a = new Object[size];
}
public void set(int i, T val) {
val.setIndex(i);
a[i] = val;
}
public T get(int i) {
return (T)a[i];
}
public int size() {
return a.length;
}
}
// An example of an indexed element implementation.
class IndexedString implements ZenArray.IndexedElement {
int i;
String val;
public IndexedString(String val) {
this.val = val;
}
public String getVal() {
return val;
}
#Override
public void setIndex(int i) {
this.i = i;
}
#Override
public int getIndex() {
return i;
}
}
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