String x = (String) null;
لماذا لا يوجد استثناء في هذا البيان؟
String x = null;
System.out.println(x);
يطبع null
. ولكن .toString()
الأسلوب يجب أن يلقي استثناء مؤشر فارغة.
يمكنك إرسال null
لأي نوع مرجعي دون الحصول على أي استثناء.
الأسلوب println
لا يرمي مؤشرًا خاليًا لأنه يتحقق أولاً مما إذا كان الكائن خاليًا أم لا. إذا كانت فارغة ، فستقوم ببساطة بطباعة السلسلة "null"
. وإلا فإنه سيتم استدعاء الأسلوب toString
لهذا الكائن.
إضافة المزيد من التفاصيل: أساليب الطباعة داخليًا استدعاء String.valueOf(object)
method على كائن الإدخال. وفي طريقة valueOf
، يساعد هذا الاختيار في تجنب استثناء مؤشر فارغ:
return (obj == null) ? "null" : obj.toString();
بالنسبة لبقية التشويش ، يجب أن يؤدي استدعاء أي طريقة على كائن فارغ إلى استثناء مؤشر فارغ ، إن لم يكن حالة خاصة.
يمكنك إرسال null
إلى أي نوع مرجعي. يمكنك أيضًا استدعاء الأساليب التي تتعامل مع null
كوسيطة ، على سبيل المثال يعمل System.out.println(Object)
، لكن لا يمكنك الرجوع إلى قيمة null
واستدعاء طريقة عليها.
راجع للشغل هناك موقف صعب حيث يمكنك استدعاء الأساليب الثابتة على قيم null
.
Thread t = null;
t.yield(); // Calls static method Thread.yield() so this runs fine.
هذا حسب التصميم. يمكنك إرسال null
إلى أي نوع مرجع. وإلا فلن تكون قادرًا على تعيينه إلى متغيرات مرجعية.
يُطلب صب القيم الفارغة لاتباع البنية التي يتم فيها تحميل الأسلوب بطريقة زائدة وإذا تم نقل القيمة الفارغة إلى هذه الطرق الزائدة ، فإن المترجم لا يعرف كيفية مسح الغموض ومن ثم نحتاج إلى كتابة البادئة في هذه الحالات:
class A {
public void foo(Long l) {
// do something with l
}
public void foo(String s) {
// do something with s
}
}
new A().foo((String)null);
new A().foo((Long)null);
خلاف ذلك ، لا يمكنك الاتصال بالطريقة التي تحتاجها.
Println(Object)
يستخدم String.valueOf()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Print(String)
does check null.
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
كما كتب آخرون ، يمكنك إلقاء أي شيء على كل شيء. عادة ، لن تحتاج إلى ذلك ، يمكنك الكتابة:
String nullString = null;
دون وضع المدلى بها هناك.
ولكن هناك مناسبات يكون فيها هذا الممثلون منطقيون:
أ) إذا كنت تريد التأكد من أن طريقة معينة تسمى ، مثل:
void foo(String bar) { ... }
void foo(Object bar) { ... }
بعد ذلك سوف يحدث فرقًا إذا كتبت
foo((String) null) vs. foo(null)
ب) إذا كنت تنوي استخدام IDE لإنشاء رمز ؛ على سبيل المثال ، أكتب عادةً اختبارات وحدة مثل:
@Test(expected=NullPointerException.class)
public testCtorWithNullWhatever() {
new MyClassUnderTest((Whatever) null);
}
أنا أفعل TDD. هذا يعني أن الفئة "MyClassUnderTest" ربما لم تكن موجودة بعد. من خلال كتابة هذا الرمز ، يمكنني حينئذٍ استخدام IDE لإنشاء أول فئة جديدة ؛ ثم لإنشاء مُنشئ يقبل وسيطة "Whatever" خارج المربع "- يمكن لـ IDE معرفة من خلال اختباري أن المُنشئ يجب أن يأخذ وسيطة واحدة تمامًا من النوع Whatever.
العديد من الإجابات هنا أذكر بالفعل
يمكنك يلقي لاغية لأي نوع مرجعي
و
إذا كانت الوسيطة خالية ، فسلسلة تساوي "خالية"
تساءلت أين تم تحديد ذلك وبحثت عنه في مواصفات Java:
يمكن دائمًا تعيين المرجع الفارغ أو تحويله إلى أي نوع مرجعي (الفقرة 5.2 ، الفقرة 3.5 ، الفقرة 5.5).
إذا كان المرجع فارغًا ، فسيتم تحويله إلى السلسلة "خالية" (أربعة ASCII أحرف n ، u ، l ، l).
هذا مفيد جدًا عند استخدام طريقة قد تكون غامضة. على سبيل المثال: لدى JDialog مُنشئين بالتوقيعات التالية:
JDialog(Frame, String, boolean, GraphicsConfiguration)
JDialog(Dialog, String, boolean, GraphicsConfiguration)
أحتاج إلى استخدام هذا المُنشئ ، لأنني أرغب في تعيين GraphicsConfiguration ، لكن ليس لدي أصل لهذا الحوار ، لذلك يجب أن تكون الوسيطة الأولى خالية. عن طريق
JDialog(null, String, boolean, Graphicsconfiguration)
غامض ، لذلك في هذه الحالة يمكنني تضييق نطاق المكالمة عن طريق إرسال قيمة خالية إلى أحد الأنواع المدعومة:
JDialog((Frame) null, String, boolean, GraphicsConfiguration)
ميزة اللغة هذه مريحة في هذا الموقف.
public String getName() {
return (String) memberHashMap.get("Name");
}
إذا قام memberHashMap.get ("Name") بإرجاع قيمة خالية ، فأنت لا تزال ترغب في إرجاع الطريقة أعلاه خالية دون رمي استثناء. بغض النظر عن الفئة ، لاغية.