6

假设这是 C++ 代码:

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

或者

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

两者都会改变全局 x,对吧?

那么我怎么能在java中做这样的事情呢?
具体来说,我想指向一个 Vector 对象

但由于 Java 没有指针,我不知道该怎么做。
通过搜索互联网,我看到人们说 Java 以其他方式做到这一点,但我没有找到任何真实的例子。

感谢帮助!

4

6 回答 6

13

在 Java 中,不是指针,而是对对象的引用。您不能通过引用传递原始类型,但可以将原始类型包装在对象中,然后传递对该对象的引用。

Java 提供了Integerwraps的类型int,但是这种类型是不可变的,因此您无法在构造后更改其值。但是,您可以MutableInt从 Apache Commons 使用:

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

对 x 的更改将对调用者可见。


具体来说,我想指向一个 Vector 对象

当您编写时,您正在为变量Vector v = ...;分配对向量的引用v。Java 中的引用与指针非常相似。引用实际上是在内部使用指针实现的。

Java 使用按值传递。将向量传递给方法时,实际上是在复制对该向量的引用。它不会克隆载体本身。因此,在 Java 中传递引用与在 C++ 中传递指针非常相似。

于 2012-04-15T08:36:55.013 回答
4

使用 Java,您不能像int通过引用一样传递原始类型,它们只能通过值传递。

您唯一能做的就是找到技巧来做到这一点,因为它Objects是通过引用传递的。这里举两个例子。

使用单值数组,像这样

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;
}

或者第二种方法使用持有者类:

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;
}

在这种情况下,我使用带有泛型的持有者类实现,但您也可以有一个简单的持有者,仅适用于整数。例如:

public class IntHolder {
  public int value;
  public IntHolder(int value) {
    this.value = value;
  }
}
于 2012-04-15T08:46:32.243 回答
1

Java 总是按值传递,并且没有 C++ 意义上的全局变量。因此,如果您想在 C++ 中执行相同的操作,则需要返回新值。

因此:

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

要测试它:

int x = 2;

change(x);

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

x = change(x);

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

所以让方法被调用没有任何意义,change按照calculateThisInt.


Java 确实按值传递对象。但正如Mark Byers提到的,Integer类是不可变的,您可以MutableInt从 Apache Commons 库中使用。为了描述它是如何工作的,您可以自己为您的示例实现它:

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++;
    }

}

您需要更改change函数以将上述MyInt对象作为参数:

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

用法:

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

change(x);

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

在您的情况下,您想更改Vector对象...

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

希望这一切都有意义。

于 2012-04-15T08:39:45.933 回答
0

虽然您无法替换已传递给函数的对象,但您可以通过直接更改字段或调用方法来更改其状态。如果您需要类似指向原语的指针,请将其包装在一个对象中。要遵循您的代码,您可以这样做:

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

然后在其他地方你可以说:

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

这可能看起来有点尴尬,但它并没有像你想象的那样经常出现。我更有可能做这样的事情:

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

所以在其他地方我可以说:

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

换句话说,我的数据往往已经包装在某种对象中,并且我倾向于使用数据对象的方法来调解任何更改。

于 2012-04-15T09:08:09.893 回答
0

两者都会改变全局 x,对吧?

那么我怎么能在java中做这样的事情呢?具体来说,我想指向一个 Vector 对象

这个问题有点模糊,但我的印象是你最终想要一个可以保存东西的全局向量?

有很多方法可以做到这一点,但最简单的方法之一是在类中拥有一个静态字段,并使用公共静态方法来访问它。(或者只是一个可以直接访问的公共静态字段,但这在 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 
}

代码中的其他任何地方:

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

(顺便说一句,Vector有点过时了,通常我们现在会使用 ArrayList 代替它。正如 Javadoc 所说,它已经过改造以实现 List 接口,我也在示例中使用了该接口。)

于 2012-04-15T09:33:20.520 回答
0

Java 支持它所谓的“引用”。引用的行为很像 C/C++ 类语言中的指针。它们的行为方式与这些语言中的“参考”工作方式不同。

C 中的指针和 Java 中的引用之间的主要区别是:

您不能在 Java 中进行指针运算(即,您不能从 Java 引用中“添加”或“减去”,您只能取消引用它或将其与另一个引用进行比较)。您不能将其转换为不兼容的类型:Java 是强类型安全的,您不能将内存中的字节“重新解释”为其他对象。对于指针的某些用途,这没有真正的影响(例如,链表在两种语言中的工作方式几乎相同),对于其他人来说,差异很大(C 中的数组只是花哨的指针算法,在 Java 中它们的工作方式完全不同)。

所以在某种程度上,Java 引用可以称为“受限指针”。

于 2017-11-27T15:03:03.283 回答