java指針的指針
『壹』 java中有沒有指針
首先,指針用於指向某一塊內存的地址,在C、C++中有明確的指針的概念,而在Java中,同樣會有指向某一塊內存地址的存在,但是不叫指針,在Java中稱之為 引用(reference),你可以理解為智能指針。可以這么說Java其實處處皆為指針,但是我們開發人員卻感覺不到而已。
『貳』 java為什麼沒有指針
為了安全。。。你不知道空指針有多麼可怕,而且,指針的操作也是很復雜的,容易出錯 而且,指針也不是什麼必須的東西,只是更加快一點而已,而java 程序慢一點其實沒什麼影響,它主要關注的是(那個術語我一時想不起來怎麼說了。。。)
『叄』 Java語言中的指針到底是個什麼東西
Java語言的一個優點就是取消了指針的概念,但也導致了許多程序員在編程中常常忽略了對象與引用的區別,本文會試圖澄清這一概念。並且由於Java不能通過簡單的賦值來解決對象復制的問題,在開發過程中,也常常要要應用clone()方法來復制對象。本文會讓你了解什麼是影子clone與深度clone,認識它們的區別、優點及缺點。
看到這個標題,是不是有點困惑:Java語言明確說明取消了指針,因為指針往往是在帶來方便的同時也是導致代碼不安全的根源,同時也會使程序的變得非常復雜難以理解,濫用指針寫成的代碼不亞於使用早已臭名昭著的GOTO語句。Java放棄指針的概念絕對是極其明智的。但這只是在Java語言中沒有明確的指針定義,實質上每一個new語句返回的都是一個指針的引用,只不過在大多時候Java中不用關心如何操作這個指針,更不用象在操作C++的指針那樣膽戰心驚。唯一要多多關心的是在給函數傳遞對象的時候。如下常式:
package reference;
c2.strBuff.append( change strBuff clone);
改成下面這樣:
c2.str.substring(0,5);
c2.strBuff.append( change strBuff clone);
去掉了重新賦值的過程,c2.str也就不能有變化了,我們的把戲也就露餡了。但在編程過程中只調用
c2.str.substring(0,5);
語句是沒有任何意義的。
應該知道的是在Java中所有的基本數據類型都有一個相對應的類,象Integer類對應int類型,Double類對應double類型等等,這些類也與String類相同,都是不可以改變的類。也就是說,這些的類中的所有方法都是不能改變其自身的值的。這也讓我們在編clone類的時候有了一個更多的選擇。同時我們也可以把自己的類編成不可更改的類。
參考資料: http://www.itwen.com/04web/07jsp/jsp20050912/17128.html
『肆』 java中指針怎麼理解
實際上,java力圖使程序員忘記指針,這包括2個方面:
第一,java限制指針,去除了指針運算。
第二,java從語法上努力隱藏指針,讓指向某對象的指針看起來更像那個對象本身!
是的,所有的java書籍都讓人忘記了指針這回事,我們彷彿只跟對象打交道。偶爾,會被迫分清引用和
對象的關系。這就是目前的情形。多麼好的想法!對象可比那些個不知所以的指針親和多了!這是一種偉大的抽象!
這里,我們也更願意把引用和對象混淆。是的,為什麼不呢?那樣,整個世界都是對象,太好理解了!
可事實上,為了節省內存,java不能把引用(指針)完全廢除。要知道,復制一個引用(指針)要比
復制整個對象有效得多!所以我們不得不面對引用和對象共存的事實。
下面我就好好分析分析:
指針已經被抽象成了引用,現在指針不能夠隨心所欲的運算,並且看起來就像個對象,完全沒有了指針
的模樣。但它畢竟和對象還是不同的,還要經過一層「轉換」(從指向的那個對象里取數據)。如果我們
在引用滿天飛的時候總想著這樣一層轉換,真的是很不舒服。比如:
String key="name";
String value="hyq";
HashMap map=new HashMap();
map.put(key,value);
你得想著:key只是個引用,value也是個引用,map還是個引用,我們剛剛做的是把key和value
這2個引用放進了map(也是個HashMap對象的引用)中,到時候我就可以通過map這個引用取得
裡面的對應於key引用的value引用!
你不暈我就服了。
一旦你這樣想,你每時每刻都要面對這樣的繞口令。因為我們對對象的操作全部要通過引用!java沒有提供語法讓你直接得到對象!(指的是直接定址)這一點通過比較原始類型很好理解,int i=8,那麼
i就是8,不是什麼指針,要先找到放著8那塊內存的地址再把8拿出來。這樣多直接,多方便啊!
所以,我們對引用最好也這么來理解,就輕松多了。
還是上面的例子,key就是個String,value也是個String,map是個HashMap,我們把key和value
放進map里,將來可以按key取出value。——多簡單!
其實,這樣的理解是很符合人的思維習慣的,我相信大多數人剛學java時都會自然而然的這么理解,
但是我們一定要注意在什麼時候不能這么理解。只要記住什麼時候不能這么理解,我們就不會因為
這種「近似」的理解方式而犯錯,而同時從這種理解方式里得到了方便和好處。
把引用直接當作對象本身的好處是簡單直接,容易理解,而「誤差」的地方就在於,假設只有這個引用
可以修改此對象。換句話說,當別的引用修改了對象的時候,我們毫不知情並很感費解。比如:
String name=null;
HashMap map=new HashMap();
map.put("name",name);
//do a lot of things
name="hyq";
當我們再從map里取出name的時候,發現它已經被賦值為hyq了!放進去的時候明明是啥都沒有啊!
咋就變了訥?
引用到name那個對象的不只你map一個阿!
在同一個函數里出現這種情況還不是很常見,我們一般也不必這么寫,更多的是出現在函數調用、傳參的時候,這樣更加隱蔽,不易發現,也讓代碼可讀性下降。比如:
String name=null;
HashMap map=new HashMap();
map.put("name",name);
alterName(name);
在alterName函數里我們修改了name對象,這會直接影響到函數外的map。
所以,當我們把引用和對象故意混淆時,一定要記住什麼時候應該分清楚。
對象的使用不外乎以下幾種情況:
1
String name=new String("hyq");
然後使用name,引用生命周期一結束,對象失效(無法被取用)了事。這里只有name一個引用指向此對象,隨便怎麼弄都不會出事。
2
String name=new String("hyq");
String anotherName=name;
這里假設只有name會修改對象,並且在anotherName引用此對象前做完所有修改,anotherName只是取用這個對象調用方法。在這種情況下,也不會出事。這也是我們經常遇到的情況,並且一般都是在函數調用傳參時出現。注意傳參實際上就是String anotherName=name;
這里尤其要注意的是2個引用的生命周期:name修改對象的時候另一個引用還沒出世,而等它出世後
發現它又不會修改對象,怎一個爽字了得!
3
String name=new String("hyq");
String anotherName=name;
代碼和上面一樣,但是這里要麼2個引用都會修改對象,要麼只有一個修改但會影響到另一個。這個時候無論如何你不能再把引用當對象了,你必須分清楚它們。你必須小心仔細,不能有絲毫疏忽。
當然,這種寫法和風格無論如何是不值得提倡的,若非必要(沒辦法)請勿模仿!因為必然有一個引用
在不知情的情況下被人修改了對象,等它用的時候會大吃一驚,而這個對象是在什麼時候被什麼人修改的,極難排查。
(上面例子舉得不好,String類是不變類,汗!)
StringBuffer name=new StringBuffer("hyq");
StringBuffer anotherName=name;
//do a lot of things
anotherName.append("is my gf");
你可能寫得爽,一時痛快就這么寫了,你也知道是什麼人在什麼時候修改了對象,但是別人呢?
要知道,這里可能不是相隔幾行代碼這么簡單,可能是嵌套了好幾層函數調用!你把那個anotherName傳到第5層函數裡面,然後喪心病狂的修改了那個對象,除了天知地知你知,鬼
都看不出來!
『伍』 JAVA為什麼會空指針異常
1.所謂的指針,就是java中的對象的引用。比如String s;這個s就是指針。 2.所謂的空指針,就是指針的內容為空,比如上面的s,如果令它指向null,就是空指針。 3.所謂的空指針異常,就是一個指針是空指針,你還要去操作它,既然它指向的是空對象,它就不能使用這個對象的方法。比如上面的s假如為null,你還要用s的方法,比如s.equals( String x);那麼就會產生空指針異常。
『陸』 java 中指針是怎麼定義的
Java語言的一個優點就是取消了指針的概念,但也導致了許多程序員在編程中常常忽略了對象與引用的區別,本文會試圖澄清這一概念。並且由於Java不能通過簡單的賦值來解決對象復制的問題,在開發過程中,也常常要要應用clone()方法來復制對象。本文會讓你了解什麼是影子clone與深度clone,認識它們的區別、優點及缺點。
看到這個標題,是不是有點困惑:Java語言明確說明取消了指針,因為指針往往是在帶來方便的同時也是導致代碼不安全的根源,同時也會使程序的變得非常復雜難以理解,濫用指針寫成的代碼不亞於使用早已臭名昭著的GOTO語句。Java放棄指針的概念絕對是極其明智的。但這只是在Java語言中沒有明確的指針定義,實質上每一個new語句返回的都是一個指針的引用,只不過在大多時候Java中不用關心如何操作這個指針,更不用象在操作C++的指針那樣膽戰心驚。唯一要多多關心的是在給函數傳遞對象的時候。如下常式:
package reference;
c2.strBuff.append( change strBuff clone);
改成下面這樣:
c2.str.substring(0,5);
c2.strBuff.append( change strBuff clone);
去掉了重新賦值的過程,c2.str也就不能有變化了,我們的把戲也就露餡了。但在編程過程中只調用
c2.str.substring(0,5);
語句是沒有任何意義的。
應該知道的是在Java中所有的基本數據類型都有一個相對應的類,象Integer類對應int類型,Double類對應double類型等等,這些類也與String類相同,都是不可以改變的類。也就是說,這些的類中的所有方法都是不能改變其自身的值的。這也讓我們在編clone類的時候有了一個更多的選擇。同時我們也可以把自己的類編成不可更改的類。
『柒』 java中指針操作是什麼意思
眾所周知,在java裡面是沒有指針的。那為何此處還要說java裡面的「指針」呢?我們知
道在C/C++中,指針是指向內存中的地址,該地址就是存儲變數的值。該地址所存儲的變數值是「公有」的,此處的「公有」是對於擁有該地址的變數而言。它
們都可以訪問該地址的內容,並且可對其就行修改,一經修改則所有指向該地址的變數值也將改變。那麼在Java裡面何來的指針?在java裡面沒有指針的定
義。但是java裡面的「指針」無處不在。下面將進行介紹。我們知道JAVA裡面用的最多的就是對象,我們經常將一個對象傳遞給不同的變數,例如:
Student s1 = new Student();
Student s2 = s1;
此時s1和s2是指向同一個對象的,也就是s1和s2引用同一個對象,我們知道java裡面創建一個對象是存放在堆的,當我們new一個對象的時候其實是
在堆中開辟了一個存儲該對象的空間,返回是的存儲該對象在堆中的地址,所以在java中我們所謂的對象引用就是指針,只是沒有像C/C++中給出了一個明
確的定義。java是為了避免指針帶來的使用上的麻煩,所以就使用對象的引用來代替了指針。上面的例子中,當我們在s1中進行修改Student中的屬性
的時候,那麼當s2取Student中屬性的值的時候便是取得了s1修改後的值,這是因為s1和s2是指向堆中的同一塊內容,所以只要其中一個變數修改了
堆中的值,則其他的變數將取得堆中最後更新的值。所以我們可以知道,s2=s1並不是又在堆中創建了一塊內存,而只是把一個對象的地址賦給了s2,此時還
是只是創建了一個對像,而不是兩個。在實際開發中會經常碰到這些,假設創建一個Map<String,Object>類型的對象,它的
value是一個對象,而key是一個字元串,定義如下:
class Student{
private String name;
private int age;
public void setAge(int age)
{
this.age = age;
}
public Student(String name)
{
this.name = name;
}
}
Map<String,Student> studentMap = new HashMap<String,Student>();
Student s1 = new Student("張三");
Student s2 = new Student("李四");
studentMap.put(s1.name,s1);
studentMap.put(s2.name,s2);
此處是一個學生姓名對應了一個
學生,所以此處的Map的key是學生姓名,value是一個學生對象。那麼就是將一個Student對象的引用賦給了Map中key所對應的
value,所以當程序在別處改變了s1/s2的值後,不必將s1和s2的信息更新到studentMap中,studentMap就會獲得key所對應
的value最新的值,例如:在程序的某處我們將s1的age修改成了「23」,我們不必將s1的最新信息更新到studentMap
中,studentMap就會獲得s1的最新值。這是因為已經將s1對象的引用賦給了studentMap中張三所對應的value,也就是將對象在堆中
的地址賦給了value。所以只要s1一更新,studentMap就可以獲得最新的值。
有時候這種情況會影響我們程序的執行和我們想想的會有偏差,當我們需要保存一個對象在某時刻的狀態時,按照一般的理解是將此時的對象賦給一個變數來進行
存儲,但是在java裡面這樣是行不通的!因為這樣直接將該對象賦給另一個變數只是將該對象的引用賦給了此變數,該變數的值並不能保持在此刻該對象的值,
會隨著程序的執行,該對象的改變而變化。所以達不到我們的目的。下面就舉個例子來說明解決該現象:
class Student{
private String name;
private int age;
public void setAge(int age)
{
this.age = age;
}
public Student(String name)
{
this.name = name;
}
public Student(Student student)
{
this.name = student.name;
this.age = student.age;
}
}
上面還是student類,基
本和上面一樣,只是多添加了一個構造函數——Student(Student
student),為什麼要多加這樣一個函數呢?這就是為了滿足我們上面的需求(保存對象某個時刻下的狀態),我們知道直接將一個對象賦給一個變數會存在
對象的引用,不能保存對象某時刻的狀態。同時也知道要想保存一個對象就要在堆中開辟一個空間,用於存放我們的對象。其實上面的需求可以看做當我們要保存某
時刻下對象的狀態,其實就是該對象的狀態不會隨以後對象的變化而變化,所以何不將當前某時刻下對象的狀態屬性全部都復制到一個新的對象中去!這樣保存下來
的屬性就不會受以後對象的變化而變化了。就上面的例子,舉例說明:
Student s1 = new Student("王麻子");
s1.age=23;
........
//此時要保存s1此刻的狀態
Student s2 = new Student(s1);
此時s1和s2就不是指向堆中的一個地址了,因為s2不是直接將s1賦給它的,而是通過new出來的!上面說了new可以在堆中開辟一個存儲當前new的
對象的空間。這種操作可以實現將s1中的狀態全都轉移到s2中,所以在值的方面看s2和s1此時是一樣的,但是在堆中確實不一樣的,s1!=s2,因為
s1和s2的hashcode不一樣!但是s1.name.equal(s2.name)==ture,s1.age=s2.age。這不就實現了保存某
個對象某個時刻下的狀態了嗎?而切不會在受程序執行的影響!
到此已全部介紹完有關java「指針」,其實java「指針」就是對象的引用,而對象就是存放在堆中的。我們知道java中的內存分為堆內存(heap)
和棧內存(stack)。堆就是用來存放對象的,而棧則是存放一些數據基本類型的值,如int,float,double,char.......。
『捌』 java中到底有沒有指針
學過c/c++,然後學Java的人往往心中有此糾結,java中到底有沒有指針?
如果一定要在是或否里選擇一個,OK,java中沒有指針。
那麼,java中的引用(reference)和c/c++中的指針(如無特別說明,後文指針均指c/c++中的指針)究竟有著什麼樣糾葛不清的關系呢?
在開始之前先說一下c/c++的引用,它跟java的引用完全不是一個東西,c/c++的引用是同一塊內存的不同名字。而java的引用是指向一個對象,引用本身也佔用了內存。
首先,列舉一下能對指針進行的一些常見操作:
1、指向一個對象,如 Person *p = new Person….;int *iv = new int….
2、對指針所指的對象進行操作:P->getAge(); (*p).getAge();
3、獲取存儲在指針中的地址值。
4、將指針指向另外一個對象:Person *p1 = new Person…; p = p1; 但,不可以*p = p1這樣來賦值。
5、刪除new的空間,delete p1;
6、其它諸多操作
這么多已經足夠了,接下來看看java引用能做什麼操作。
a、指向一個對象,如Person p = new Person…
b、調用對象的方法,p.getAge();
c、指向另外一個對象,Person p1 = new Person…; p = p1;
OK,就這么多了。
對於a和1,他們的功能是類似的,但java引用無法指向一個基本變數。。
對於b,java引用和指針就不同了,在這點上,Java reference更像是解引用(dereference)了的指針;或者說java中的.操作符某種程度上等價於指針的->操作符,如果是這樣種解釋的話,我們無法再對java的reference解引用了。
對c和4,是類同的。
除此,我們無法獲取java引用存的地址,我們不能delete,還有很多……
綜上,竊以為java的引用可以看成是一個功能受限的指針(或者說被閹割的指針)。另一方面,功能如此受限,它還能叫指針嗎?了解了指針和java引用的區別與聯系,還需要糾結「java中有沒有指針」這個問題嗎!