JavaRush /Java Blog /Random EN /Mistakes of beginner java programmers. Part 2
articles
Level 15

Mistakes of beginner java programmers. Part 2

Published in the Random EN group
Mistakes of beginner java programmers. Part 1

9. Calling non-static class methods from the main() method

The entry point of any Java program should be a static method main:
Mistakes of beginner java programmers.  Part 2 - 1
public static void main(String[] args) {
  ...
}
Since this method is static, you cannot call non-static class methods from it. Students often forget about this and try to call methods without creating an instance of the class. This mistake is usually made at the very beginning of training, when students write small programs. Wrong example:
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);
        }
    }
}
There are 2 ways to fix the error: make the desired method static or create an instance of the class. To choose the right method, ask yourself whether the method uses a field or other class methods. If yes, then you should create an instance of the class and call a method on it, otherwise you should make the method static. Corrected example 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);
        }
    }
}
Corrected example 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. Using String class objects as method parameters.

In Java, a class java.lang.Stringstores string data. However, strings in Java
  1. have permanence (that is, they cannot be changed),
  2. are objects.
Therefore, they cannot be treated as just a character buffer; they are immutable objects. Sometimes students pass strings in the mistaken expectation that the string object will be passed as a character array by reference (as in C or C++). The compiler usually does not consider this an error. Wrong example.
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();
}
In the example above, the student wants to change the value of a local variable test1by assigning a new value to a parameter linein a method appendTodaysDate. Naturally this won't work. The meaning linewill change, but the meaning test1will remain the same. This error occurs due to a misunderstanding that (1) java objects are always passed by reference and (2) strings in java are immutable. You need to understand that string objects never change their value, and all operations on strings create a new object. To fix the error in the example above, you need to either return a string from the method, or pass an object StringBufferas a parameter to the method instead of String. Corrected example 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());
}
Corrected example 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());
}

approx. translation
Actually, it’s not so easy to understand what the error is. Since objects are passed by reference, it means lineit refers to the same place as test1. This means that by creating a new one line, we create a new one test1. In the wrong example, everything looks as if the transfer Stringis by value, and not by reference.

11. Declaring a constructor as a method

Object constructors in Java are similar in appearance to regular methods. The only differences are that the constructor does not specify a return type and the name is the same as the class name. Unfortunately, Java allows the method name to be the same as the class name. In the example below, the student wants to initialize a class field Vector listwhen creating the class. This won't happen because a method 'IntList'is not a constructor. Wrong example.
public class IntList {
    Vector list;

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

    public append(int n) {
        list.addElement(new Integer(n));
    }
}
The code will throw an exception NullPointerExceptionthe first time the field is accessed list. The error is easy to fix: you just need to remove the return value from the method header. Corrected example:
public class IntList {
    Vector list;

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

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

12. Forgot to cast an object to the required type

Like all other object-oriented languages, in Java you can refer to an object as its superclass. This is called 'upcasting', it is done automatically in Java. However, if a variable, class field, or method return value is declared as a superclass, the fields and methods of the subclass will be invisible. Referring to a superclass as a subclass is called 'downcasting', you need to register it yourself (that is, bring the object to the desired subclass). Students often forget about subclassing an object. This most often happens when using arrays of Objects and collections from a package java.util(meaning the Collection Framework ). The example below Stringputs an object into an array and then removes it from the array to compare it to another string. The compiler will detect an error and will not compile the code until a type cast is explicitly specified. Wrong example.
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]);
}
The meaning of type casting is difficult for some. Dynamic methods especially often cause difficulties. In the example above, if the method had been used equalsinstead of compareTo, the compiler would not have thrown an error, and the code would have worked correctly, since the method equalsof the class would have been called String. You need to understand that dynamic linking is different from downcasting. Corrected example:
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. Using interfaces.

For many students, the difference between classes and interfaces is not entirely clear. Therefore, some students try to implement interfaces such as Observeror Runnableusing the extends keyword instead of implements . To correct the error, you just need to correct the keyword to the correct one. Wrong example:
public class SharkSim extends Runnable {
    float length;
    ...
}
Corrected example:
public class SharkSim implements Runnable {
    float length;
    ...
}
Related error: Incorrect order of extends and implements blocks . According to the Java specification, class extension declarations must come before interface implementation declarations. Also, for interfaces, the implements keyword needs to be written only once; multiple interfaces are separated by commas. Some more erroneous examples:
// Неправильный порядок
public class SharkSim implements Swimmer extends Animal {
    float length;
    ...
}

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

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

14. Forgot to use the return value of a superclass method

Java allows you to call a similar superclass method from a subclass using the keyword keyword. Sometimes students have to call superclass methods, but often forget to use the return value. This happens especially often among those students who have not yet understood methods and their return values. In the example below, a student wants to insert the result of a toString()superclass method into the result of a toString()subclass method. However, it does not use the return value of the superclass method. Wrong example:
public class GraphicalRectangle extends Rectangle {
      Color fillColor;
      boolean beveled;
      ...
      public String toString() {
          super();
          return("color=" + fillColor + ", beveled=" + beveled);
      }
}
To correct the error, it is usually sufficient to assign the return value to a local variable, and then use that variable when calculating the result of the subclass method. Corrected example:
public class GraphicalRectangle extends Rectangle {
      Color fillColor;
      boolean beveled;
      ...
      public String toString() {
          String rectStr = super();
          return(rectStr + " - " +
         "color=" + fillColor + ", beveled=" + beveled);
      }
}

15. Forgot to add AWT components

AWT uses a simple GUI design model: each interface component must first be created using its own constructor, and then placed into the application window using a add()parent component method. Thus, the interface on AWT receives a hierarchical structure. Students sometimes forget these 2 steps. They create a component but forget to place it in the enlargement window. This will not cause errors at the compilation stage; the component simply will not appear in the application window. Wrong example.
public class TestFrame extends Frame implements ActionListener {
    public Button exit;

    public TestFrame() {
        super("Test Frame");
        exit = new Button("Quit");
    }
}
To fix this error, you simply need to add the components to their parents. The example below shows how to do this. It should be noted that often a student who forgets to add a component to an application window also forgets to assign event listeners to that component. Corrected example:
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. Forgot to start the stream

Multithreading in Java is implemented using the java.lang.Thread. The life cycle of a thread consists of 4 stages: initialized, started, blocked and stopped. The newly created thread is in an initialized state. To put it into a running state, you need to call its start(). Sometimes students create threads but forget to start them. Usually the error occurs when the student has insufficient knowledge about parallel programming and multithreading. (approx. transl.: I don’t see the connection) To fix the error, you just need to start the thread. In the example below, a student wants to create an animation of a picture using the interface Runnable, but he forgot to start the thread. Wrong example
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);
                }
        }
        ...
}
Corrected example:
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);
                }
        }
        ...
}
The life cycle of a thread and the relationship between threads and classes that implement an interface Runnableis a very important part of Java programming, and it would be useful to focus on this.

18. Using the forbidden readLine() method of the java.io.DataInputStream class

readLine()In Java version 1.0, you had to use a class method to read a string of text java.io.DataInputStream. Java version 1.1 added a whole set of I/O classes to provide I/O operations for text: the Readerand Writer. Thus, from version 1.1 to read a line of text, you must use the readLine()class method java.io.BufferedReader. Students may not be aware of this change, especially if they were taught from older books. (approx. Translation: actually no longer relevant. It’s unlikely that anyone will now study from books that were 10 years old). The old method readLine()remains in the JDK, but is declared illegal, which often confuses students. What you need to understand is that using a readLine()class method java.io.DataInputStreamis not wrong, it's just outdated. You must use the class BufferedReader. Wrong example:
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;
    }
}
Corrected example:
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;
    }
}
There are other prohibited methods in versions later than 1.0, but this one is the most common.

19. Using double as float

Like most other languages, Java supports operations on floating point numbers (fractional numbers). Java has two primitive types for floating-point numbers: doubleIEEE 64-bit precision, and floatIEEE 32-bit precision. The difficulty is when using decimal numbers such as 1.75, 12.9e17 or -0.00003 - the compiler assigns them to type double. Java does not perform type casts in operations where loss of precision may occur. This type casting must be done by the programmer. For example, Java will not allow you to assign a type value to a type intvariable bytewithout a type cast, as shown in the example below.
byte byteValue1 = 17; /* неправильно! */
byte byteValue2 = (byte)19; /* правильно */
Since fractional numbers are represented by type double, and assignment doubleto a variable of type floatcan lead to loss of precision, the compiler will complain about any attempt to use fractional numbers as float. So using the assignments below will prevent the class from compiling.
float realValue1 = -1.7;          /* неправильно! */
float realValue2 = (float)(-1.9); /* правильно */
This assignment would work in C or C++, but in Java it's much stricter. There are 3 ways to get rid of this error. You can use type doubleinstead of float. This is the simplest solution. In fact, there is little point in using 32-bit arithmetic instead of 64-bit; the difference in speed is still eaten up by the JVM (besides, in modern processors all fractional numbers are converted to the format of an 80-bit processor register before any operation). The only advantage of using them floatis that they take up less memory, which is useful when working with a large number of fractional variables. You can use a number type modifier to tell the compiler how to store the number. Modifier for type float - 'f'. Thus, the compiler will assign the type 1.75 to double, and 1.75f - float. For example:
float realValue1 = 1.7;    /* неправильно! */
float realValue2 = 1.9f;   /* правильно */
You can use explicit type casting. This is the least elegant way, but it is useful when converting a type variable doubleto a type float. Example:
float realValue1 = 1.7f;
double realValue2 = 1.9;
realValue1 = (float)realValue2;
You can read more about floating point numbers here and here.

-- translator's comment --
That's it.
In example 10, error 9 was actually made. I noticed it right away, but forgot to write a note. but did not correct it so that there would be no discrepancies with the original source.

Author: A.Grasoff™ Link to source: Mistakes of beginner java programmers
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION