簡體   English   中英

Java“指針”如何工作?

[英]How Java “pointers” work?

讓我們說這是C ++代碼:

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

要么

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

兩者都會改變全局x,對吧?

那我怎么能在java中做那樣的事情呢?
具體來說,我想指向一個Vector對象

但由於Java沒有指針,我不知道該怎么做。
從搜索互聯網上我看到人們說Java以其他方式做到了這一點,但我沒有找到任何真實的例子。

感謝幫助!

在Java中,您可以使用對象的引用而不是指針。 您不能通過引用傳遞基本類型,但可以將基本類型包裝在對象中,然后將引用傳遞給該對象。

Java提供了包裝int Integer類型,但是這種類型是不可變的,所以你不能在構造之后改變它的值。 但是你可以使用Apache Commons的MutableInt

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

調用者可以看到對x的更改。


具體來說,我想指向一個Vector對象

當你寫Vector v = ...; 您正在為變量v指定向量的引用 Java中的引用與指針非常相似。 實際上,引用是使用指針在內部實現的。

Java使用pass by value。 將向量傳遞給方法時,實際上是在復制對該向量的引用 它不會克隆載體本身。 因此,在Java中傳遞引用與在C ++中傳遞指針非常相似。

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

在這種情況下,我使用帶有泛型的holder類實現,但是你也可以有一個簡單的holder,只用於整數。 例如:

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

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類是不可變的,你可以使用Apache Commons庫中的MutableInt 要描述這是如何工作的,您可以自己為您的示例實現它:

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

希望這一切都有意義。

雖然您無法替換已傳遞給函數的對象,但您可以通過直接更改字段或調用方法來更改其狀態。 如果您需要類似指向基元的指針,請將其包裝在對象中。 要遵循您的代碼,您可以這樣做:

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

換句話說,我的數據往往已經包含在某種對象中,我傾向於使用數據對象的方法來調解任何更改。

兩者都會改變全局x,對吧?

那我怎么能在java中做那樣的事情呢? 具體來說,我想指向一個Vector對象

問題有些模糊,但我覺得你最終想要一個可以保存內容的全局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接口,我也在示例中使用過。)

Java支持它所謂的“引用”。 引用很像C / C ++中的指針 - 就像語言一樣。 它們的行為與“引用”在這些語言中的工作方式不同。

C中的指針與Java中的引用之間的主要區別是:

您不能在Java中執行指針運算(即,您不能從Java引用中“添加”或“減去”,您只能取消引用它或將其與另一個進行比較)。 您不能將其轉換為不兼容的類型:Java是強類型安全的,您不能將內存中的字節“重新解釋”為其他對象。 對於指針的某些用途,這沒有實際效果(例如鏈接列表在兩種語言中的工作方式幾乎相同),對於其他用途,差異非常大(C中的數組只是花哨的指針算術,在Java中它們的工作方式完全不同)。

因此,在某種程度上,Java引用可以稱為“受限指針”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM