JavaRush /Java Blog /Random-IT /Errori dei programmatori Java principianti. Parte 1
articles
Livello 15

Errori dei programmatori Java principianti. Parte 1

Pubblicato nel gruppo Random-IT

1. Il nome della classe è diverso dal nome del file in cui è archiviato

Tutti i framework Java che ho utilizzato, inclusi i JDK Javasoft, presuppongono che il codice sorgente di una classe con il modificatore public sia archiviato in un file con esattamente lo stesso nome della classe e un'estensione .java. La mancata osservanza di questa convenzione può causare molti problemi che si manifesteranno durante la compilazione.
Errori dei programmatori Java principianti.  Parte 1 - 1
Gli studenti principianti (programmatori) spesso dimenticano questa convenzione e, ad esempio, impostano il nome del file in base al compito: Lab6.java. Esempio sbagliato: nome fileLab6.java
public class Airplane extends Vehicle
  Seat pilot;
  public Airplane() {
    pilot = new Seat();
  }
}
Esempio corretto: nome fileAirplane.java
public class Airplane extends Vehicle
  Seat pilot;
  public Airplane() {
    pilot = new Seat();
  }
}
Notare che:si presuppone che il nome della classe inizi con una lettera maiuscola. I sistemi operativi che fanno distinzione tra maiuscole e minuscole nei nomi dei file possono presentare ulteriori problemi, soprattutto per gli studenti che imparano Java su Unix e sono abituati al sistema di denominazione dei file DOS. La classe MotorVehicledovrebbe essere memorizzata in un file MotorVehicle.java, ma non in un file motorvehicle.java.

2. Confronto utilizzando==

In Java, le stringhe sono oggetti della classe java.lang.String. L'operatore ==applicato agli oggetti verifica l'uguaglianza dei riferimenti agli oggetti! A volte gli studenti non comprendono la semantica dell'operatore ==e provano a usarlo per confrontare le stringhe. Esempio sbagliato:
// проверим, equals ли первый аргумент "-a"
if (args[0] == "-a") {
    optionsAll = true;
}
Il modo corretto per confrontare 2 stringhe per verificarne l'uguaglianza è utilizzare il metodo equals()class java.lang.String. Restituisce truese le stringhe hanno la stessa lunghezza e contengono gli stessi caratteri. (Nota: in realtà questo non garantisce l'uguaglianza. Infatti, equalscontrolla se 2 stringhe sono uguali carattere per carattere) Esempio corretto:
//  проверим, equals ли первый аргумент "-a"
if ("-a".equals(args[0])) {
    optionsAll = true;
}
Questo errore è stupido, perché in effetti il ​​codice Java risulta sintatticamente corretto, ma alla fine non funziona come previsto. Alcuni studenti provano anche a utilizzare gli operatori di confronto >invece dei <=metodi compareTo()di classe java.lang.String. Questo errore è più semplice da rilevare perché provoca errori durante la fase di compilazione.

3. Ho dimenticato di inizializzare gli oggetti che sono elementi dell'array.

In Java, un array di oggetti è in realtà un array di riferimenti a oggetti. Creare un array significa semplicemente creare un insieme di riferimenti che non puntano a nulla (ovvero sono nulli). Per creare effettivamente un array "completo" di oggetti, è necessario inizializzare ciascun elemento dell'array. Molti studenti non lo capiscono; credono che creando una serie di oggetti, creino automaticamente gli oggetti stessi. (Nella maggior parte dei casi, gli studenti portano questo concetto dal C++, dove la creazione di un array di oggetti comporta la creazione degli oggetti stessi chiamando il loro costruttore predefinito.) Nell'esempio seguente, lo studente desidera creare 3 oggetti della classe StringBuffer. Il codice verrà compilato senza errori, ma si verificherà un'eccezione nell'ultima riga NullPointerException, dove si accede ad un oggetto inesistente. Esempio sbagliato:
// Создаем массив из StringBuffer
StringBuffer [] myTempBuffers;
myTempBuffers = new StringBuffer[3];
myTempBuffers[0].add(data);
Per evitare questo errore, è necessario ricordarsi di inizializzare gli elementi dell'array. Esempio corretto:
// Создаем массив из StringBuffer и инициализируем элементы
StringBuffer [] myTempBuffers;
myTempBuffers = new StringBuffer[3];
for (int ix = 0; ix < myTempBuffers.length; ix++)
     myTempBuffers[ix] = new StringBuffer();

myTempBuffers[0].add(data);

4. Inserimento di più classi con un modificatore in un file contemporaneamentepublic

I file sorgente Java sono associati in determinati modi alle classi contenute in tali file. La relazione può essere caratterizzata come segue: qualsiasi classe Java viene memorizzata in non più di un file. In qualsiasi file di codice sorgente non puoi inserire più di 1 classe con il modificatore public. Se c'è una classe con un modificatore nel file del codice sorgente public, il nome del file e il nome della classe devono essere rigorosamente uguali (nota di traduzione: fino al caso, vedere il punto 1) A volte gli studenti dimenticano la seconda regola, il che porta a errori in fase di compilazione. Il messaggio di errore per la 2a e la 3a regola sarà lo stesso (che è ciò che rende effettivamente difficile riconoscere questo errore).

5. Sostituzione di un campo di classe con una variabile locale.

Java consente di dichiarare variabili all'interno di un metodo il cui nome corrisponde ai campi della classe. In questo caso, le variabili locali avranno la precedenza e verranno utilizzate al posto dei campi. Il compilatore genererà un errore se le variabili con gli stessi nomi sono di tipo diverso. Se sono dello stesso tipo, non si verificherà alcun errore di compilazione e le ragioni dell’errato funzionamento del programma non saranno chiare. Esempio sbagliato:
public class Point3 {
    int i = 0;
    int j = 0;
    int k = 0;

    public boolean hits(Point[] p2list) {
      for(int i = 0; i < p2list.length; i++) {
        Point p2 = p2list[i];
        if (p2.x == i && p2.y == j)
          return true;
      }
      return false;
    }
}
Esistono diversi modi per correggere questo errore. Il più semplice è accedere ai campi della classe utilizzando un puntatore implicito this: this.Name_поля. Il modo migliore è rinominare il campo della classe o la variabile locale, quindi la sostituzione non avverrà. (circa Trad.: Il 2° metodo non è il nostro metodo. Inoltre, non garantisce che un giorno non sostituirò accidentalmente un campo di una variabile. Una difficoltà ancora maggiore sorge con l'ereditarietà, quando non vedo affatto quali campi la classe ha ) Esempio corretto:
// One way to fix the problem
  int i = 0;
  int j = 0;
  int k = 0;

  public boolean hits(Point[] p2list) {
    for(int i = 0; i < p2list.length; i++) {
      Point p2 = p2list[i];
      if (p2.x == this.i && p2.y == this.j)
        return true;
    }
    return false;
  }

  // *****************************
  // Лучший способ
  int x = 0;
  int y = 0;
  int z = 0;

  public boolean hits(Point[] p2list) {
    for(int i = 0; i < p2list.length; i++) {
      Point p2 = p2list[i];
      if (p2.x == x && p2.y == y)
        return true;
    }
    return false;
  }
Un altro possibile luogo in cui si verifica questo errore è impostare il nome del parametro del metodo in modo che corrisponda al nome del campo della classe. Questo sembra buono nei costruttori, ma non è adatto ai metodi normali.

ca. traduzione

un po' caotico, ma questo è il succo

public class Test {
   private int param = 0;

   public Test(int param) {
      this.param = param;
   }
}

cioè, tutto sembra bello nel costruttore, ma questo non dovrebbe essere usato per i metodi ordinari.

6. Ho dimenticato di chiamare il costruttore genitore (superclasse).

Quando una classe estende un'altra classe, ogni costruttore di sottoclasse deve chiamare qualche costruttore di superclasse. Questo di solito si ottiene chiamando il costruttore della superclasse con il metodo super(x)posizionato sulla prima riga del costruttore. Se nella prima riga del costruttore non è presente alcuna chiamata super(x), il compilatore stesso inserisce questa chiamata, ma senza parametri: super(). (trad. ca.: x...se, ma non lo sapevo) A volte gli studenti dimenticano questo requisito. Solitamente questo non è un problema: la chiamata al costruttore della superclasse viene inserita dal compilatore e tutto funziona bene. Tuttavia, se la superclasse non ha un costruttore predefinito, il compilatore genererà un errore. Nell'esempio seguente, tutti i costruttori della superclasse java.io.Filehanno 1 o 2 parametri: Esempio errato:
public class JavaClassFile extends File {
    String classname;
    public JavaClassFile(String cl) {
        classname = cl;
    }
}
La soluzione al problema è inserire una chiamata esplicita al costruttore della superclasse corretto: Esempio corretto:
public class JavaClassFile extends File {
    String classname;
    public JavaClassFile(String cl) {
        super(cl + ".class");
        classname = cl;
    }
}
Una situazione più spiacevole si verifica quando la superclasse ha un costruttore predefinito, ma non inizializza completamente l'oggetto. In questo caso, il codice verrà compilato, ma l'output del programma potrebbe non essere corretto o potrebbe verificarsi un'eccezione.

7. Rilevamento errato delle eccezioni

Il sistema di gestione delle eccezioni di Java è piuttosto potente, ma difficile da comprendere per i principianti. Gli studenti esperti in C++ o Ada di solito non hanno le stesse difficoltà dei programmatori C e Fortran. Gli esempi seguenti mostrano alcuni errori comuni. In questo esempio, l'eccezione non ha un nome. Il compilatore indicherà questo errore in fase di compilazione, quindi è facile risolverlo da solo. Esempio sbagliato:
try {
    stream1 = new FileInputStream("data.txt");
} catch (IOException) {
    message("Could not open data.txt");
}
Esempio corretto:
try {
   stream1 = new FileInputStream("data.txt");
} catch (IOException ie) {
   message("Could not open data.txt: " + ie);
}
L'ordine dei blocchi catchdetermina l'ordine in cui vengono catturate le eccezioni. È necessario tenere presente che ciascuno di questi blocchi catturerà tutte le eccezioni della classe specificata o di una qualsiasi delle sue sottoclassi. Se non si tiene conto di ciò, è possibile che ci si ritrovi con un blocco catch irraggiungibile, che il compilatore segnalerà. Nell'esempio seguente SocketExceptionc'è una sottoclasse di IOException. Esempio sbagliato:
try {
    serviceSocket.setSoTimeout(1000);
    newsock = serviceSocket.accept();
} catch (IOException ie) {
    message("Error accepting connection.");
} catch (SocketException se) {
    message("Error setting time-out.");
}
Esempio corretto:
try {
    serviceSocket.setSoTimeout(1000);
    newsock = serviceSocket.accept();
} catch (SocketException se) {
    message("Error setting time-out.");
} catch (IOException ie) {
    message("Error accepting connection.");
}
Se è possibile che si verifichi un'eccezione nel codice che non viene rilevata da alcun blocco try-catch, allora questa eccezione dovrebbe essere dichiarata nell'intestazione del metodo. RuntimeException( Questo non è necessario per le eccezioni - sottoclassi di una classe ). Gli studenti a volte dimenticano che chiamare un metodo può generare un'eccezione. Il modo più semplice per risolvere questo problema è inserire la chiamata al metodo in un blocco try-catch. Esempio sbagliato:
public void waitFor(int sec) {
    Thread.sleep(sec * 1000);
}
Esempio corretto:
public void waitFor(int sec) throws InterruptedException {
    Thread.sleep(sec * 1000);
}

8. Il metodo di accesso ha un tipovoid

Questo è un errore molto semplice. Lo studente crea un metodo per accedere a una variabile, ma specifica che il metodo non restituisce nulla (inserisce un modificatore voidnell'intestazione del metodo). Per correggere questo errore, è necessario specificare il tipo di reso corretto. Esempio sbagliato:
public class Line {
    private Point start, end;
    public void getStart() {
      return start;
    }
}
Esempio corretto:
public class Line {
    private Point start, end;
    public Point getStart() {
      return start;
    }
}
Specificare il tipo di reso errato genera un'intera classe di errori. In genere il compilatore riconoscerà questi errori e li segnalerà in modo che gli studenti possano correggerli da soli. Autore: A. Grasoff™ Leggi il seguito Link alla fonte: Errori dei programmatori Java principianti
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION