Kesalahan programmer java pemula. Bagian 1
Penulis: A.Grasoff™ Tautan ke sumber: Kesalahan programmer java pemula
9. Memanggil metode kelas non-statis dari metode main()
Titik masuk program Java apa pun harus berupa metode statismain
:
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, kelasjava.lang.String
menyimpan data string. Namun, string di Java
- bersifat permanen (yaitu tidak dapat diubah),
- adalah objek.
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 test1
dengan memberikan nilai baru pada parameter line
dalam suatu metode appendTodaysDate
. Tentu saja ini tidak akan berhasil. Maknanya line
akan berubah, namun maknanya test1
akan 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 StringBuffer
sebagai 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 |
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 kelasVector list
saat 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 NullPointerException
saat 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 String
menempatkan 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 equals
bukan compareTo
, kompiler tidak akan menimbulkan kesalahan, dan kode akan bekerja dengan benar, karena metode equals
kelas 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 sepertiObserver
atau Runnable
menggunakan 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 metodetoString()
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 menggunakanadd()
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 menggunakanjava.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 Runnable
adalah 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 Reader
dan 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.DataInputStream
tidaklah 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:double
presisi IEEE 64-bit, dan float
presisi 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 int
variabel tipe byte
tanpa 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 double
ke variabel bertipe float
dapat 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 double
alih-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 float
adalah 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 double
menjadi 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 -- |
GO TO FULL VERSION