[java] 생성자 또는 선언시 클래스 필드를 초기화 하시겠습니까?

최근에 C # 및 Java로 프로그래밍하고 있으며 클래스 필드를 초기화하는 가장 좋은 곳이 궁금합니다.

선언 할 때해야합니까? :

public class Dice
{
    private int topFace = 1;
    private Random myRand = new Random();

    public void Roll()
    {
       // ......
    }
}

또는 생성자에서? :

public class Dice
{
    private int topFace;
    private Random myRand;

    public Dice()
    {
        topFace = 1;
        myRand = new Random();
    }

    public void Roll()
    {
        // .....
    }
}

참전 용사 중 일부가 최선의 방법이라고 생각합니다. 일관성 있고 하나의 접근 방식을 고수하고 싶습니다.



답변

내 규칙:

  1. 선언의 기본 값으로 초기화하지 마십시오 ( null, false, 0, 0.0…).
  2. 필드 값을 변경하는 생성자 매개 변수가없는 경우 선언에서 초기화를 선호하십시오.
  3. 생성자 매개 변수로 인해 필드 값이 변경되면 생성자에 초기화를 두십시오.
  4. 연습에서 일관성을 유지하십시오 (가장 중요한 규칙).

답변

C #에서는 중요하지 않습니다. 당신이 제공하는 두 코드 샘플은 완전히 동일합니다. 첫 번째 예에서 C # 컴파일러 (또는 CLR?)는 빈 생성자를 생성하고 마치 마치 생성자에있는 것처럼 변수를 초기화합니다 (Jon Skeet이 아래 주석에서 설명하는 것과 약간의 차이가 있습니다). 이미 생성자가 있으면 “위”의 초기화가 맨 위로 이동합니다.

모범 사례의 관점에서 전자는 다른 생성자를 쉽게 추가하고 연결하는 것을 잊어 버릴 수 있기 때문에 전자가 후자보다 오류가 적습니다.


답변

C #의 의미는 여기서 Java와 약간 다릅니다. C #에서는 선언에서 선언이 수퍼 클래스 생성자를 호출하기 전에 수행됩니다. Java에서는 ‘this’를 사용할 수있게 된 직후에 수행되며 (익명 내부 클래스에 특히 유용함) 두 형식의 의미가 실제로 일치 함을 의미합니다.

가능하면 필드를 최종적으로 만드십시오.


답변

하나의 경고가 있다고 생각합니다. 한 번 그런 오류를 저지른 적이 있습니다. 파생 클래스 내부에서 추상 기본 클래스에서 상속 된 필드를 “선언시 초기화”하려고했습니다. 그 결과 두 개의 필드 세트가 존재했습니다. 하나는 “기본”이고 다른 하나는 새로 선언 된 것이므로 디버그하는 데 시간이 꽤 걸립니다.

교훈 : 상속 된 필드 를 초기화 하려면 생성자 내에서 수행하십시오.


답변

예제에서 유형을 가정하면 생성자에서 필드를 초기화하는 것이 좋습니다. 예외적 인 경우는 다음과 같습니다.

  • 정적 클래스 / 메소드의 필드
  • 정적 / 최종 / et al로 입력 된 필드

나는 항상 클래스 상단의 필드 목록을 목차 (사용 방법이 아니라 여기에 포함 된 내용)로, 생성자를 소개로 생각합니다. 물론 방법은 장입니다.


답변

내가 말하면 어떻게됩니까?

나는 일반적으로 모든 것을 초기화하고 일관된 방식으로 수행합니다. 예, 지나치게 명시 적이지만 유지 관리가 조금 더 쉽습니다.

우리가 성능에 대해 걱정한다면 잘해야 할 일만 초기화하고 가장 많은 돈을 벌 수있는 영역에 배치하십시오.

실시간 시스템에서는 변수 또는 상수가 필요한지 의문입니다.

그리고 C ++에서는 종종 어느 곳에서나 초기화하지 않고 Init () 함수로 옮깁니다. 왜? 글쎄, C ++에서 객체 생성 중에 예외를 던질 수있는 것을 초기화하면 메모리 누수가 발생합니다.


답변

많은 상황이 있습니다.

빈 목록 만 있으면됩니다

상황은 분명하다. 내 목록을 준비하고 누군가가 목록에 항목을 추가 할 때 예외가 발생하지 않도록해야합니다.

public class CsvFile
{
    private List<CsvRow> lines = new List<CsvRow>();

    public CsvFile()
    {
    }
}

나는 가치를 안다

나는 기본적으로 어떤 값을 갖고 싶은지 알고 있거나 다른 논리를 사용해야합니다.

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = new List<string>() {"usernameA", "usernameB"};
    }
}

또는

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = GetDefaultUsers(2);
    }
}

가능한 값이있는 빈 목록

때로는 다른 생성자를 통해 값을 추가 할 수있는 빈 목록이 기본적으로 필요합니다.

public class AdminTeam
{
    private List<string> usernames = new List<string>();

    public AdminTeam()
    {
    }

    public AdminTeam(List<string> admins)
    {
         admins.ForEach(x => usernames.Add(x));
    }
}