لماذا Class.newInstance () "الشر"؟
-
10-07-2019 - |
سؤال
ريان Delucchi وطلب <لأ href = "https://stackoverflow.com/questions/194698/how -to الحمل واحد في جرة ملف-في-وقت التشغيل # 194712 "> هنا في تعليق رقم 3 ل<لأ href =" https://stackoverflow.com/users/4725/tom-hawtin-tackline "> الجواب توم Hawtin الصورة:
<اقتباس فقرة>وماذا Class.newInstance () "الشر"؟
اقتباس فقرة>وهذا ردا على نموذج التعليمات البرمجية:
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
وهكذا، لماذا هو الشر؟
المحلول
وتوضح وثائق API جافا لماذا (<لأ href = "http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance ()" يختلط = "noreferrer" > http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance () ):
<اقتباس فقرة> لاحظ أن هذه الطريقة تنتشر أي استثناء القيت من قبل منشئ nullary، بما في ذلك استثناء محددا. استخدام هذه الطريقة تجاهلت بشكل فعال استثناء فحص وقت الترجمة التي لولاها أن يقوم بها المترجم. طريقة Constructor.newInstance
يتجنب هذه المشكلة عن طريق التفاف أي استثناء القيت من قبل منشئ في (محددة) InvocationTargetException
.
وبعبارة أخرى، فإنه يمكن هزيمة نظام التحقق من الاستثناءات.
نصائح أخرى
واحد من الأسباب:
وبيئات التطوير الحديثة تسمح لك العثور على الأعراف الدرجة - أنه يساعد خلال إعادة بيع ديون، إذا كنت وIDE بالمحتويات كود تستخدم الفئة التي كنت تخطط لتغيير
وعندما لم يكن لقيام الاستخدام الصريح للمنشئ، ولكن استخدام Class.newInstance () بدلا من ذلك، هل خطر لا لتجد أن الاستخدام خلال إعادة بيع ديون وهذه مشكلة لا يعبر عن نفسه عند ترجمة.
وأنا لا أعرف لماذا لم يقدم أي واحد مثال بسيط على أساس تفسير لهذا، بالمقارنة مع Constructor::newInstance
على سبيل المثال، منذ <م> أخيرا م> تم إهمال Class::newInstance
منذ جافا-9.
وافترض أن لديك هذه فئة بسيطة جدا (لا يهم أن ما تم كسرها):
static class Foo {
public Foo() throws IOException {
throw new IOException();
}
}
ومحاولة إنشاء مثيل من ذلك عن طريق التفكير. Class::newInstance
أولا:
Class<Foo> clazz = ...
try {
clazz.newInstance();
} catch (InstantiationException e) {
// handle 1
} catch (IllegalAccessException e) {
// handle 2
}
ووصف هذا سيؤدي إلى IOException
التي القيت - المشكلة هي أن التعليمات البرمجية لا التعامل معها، لا handle 1
ولن handle 2
قبض عليه
في المقابل عندما يفعلون ذلك عن طريق Constructor
:
Constructor<Foo> constructor = null;
try {
constructor = clazz.getConstructor();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
Foo foo = constructor.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
System.out.println("handle 3 called");
e.printStackTrace();
}
والتي تتعامل مع وسوف يطلق 3، وبالتالي سوف التعامل معها.
وعلى نحو فعال، Class::newInstance
يتجاوز معالجة الاستثناء - الذي كنت حقا لا تريد