Java Script! = JavaScript. Lima jawa dalam satu kelas. Kami skrip sehingga kami ingat selamanya


Minggu ini, Grup JUG.ru kemungkinan akan merilis pengumuman. Sampai aku mengatakan apa. Partisipasi dalam proyek-proyek rahasia membangkitkan kreativitas, jadi di sini ada video malam tentang Jawa.

Berita luar biasa: sekarang tidak satu setengah jam panjang, tetapi sekitar 20 menit, dan bahkan ada sesuatu untuk ditonton. Sedikit kurang sepenuhnya, terdiri dari screencast. Mereka yang tidak tahan dengan sampah video ini dan suka menggunakan dekripsi teks, harus memotong banyak teks setelah dipotong. Welkam, dan mungkin Jawa bersama Anda.

Segera 12 Java akan dirilis, dan banyak yang masih duduk di Semerochka dan percaya bahwa dalam hal upgrade mereka tidak akan melihat sesuatu yang baru atau menarik. Dalam edisi super pendek ini, kita akan belajar bagaimana mengubah kehidupan rekan-rekan kita menjadi neraka dengan bantuan Java yang ditulis, dan di beberapa tempat saya akan mengacaukan gadget baru. Nah, ahli Obskurantis, tentu saja, tidak akan selamat dari kemajuan.

Katakan, mengapa Anda memperbarui Ide Anda? Fitur baru terus muncul di sana, beberapa pintasan baru, sepuluh kali meningkatkan produktivitas Anda sebagai pengembang. Tetapi Anda tidak tahu tentang mereka. Apakah Anda benar-benar membaca berita ini? Jika Anda adalah pengguna biasa, maka mungkin tidak. Anda, pada prinsipnya, tidak peduli dengan sebagian besar waktu. Anda memperbarui Ide hanya karena ... Anda bisa. Karena kulitnya indah, tema gelap, panel sentuh di MacBook. Namun penjelasan seperti itu tidak gagal di hadapan pihak berwenang sebagai jawaban "mengapa membeli Ide".

Sebagai gantinya, kita dapat mengatakan bahwa pada 29 Oktober, baru-baru ini, JetBrains menyematkan dukungan untuk jalur mentah dalam Idea versi beta. Idenya dalam versi beta, garisnya ada di pratinjau, tetapi ini tidak lagi penting bagi siapa pun. Jika Anda begitu keras kepala sehingga Anda menempatkan 12 java, maka Anda memiliki masalah yang lebih serius. Saya tahu sendiri.

Mari kita lihat tampilannya dalam praktik. Untuk melakukan ini, cobalah untuk menyelesaikan beberapa jenis masalah demonstrasi. Cukup sering ada masalah scripting sesuatu. Misalnya, dalam game komputer ini adalah pencarian, di jenkins ini adalah skrip build, dan sebagainya. Biasanya, Python atau Groove digunakan untuk ini, dan mari kita ambil dan gunakan Java telanjang! Kenapa, kenapa? Karena kita bisa, dalam tiga baris, dan bahkan tanpa peretasan. Kedengarannya seperti ide bagus :-)

Tempat menonton


Semuanya ada di github .

Lingkup


Bayangkan kita memiliki file seperti ini:

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

Kami ingin dieksekusi bukan ketika kompilasi seluruh aplikasi, tetapi sebagai string - setelah peluncuran. Seperti naskah, itu.

Secara manual


Pertama, Anda perlu menyalip semuanya menjadi string.

 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"; 

Semua plus dan indentasi ini terlihat sangat menyedihkan.

Sebelumnya, yang bisa kami lakukan hanyalah memasukkan kode ke dalam file dan membacanya. Ini mungkin solusi yang baik, tetapi tidak selalu cocok. Misalnya, Anda adalah pembicara di konferensi dan mendemonstrasikan kode dari slide. Bahkan konstruksi di atas jauh lebih baik daripada hanya referensi tidak berdasar bahwa Anda memiliki kode di suatu tempat yang melakukan sesuatu di sana. Pergantian slide menghabiskan waktu dan perhatian audiens. Baik dan sebagainya. Singkatnya, kasus, ketika Anda membutuhkan kode persis inline, Anda dapat membuat.

Sekarang kita memiliki kesempatan untuk membuang sampah menggunakan string mentah. Kami bangun dengan kursor pada kode, tekan Alt + Enter (atau apa pun yang berjalan pada OS Anda Quck Fix di Idea). Pilih "convert to raw string literal" dan dapatkan nyashka ini:

 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"; 

Menurut pendapat saya, demi fitur ini, sudah layak dijalankan untuk menginstal JDK 12.

Omong-omong, agar fitur tersebut berfungsi, Anda perlu melakukan beberapa hal:

  • Unduh JDK 12 dan daftar di pengaturan proyek
  • Dalam pengaturan javac global, atur flag --release , bytecode versi 12, flag tambahan --enable-preview -Xlint:preview
  • Sekarang dalam konfigurasi jalankan / debug Anda perlu menambahkan flag VM --enable-preview

Jika Anda tidak mengerti, bagaimana melakukannya, lihat screencast saya dari pos pos, semuanya cukup jelas di sana.

Sekarang, untuk memulai, Anda perlu melakukan tiga langkah sederhana: mengubah string menjadi representasi internal sumber yang nyaman, kompilasi dan jalankan:

  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); } 

Ada kelas SimpleJavaFileObject untuk "representasi yang mudah", tetapi memiliki satu fitur yang menarik. Ini sangat abstrak. Yaitu, metode kuncinya, yang harus dikembalikan oleh sumber yang dikompilasi, selalu melakukan eksekusi dengan harapan bahwa kami akan mensubklasifikasikannya:

  /** * 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(); } 

Jadi, Anda harus menulis beberapa ahli waris Anda. Harap perhatikan bahwa konstruktor SimpleJavaFileObject asli menginginkan URI untuk kelas yang dikompilasi, tetapi di mana kita mendapatkannya? Karena itu, saya sarankan hanya menempelkannya dengan cara yang paling jelas, seperti di sini di fungsi 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; } 

Sekarang mari kita beralih ke kompilasi:

  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"); } } 

Harap dicatat: kami melewati empat flag untuk perakitan, tiga di antaranya bertanggung jawab untuk menentukan opsi yang persis sama dengan yang kami lakukan dengan mouse di pengaturan javac di Ide.

Dan akhirnya, jalankan kelas sementara kami:

  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; } 

Harap dicatat bahwa var clss = loader.loadClass lebih nyaman untuk menulis daripada Class<?> clss = loader.loadClass , dan tidak memperkenalkan vorings baru. Kata kunci var muncul di Sepuluh Teratas.

Perhatikan juga bahwa clss.newInstance() diusulkan untuk dipotong mulai dari Nine. Dia menelan pengecualian, yang merupakan hal buruk. Sembilan menyarankan pertama memanggil getConstructor , yang parameter dan melemparkan pengecualian yang benar.

Harap perhatikan juga bahwa saya memanggil variabel class kata, tetapi Java tidak bersumpah. Pekerjaan rumah: Anda dapat melakukan ini dalam beberapa cara, Anda perlu memahami mana yang paling menarik dan mengapa.

Secara umum, itu saja. Itu bekerja.

Otomasi


Di sini kritik akan berseru, semuanya hitam di sini, karena ada perpustakaan di dunia Jawa yang mengkompilasi semuanya untuk Anda dalam satu baris.

OK, mari kita lihat. Berikut adalah kode di perpustakaan JOOR, yang terletak di bagian atas 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()); } } 

Seolah semuanya baik-baik saja. Memang, dalam satu baris, kecuali bahwa saya harus menyeret saplayer.

Namun ada nuansa. Coba kembalikan "Hello Habr!" seperti string string literal:

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

Semuanya akan langsung macet dengan kesalahan "(gunakan --able-preview untuk mengaktifkan literal string mentah)". Tapi apakah kita sudah menyalakannya? Ya, persetan dengan dua. Kami memasukkannya ke dalam Ide, dan JOOR membangunnya dengan kompiler sistem! Mari kita lihat apa yang ada di dalamnya:

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

Dan bagaimana dengan kita ketika kita sendiri memanggil JavaCompiler yang sama?

  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); 

Dan di JOOR hanya ada nol kosong bukan opsi. Mereka bahkan tidak bisa lewat di dalam!

Mungkin merupakan ide yang bagus untuk mengirimi mereka permintaan tarik seperti itu ke Github di JOOR. Jika saya tidak akan melakukannya sendiri, Anda melakukannya, ya?

Dan moralnya sederhana, takut akan hadiah sumber terbuka. Terkadang lebih mudah untuk menulis dinding teks kecil, tetapi memiliki kontrol atasnya.

Cara termudah


Ada cara untuk tidak menulis dinding teks, dan tidak menggunakan perpustakaan yang mencurigakan. Dimulai dengan Java 9, kami memiliki shell interaktif (mirip dengan yang ada di Python, Ruby, dan bahasa scripting lainnya) yang dapat menjalankan perintah Java. Dan tentu saja, itu ditulis dalam Java itu sendiri dan tersedia sebagai kelas Java. Anda dapat membuat instance dan hanya melakukan tugas yang diperlukan secara langsung:

 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)); } } 

Streaming muncul di Java 8, dan sekarang digunakan di mana-mana, dan Anda bahkan tidak perlu memanggil stream() sendiri, orang lain akan menyebutnya untuk Anda. Dalam hal ini, memanggil variables() mengembalikan aliran tepat, bukan ArrayList, seperti yang dilakukan seseorang dari tujuh masa kecil yang sulit. Hasil aliran langsung dapat dituangkan ke var .

Perhatikan bahwa sekarang Anda dapat menulis var juga dalam parameter lambda. Fitur ini telah bersama kami sejak Java 11.

Secara umum, ini adalah kelas yang sangat signifikan. Ini menggunakan banyak fitur dari berbagai generasi Jawa, dan semua ini terlihat secara holistik dan harmonis. Saya yakin bahwa hal-hal seperti itu akan digunakan oleh semua orang dan di mana saja, jadi kode di Java 12 akan langsung berbeda secara visual dari yang kami miliki di Java 7.

Untuk meringkas


Kami melihat beberapa fitur:

  • 8: Aliran (untuk yang ada di tangki)
  • 9: JShell dan metode usang baru
  • 10: kata kunci var
  • 11: Pengembangan Var untuk parameter lambda
  • 12: Raw String Literals dan dukungannya di IntelliJ IDEA

Sedikit peringatan untuk pemula. Jika Anda terus-menerus melakukan ini dalam aplikasi nyata tanpa makna khusus, maka rekan kerja Anda akan menjadi gila pada awalnya, mencoba memahami apa yang Anda tulis, dan kemudian mereka dapat mengalahkan Anda dengan sangat menyakitkan. Dan saya tidak berbicara tentang fitur Java baru sekarang, tetapi tentang kompilasi dalam runtime, tentu saja.

Jika Anda ingin mempelajari lebih lanjut tentang Java sebagai bahasa, maka Anda harus, misalnya, melihat laporan Tagir Valeev. Anda mengenalnya sebagai seorang pria dari atas pusat Jawa di Habrรฉ, lany . Di Joker ia berbicara tentang Amber , dan di JPoint - teka - teki terkenalnya, dan seterusnya dan seterusnya. Di sana, dan tentang bahasa Jawa, dan tentang IntelliJ IDEA, semuanya ada di sana. Semua ini dapat ditemukan di YouTube . Sebenarnya, karena cemburu pada Tagir, yang bisa mengatakan sesuatu tentang bahasa itu sendiri, tapi saya tidak dan posting ini ternyata. Juga akan ada pelawak dan JPoint baru, tetapi kita akan membahas ini nanti.

Saya memenuhi kewajiban moral saya, kewajiban ke Jawa. Dari sisiku, peluru itu terbang keluar. Dan Anda di sana, pada tujuh, yang tidak memiliki Jawa kedua belas, tetap di sini, Anda semua yang terbaik, suasana hati yang baik dan kesehatan. Terima kasih

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


All Articles