JavaRush /Java Blog /Random-ID /Kesalahan programmer java pemula. Bagian 2
articles
Level 15

Kesalahan programmer java pemula. Bagian 2

Dipublikasikan di grup Random-ID
Kesalahan programmer java pemula. Bagian 1

9. Memanggil metode kelas non-statis dari metode main()

Titik masuk program Java apa pun harus berupa metode statis main:
Kesalahan programmer java pemula.  Bagian 2 - 1
public static void main(String[] args) {
  ...
}
Karena metode ini statis, Anda tidak dapat memanggil metode kelas non-statis dari metode ini. Siswa sering melupakan hal ini dan mencoba memanggil metode tanpa membuat instance kelas. Kesalahan ini biasanya dilakukan pada awal pembelajaran, ketika siswa menulis program kecil. Contoh yang salah:
public class DivTest {
    boolean divisible(int x, int y) {
        return (x % y == 0);
    }

    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;

        // на следующие строки компилятор выдаст ошибку
        if (divisible(v1, v2)) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}
Ada 2 cara untuk memperbaiki kesalahan: membuat metode yang diinginkan menjadi statis atau membuat instance kelas. Untuk memilih metode yang tepat, tanyakan pada diri Anda apakah metode tersebut menggunakan metode field atau metode kelas lainnya. Jika ya, maka Anda harus membuat instance kelas dan memanggil metode di dalamnya, jika tidak, Anda harus menjadikan metode tersebut statis. Contoh yang diperbaiki 1:
public class DivTest {
    int modulus;

    public DivTest(int m) {
      modulus = m;
    }

    boolean divisible(int x) {
        return (x % modulus == 0);
    }

    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;

        DivTest tester = new DivTest(v2);

        if (tester.divisible(v1) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}
Contoh yang diperbaiki 2:
public class DivTest {
    static boolean divisible(int x, int y) {
        return (x % y == 0);
    }

    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;

        if (divisible(v1, v2)) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}

10. Menggunakan objek kelas String sebagai parameter metode.

Di Java, kelas java.lang.Stringmenyimpan data string. Namun, string di Java
  1. bersifat permanen (yaitu tidak dapat diubah),
  2. adalah objek.
Oleh karena itu, mereka tidak dapat diperlakukan hanya sebagai buffer karakter; mereka adalah objek yang tidak dapat diubah. Terkadang siswa meneruskan string dengan harapan yang salah bahwa objek string akan diteruskan sebagai array karakter dengan referensi (seperti dalam C atau C++). Kompiler biasanya tidak menganggap ini sebagai kesalahan. Contoh yang salah.
public static void main(String args[]) {
   String test1 = "Today is ";
   appendTodaysDate(test1);
   System.out.println(test1);
}

/* прим. редактора: закомментированный метод должен иметь модификатор
    static (здесь автором допущена ошибка №9)
public void appendTodaysDate(String line) {
    line = line + (new Date()).toString();
}
*/

public static void appendTodaysDate(String line) {
    line = line + (new Date()).toString();
}
Pada contoh di atas, siswa ingin mengubah nilai variabel lokal test1dengan memberikan nilai baru pada parameter linedalam suatu metode appendTodaysDate. Tentu saja ini tidak akan berhasil. Maknanya lineakan berubah, namun maknanya test1akan tetap sama. Kesalahan ini terjadi karena kesalahpahaman bahwa (1) objek Java selalu diteruskan dengan referensi dan (2) string di Java tidak dapat diubah. Anda perlu memahami bahwa objek string tidak pernah mengubah nilainya, dan semua operasi pada string membuat objek baru. Untuk memperbaiki kesalahan pada contoh di atas, Anda perlu mengembalikan string dari metode, atau meneruskan objek StringBuffersebagai parameter ke metode, bukan String. Contoh yang diperbaiki 1:
public static void main(String args[]) {
   String test1 = "Today is ";
   test1 = appendTodaysDate(test1);
   System.out.println(test1);
}

public static String appendTodaysDate(String line) {
    return (line + (new Date()).toString());
}
Contoh yang diperbaiki 2:
public static void main(String args[]) {
   StringBuffer test1 = new StringBuffer("Today is ");
   appendTodaysDate(test1);
   System.out.println(test1.toString());
}

public static void appendTodaysDate(StringBuffer line) {
    line.append((new Date()).toString());
}

kira-kira. terjemahan
Sebenarnya tidak mudah untuk memahami apa kesalahannya. Karena objek diteruskan dengan referensi, artinya lineobjek tersebut merujuk ke tempat yang sama dengan test1. Artinya dengan membuat yang baru line, kita membuat yang baru.Dalam test1contoh yang salah, semuanya tampak seolah-olah transfer Stringdilakukan berdasarkan nilai, dan bukan berdasarkan referensi.

11. Mendeklarasikan konstruktor sebagai suatu metode

Konstruktor objek di Java memiliki tampilan yang mirip dengan metode biasa. Satu-satunya perbedaan adalah konstruktor tidak menentukan tipe nilai kembalian dan namanya sama dengan nama kelas. Sayangnya, Java mengizinkan nama metode sama dengan nama kelas. Pada contoh di bawah, siswa ingin menginisialisasi kolom kelas Vector listsaat membuat kelas. Ini tidak akan terjadi karena suatu metode 'IntList'bukan konstruktor. Contoh yang salah.
public class IntList {
    Vector list;

    // Выглядит How конструктор, но на самом деле это метод
    public void IntList() {
        list = new Vector();
    }

    public append(int n) {
        list.addElement(new Integer(n));
    }
}
Kode ini akan memunculkan pengecualian NullPointerExceptionsaat pertama kali bidang tersebut diakses list. Kesalahannya mudah diperbaiki: Anda hanya perlu menghapus nilai kembalian dari header metode. Contoh yang diperbaiki:
public class IntList {
    Vector list;

    // Это конструктор
    public IntList() {
        list = new Vector();
    }

    public append(int n) {
        list.addElement(new Integer(n));
    }
}

12. Lupa memasukkan objek ke tipe yang diperlukan

Seperti semua bahasa berorientasi objek lainnya, di Java Anda bisa menyebut suatu objek sebagai superkelasnya. Ini disebut 'upcasting', ini dilakukan secara otomatis di Java. Namun, jika variabel, bidang kelas, atau nilai pengembalian metode dideklarasikan sebagai superkelas, bidang dan metode subkelas tersebut tidak akan terlihat. Mengacu pada superkelas sebagai subkelas disebut 'downcasting', Anda perlu mendaftarkannya sendiri (yaitu, membawa objek ke subkelas yang diinginkan). Siswa sering lupa tentang subkelas suatu objek. Hal ini paling sering terjadi ketika menggunakan array Objek dan koleksi dari suatu paket java.util(artinya Collection Framework ). Contoh di bawah ini Stringmenempatkan objek ke dalam array dan kemudian menghapusnya dari array untuk membandingkannya dengan string lain. Kompiler akan mendeteksi kesalahan dan tidak akan mengkompilasi kode sampai tipe cast ditentukan secara eksplisit. Contoh yang salah.
Object arr[] = new Object[10];
arr[0] = "m";
arr[1] = new Character('m');

String arg = args[0];
if (arr[0].compareTo(arg) < 0) {
    System.out.println(arg + " comes before " + arr[0]);
}
Arti type casting sulit bagi sebagian orang. Metode dinamis khususnya seringkali menimbulkan kesulitan. Dalam contoh di atas, jika metode yang digunakan equalsbukan compareTo, kompiler tidak akan menimbulkan kesalahan, dan kode akan bekerja dengan benar, karena metode equalskelas tersebut akan dipanggil String. Anda perlu memahami bahwa tautan dinamis berbeda dengan tautan downcasting. Contoh yang diperbaiki:
Object arr[] = new Object[10];
arr[0] = "m";
arr[1] = new Character('m');

String arg = args[0];
if ( ((String) arr[0]).compareTo(arg) < 0) {
    System.out.println(arg + " comes before " + arr[0]);
}

13. Menggunakan antarmuka.

Bagi banyak siswa, perbedaan antara kelas dan antarmuka tidak sepenuhnya jelas. Oleh karena itu, beberapa siswa mencoba mengimplementasikan antarmuka seperti Observeratau Runnablemenggunakan kata kunci extends alih-alih mengimplementasi . Untuk memperbaiki kesalahan tersebut, Anda hanya perlu mengoreksi kata kunci ke kata kunci yang benar. Contoh yang salah:
public class SharkSim extends Runnable {
    float length;
    ...
}
Contoh yang diperbaiki:
public class SharkSim implements Runnable {
    float length;
    ...
}
Kesalahan terkait: Urutan blok perluasan dan implementasi salah . Menurut spesifikasi Java, deklarasi ekstensi kelas harus dilakukan sebelum deklarasi implementasi antarmuka. Selain itu, untuk antarmuka, kata kunci implementasi hanya perlu ditulis satu kali; beberapa antarmuka dipisahkan dengan koma. Beberapa contoh yang lebih salah:
// Неправильный порядок
public class SharkSim implements Swimmer extends Animal {
    float length;
    ...
}

// ключевое слово implements встречается несколько раз
public class DiverSim implements Swimmer implements Runnable {
    int airLeft;
    ...
}
Contoh yang diperbaiki:
// Правильный порядок
public class SharkSim extends Animal implements Swimmer {
    float length;
    ...
}

// Несколько интерфейсов разделяются запятыми
public class DiverSim implements Swimmer, Runnable {
    int airLeft;
    ...
}

14. Lupa menggunakan nilai kembalian metode superkelas

Java memungkinkan Anda memanggil metode superkelas serupa dari subkelas menggunakan kata kunci kata kunci. Terkadang siswa harus memanggil metode superclass, tetapi sering kali lupa menggunakan nilai kembaliannya. Hal ini sering terjadi terutama di kalangan siswa yang belum memahami metode dan nilai baliknya. Pada contoh di bawah, seorang siswa ingin memasukkan hasil metode toString()superkelas ke dalam hasil toString()metode subkelas. Namun, metode ini tidak menggunakan nilai kembalian dari metode superclass. Contoh yang salah:
public class GraphicalRectangle extends Rectangle {
      Color fillColor;
      boolean beveled;
      ...
      public String toString() {
          super();
          return("color=" + fillColor + ", beveled=" + beveled);
      }
}
Untuk memperbaiki kesalahan, biasanya cukup dengan menetapkan nilai kembalian ke variabel lokal, dan kemudian menggunakan variabel tersebut saat menghitung hasil metode subkelas. Contoh yang diperbaiki:
public class GraphicalRectangle extends Rectangle {
      Color fillColor;
      boolean beveled;
      ...
      public String toString() {
          String rectStr = super();
          return(rectStr + " - " +
         "color=" + fillColor + ", beveled=" + beveled);
      }
}

15. Lupa menambahkan komponen AWT

AWT menggunakan model desain GUI sederhana: setiap komponen antarmuka harus dibuat terlebih dahulu menggunakan konstruktornya sendiri, dan kemudian ditempatkan ke dalam jendela aplikasi menggunakan add()metode komponen induk. Dengan demikian, antarmuka pada AWT menerima struktur hierarki. Siswa terkadang melupakan 2 langkah ini. Mereka membuat komponen tetapi lupa menempatkannya di jendela pembesaran. Ini tidak akan menyebabkan kesalahan pada tahap kompilasi, komponen tidak akan muncul di jendela aplikasi. Contoh yang salah.
public class TestFrame extends Frame implements ActionListener {
    public Button exit;

    public TestFrame() {
        super("Test Frame");
        exit = new Button("Quit");
    }
}
Untuk memperbaiki kesalahan ini, Anda hanya perlu menambahkan komponen ke induknya. Contoh di bawah ini menunjukkan cara melakukan hal ini. Perlu dicatat bahwa sering kali siswa yang lupa menambahkan komponen ke jendela aplikasi juga lupa menugaskan pendengar acara ke komponen tersebut. Contoh yang diperbaiki:
public class TestFrame extends Frame implements ActionListener {
    public Button exit;

    public TestFrame() {
        super("Test Frame");

        exit = new Button("Quit");

        Panel controlPanel = new Panel();
        controlPanel.add(exit);

        add("Center", controlPanel);

        exit.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        System.exit(0);
    }
}

17. Lupa memulai streaming

Multithreading di Java diimplementasikan menggunakan java.lang.Thread. Siklus hidup thread terdiri dari 4 tahap: inisialisasi, dimulai, diblokir, dan dihentikan. Thread yang baru dibuat berada dalam keadaan terinisialisasi. Untuk memasukkannya ke dalam kondisi berjalan, Anda perlu memanggilnya start(). Terkadang siswa membuat thread tetapi lupa memulainya. Biasanya error terjadi ketika siswa kurang memiliki pengetahuan tentang pemrograman paralel dan multithreading. (kira-kira terjemahan: Saya tidak melihat koneksinya) Untuk memperbaiki kesalahan, Anda hanya perlu memulai thread. Pada contoh di bawah, seorang siswa ingin membuat animasi gambar menggunakan antarmuka Runnable, tetapi dia lupa memulai thread. Contoh yang salah
public class AnimCanvas extends Canvas implements Runnable {
        protected Thread myThread;
        public AnimCanvas() {
                myThread = new Thread(this);
        }

        // метод run() не будет вызван,
        // потому что поток не запущен.
        public void run() {
                for(int n = 0; n < 10000; n++) {
                   try {
                     Thread.sleep(100);
                   } catch (InterruptedException e) { }

                   animateStep(n);
                }
        }
        ...
}
Contoh yang diperbaiki:
public class AnimCanvas extends Canvas implements Runnable {
        static final int LIMIT = 10000;
        protected Thread myThread;

        public AnimCanvas() {
                myThread = new Thread(this);
                myThread.start();
        }

        public void run() {
                for(int n = 0; n < LIMIT; n++) {
                        try {
                          Thread.sleep(100);
                        } catch (InterruptedException e) { }

                        animateStep(n);
                }
        }
        ...
}
Siklus hidup thread dan hubungan antara thread dan kelas yang mengimplementasikan antarmuka Runnableadalah bagian yang sangat penting dalam pemrograman Java, dan akan berguna untuk fokus pada hal ini.

18. Menggunakan metode readLine() terlarang dari kelas java.io.DataInputStream

readLine()Di Java versi 1.0, Anda harus menggunakan metode kelas untuk membaca string teks java.io.DataInputStream. Java versi 1.1 menambahkan seluruh rangkaian kelas I/O untuk menyediakan operasi I/O untuk teks: the Readerdan Writer. Jadi, mulai versi 1.1 untuk membaca sebaris teks, Anda harus menggunakan metode readLine()kelas java.io.BufferedReader. Siswa mungkin tidak menyadari perubahan ini, terutama jika mereka diajarkan dari buku-buku lama. (kira-kira Terjemahan: sebenarnya sudah tidak relevan lagi. Sekarang tidak mungkin ada orang yang belajar dari buku yang berumur 10 tahun). Cara lama readLine()tetap ada di JDK, namun dinyatakan ilegal sehingga sering membingungkan siswa. Yang perlu anda pahami adalah menggunakan metode readLine()kelas java.io.DataInputStreamtidaklah salah, hanya saja sudah ketinggalan jaman. Anda harus menggunakan kelas BufferedReader. Contoh yang salah:
public class LineReader {
    private DataInputStream dis;

    public LineReader(InputStream is) {
        dis = new DataInputStream(is);
    }

    public String getLine() {
        String ret = null;

        try {
          ret = dis.readLine();  // Неправильно! Запрещено.
        } catch (IOException ie) { }

        return ret;
    }
}
Contoh yang diperbaiki:
public class LineReader {
    private BufferedReader br;

    public LineReader(InputStream is) {
        br = new BufferedReader(new InputStreamReader(is));
    }

    public String getLine() {
        String ret = null;

        try {
          ret = br.readLine();
        } catch (IOException ie) { }

        return ret;
    }
}
Ada metode lain yang dilarang di versi lebih baru dari 1.0, tetapi metode ini adalah yang paling umum.

19. Menggunakan double sebagai pelampung

Seperti kebanyakan bahasa lainnya, Java mendukung operasi pada bilangan floating point (bilangan pecahan). Java memiliki dua tipe primitif untuk bilangan floating-point: doublepresisi IEEE 64-bit, dan floatpresisi IEEE 32-bit. Kesulitannya adalah ketika menggunakan angka desimal seperti 1.75, 12.9e17 atau -0.00003 - kompiler menugaskannya untuk mengetik double. Java tidak melakukan pengecoran tipe dalam operasi yang dapat menyebabkan hilangnya presisi. Pengecoran jenis ini harus dilakukan oleh programmer. Misalnya, Java tidak akan mengizinkan Anda untuk menetapkan nilai tipe ke intvariabel tipe bytetanpa pemeran tipe, seperti yang ditunjukkan pada contoh di bawah ini.
byte byteValue1 = 17; /* неправильно! */
byte byteValue2 = (byte)19; /* правильно */
Karena bilangan pecahan diwakili oleh tipe double, dan penugasan doubleke variabel bertipe floatdapat menyebabkan hilangnya presisi, kompiler akan mengeluh tentang segala upaya untuk menggunakan bilangan pecahan sebagai float. Jadi menggunakan tugas di bawah ini akan mencegah kelas melakukan kompilasi.
float realValue1 = -1.7;          /* неправильно! */
float realValue2 = (float)(-1.9); /* правильно */
Penugasan ini dapat dilakukan di C atau C++, namun di Java jauh lebih ketat. Ada 3 cara untuk menghilangkan kesalahan ini. Anda dapat menggunakan type doublealih-alih float. Ini adalah solusi paling sederhana. Faktanya, tidak ada gunanya menggunakan aritmatika 32-bit daripada 64-bit; perbedaan kecepatan masih dimakan oleh JVM (selain itu, dalam prosesor modern semua bilangan pecahan diubah ke format prosesor 80-bit mendaftar sebelum operasi apa pun). Satu-satunya keuntungan menggunakannya floatadalah menggunakan lebih sedikit memori, yang berguna saat bekerja dengan variabel pecahan dalam jumlah besar. Anda dapat menggunakan pengubah tipe angka untuk memberi tahu kompiler cara menyimpan nomor tersebut. Pengubah untuk tipe float - 'f'. Dengan demikian, kompiler akan menetapkan tipe 1.75 ke double, dan 1.75f - float. Misalnya:
float realValue1 = 1.7;    /* неправильно! */
float realValue2 = 1.9f;   /* правильно */
Anda dapat menggunakan casting tipe eksplisit. Ini adalah cara yang paling tidak elegan, tetapi berguna saat mengonversi variabel tipe doublemenjadi tipe float. Contoh:
float realValue1 = 1.7f;
double realValue2 = 1.9;
realValue1 = (float)realValue2;
Anda dapat membaca lebih lanjut tentang bilangan floating point di sini dan di sini.

-- komentar penerjemah --
Itu saja.
Pada contoh 10 sebenarnya terjadi error 9. Saya langsung menyadarinya, tetapi lupa menulis catatan. namun tidak memperbaikinya agar tidak terjadi perbedaan dengan sumber aslinya.

Penulis: A.Grasoff™ Tautan ke sumber: Kesalahan programmer java pemula
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION