मुझे पता है कि जावा में पॉइंटर्स नहीं हैं, लेकिन मैंने सुना है कि जावा प्रोग्राम पॉइंटर्स के साथ बनाए जा सकते हैं और यह उन कुछ लोगों द्वारा किया जा सकता है जो जावा में विशेषज्ञ हैं। क्या यह सच है?
मुझे पता है कि जावा में पॉइंटर्स नहीं हैं, लेकिन मैंने सुना है कि जावा प्रोग्राम पॉइंटर्स के साथ बनाए जा सकते हैं और यह उन कुछ लोगों द्वारा किया जा सकता है जो जावा में विशेषज्ञ हैं। क्या यह सच है?
जवाबों:
जावा में सभी ऑब्जेक्ट संदर्भ हैं और आप उन्हें पॉइंटर्स की तरह उपयोग कर सकते हैं।
abstract class Animal
{...
}
class Lion extends Animal
{...
}
class Tiger extends Animal
{
public Tiger() {...}
public void growl(){...}
}
Tiger first = null;
Tiger second = new Tiger();
Tiger third;
एक अशक्त करना:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
अलियासिंग समस्या:
third = new Tiger();
first = third;
सेल खोना:
second = third; // Possible ERROR. The old value of second is lost.
आप पहले यह आश्वासन देकर सुरक्षित कर सकते हैं कि दूसरे के पुराने मूल्य की कोई आवश्यकता नहीं है या दूसरे सूचक को दूसरे का मान निर्दिष्ट करने की आवश्यकता नहीं है।
first = second;
second = third; //OK
ध्यान दें कि दूसरे तरीकों से एक मूल्य देना (NULL, नया ...) बस एक संभावित त्रुटि है और इसका परिणाम उस वस्तु को खोने में हो सकता है जो इसे इंगित करता है।
OutOfMemoryError
जब आप नया कॉल करेंगे तो जावा सिस्टम एक अपवाद ( ) फेंक देगा और आवंटनकर्ता अनुरोधित सेल को आवंटित नहीं कर सकता है। यह बहुत दुर्लभ है और आम तौर पर भाग-दौड़ पुनरावृत्ति के परिणामस्वरूप होता है।
ध्यान दें कि, भाषा की दृष्टि से, कचरा संग्रहकर्ता को वस्तुओं को छोड़ना बिल्कुल भी त्रुटि नहीं है। यह सिर्फ कुछ है जो प्रोग्रामर को जागरूक होना चाहिए। एक ही चर अलग-अलग समय पर अलग-अलग वस्तुओं को इंगित कर सकता है और जब कोई पॉइंटर उन्हें संदर्भित करता है तो पुराने मूल्यों को पुनः प्राप्त किया जाएगा। लेकिन अगर कार्यक्रम के तर्क में ऑब्जेक्ट के कम से कम एक संदर्भ को बनाए रखने की आवश्यकता होती है, तो यह एक त्रुटि का कारण होगा।
Novices अक्सर निम्न त्रुटि करते हैं।
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
आपके कहने का मतलब क्या था:
Tiger tony = null;
tony = third; // OK.
अनुचित कास्टिंग:
Lion leo = new Lion();
Tiger tony = (Tiger)leo; // Always illegal and caught by compiler.
Animal whatever = new Lion(); // Legal.
Tiger tony = (Tiger)whatever; // Illegal, just as in previous example.
Lion leo = (Lion)whatever; // Legal, object whatever really is a Lion.
सी में संकेत:
void main() {
int* x; // Allocate the pointers x and y
int* y; // (but not the pointees)
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
*y = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
*y = 13; // Dereference y to store 13 in its (shared) pointee
}
जावा में संकेत:
class IntObj {
public int value;
}
public class Binky() {
public static void main(String[] args) {
IntObj x; // Allocate the pointers x and y
IntObj y; // (but not the IntObj pointees)
x = new IntObj(); // Allocate an IntObj pointee
// and set x to point to it
x.value = 42; // Dereference x to store 42 in its pointee
y.value = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
y.value = 13; // Deference y to store 13 in its (shared) pointee
}
}
अद्यतन: जैसा कि टिप्पणियों में सुझाया गया है कि किसी को ध्यान देना चाहिए कि सी सूचक अंकगणित है। हालाँकि, जावा में हमारे पास ऐसा नहीं है।
जावा में संकेत हैं। किसी भी समय आप जावा में एक ऑब्जेक्ट बनाते हैं, आप वास्तव में ऑब्जेक्ट को एक पॉइंटर बना रहे हैं; यह पॉइंटर तब किसी भिन्न ऑब्जेक्ट या पर सेट किया जा सकता है null
, और मूल ऑब्जेक्ट अभी भी मौजूद रहेगा (लंबित कचरा संग्रह)।
आप जावा में क्या नहीं कर सकते हैं सूचक अंकगणित है। आप किसी विशिष्ट मेमोरी एड्रेस को डिफाइन नहीं कर सकते हैं या पॉइंटर को बढ़ा सकते हैं।
यदि आप वास्तव में निम्न-स्तर प्राप्त करना चाहते हैं, तो ऐसा करने का एकमात्र तरीका जावा नेटिव इंटरफ़ेस है ; और फिर भी, निम्न-स्तरीय भाग को C या C ++ में किया जाना चाहिए।
चूंकि जावा में कोई संकेतक डेटा प्रकार नहीं है, इसलिए जावा में पॉइंटर्स का उपयोग करना असंभव है। यहां तक कि कुछ विशेषज्ञ जावा में पॉइंटर्स का उपयोग करने में सक्षम नहीं होंगे।
अंतिम बिंदु भी देखें: जावा भाषा पर्यावरण
जावा में पॉइंटर्स हैं, लेकिन आप उन्हें उस तरह से जोड़ नहीं सकते हैं जो आप C ++ या C. में कर सकते हैं। जब आप कोई ऑब्जेक्ट पास करते हैं, तो आप उस ऑब्जेक्ट के लिए एक पॉइंटर पास कर रहे हैं, लेकिन C ++ की तरह ही नहीं। उस वस्तु को निष्क्रिय नहीं किया जा सकता है। यदि आप इसके मूल एक्सेसर्स का उपयोग करके इसके मान सेट करते हैं, तो यह बदल जाएगा क्योंकि जावा पॉइंटर के माध्यम से अपनी मेमोरी लोकेशन जानता है। लेकिन सूचक अपरिवर्तनीय है। जब आप पॉइंटर को एक नए स्थान पर सेट करने का प्रयास करते हैं, तो आप दूसरे के समान नाम के साथ एक नए स्थानीय ऑब्जेक्ट के साथ समाप्त होते हैं। मूल वस्तु अपरिवर्तित है। यहाँ अंतर प्रदर्शित करने के लिए एक संक्षिप्त कार्यक्रम है।
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
public static void main(String[] args) throws java.lang.Exception {
System.out.println("Expected # = 0 1 2 2 1");
Cat c = new Cat();
c.setClaws(0);
System.out.println("Initial value is " + c.getClaws());
// prints 0 obviously
clawsAreOne(c);
System.out.println("Accessor changes value to " + c.getClaws());
// prints 1 because the value 'referenced' by the 'pointer' is changed using an accessor.
makeNewCat(c);
System.out.println("Final value is " + c.getClaws());
// prints 1 because the pointer is not changed to 'kitten'; that would be a reference pass.
}
public static void clawsAreOne(Cat kitty) {
kitty.setClaws(1);
}
public static void makeNewCat(Cat kitty) {
Cat kitten = new Cat();
kitten.setClaws(2);
kitty = kitten;
System.out.println("Value in makeNewCat scope of kitten " + kitten.getClaws());
//Prints 2. the value pointed to by 'kitten' is 2
System.out.println("Value in makeNewcat scope of kitty " + kitty.getClaws());
//Prints 2. The local copy is being used within the scope of this method.
}
}
class Cat {
private int claws;
public void setClaws(int i) {
claws = i;
}
public int getClaws() {
return claws;
}
}
इसे Ideone.com पर चलाया जा सकता है।
Java में C जैसे पॉइंटर्स नहीं हैं, लेकिन यह आपको ढेर पर नई ऑब्जेक्ट बनाने की अनुमति देता है जो कि चर द्वारा "संदर्भित" हैं। पॉइंटर्स की कमी जावा प्रोग्राम्स को अवैध रूप से मेमोरी स्थानों को संदर्भित करने से रोकना है, और यह भी कचरा संग्रह को जावा वर्चुअल मशीन द्वारा स्वचालित रूप से बाहर करने में सक्षम बनाता है।
आप असुरक्षित वर्ग का उपयोग करके पते और संकेत का उपयोग कर सकते हैं। हालांकि जैसा कि नाम से पता चलता है, ये तरीके UNSAFE और आम तौर पर एक बुरा विचार हैं। गलत उपयोग आपके JVM को बेतरतीब ढंग से मर सकता है (वास्तव में यही समस्या सी / सी ++ में गलत तरीके से पॉइंटर्स का उपयोग करने पर मिलती है)
जब आपको संकेत करने के लिए इस्तेमाल किया जा सकता है और आपको लगता है कि आपको उनकी आवश्यकता है (क्योंकि आप किसी अन्य तरीके से कोड करना नहीं जानते हैं), तो आप पाएंगे कि आप नहीं करते हैं और आप इसके लिए बेहतर होंगे।
तकनीकी रूप से, सभी जावा ऑब्जेक्ट पॉइंटर्स हैं। सभी आदिम प्रकार हालांकि मान हैं। उन बिंदुओं का मैनुअल नियंत्रण लेने का कोई तरीका नहीं है। जावा केवल आंतरिक रूप से पास-बाय-संदर्भ का उपयोग करता है।
नहीं वास्तव में कोई नहीं।
जावा में संकेत नहीं हैं। यदि आप वास्तव में चाहते थे कि आप प्रतिबिंब जैसी किसी चीज के आसपास निर्माण करके उनका अनुकरण करने की कोशिश कर सकें, लेकिन यह सभी बिंदुओं की जटिलता के साथ होगा जिनमें से कोई भी लाभ नहीं है ।
जावा में पॉइंटर्स नहीं हैं क्योंकि उन्हें इसकी आवश्यकता नहीं है। इस सवाल से आप किस तरह के जवाब की उम्मीद कर रहे थे, यानी गहराई से आपको उम्मीद थी कि आप उन्हें किसी चीज़ के लिए इस्तेमाल कर सकते हैं या यह सिर्फ उत्सुकता थी?
जावा में सभी वस्तुओं को प्राइमरी को छोड़कर संदर्भ प्रतिलिपि द्वारा कार्यों के लिए पारित किया जाता है।
वास्तव में, इसका मतलब यह है कि आप सूचक की एक प्रति मूल वस्तु की बजाय एक वस्तु को भेज रहे हैं।
कृपया एक टिप्पणी छोड़ें यदि आप इसे समझने के लिए एक उदाहरण चाहते हैं।
swap
जावा में एक फ़ंक्शन नहीं लिख सकते हैं जो दो वस्तुओं को स्वैप करेगा।
जैसा कि दूसरों ने कहा है, संक्षिप्त उत्तर "नहीं" है।
ज़रूर, आप जेएनआई कोड लिख सकते हैं जो जावा पॉइंटर्स के साथ खेलता है। आप जो हासिल करने की कोशिश कर रहे हैं, उसके आधार पर, हो सकता है कि यह आपको कहीं मिल जाए और शायद ऐसा न हो।
आप हमेशा एरे बनाकर और इंडेक्स के साथ एरे में काम करके पॉइंट्स का अनुकरण कर सकते हैं। फिर, जो आप पूरा करने की कोशिश कर रहे हैं, उसके आधार पर, जो उपयोगी हो सकता है या नहीं।
गॉडफ्रे नोलन द्वारा Decompiling Android नाम की पुस्तक से
सुरक्षा तय करती है कि जावा में पॉइंटर्स का उपयोग नहीं किया जाता है इसलिए हैकर्स किसी एप्लिकेशन से बाहर और ऑपरेटिंग सिस्टम में नहीं जा सकते। कोई संकेत का मतलब यह नहीं है कि कुछ और ---- इस मामले में, जेवीएम ---- को आवंटन और मुक्त स्मृति का ख्याल रखना होगा। मेमोरी लीक भी अतीत की बात बन जाना चाहिए, या इसलिए सिद्धांत जाता है। C और C ++ में लिखे गए कुछ एप्लिकेशन एक छलनी की तरह मेमोरी को लीक करने के लिए कुख्यात हैं क्योंकि प्रोग्रामर उचित समय पर अवांछित मेमोरी को मुक्त करने पर ध्यान नहीं देते हैं ---- ऐसा नहीं है कि इसे पढ़ने वाला कोई भी व्यक्ति ऐसे पाप का दोषी होगा। कचरा संग्रह भी प्रोग्रामर को अधिक उत्पादक बनाना चाहिए, जिसमें डिबगिंग मेमोरी समस्याओं पर कम समय खर्च होता है।
आप शाब्दिक रूप से भी संकेत दे सकते हैं। आपको उन्हें स्वयं लागू करना होगा। यह विशेषज्ञों के लिए बहुत बुनियादी है;)। इंट / ऑब्जेक्ट / लॉन्ग / बाइट और वॉइला की एक सरणी का उपयोग करें जो आपके पास पॉइंटर्स को लागू करने के लिए मूल बातें हैं। अब कोई भी int value उस array int [] का पॉइंटर हो सकता है। आप पॉइंटर को बढ़ा सकते हैं, आप पॉइंटर को बढ़ा सकते हैं, आप पॉइंटर को गुणा कर सकते हैं। आप वास्तव में सूचक अंकगणित है! यह 1000 इंट एट्रिब्यूट कक्षाओं को लागू करने का एकमात्र तरीका है और एक जेनेरिक पद्धति है जो सभी विशेषताओं पर लागू होती है। आप इंट [] के बजाय एक बाइट [] सरणी का भी उपयोग कर सकते हैं
हालाँकि, मैं चाहता हूँ कि जावा आपको संदर्भ द्वारा शाब्दिक मान दे। रेखाओं के साथ कुछ
//(* telling you it is a pointer)
public void myMethod(int* intValue);
सभी जावा ऑब्जेक्ट पॉइंटर हैं क्योंकि एक वैरिएबल जो एड्रेस को रखता है उसे पॉइंटर और ऑब्जेक्ट होल्ड एड्रेस कहा जाता है। ऑब्जेक्ट पॉइंटर वेरिएबल है।