[英]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.