「こんにちは、アミーゴ! 間違いについて話を続けましょう。今回は、コンパイラーが必ずしも解決してくれるわけではない間違いについて調べていきます。注意してください。そうすれば、あなた自身について何かを学ぶことができます。」

「聞く準備はできています、ディエゴ。これが私にとってあまり恥ずかしいことではないといいのですが。」

オブジェクトを比較する==

「初心者プログラマーの最もよくある間違いのリストは、==演算子を使用してオブジェクト (特に文字列) を比較することから始まります。」

例:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1 == s2)
{
   System.out.println("The strings are equal");
}

「私はこれを頻繁に行ってきました。ステートメントは 2 つの異なる文字列オブジェクトへの参照を比較するため、このコードでは決して「文字列が等しい」と表示されないことがはっきりとわかりますif

「はい。そのため、正しい選択肢は次のようになります。

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1.equals(s2))
{
   System.out.println("The strings are equal");
}

Stringオブジェクトの変更

「初心者のプログラマは、クラスのすべてのオブジェクトが不変であること、およびStringクラスのすべてのメソッドが新しいオブジェクトを返すこと、つまり現在のオブジェクトは決して変更されないことを忘れがちです。」

「私が不変の意味を学んだのはそれほど前のことではありませんが、これはできたと思います。

「私はそれをかなり確信しています。例:

String s = "Hello";
s.toUpperCase (); // Convert to uppercase

「このコードは正しいコードとよく似ていますが、期待どおりに動作しません。このtoUpperCase()メソッドは、呼び出されるオブジェクトを変更しません。正しいコードは次のようになります。

String s = "Hello";
String result = s.toUpperCase(); // Convert to uppercase

「そのとおりです。私もそれを実行しましたが、何が間違っていたのかさえよくわかりませんでした。説明してくれてありがとう!」

配列の要素であるオブジェクトの初期化を忘れる

「もう 1 つのよくある間違いは、配列変数の初期化を忘れることです。例:

int[] array;
array[0] = 1;
array[0] = 2;

「このコードは機能しません。配列の要素を格納するコンテナ オブジェクトへの参照と等しい配列変数を明示的に設定する必要があります。正しいバージョン:

int[] array = new int[10];
array[0] = 1;
array[0] = 2;

インスタンス変数の代わりにローカル変数を使用します。

「初心者は変数に長くて意味のある名前を考えるのを好みません。」

「それはその通りです。私は、物事を早く終わらせるために、変数にab、 などの名前を付けることがありますi。」

「やめてください。コードに次のような変数がいくつかある場合、それは残酷な行為です。

配列の 100 個のセルに数値 99 を入れます
class Solution
{
  public static int a = 99;
  public static int i = 100;

  public static void main(String[] args)
  {
    int[] a = new int[i];
    for (int i = 0; i < 10; i++)
    {
      a[i] = a;
    }
  }
}

「固有名を持つコードでは間違いを犯すことがはるかに困難です。正しいバージョンは次のようになります。

配列の 100 個のセルに数値 99 を入れます
class Solution
{
   public static int value = 99;
   public static int count = 100;

   public static void main(String[] args)
   {
      int[] a = new int[count];
      for (int i = 0; i < 10; i++)
      {
         a[i] = value;
      }
   }
}

コレクションアイテムの削除

「もうコレクションを調べましたか?」

「文字通り、片目だけです。」

「私が何を言っているのかわからない場合は、将来見直すために自分用にメモしておいてください。特定の要素をコレクションから削除する必要がある状況が非常によくあります。コードは大まかに次のようになります。これ:

ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

for (Integer value: list)
   if (value < 0)
      list.remove(value);

for-each「ループを使用してコレクションの要素を同時に走査し、そのコレクションを変更することはできないため、このコードは機能しません。

「解決策はいくつかあります。まず、1 つのコレクションを調べて、別のコレクションを変更します。

解決策 1
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

ArrayList<Integer> copy = new ArrayList<Integer>(list);
for (Integer value: copy)
   if (value < 0)
      list.remove(value);

「第二に、Java 8 以降、コレクションremoveIf()には、どの要素を削除するかを示すルール (ラムダ関数) を渡すことができるメソッドがあります。例:

解決策 2
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

list.removeIf( x-> x<0 );

修飾子を含む複数のクラスをpublic1 つのファイルに配置する

「ファイル内に存在できるパブリック クラスは 1 つだけです。ファイル内でさらに多くのクラスを宣言できますが、それらはパブリック クラスの内部クラスであるか、修飾子を持たない必要があります。例public:

Solution.java ファイルの内容 ノート
public class Solution
{
}
public class Main
{
}
これは許可されていません。1 つのファイル内に 2 つのパブリック クラスがあります。
public class Solution
{
}
class Main
{
}
しかし、これならできます。Mainクラスはパブリックではありません
public class Solution
{
  public static class Main
  {
  }
}
そして、これを行うことができます。Main クラスはネストされたクラスです

main()静的メソッドからクラスの通常の (非静的) メソッドを呼び出す

「初心者プログラマは、メソッドや他の静的メソッドから非静的変数やメソッドにアクセスしようとすることがありますmain()。もちろん、そのようなコードは機能しません。

public class Solution
{
   public int n = 100;
   public int[] createArray()
   {
      return new int[n];
   }

   public static void main(String[]args)
   {
      int[] array = createArray();
   }
}

mainメソッドは静的メソッド/変数のみを参照できます。そうですね、または、最初にクラスのインスタンスを作成してからSolution、そのオブジェクトの非静的メソッドを呼び出す必要があります。例:

解決策 1 解決策 2
public class Solution
{
  public static int n = 100;

  public static int[] createArray()
  {
    return new int[n];
  }

  public static void main(String[]args)
  {
    int[] array = createArray();
  }
}
public class Solution
{
  public int n = 100;

  public int[] createArray()
  {
    return new int[n];
  }

  public static void main(String[]args)
  {
    Solution sol = new Solution();
    int[] array = sol.createArray();
  }
}

コンストラクターをメソッドのように宣言する

「もう 1 つのよくある間違いは、クラス コンストラクターを誤って宣言することです。コンストラクターの名前はクラスの名前と同じである必要があり、コンストラクターには結果の型がありません。最も一般的な間違いは次のとおりです。

public class Person
{
   private String value;

   void Person(String value)
   {
      this.value = value;
   }
}
ここには戻り値の型があってはなりません
public class Person
{
   private String value;

   constructor(String value)
   {
      this.value = value;
   }
}
コンストラクター名が無効です。クラス名と一致する必要があります
public class Person
{
   private String value;

   Person(String value)
   {
      value = value;
   }
}
this 不足している。変数valueはそれ自体に割り当てられます
public class Person
{
   private String value;

   Person(String value)
   {
      this.value = value;
   }
}
それはすべて正しいです。

インターフェイスの不正な継承

「Java の作成者は Java を英語に非常に近づけようとしたため、特定の関連する概念に対して異なるキーワードを選択しました。

クラスがクラスを継承するときは、次のextendsキーワードを使用する必要があります。

class Pet
{
}

class Cat extends Pet
{
}

「クラスがインターフェイスを継承するとき、より正確にはインターフェイスを実装するときは、次のキーワードを使用する必要がありますimplements

interface Meow
{
}

class Cat implements Meow
{
}

「インターフェイスがインターフェイスを継承する場合は、extends次のキーワードを使用します。

interface Meow
{
}

interface Voice extends Meov
{
}

ステートメントbreakでの省略switch

break「そして、今日の最後の間違いは、初心者にとって最後の間違いではありませんが、ステートメントにステートメントを含めないことですswitch。例:

間違い
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Monday");
   case TUESDAY:
      System.out.println("Tuesday");
   case WEDNESDAY:
      System.out.println("Wednesday");
   case THURSDAY:
      System.out.println("Thursday");
   case FRIDAY:
      System.out.println("Friday");
   case SATURDAY:
      System.out.println("Saturday");
   case SUNDAY:
      System.out.println("Sunday");
}
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Monday");
      break;
   case TUESDAY:
      System.out.println("Tuesday");
      break;
   case WEDNESDAY:
      System.out.println("Wednesday");
      break;
   case THURSDAY:
      System.out.println("Thursday");
      break;
   case FRIDAY:
      System.out.println("Friday");
      break;
   case SATURDAY:
      System.out.println("Saturday");
      break;
   case SUNDAY:
      System.out.println("Sunday");
      break;
}

「ご存知のように、ディエゴ...ここであなたが示した一連の間違いから判断すると、あなたは私の個人的な日記を読んでいるように感じられます...あるいは、私が課題を解決するのを見ていたようです。」

「ハッ! それについては疑いの余地はありません。私は読んで、追跡し、そしてそうし続けています。だから、警戒してください!」

「???」

「心配しないでください。冗談です。用心して愚かな間違いを減らしてください。」