السلام عليكم ورحمة الله تعالى وبركاته
أنا مبتدئ في الجافا، وأظن أن مشكلتي واضحة من العنوان، فهل هذا هو الـ Standard المستخدم ؟
السلام عليكم ورحمة الله تعالى وبركاته
أنا مبتدئ في الجافا، وأظن أن مشكلتي واضحة من العنوان، فهل هذا هو الـ Standard المستخدم ؟
تم تعديل هذه المشاركة بواسطة zirek99i في 13 نوفمبر 2013 في 01:26
أهلاً أخي :)
بصراحة لا أدري لماذا هناك اعتقاد بأن جافا لا تحوي مؤشّرات .. بالعكس .. جافا لا تحوي غير المؤشرات !
فالمؤشر حسب التعريف هو متغير صحيح يحوي عنواناً .. وهذا بالضبط حال جميع كائنات جافا .. ليست إلا مؤشرات للكائن ..
مثلا في C
string x;
بدون مؤشرات ..
string *x=new string();
مع مؤشرات ...
اما جافا فلا تسمح لك إلا بــ :
String x=new String();
يسمّونها مرجعيات Reference ولكنها عين المؤشرات ..
وتمرير الكائنات دائما يكون بالمرجع ( أي مؤشر ) وليس بالقيمة .
الخلاصة : ما الذي يمكنك عمله بالمؤشرات ولا يمكنك عمله داخل جافا ؟ معرفة العنوان الحقيقي للعنصر ؟ أصلاً جافا تستعمل آلة افتراضية :D ماذا غير ذلك ؟ لا شيء !!
(كله رأي شخصي ولم أقرأه في أي مكان .. واحتمال الخطأ كبير )
بما أنك قادم من ++C فما رأيك بالدخول بسرعة خاطفة والاطلاع على مقالات :انتقل من ++C إلى Java بسلاسة ..
بالتوفيق
حسنا، ماتقولونه يبدو منطقياً جداً،
صحح لي ما يلي إن كنت مخطئاً،
عندما أقوم بتعريف Instance جديدة لـ Class بالشكل التالي:
String str = new String ();
فإن ماأقوم به، هو إنشاء Reference بالـ Stack الى String التي يتم حجز مساحتها في الـ Heap، ما يعني أن الكود السابق هو مرادف لآستخدام malloc في السي أو new في السي++، أو HeapAlloc بالويندوز .. الخ، المهم، أنني على سرت على نفس المنطق وقمت بإنشاء الكود التالي:
class Zirek99i
{
private int id;
private String name;
public Zirek99i (int id, String name)
{
this.id = id;
this.name = name;
}
public String toString() {
return "Zirek99i [id=" + id + ", name=" + name + "]";
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
Zirek99i zr = new Zirek99i(18, "OUSSAMA");
System.out.println(zr.toString());
/* this passed the value reside on the stack */
printInfo(zr);
System.out.println(zr.toString());
}
static void printInfo(Zirek99i zr)
{
/* This print the info from the heap */
System.out.println(zr.toString());
zr.setId(99);
/* The original data is damaged LOST - */
System.out.println(zr.toString());
System.out.println();
}
}لكن الداتا قد تعرضت للتلف أثناء إستخدام الدالة، المهم قمت بتعديل طفيف على الـ Methods وإضافة الـ Getters و Setters كما بالكود التالي:
static void printInfo(Zirek99i zr)
{
Zirek99i ri = new Zirek99i (zr.getId(), zr.getName());
System.out.println(ri.toString());
ri.setId(888);
ri.setName("ZIREK99I");
System.out.println(ri.toString());
}حسنا، لقد قمت بحل المشكل لكنني غير راض عن هذا الحل، لأنه غش، المهم إستخدمت نفس الطريقة، مع الكلاس التي أريد إستخدامها، والتي من أجلها طرحت السؤال بالمنتدى،
public class Test {
public static void main(String[] args) {
LinkedList<String> Active_hosts = new LinkedList<>();
Active_hosts.add("host_1");
Active_hosts.add("host_2");
Active_hosts.add("host_3");
Active_hosts.add("host_4");
Active_hosts.add("host_5");
printAvailableHosts(Active_hosts);
}
static void printInfo(LinkedList<String> ls)
{
/*
* how can i filter, remove unwanted items using this methods
* without affecting the original one?
*
* i guess that it must be a simple way, to accomplish my gool, like just passing by
* value something may look like: static void printInfo(new LinkedList<String> ls)
*
* but it did not compile
*/
/*
* this is my attempt:
*/
// .. not working deleted !!
return;
}
static void printAvailableHosts(LinkedList<String> ls)
{
System.out.println("number of available hosts: " + ls.size());
for (Iterator<String> iterator = ls.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
return;
}
}لكن، صراحة لم أعلم من أين أبدأ؟
تم تعديل هذه المشاركة بواسطة zirek99i في 13 نوفمبر 2013 في 03:25
السلام عليكم
بداية, أحب أن أؤكد أنه لا وجود للمؤشرات في الجافا :)
@مصطفى
باستخدام الـ references في الجافا, هل يمكنك كتابة كود مُكافئ لـ :
char * string_in() {
char c = 0;
char * tmp = NULL;
int length = 100;
int size = -1;
tmp = (char *) calloc(sizeof (char), length);
while ((c = getchar()) != '\n') {
if (size++ == length) length += length, tmp = (char *) realloc(tmp, sizeof (char) * length);
if (tmp == NULL) {
printf("No free memory for string!\n");
exit(-1);
}
tmp[size] = c;
}
tmp = (char *) realloc(tmp, sizeof (char) * size);
if (tmp == NULL) {
printf("No free memory for string!\n");
exit(-1);
}
return tmp;
}أو كود آخر يُكافئ هذا مثلا :
bool is_number(const char* number_string) {
int counter = 0;
while (*number_string) {
char c = *number_string++;
if (c == '.') {
counter++;
if (counter > 1)
return false;
} else {
if (!std::isdigit(c))
return false;
}
}
return true;
}هناك بعض الملاحظات المهمة بخصوص الـ references في الجافا :
بما أنك جديد على الجافا و قادم من السي++, أنصحك بقراءة هذا الكتاب, سيفيدك جداً.
تحياتي.
تم تعديل هذه المشاركة بواسطة Snack3r في 13 نوفمبر 2013 في 03:51
C++ and Java, say, are presumably growing faster than plain C, but I bet C will still be around. ― Dennis Ritchie
~OoO~________--------------------------------------------________~OoO~
من مواضيعي :
لقد حللت المشكل ;) ، وفهمت طريقة عمل الـ references في الجافا، شكرا لك Snacker و مصطفي
import java.util.Iterator;
import java.util.LinkedList;
public class Test {
public static void main(String[] args) {
LinkedList<String> Active_hosts = new LinkedList<>();
Active_hosts.add("host_1");
Active_hosts.add("host_2");
Active_hosts.add("host_3");
Active_hosts.add("host_4");
Active_hosts.add("host_5");
System.out.println("the original");
printAvailableHosts(Active_hosts);
editInfo(Active_hosts);
System.out.println("in the end");
printAvailableHosts(Active_hosts);
}
static void editInfo(LinkedList<String> ls) {
LinkedList<String> k = new LinkedList<String>(ls);
System.out.println("Inside the editInfo methods");
printAvailableHosts(k);
k.removeFirst();
k.removeLast();
printAvailableHosts(k);
System.out.println();
return;
}
static void printAvailableHosts(LinkedList<String> ls) {
System.out.println("number of available hosts: " + ls.size());
for (Iterator<String> iterator = ls.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
return;
}
}يبدو أنك حللت المشكلة فقط بالنسبة لحالة LinkedList أو الكائنات التي تأخذ وسيطا في بانيها كائناً آخر ..
ولكن سأتابع ردي الذي كتبته
اقتباسصحح لي ما يلي إن كنت مخطئاً،
عندما أقوم بتعريف Instance جديدة لـ Class بالشكل التالي:
String str = new String (); فإن ماأقوم به، هو إنشاء Reference بالـ Stack الى String التي يتم حجز مساحتها في الـ Heap، ما يعني أن الكود السابق هو مرادف لآستخدام malloc في السي أو new في السي++، أو HeapAlloc بالويندوز .. الخ
كلام صحيح ويدل على فهمك للأمر ..
يوماً عن يوم .. أزداد ثقة بأن جافا تتعامل مع المؤشرات
__________________________________________
بالنسبة لسؤالك أخي Zi فهو يؤكّد كلامي .. لا يوجد في جافا تمرير للكائنات إلا بالمرجع أي كأنك تستند مؤشرات لبعضها ..
وبالنسبة لسؤالك
/*
* how can i filter, remove unwanted item for this methods
* without affecting the original one?
*
* i guess that it must a simple method, like just passing by
* value solething like: static void printInfo(new LinkedList<String> ls)
*
* but it did not compile
*/
/*
* this is my attempt:
*/ببساطة ليس هناك سوى طريقة واحدة .. تنشئ كائن جديد وتنسخ محتويات الكائن القديم عنصراً عنصراً .. إذا كنت تريد التعديل ..فلا بد أن تنسخ المحتويات .. مرة أخرىimport java.util.ArrayList;
public class pointers2 {
public static void main(String[] args) {
ArrayList <test>array1=new ArrayList<test>();
ArrayList <test>array2=new ArrayList<test>();
for(int i=0;i<10;i++)
{
array1.add(new test(i,'b'));
array2.add(array1.get(i));
}
array2.get(5).set(-5, 'a');
for(int i=0;i<10;i++)
{
System.out.print( array1.get(i).a+" "+array2.get(i).a);
System.out.println(" "+ array1.get(i).b+" "+array2.get(i).b);
}
}
}
class test{
int a;
char b;
test(int a,char b)
{
this.a=a;
this.b=b;
}
void set(int a,char b)
{
this.a=a;
this.b=b;
}
}ولا أعرف يوجود حل آخر غير إنشاء نسخ المتغيرات واحدا واحداً . .. ولكن الأمر ليس بهذه الصعوبة ..استخدم الدالة clonearray2.add(array1.get(i).clone());يمكنك القيام بـoverride للدالة فهي من Object كما يمكنك كتابة واحدة خاصة بك ..وتذكّر أن تنسخ جميع العناصر الداخلية باستخدام clone إن لم تكن أنواعاً رئيسية (أولية)
char [] string_in() {
char c = 0;
char [] tmp = NULL;
int
length = 100;
int size = -1;
tmp =(char[])calloc(sizeof ("char"), length);
while ((c = getchar()) != '\n') {
if (size++ == length){ length += length; tmp = (char[])realloc(tmp, sizeof ("char") * length);}
if (tmp == NULL) {
printf("No free memory for string!\n");
exit(-1);
}
tmp[size] = c;
}
tmp = (char[])realloc(tmp, sizeof ("char") * size);
if (tmp == NULL) {
printf("No free memory for string!\n");
exit(-1);
}
return tmp;
}طبعاً حتى يعمل قمت بتنفيذ الدوال السابقة من باب الإثبات أكثر وهذه هي أجسام الدوال :private static final char[] NULL = null; private char[] calloc(int sizeof, int length) { return new char[sizeof*length]; } private char[] realloc(char[] tmp, int i) { char[]T=new char; for(int j=0;j<i;j++) T[j]=tmp; return T; } private int sizeof(String string) { if(string.contains("char")) return 2;//char is 2 bytes in java if(string.contains("short")) return 2; if(string.contains("double")) return 8; return 4; } private void exit(int i) { System.exit(i); } private void printf(String string) { System.out.println(string); } private char getchar() { try { return (char)System.in.read(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return 0; } }ما رأيك الآن :) ... أعرف أن جميع المراجع لا تذكر ذلك .. ولكن هذه هي الحقيقة ..اقتباسيتم تسيير الذاكرة بشكل تلقائي عن طريق الـ GC.
اقتباسهناك فرق شاسع بين الـ references الموجودة في سي++ و تلك الموجودة في جافا.
ويمكنني القول بثقة أن references الــ Java هي ذاتها pointers ++C مع الاختلاف الوحيد في عدم سماح Java بالتعامل مع عناوين الذاكرة بشكل مباشر .. مثل زيادة العنوان الذي يشير له المؤشر أو إسناد قيمة عنوان بشكل مباشر .. حيث تسمح جافا باستخدام new فقط لإسناد المؤشرات أو بإسناد مؤشر لمؤشر سابق .. كما قلت .. الكلام السابق استنتاجي بحت من الفروق بين اللغتين .. ولا أظن أن أحد المراجع سيتجرّأ على قول مثله :D
إلا أن الـ Pointers في السي++، يمكن التحكم فيها بشكل عادي تماماً،
صراحة كنت أنثظر ردك، حول هذه المسألة، فأنا أحتاج أن أفهم بالضبط كيف تعمل الجافا من الداخل، وليس تلك الكلمات السطحية من الكتب،
المهم بحتث كثيرا في اليومين الماضيين حول هذه المسألة، وأفضل جواب وجدته،
http://stackoverflow.com/questions/869033/how-do-i-copy-an-object-in-java
وهو تقريباً نفس ماطرحته في مشاركتك.
أنا الآن أبحث عن طريقة، تمكنني من كتابة، method بالشكل التالي
static void my_CopyObject(_in_ objectToCopyTo, _in_ ObjectToCopy, _opt_ sizeof(ObjectToCopy))
{
// reserve memory for objectToCopyTo
// copy objectToCopy in objectToCopyTo
}لكنني أشعر كمن يبحث في لاشئ، فما أسهل كتابة مثل هذه الدالة بالسي أو الأسمبلي لكن بالجافا .......؟؟؟؟
يقول John Wiley في كتابة Assembly language step by step : كلما سألت أحداً ولم يكن يعرف الإجابة يقول بكل برود : " ولم قد ترغب بفعل ذلك ؟" ..
وأقولها لك : لماذا قد ترغب بفعل ذلك ؟ الجافا لها طريقة تفكير مختلفة والدالة clone موجودة في الفئة Object ومعظم الفئات قامت بعمل Override لها .. وهي تقوم بما تريد القيام به بالتحديد ..
بصراحة أشعر أن جافا تقول لنا دائما : "استعمل .. لا تخترع " على عكس C ..
اقرأ عن الدالة clone
بالتوفيق
اقتباسانظر إلى الكود الأول الذي أرفقته .. فقط استبدلت كل * بــ [] حيث أن جافا تعتبر المصفوفات كائنات فهي بالتالي كما أكدت مراراً مؤشرات
وإليك الإثبات : هذا هو الكود الأول
يا حبيبي :P
و هل تظن أن كود realloc يعمل بالسهولة التي كتبتَ أنت بالجافا ؟ :huh:
realloc تقوم بتوسيع حجم الذاكرة التي يُشير إليها المؤشر المُمرر كوسيط بينما أنت تقوم بحجز ذاكرة جديدة مختلفة تماماً ..
.. إذا قلت لك اكتب لي كود يُكافئ هذا :
void realloc_s(char **p, size_t size)
{
char *d = (char*) realloc(*p, size * sizeof (char));
if (d) *p = d;
else {
puts("no memory !!");
free(*p);
*p = 0;
exit(EXIT_FAILURE);
}
return;
}ماذا ستفعل ؟ :D
تم تعديل هذه المشاركة بواسطة Snack3r في 13 نوفمبر 2013 في 19:27
C++ and Java, say, are presumably growing faster than plain C, but I bet C will still be around. ― Dennis Ritchie
~OoO~________--------------------------------------------________~OoO~
من مواضيعي :
:D
قلت أن الفرق الوحيد هو صلاحية الوصول لعناوين الذاكرة الفعلية .. فجافا (من باب الأمان ربما) تبقي المطوّر بعيداً عن الذاكرة الفعلية وتعيشه في عناوين وهمية ..
يعني إذا كان لا يهمّك فعليّاً ماذا حدث .. فلن تشعر بأي فرق ..
بالنسبة للكود الذي طلبته :
يمكن كتابته هكذا :
void realloc_s(char [][]p, int size)
{
try{
char []d = (char[]) realloc(p[0], size * sizeof ("char"));
}
catch(OutOfMemoryError x)
puts("no memory !!");
//free(*p);//TO GC
p[0] = null;
exit(EXIT_FAILURE);
}
p[0] = d;
return;
}والفرق هو إصدار استثناء عوضاً عن الإسناد إلى NULL وهذا تابع للدالة realloc وليس للمؤشرات !
هل هناك فرق آخر ؟ غير صلاحية الوصول لعناوين الذاكرة :)
يا مصطفى حرام عليك :D
هل قمت بتجربة الكود الذي قمت بكتابته ؟ أنا جربته و طلع لي exception مكتوب فيه "مفيش يا عم مؤشرات في الجافا" :P
لدي بعض الملاحظات على كودك علما أنه لا يؤدي المطلوب (حتى اللحظة) :
تحياتي.
C++ and Java, say, are presumably growing faster than plain C, but I bet C will still be around. ― Dennis Ritchie
~OoO~________--------------------------------------------________~OoO~
من مواضيعي :
هل تناقشني في الموضوع بشكل جدّي إلى هذه الدرجة :D
الفكرة لا تحتاج كل هذا النقاش .. طبعاً مؤشرات C غير قابلة للمناقشة بمرونتها وفعاليتها ..
ولكن كل ما كنت أقوله أن جافا تتيح التعامل مع الكائنات تماماً كما تتيح ++C التعامل مع مؤشرات إلى كائنات .. وتمنعك من الوصول لعناوين الذاكرة الحقيقية وكل ملحقاتها ..
لا أناقش أن جافا توفر مؤشرات C ولكنها تستعمل نفس المفهوم في التعامل مع الكائنات ... وبس :)
اقتباسأنا جربته و طلع لي exception مكتوب فيه "مفيش يا عم مؤشرات في الجافا"
جميل .. بيئة تطوير عربية :D
أعتذر لإطالة النقاش .. ولكن بصراحة كنت كاتب مقال صغير عن " المؤشرات في جافا" وخفت من نشره لأنه يُمثّل وجهة نظري فقط .. يعني كان الجافاويين رح ياكلوني بلا ملح :)
على العموم هذه هي المقالة في المرفقات .. حتى أريح ضميري :]
شكراً لتحمّلي ;)
اقتباسكنت كاتب مقال صغير عن " المؤشرات في جافا" وخفت من نشره لأنه يُمثّل وجهة نظري فقط .. يعني كان الجافاويين رح ياكلوني بلا ملح :) على العموم هذه هي المقالة في المرفقات .. حتى أريح ضميري
اكتبها في موضوع منفصل, تبدو جميلة :)
مع أنني لم أتمكن من قراءتها لأن النوتباد عندي ما يقرأ الملفات العربية :mellow:
C++ and Java, say, are presumably growing faster than plain C, but I bet C will still be around. ― Dennis Ritchie
~OoO~________--------------------------------------------________~OoO~
من مواضيعي :
لقد قرأت المقالة وهي رائعة جداً، شكراً لك،
سيكون من الجيد لو قمت بإضافة صور لتنقيح الأكواد التي كتبتها، حتى تنبذ أي رأي مخالف وتنشر الموضوع بالمنتدى،
والله ولي التوفيق
المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية
جارٍ التحقق من المتواجدين…