1. 변수 초기화

이미 알고 있듯이 클래스에서 여러 변수를 선언할 수 있으며 단순히 선언하는 것이 아니라 초기 값으로 즉시 초기화할 수도 있습니다.

그리고 이와 동일한 변수를 생성자에서도 초기화할 수 있습니다. 이는 이론적으로 이러한 변수에 값을 두 번 할당할 수 있음을 의미합니다. 예

암호 메모
class Cat
{
   public String name;
   public int age = -1;

   public Cat(String name, int age)
   {
     this.name = name;
     this.age = age;
   }

   public Cat()
   {
     this.name = "Nameless";
   }
}



변수 age에 초기값이 할당됩니다.




초기값이 덮어쓰여집니다.


연령 변수는 초기값을 저장합니다.
 Cat cat = new Cat("Whiskers", 2);
이것은 허용됩니다: 첫 번째 생성자가 호출됩니다
 Cat cat = new Cat();
이것은 허용됩니다: 두 번째 생성자가 호출됩니다

이것이 Cat cat = new Cat("Whiskers", 2);실행될 때 일어나는 일입니다.

  • 개체 Cat가 생성됩니다.
  • 모든 인스턴스 변수는 초기 값으로 초기화됩니다.
  • 생성자가 호출되고 해당 코드가 실행됩니다.

즉, 변수는 먼저 초기 값을 얻은 다음에만 생성자의 코드가 실행됩니다.


2. 클래스에서 변수 초기화 순서

변수는 생성자가 실행되기 전에 초기화되는 것이 아니라 잘 정의된 순서, 즉 클래스에서 선언된 순서로 초기화됩니다.

몇 가지 흥미로운 코드를 살펴보겠습니다.

암호 메모
public class Solution
{
   public int a = b + c + 1;
   public int b = a + c + 2;
   public int c = a + b + 3;
}

이 코드는 컴파일되지 않습니다. 변수가 생성될 때  및  변수가 아직 a없기 때문입니다. 그러나 다음과 같이 코드를 작성할 수 있습니다. 이 코드는 컴파일되고 정상적으로 실행됩니다 .bc

암호 메모
public class Solution
{
   public int a;
   public int b = a + 2;
   public int c = a + b + 3;
}


0
0+2
0+2+3

그러나 코드는 다른 개발자에게 투명해야 합니다. 이와 같은 기술은 코드의 가독성을 손상시키므로 사용하지 않는 것이 좋습니다.

여기서 변수에 값을 할당하기 전에 기본값 이 있음을 기억해야 합니다 . 유형 의 경우 int이것은 0입니다.

JVM이 a변수를 초기화할 때 단순히 int 유형의 기본값인 0을 할당합니다.

에 도달하면 ba 변수는 이미 알려져 있고 값을 가지므로 JVM은 값 2를 할당합니다.

c그리고 변수 에 도달하면 ab변수는 이미 초기화되어 있으므로 JVM은 c0+2+3에 대한 초기 값을 쉽게 계산합니다.

메서드 내에서 변수를 생성하는 경우 이전에 값을 할당하지 않으면 사용할 수 없습니다. 그러나 이것은 클래스의 변수에는 해당되지 않습니다! 클래스의 변수에 초기값이 지정되지 않은 경우 기본값이 지정됩니다.


3. 상수

개체가 생성되는 방식을 분석하는 동안 상수, 즉 수정자가 있는 변수의 초기화를 다룰 가치가 있습니다 final.

변수에 final한정자가 있으면 초기값을 할당해야 합니다. 당신은 이미 이것을 알고 있으며 그것에 대해 놀라운 것은 없습니다.

하지만 모르는 것은 초기값을 생성자에서 대입하면 바로 대입할 필요가 없다는 것입니다. 이것은 최종 변수에 대해 잘 작동합니다. 유일한 요구 사항은 생성자가 여러 개인 경우 각 생성자에서 최종 변수에 값을 할당해야 한다는 것입니다.

예:

public class Cat
{
   public final int maxAge = 25;
   public final int maxWeight;

   public Cat (int weight)
   {
     this.maxWeight = weight; // Assign an initial value to the constant
   }
}


4. 생성자의 코드

그리고 생성자에 대한 몇 가지 더 중요한 참고 사항입니다. 나중에 Java를 계속 배우면서 상속, 직렬화, 예외 등과 같은 것을 접하게 될 것입니다. 이들은 모두 생성자의 작업에 다양한 정도로 영향을 미칩니다. 지금 이 주제에 대해 깊이 파고드는 것은 말이 안 되지만, 최소한 그 주제를 다루어야 할 의무가 있습니다.

예를 들어 다음은 생성자에 대한 중요한 설명입니다. 이론상으로는 생성자에서 복잡한 코드를 작성할 수 있습니다. 하지만 이러지 마세요. 예:

class FilePrinter
{
   public String content;

   public FilePrinter(String filename) throws Exception
   {
      FileInputStream input = new FileInputStream(filename);
      byte[] buffer = input.readAllBytes();
      this.content = new String(buffer);
   }

   public void printFile()
   {
      System.out.println(content);
   }
}






파일 읽기 스트림 열기
파일을 바이트 배열로 읽기
바이트 배열을 문자열로 저장




파일 내용을 화면에 표시

FilePrinter 클래스 생성자에서 파일의 바이트 스트림을 즉시 열고 내용을 읽었습니다. 이는 복잡한 동작이며 오류가 발생할 수 있습니다.

그런 파일이 없다면? 파일을 읽는 데 문제가 있으면 어떻게 합니까? 너무 크면 어떡하지?

복잡한 논리는 높은 오류 가능성을 의미하며 이는 코드가 예외를 올바르게 처리해야 함을 의미합니다.

예제 1 — 직렬화

표준 Java 프로그램에는 클래스의 객체를 생성하는 사람이 아닌 상황이 많이 있습니다. 예를 들어 네트워크를 통해 개체를 보내기로 결정했다고 가정합니다. 이 경우 Java 시스템 자체가 개체를 바이트 집합으로 변환하고 보낸 다음 바이트 집합에서 개체를 다시 만듭니다.

그러나 파일이 다른 컴퓨터에 존재하지 않는다고 가정합니다. 생성자에 오류가 있을 것이고 아무도 그것을 처리하지 않을 것입니다. 그리고 그것은 프로그램을 종료시킬 수 있습니다.

예제 2 — 클래스의 필드 초기화

클래스 생성자가 확인된 예외를 throw할 수 있는 경우(예: throws 키워드로 표시됨) 개체를 생성하는 메서드에서 표시된 예외를 catch해야 합니다.

하지만 그런 방법이 없다면? 예:

암호  메모
class Solution
{
   public FilePrinter reader = new FilePrinter("c:\\readme.txt");
}
이 코드는 컴파일되지 않습니다.

클래스 생성자는 확인된 예외를FilePrinter throw할 수 있습니다 . 즉, try-catch 블록에서 개체를 래핑하지 않고는 개체를 만들 수 없습니다. 그리고 try-catch 블록은 메서드에만 쓸 수 있습니다.FilePrinter



5. 기본 클래스 생성자

이전 수업에서 우리는 상속에 대해 조금 논의했습니다. 불행하게도 상속과 OOP에 대한 우리의 전체 논의는 OOP 전용 레벨을 위해 예약되어 있으며 생성자의 상속은 이미 우리와 관련이 있습니다.

클래스가 다른 클래스를 상속하는 경우 상위 클래스의 개체가 클래스의 개체 안에 포함됩니다. 또한 부모 클래스에는 자체 변수와 자체 생성자가 있습니다.

즉, 클래스에 부모 클래스가 있고 해당 변수와 메서드를 상속할 때 변수가 초기화되고 생성자가 호출되는 방법을 알고 이해하는 것이 매우 중요합니다.

클래스

변수가 초기화되고 생성자가 호출되는 순서를 어떻게 알 수 있습니까? 두 클래스에 대한 코드를 작성하는 것으로 시작하겠습니다. 하나는 다른 하나를 상속합니다.

암호 메모
class ParentClass
{
   public String a;
   public String b;

   public ParentClass()
   {
   }
}

class ChildClass extends ParentClass
{
   public String c;
   public String d;

   public ChildClass()
   {
   }
}










클래스 는 클래스를 ChildClass 상속합니다 ParentClass.

변수가 초기화되고 생성자가 호출되는 순서를 결정해야 합니다. 로깅은 이를 수행하는 데 도움이 됩니다.

벌채 반출

로깅은 프로그램이 실행될 때 수행한 작업을 콘솔이나 파일에 기록하여 기록하는 프로세스입니다.

생성자가 호출되었는지 확인하는 것은 매우 간단합니다. 생성자 본문에서 콘솔에 메시지를 작성합니다. 그러나 변수가 초기화되었는지 어떻게 알 수 있습니까?

실제로 이것은 그다지 어렵지 않습니다. 변수를 초기화하는 데 사용되는 값을 반환하는 특수 메서드를 작성하고 초기화를 기록합니다. 코드는 다음과 같습니다.

최종 코드

public class Main
{
   public static void main(String[] args)
   {
      ChildClass obj = new ChildClass();
   }

   public static String print(String text)
   {
      System.out.println(text);
      return text;
   }
}

class ParentClass
{
   public String a = Main.print("ParentClass.a");
   public String b = Main.print("ParentClass.b");

   public ParentClass()
   {
      Main.print("ParentClass.constructor");
   }
}

class ChildClass extends ParentClass
{
   public String c = Main.print("ChildClass.c");
   public String d = Main.print("ChildClass.d");

   public ChildClass()
   {
      Main.print("ChildClass.constructor");
   }
}




ChildClass개체 만들기


이 메서드는 전달된 텍스트를 콘솔에 쓰고 반환합니다. Display text 클래스를





선언하고 이를 사용하여 변수를 초기화합니다. 생성자가 호출되었다는 메시지를 작성합니다. 반환 값을 무시하십시오. Display text 클래스를 선언하고 이를 사용하여 변수를 초기화합니다. 생성자가 호출되었다는 메시지를 작성합니다. 반환 값을 무시하십시오. ParentClass









ChildClass






이 코드를 실행하면 다음과 같이 화면에 텍스트가 표시됩니다.

메서드 의 콘솔 출력Main.print()
ParentClass.a
ParentClass.b
ParentClass.constructor
ChildClass.c
ChildClass.d
ChildClass.constructor

따라서 생성자가 호출되기 전에 클래스의 변수가 초기화되도록 항상 개인적으로 확인할 수 있습니다. 기본 클래스는 상속된 클래스가 초기화되기 전에 완전히 초기화됩니다.