Java Script! = JavaScript. خمسة javas في فصل واحد. نكتب حتى نتذكر إلى الأبد


هذا الأسبوع ، من المرجح أن تنشر مجموعة JUG.ru إعلانًا. حتى أقول ما. المشاركة في المشاريع السرية تُوقظ الإبداع ، لذا إليك مقطع فيديو ليلي آخر حول Java.

أخبار مدهشة: الآن ليست ساعة ونصف طويلة ، ولكن حوالي 20 دقيقة ، وهناك شيء يجب مراقبته. أقل بقليل من تمامًا ، وتتكون من شاشة تسجيل. أولئك الذين لا يستطيعون تحمل هراء الفيديو هذا ويحبون استخدام فك تشفير النص ، كان عليهم قص الكثير من النص بعد القطع. Welkam ، وربما تكون جافا معك.

سيتم إطلاق 12 جافا قريبًا ، ولا يزال الكثيرون يجلسون في Semerochka ويعتقدون أنهم إذا قاموا بالترقية ، فلن يروا أي شيء جديد أو مثير للاهتمام. في هذا العدد القصير للغاية ، سنتعلم كيفية تحويل حياة زملائنا إلى جحيم بمساعدة جافا سكريبت ، وفي مكانين سأقوم بتثبيت أدوات جديدة. حسنًا ، لن يتم إنقاذ الظلاميين بالطبع من التقدم.

قل لي ، لماذا تقوم بتحديث فكرتك؟ تظهر ميزات جديدة باستمرار هناك ، بعض الاختصارات الجديدة ، تزيد إنتاجيتك كمطور. لكنك لا تعرف عنها. هل تقرأ هذا الخبر حقا؟ إذا كنت مستخدمًا عاديًا ، فربما لا. أنت ، من حيث المبدأ ، لا تبالي في معظم الوقت. أنت تقوم بتحديث الفكرة ببساطة لأنك تستطيع. لأن الأسطح جميلة ، السمة المظلمة ، شريط اللمس على MacBook. لكن مثل هذا التفسير لا يفشل أمام السلطات باعتباره الجواب "لماذا تشتري الفكرة".

بدلاً من ذلك ، يمكننا القول أنه في 29 أكتوبر ، مؤخرًا ، قامت JetBrains بتثبيت الدعم للخطوط الخام في الإصدار التجريبي من Idea . الفكرة في مرحلة تجريبية ، السطور في المعاينة ، لكن هذا لم يعد مهمًا لأي شخص. إذا كنت عنيدًا جدًا لدرجة أنك وضعت 12 جافا ، فأنت تعاني من مشاكل أكثر خطورة. أعرف بنفسي.

دعونا نرى كيف تبدو في الممارسة العملية. للقيام بذلك ، حاول حل نوع من مشكلة العرض التوضيحي. غالبًا ما تكون هناك مشكلة في كتابة شيء ما. على سبيل المثال ، في ألعاب الكمبيوتر ، هذه أسئلة ، وفي جنكينز ، هذه نصوص بناء ، وما إلى ذلك. عادة ، يتم استخدام Python أو Groove لهذا ، ودعونا نأخذ واستخدام جافا عارية! لماذا ، لماذا؟ لأننا نستطيع ، في ثلاثة أسطر ، وحتى بدون اختراق. تبدو فكرة رائعة :-)

أين تشاهد


كل شيء على جيثب .

النطاق


تخيل أن لدينا ملف مثل هذا:

package io.javawatch; public class HelloHabrPrototype { public String get() { return "Hello Habr!"; } }; 

نريد أن يتم تنفيذه ليس عند تجميع التطبيق بأكمله ، ولكن كسلسلة - بعد الإطلاق. مثل النص ، هذا هو.

يدويًا


تحتاج أولاً إلى تجاوز كل شيء في سلسلة.

 private static final String SOURCE = "\n" + " package io.javawatch;\n" + " public class HelloHabr {\n" + " public String get() {\n" + " return \"Hello Habr!\";\n" + " }\n" + " };"; public static final String CNAME = "io.javawatch.HelloHabr"; private static String CODE_CACHE_DIR = "C:/temp/codeCache"; 

تبدو كل هذه الإيجابيات و "\ n" بائسة للغاية.

في السابق ، كل ما يمكننا فعله هو وضع الشفرة في ملف وقراءتها. ربما يكون هذا حلاً جيدًا ، ولكنه ليس مناسبًا دائمًا. على سبيل المثال ، أنت متحدث في مؤتمر وعرض التعليمات البرمجية من الشرائح. حتى البناء أعلاه أفضل بكثير من مجرد مرجع لا أساس له أن لديك رمزًا في مكان ما يفعل شيئًا هناك. تبديل الشرائح يستهلك وقت واهتمام الجمهور. حسنا وهلم جرا. باختصار ، في الحالات التي تحتاج فيها إلى الرمز مضمّن تمامًا ، يمكنك التوصل إليه.

الآن لدينا الفرصة للتخلص من القمامة باستخدام الأوتار الخام. نحصل على المؤشر على الرمز ، اضغط على Alt + Enter (أو أيا كان يعمل على أنظمة تشغيل Quck Fix في الفكرة). حدد "تحويل إلى سلسلة حرفية الخام" والحصول على هذا nyashka:

 private static final String SOURCE = ` package io.javawatch; public class HelloHabr { public String get() { return "Hello Habr!"; } };`; public static final String CNAME = "io.javawatch.HelloHabr"; private static String CODE_CACHE_DIR = "C:/temp/codeCache"; 

في رأيي ، من أجل هذه الميزة ، يستحق الأمر بالفعل تثبيت JDK 12.

بالمناسبة ، لكي تعمل الميزة ، ستحتاج إلى القيام بعدة أشياء:

  • قم بتنزيل JDK 12 وقم بالتسجيل في إعدادات المشروع
  • في إعدادات javac العامة ، قم بتعيين --release العلم ، الإصدار 12 من bytecode ، إشارات إضافية --enable-preview -Xlint:preview
  • الآن في أي تكوين تشغيل / تصحيح ، تحتاج إلى إضافة --enable-preview VM --enable-preview

إذا لم تفهم ذلك ، كيف يتم ذلك ، شاهد تسجيل الشاشة الخاص بي من عنوان المشاركة ، كل شيء واضح جدًا هناك.

الآن ، للبدء ، تحتاج إلى تنفيذ ثلاث خطوات بسيطة: تحويل السلسلة إلى تمثيل داخلي ملائم للمصدر ، وتجميعها وتشغيلها:

  public static void main(String[] args) throws Exception { /* 1 */ RuntimeSource file = RuntimeSource.create(); //SimpleJavaFileObject /* 2 */ compile(Collections.singletonList(file)); /* 3 */ String result = run(); /* 4 */ /* ??? */ /* 5 */ /* PROFIT! */ System.out.println(result); } 

هناك فئة SimpleJavaFileObject "للتمثيل المريح" ، ولكن لديها ميزة واحدة مثيرة للاهتمام. إنها مجردة وحشية. أي أن طريقته الرئيسية ، التي يجب أن يعودها المصدر المترجم ، دائمًا ما تؤدي إلى تنفيذ على أمل أن نقوم بتصنيفها الفرعي:

  /** * This implementation always throws {@linkplain * UnsupportedOperationException}. Subclasses can change this * behavior as long as the contract of {@link FileObject} is * obeyed. */ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { throw new UnsupportedOperationException(); } 

لذا عليك كتابة بعض من وريثك. يرجى ملاحظة أن مُنشئ SimpleJavaFileObject الأصلي يريد URI للفئة المترجمة ، ولكن من أين نحصل عليه؟ لذلك ، أقترح فقط التمسك بها بأكثر الطرق وضوحًا ، كما هو الحال هنا في وظيفة buildURI :

  public static class RuntimeSource extends SimpleJavaFileObject { private String contents = null; @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return contents; } private static RuntimeSource create() throws Exception { return new RuntimeSource(CNAME, SOURCE); } public RuntimeSource(String className, String contents) throws Exception { super(buildURI(className), Kind.SOURCE); this.contents = contents; } public static URI buildURI(String className) { // io.javawatch.HelloHabr -> // string:///io/javawatch/HelloHabr.java URI uri = URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension); System.out.println(uri); return uri; } 

الآن دعنا ننتقل إلى التجميع:

  public static void compile(List<RuntimeSource> files) throws IOException { File ccDir = new File(CODE_CACHE_DIR); if (ccDir.exists()) { FileUtils.deleteDirectory(ccDir); FileUtils.forceMkdir(ccDir); } JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); Logger c = new Logger(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(c, Locale.ENGLISH, null); Iterable options = Arrays.asList("-d", CODE_CACHE_DIR, "--release=12", "--enable-preview", "-Xlint:preview"); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, c, options, null, files); if (task.call()) { System.out.println("compilation ok"); } } 

يرجى ملاحظة: نقوم بتمرير أربعة أعلام للتجميع ، ثلاثة منها مسؤولة عن وصف نفس الخيارات بالضبط التي قمنا بها باستخدام الماوس في إعدادات javac في Idea.

وأخيرًا ، قم بإدارة الفصل المؤقت لدينا:

  public static String run() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, MalformedURLException { //   File ccDir = new File(CODE_CACHE_DIR); ClassLoader loader = new URLClassLoader(new URL[]{ccDir.toURL()}); var clss = loader.loadClass("io.javawatch.HelloHabr"); // Java 10 //    Object instance = clss.getConstructor().newInstance(); // Java 9 // Object instance = clss.newInstance(); Method thisMethod = clss.getDeclaredMethod("get"); Object result = thisMethod.invoke(instance); return (String) result; } 

يرجى ملاحظة أن var clss = loader.loadClass في الكتابة من Class<?> clss = loader.loadClass ، ولا تقدم أي vorings جديدة. ظهرت الكلمة var في العشرة الأوائل.

لاحظ أيضًا أنه يُقترح قطع clss.newInstance() بدءًا من تسعة. يبتلع الاستثناءات وهو أمر سيئ. يقترح The Nine الاستدعاء الأول getConstructor ، والذي يتم تعيين معلمات له ويلقي الاستثناءات الصحيحة.

يرجى أيضًا ملاحظة أنني دعوت المتغير class الكلمة ، لكن جافا لم تقسم. الواجبات المنزلية: يمكنك القيام بذلك بعدة طرق ، تحتاج إلى فهم أيهما أكثر إثارة للاهتمام ولماذا.

حسنًا ، بشكل عام ، هذا كل شيء. يعمل.

الأتمتة


هنا سيهتف الناقد ، كل شيء باللون الأسود هنا ، لأن هناك مكتبات في عالم جافا تجمع كل شيء من أجلك في سطر واحد.

حسنًا ، لنلقي نظرة. إليك الرمز الموجود في مكتبة JOOR ، الموجودة في الجزء العلوي من Google:

 package io.javawatch; import org.joor.Reflect; import java.util.function.Supplier; public class Automatic { public static void main(String[] args) { Supplier<String> supplier = Reflect.compile( "io.javawatch.HelloHabr", ` package io.javawatch; public class HelloHabr implements java.util.function.Supplier<String> { public String get() { return "Hello Habr!"; } };` ).create().get(); System.out.println(supplier.get()); } } 

كما لو أن كل شيء على ما يرام. في الواقع ، في سطر واحد ، إلا أنني اضطررت إلى سحب saplayer.

ولكن هناك فارق بسيط. حاول إرجاع "Hello Habr!" مثل حرف الوتر الخام:

 public String get() { return ``Hello Habr!``; } 

كل شيء سيتعطل على الفور مع الخطأ "(استخدم --able-preview لتمكين حرفية السلسلة الأولية)". لكن هل قمنا بتشغيله بالفعل؟ نعم ، إلى الجحيم مع اثنين. قمنا بتضمينها في الفكرة ، وتقوم JOOR ببنائها باستخدام مترجم النظام! دعونا نلقي نظرة على ما بالداخل:

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); ompiler.getTask(out, fileManager, null, null, null, files).call(); 

وماذا عنا عندما نسمي أنفسنا نفس JavaCompiler؟

  Iterable options = Arrays.asList("-d", CODE_CACHE_DIR, "--release=12", "--enable-preview", "-Xlint:preview"); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, c, options, null, files); 

وفي JOOR هناك مجرد فراغ بدلاً من الخيارات. لا يمكن حتى تمريرها إلى الداخل!

ربما يكون من الجيد إرسال طلب سحب إلى Github في JOOR. إذا كنت لن أفعل ذلك بنفسي ، فأنت تفعل ذلك ، أليس كذلك؟

والمعنوي بسيط ، خاف من الهدايا مفتوحة المصدر. في بعض الأحيان يكون من الأسهل كتابة جدار صغير للنص ، ولكن يمكنك التحكم فيه.

أسهل طريقة


هناك طريقة لعدم كتابة جدار نص ، وعدم استخدام مكتبات مشبوهة. بدءًا من Java 9 ، لدينا غلاف تفاعلي (مشابه لتلك الموجودة في Python و Ruby ولغات برمجة نصية أخرى) يمكنها تنفيذ أوامر Java. وبالطبع ، هو مكتوب بلغة جافا نفسها ومتوفر كفئة جافا. يمكنك إنشاء مثيل منه وتنفيذ المهمة المطلوبة ببساطة مباشرةً:

 public class Shell { public static void main(String[] args) { var jShell = JShell.create(); //Java 9 jShell.eval("String result;"); jShell.eval(`result = "Hello Habr!";`); //Java 12 var result = jShell.variables() //Streams: Java 8, var: Java 10 .filter((@Nullable var v) -> v.name().equals("result")) //var+lambda: Java 11 .findAny() .get(); System.out.println(jShell.varValue(result)); } } 

ظهرت التدفقات في Java 8 ، والآن يتم استخدامها في كل مكان ، ولا تحتاج حتى إلى استدعاء stream() بنفسك ، وسوف يتصل به الآخرون نيابة عنك. في هذه الحالة ، يؤدي استدعاء variables() إرجاع الدفق تمامًا ، وليس ArrayList ، كما فعل شخص من طفولة صعبة السبع. يمكن صب نتيجة التيار على الفور في var .

لاحظ أنه يمكنك الآن كتابة var أيضًا في معلمات lambda. هذه الميزة كانت معنا منذ Java 11.

بشكل عام ، هذه فئة مهمة للغاية. إنه يستخدم مجموعة من الميزات من أجيال مختلفة من Java ، وكل هذا يبدو كليًا ومتناغمًا. أنا متأكد من أن مثل هذه الأشياء سيتم استخدامها من قبل الجميع وفي كل مكان ، لذلك فإن الرمز في Java 12 سيكون مختلفًا بصريًا بشكل مباشر عما كان لدينا في Java 7.

لتلخيص


نظرنا في بعض الميزات:

  • 8: تيار (لأولئك في الخزان)
  • 9: JShell والأساليب الجديدة المهجورة
  • 10: الكلمة الرئيسية var
  • 11: تطوير Var لمعلمات لامدا
  • 12: حرفية السلسلة الأولية ودعمها في IntelliJ IDEA

تحذير صغير للمبتدئين. إذا كنت تفعل هذا باستمرار في تطبيقات حقيقية دون أي معنى خاص ، فإن زملائك سيصابون بالجنون في البداية ، محاولين فهم ما كتبته ، وبعد ذلك يمكنهم أن يضربوك بشكل مؤلم للغاية. وأنا لا أتحدث عن ميزات Java الجديدة الآن ، ولكن عن التجميع في وقت التشغيل ، بالطبع.

إذا كنت تريد معرفة المزيد عن Java كلغة ، فيجب عليك ، على سبيل المثال ، الاطلاع على تقارير Tagir Valeev. أنت تعرفه على أنه رجل من قمة مركز جافا في حبري ، لاني . في جوكر تحدث عن العنبر ، وفي JPoint - ألغازه الشهيرة ، وهكذا دواليك. هناك ، وحول لغة جافا ، وحول IntelliJ IDEA ، كل شيء موجود. كل هذا يمكن العثور عليه على موقع يوتيوب . في الواقع ، بدافع الغيرة من تاجير ، الذي يمكنه أن يقول شيئًا عن اللغة نفسها ، لكنني لا أفعل ، وقد تحول هذا المنشور. سيكون هناك أيضًا نكتة جديدة و JPoint ، لكننا سنناقش ذلك لاحقًا.

لقد أوفت بواجبي الأخلاقي. من جانبي ، أطلق الرصاص. وأنت هناك ، على السبعة ، الذين ليس لديهم جافا الثاني عشر ، ابقوا هنا ، أنتم جميعاً أفضل ، مزاج جيد وصحة. شكرا لك

Source: https://habr.com/ru/post/ar429670/


All Articles