Java Challengers # 2: Perbandingan String

Java Challengers # 2: Perbandingan String


Seperti biasa, kami memiliki banyak keterlambatan untuk permulaan kursus, jadi baru kemarin mengadakan pelajaran kedua di antara utas baru "Pengembang Java" . Namun begitulah, hal-hal kecil dalam hidup, tetapi untuk sekarang kami terus menerbitkan serangkaian artikel Java Challengers, yang terjemahannya telah disiapkan untuk Anda.


Di Jawa, kelas String merangkum array char ( catatan penerjemah - dengan java 9 itu sudah menjadi byte array, lihat Compact Strings in Java 9 ). Secara sederhana, String adalah array karakter yang digunakan untuk menulis kata, kalimat, atau konstruksi lainnya.


Enkapsulasi adalah salah satu konsep paling kuat dalam pemrograman berorientasi objek. Berkat enkapsulasi, Anda tidak perlu tahu cara kerja kelas String . Anda hanya perlu tahu metode antarmuka-nya.



Saat Anda melihat kelas String di Java, Anda bisa melihat bagaimana array char dienkapsulasi:


 public String(char value[]) { this(value, 0, value.length, null); } 

Untuk lebih memahami enkapsulasi, bayangkan objek fisik: mesin. Apakah Anda perlu tahu cara mobil bekerja di bawah kap untuk mengendarainya? Tentu saja tidak, tetapi Anda harus tahu apa yang dilakukan antarmuka mobil: pedal gas, rem dan kemudi. Masing-masing antarmuka ini mendukung tindakan tertentu: akselerasi, pengereman, belok kiri, belok kanan. Hal yang sama berlaku dalam pemrograman berorientasi objek.


Artikel pertama dalam seri Java Challengers adalah tentang metode overloading, yang banyak digunakan di kelas String . Overloading dapat membuat kelas Anda sangat fleksibel:


 public String(String original) {} public String(char value[], int offset, int count) {} public String(int[] codePoints, int offset, int count) {} public String(byte bytes[], int offset, int length, String charsetName) {} //    ... 

Alih-alih mencoba memahami cara kerja kelas String , artikel ini akan membantu Anda memahami apa yang dilakukannya dan bagaimana menggunakannya dalam kode Anda.


Apa itu kumpulan string?


Kelas String adalah kelas yang paling umum digunakan di Jawa. Jika kita membuat objek baru dalam memori dinamis (tumpukan memori) setiap kali kita menggunakan String , maka kita akan membuang banyak memori. String pool memecahkan masalah ini dengan hanya menyimpan satu objek untuk setiap nilai baris.


string-in-the-string-pool


Baris di kolam baris


Meskipun kami membuat beberapa variabel String dengan nilai Duke dan Juggy , hanya dua objek yang dibuat dan disimpan dalam memori dinamis (heap). Lihat contoh kode berikut untuk bukti. (Ingat bahwa di Jawa, operator " == " digunakan untuk membandingkan dua objek dan menentukan apakah objek yang sama sama atau tidak.)


 String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println(juggy == anotherJuggy); 

Kode ini akan mengembalikan nilai true karena dua variabel String menunjuk ke objek yang sama di kumpulan string. Makna mereka sama.


Pengecualiannya adalah operator new .


Sekarang lihat kode ini - tampilannya mirip dengan contoh sebelumnya, tetapi ada perbedaan.


 String duke = new String("duke"); String anotherDuke = new String("duke"); System.out.println(duke == anotherDuke); 

Berdasarkan contoh sebelumnya, Anda mungkin berpikir bahwa kode ini akan mengembalikan true , tetapi tidak. Menambahkan operator new membuat objek String baru dalam memori. Dengan demikian, JVM akan membuat dua objek berbeda.


Metode Asli

Metode asli di Jawa adalah metode yang akan dikompilasi menggunakan bahasa C, biasanya dengan tujuan mengelola memori dan mengoptimalkan kinerja.

Metode string pools dan intern()


Untuk menyimpan string dalam kumpulan, metode yang disebut String interning digunakan.


Inilah yang Javadoc beri tahu tentang metode intern() :


  /** *      . * *   ( )   {@code String}. * *    intern,     , *    {@code String},   *  {@link #equals(Object)},     . * ,   {@code String}   *        {@code String}. * *   ,      {@code s}  {@code t}, * {@code s.intern() == t.intern()}  {@code true} *    ,  {@code s.equals(t)}  {@code true}. * *       . *      3.10.5 The Java™ Language Specification. * * @returns ,         , * , ,       . * * @jls 3.10.5 String Literals */ public native String intern(); 

Metode intern() digunakan untuk menyimpan string dalam kumpulan string. Pertama, ini memeriksa untuk melihat apakah baris yang sudah dibuat ada di kolam. Jika tidak, itu membuat baris baru di kolam. Logika pool baris didasarkan pada pola Flyweight .


Sekarang, perhatikan apa yang terjadi ketika kita menggunakan yang new untuk membuat dua baris:


 String duke = new String("duke"); String duke2 = new String("duke"); System.out.println(duke == duke2); //    false System.out.println(duke.intern() == duke2.intern()); //    true 

Berbeda dengan contoh sebelumnya dengan kata kunci new , dalam hal ini perbandingan akan menghasilkan true . Ini karena menggunakan metode intern() memastikan bahwa string ada di kumpulan.


Metode yang sama dalam kelas String


Metode equals() digunakan untuk memeriksa apakah dua kelas sama atau tidak. Karena equals() terletak di kelas Object , setiap kelas Java mewarisinya. Tetapi metode equals() harus diganti agar berfungsi dengan benar. Tentu saja, String menimpa equals() .


Lihatlah:


 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; } 

Seperti yang Anda lihat, nilai kelas String dibandingkan melalui equals() , dan bukan melalui referensi objek. Tidak masalah jika referensi ke objek berbeda; kondisi akan dibandingkan.


Metode String Umum


Ada satu hal lagi yang perlu Anda ketahui sebelum menyelesaikan masalah perbandingan string.


Pertimbangkan metode paling umum dari kelas String :


 //         trim() //     substring(int beginIndex, int endIndex) //    length() //  ,     replaceAll(String regex, String replacement) // ,     CharSequence   contains(CharSequences) 

Selesaikan masalah perbandingan string


Mari kita periksa apa yang Anda pelajari tentang kelas String dengan memecahkan puzzle kecil.


Dalam tugas ini, Anda membandingkan beberapa baris menggunakan konsep yang telah Anda pelajari. Melihat kode di bawah ini, dapatkah Anda menentukan nilai dari setiap result variabel?


 public class ComparisonStringChallenge { public static void main(String... doYourBest) { String result = ""; result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; result += "flexibleCode" == "flexibleCode" ? "2" : "3"; result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; System.out.println(result); } } 

Apa kesimpulannya?


  • A: 02468
  • B: 12469
  • C: 12579
  • D: 12568

Jawaban yang benar diberikan di akhir artikel.


Apa yang terjadi sekarang? Memahami Perilaku String


Di baris pertama kita melihat:


 result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; 

Dalam hal ini, hasilnya false , karena ketika metode trim() menghilangkan spasi, ia menciptakan String baru menggunakan operator new .


Selanjutnya kita lihat:


 result += "flexibleCode" == "flexibleCode" ? "2" : "3"; 

Tidak ada rahasia di sini, barisnya sama di baris pool. Perbandingan ini menghasilkan true .


Kemudian, kita memiliki:


 result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; 

Menggunakan lead new untuk membuat dua baris baru dan tidak masalah apakah nilainya sama atau tidak. Dalam hal ini, perbandingannya akan false bahkan jika nilainya sama.


Selanjutnya:


 result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; 

Karena kita menggunakan metode equals() , nilai string akan dibandingkan, bukan instance dari objek.


Dalam hal ini, tidak masalah apakah benda berbeda atau tidak, karena nilainya dibandingkan. Hasilnya true .


Akhirnya, kami memiliki:


 result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; 

Seperti yang Anda lihat sebelumnya, metode intern() menempatkan string dalam kumpulan string. Kedua garis menunjuk ke objek yang sama, jadi dalam hal ini true .


Kesalahan string umum


Mungkin sulit untuk menentukan apakah dua garis menunjuk ke objek yang sama atau tidak, terutama ketika garis mengandung nilai yang sama. Penting untuk diingat bahwa menggunakan new selalu mengarah ke pembuatan objek baru di memori, bahkan jika nilai stringnya sama.


Menggunakan metode String untuk membandingkan referensi objek juga bisa rumit. Keunikannya adalah bahwa jika metode mengubah sesuatu dalam baris, maka akan ada referensi yang berbeda untuk objek.


Beberapa contoh untuk membantu memperjelas:


 System.out.println("duke".trim() == "duke".trim()); 

Perbandingan ini akan benar karena metode trim() tidak membuat garis baru.


 System.out.println(" duke".trim() == "duke".trim()); 

Dalam kasus ini, metode trim() pertama trim() menghasilkan baris baru, karena metode akan melakukan tugasnya dan oleh karena itu tautannya akan berbeda.


Akhirnya, ketika trim() melakukan tugasnya, itu menciptakan baris baru:


 //   trim   String new String(Arrays.copyOfRange(val, index, index + len), LATIN1); 

Apa yang harus diingat tentang string


  • Baris tidak bisa berubah, sehingga status baris tidak dapat diubah.


  • Untuk menghemat memori, JVM menyimpan string dalam kumpulan string. Saat membuat baris baru, JVM memeriksa nilainya dan menunjuk ke objek yang ada. Jika pool tidak memiliki baris dengan nilai ini, maka JVM membuat baris baru.


  • Operator " == " membandingkan referensi objek. Metode equals() membandingkan nilai string. Aturan yang sama akan berlaku untuk semua objek.


  • Saat menggunakan operator new , baris baru akan dibuat di heap (Catatan penerjemah - ada tertulis dalam aslinya bahwa itu ada di kolam, tapi ini tidak begitu, terima kasih zagayevskiy ), bahkan jika ada garis dengan nilai yang sama.



Jawabannya


Jawaban untuk masalah ini adalah D. Kesimpulannya adalah 12568.


Dilanjutkan ...

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


All Articles