"안녕하세요, 아미고! 실수에 대해 계속 이야기합시다. 이번에는 컴파일러가 항상 도움이 되지 않는 실수를 살펴보겠습니다. 주의를 기울이면 자신에 대해 배울 수 있을 것입니다."

"난 들을 준비가 됐어, 디에고. 이 일이 나에게 너무 부끄럽지 않았으면 좋겠어."

개체 비교==

"가장 좋아하는 초보자 프로그래머 실수 목록은 ==연산자를 사용하여 개체(특히 문자열)를 비교하는 것으로 시작합니다."

예:

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

"저는 꽤 자주 그렇게 했습니다. 이제 이 코드가 "문자열이 같음"을 표시하지 않는다는 것을 분명히 알 수 있습니다. 문이 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클래스의 모든 메서드가 새 개체를 반환한다는 사실을 잊습니다. 현재 개체는 절대 변경되지 않습니다."

" Immutable 이 무엇인지 알게 된 것은 그리 오래되지 않았지만 , 나는 이것을 해본 것 같다.

"확실히 확신합니다. 예:

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

"이 코드는 올바른 코드와 매우 유사하지만 예상대로 작동하지 않습니다. 메서드는 toUpperCase()호출된 개체를 변경하지 않습니다. 올바른 코드는 다음과 같습니다.

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

"맞아요. 그렇게 했는데 뭐가 잘못된 건지 이해조차 안 됐어요. 설명해주셔서 감사합니다!"

배열의 요소인 개체를 초기화하는 것을 잊음

"또 다른 일반적인 실수는 배열 변수를 초기화하는 것을 잊는 것입니다. 예:

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

"이 코드는 작동하지 않습니다. 배열 요소를 저장할 컨테이너 개체에 대한 참조와 동일하게 배열 변수를 명시적으로 설정해야 합니다. 올바른 버전:

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

인스턴스 변수 대신 지역 변수를 사용합니다.

"뉴비들은 변수에 대해 길고 의미 있는 이름을 짓는 것을 좋아하지 않습니다."

"그렇습니다. 일을 빨리 끝내기 위해 때때로 a, b, 와 같은 변수 이름을 지정합니다 i."

"하지 마세요. 코드에 다음과 같은 여러 변수가 있을 때 하는 것은 잔인한 일입니다.

숫자 99를 배열의 100개 셀에 넣습니다.
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;
    }
  }
}

"적절한 이름을 가진 코드에서 실수를 저지르는 것이 훨씬 더 어렵습니다. 올바른 버전은 다음과 같습니다.

숫자 99를 배열의 100개 셀에 넣습니다.
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
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 );

수정자를 사용하여 여러 클래스를 public단일 파일에 배치

"파일에는 공용 클래스가 하나만 있을 수 있습니다. 파일에서 더 많은 클래스를 선언할 수 있지만 공용 클래스의 내부 클래스이거나 수정자가 없어야 합니다. 예 public:

Solution.java 파일의 내용 메모
public class Solution
{
}
public class Main
{
}
이것은 허용되지 않습니다. 단일 파일에 두 개의 공개 클래스가 있습니다.
public class Solution
{
}
class Main
{
}
그러나 당신은 이것을 할 수 있습니다. Main 클래스는 public이 아닙니다.
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();
  }
}

생성자를 메소드처럼 선언하기

"또 다른 일반적인 실수는 클래스 생성자를 잘못 선언하는 것입니다. 생성자의 이름은 클래스의 이름과 같아야 하며 생성자는 결과 유형이 없습니다. 가장 일반적인 실수는 다음과 같습니다.

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의 제작자는 영어에 매우 가깝게 만들려고 노력했기 때문에 특정 관련 개념에 대해 다른 키워드를 선택했습니다.

클래스가 클래스를 상속하는 경우 다음 키워드를 사용해야 합니다 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;
}

"있잖아, 디에고... 네가 여기서 제시한 일련의 오류로 판단하면, 네가 내 개인 일지를 읽고 있는 것 같구나... 아니면 내가 과제를 해결하는 것을 지켜보고 있었던 것 같구나."

"하! 의심하지 마세요. 읽고, 추적했고, 계속 그렇게 하고 있습니다. 그러니 경계하세요!"

"???"

"걱정하지 마세요. 농담이에요. 경계하고 어리석은 실수를 줄이세요."