简体   繁体   中英

How Java “pointers” work?

Lets say this is the C++ code:

void change(int& x){
    x++;
}

or

void change2(int* a){
    *a++;
}

Both will change the global x, right?

So how can I do something like that in java?
Specifically, I want to point to a Vector object

But since Java has no pointers, I'm not sure what to do.
From searching the internet I saw people saying that Java does that in some other way, but I haven't found any real example.

Thanks for help!

In Java, instead of pointers you have references to objects. You cannot pass a primitive type by reference, but you can wrap a primitive type inside an object and then pass a reference to that object.

Java provides the type Integer which wraps int , however this type is immutable so you cannot change its value after construction. You could however use MutableInt from Apache Commons:

void change(MutableInt x) {
    x.increment();
}

The change to x will be visible to the caller.


Specifically, I want to point to a Vector object

When you write Vector v = ...; you are assigning a reference to a vector to the variable v . A reference in Java is very similar to a pointer. References are in fact implemented internally using pointers.

Java uses pass by value. When you pass a vector to a method, you are actually copying a reference to that vector. It does not clone the vector itself. So passing a reference in Java is very similar to passing a pointer in C++.

With Java you cannot pass primitive types like int by reference, they are passed only by value.

The only things you can do is to find artifices to do that, because instead Objects are passed by reference. Here two examples.

Use an array of single value, like this

int[] value = new int[1];
value[0] = 2;

// call a method
obj.setValue(value);

// and in setValue
public void setValue(int[] value) {
  value[0] = 5;
}

Or second approach use an holder class:

public class Holder<T> {
  public T value;
  public Holder(T value) {
    this.value = value;
  }
}

// then use it in this way
Holder<Integer> h = new Holder<Integer>(2);

obj.setValue(h);

// and in setValue
public void setValue(Holder<Integer> h) {
  h.value = 5;
}

In this case I use an holder class implements with generics but you can have a simple holder too, only for integer. For example:

public class IntHolder {
  public int value;
  public IntHolder(int value) {
    this.value = value;
  }
}

Java always passes by value and there are no global variables as in the C++ sense. So if you want to do the same as in C++ you need to return the new value.

Thusly:

public int change(int x) {
    return ++x;
    // or 
    // return x + 1;
}

To test it:

int x = 2;

change(x);

System.out.println(x); // returns 2

x = change(x);

System.out.println(x); // returns 3

So it doesn't make any sense to let the method be called change , it is more sensible along the lines of calculateThisInt .


Java does pass objects by value. But as Mark Byers mentions the Integer class is immutable and you could use MutableInt from Apache Commons library. To describe how this works you could implement it yourself for your example:

public class MyInt() {

    public int i;

    public void setInt(int i) {
        this.i = i;
    }

    public int getInt() { 
        return this.i; 
    }

    public int increment() {
        this.i++;
    }

}

You need to change your change function to have the above MyInt object as argument:

public void change(MyInt i) {
    i.increment();
}

Usage:

MyInt x = new MyInt();
x.setInt(2);

change(x);

System.out.println(x.getInt); // returns 3

In your case you want to change a Vector object...

public void changeVector(Vector v) {
    // anything you do with 'v' will change it even
    // for the scope that called this method
}

// Usage:
Vector v = new Vector();
changeVector(v);
// v should be changed after calling change vector method

Hope this all makes sense.

While you can't replace an object that's been passed to a function, you can change its state by altering fields directly or calling methods. If you need something like a pointer to a primitive, wrap it in an object. To follow your code, you could do this:

public class IntPointer {
    public int value;
    public IntPointer(int value) {
        this.value = value;
    }
}

Then elsewhere you could say:

public static void change(IntPointer ipoint) {
    ipoint.value++;
}
public static void main(String[] args) {
    IntPointer a = new IntPointer(10);
    change(a);
}

This might seem a bit awkward, but it hasn't come up for me as often as you'd think. I'd be more likely to do something like this:

public class ABPair {
    private int a = 0;
    private int b = 0;
    public static void changeA() {
        a++;
    }
    public static void changeB() {
        b++;
    }
}

So that elsewhere I can say:

public static void main(String[] args) {
    ABPair ab = new ABPair();
    if (ACondition) {
        ab.changeA();
    }
}

In other words, my data tends to already be wrapped in some sort of object, and I tend to use the data object's methods to mediate any changes.

Both will change the global x, right?

So how can I do something like that in java? Specifically, I want to point to a Vector object

The question is somewhat vague, but I got the impression that you ultimately want a global Vector that you can keep stuff in?

Many ways to do that, but one of the simplest is to have a static field in a class, with public static methods for accessing it. (Or simply a public static field which is accessed directly, but that really wouldn't be idiomatic in Java.)

public class Foo {
    private static List<Integer> globalVector = new Vector<Integer>();

    public static void add(int number){
         globalVector.add(number);
    }

    // ... plus whatever other accessors to the global list that you need 
}

Anywhere else in code:

Foo.add(23); // modifies the global vector

(Btw, Vector is kinda obsolete, and typically we'd use ArrayList in its place now. As the Javadoc says, it's been retrofitted to implement the List interface, which I also used in the example.)

Java supports what it calls "references". References act alot like pointers in C/C++-like languages. They don't act the same way "references" work in those languages.

The major differences between a pointer in C and a reference in Java are:

You can't do pointer arithmetic in Java (ie you can't "add" or "subtract" from a Java reference, you can only dereference it or compare it with another one). You can't cast it to an incompatible type: Java is strongly type-safe, you can't "re-interpret" the bytes in memory as some other object. For some uses of pointers this has no real effect (for example linked lists work pretty much the same in both languages), for others the difference is quite major (arrays in C are just fancy pointer arithmetic, in Java they work quite differently).

So in a way Java references could be called "restricted pointers".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM