안녕! 오늘의 수업은 상당히... 어... 다면적일 것입니다 :) 광범위한 주제를 다룰 것이라는 의미에서 그것들은 모두 객체 생성 프로세스 와 관련될 것입니다 . 개체 생성 중 작업 순서 - 1생성자가 호출되는 방법, 필드(정적 필드 포함)가 초기화되는 방법 및 순서 등을 처음부터 끝까지 분석합니다. 이전에 기사에서 논의된 몇 가지 사항을 다루었으므로 한눈에 볼 수 있습니다. 기본 클래스 생성자 에 대한 자료 . 먼저 객체가 생성되는 방식을 기억해 봅시다. 개발자의 관점에서 이 프로세스가 어떻게 보이는지 잘 기억하실 것입니다. 그는 클래스를 생성하고 씁니다 new, 그리고 모든 것이 준비되었습니다 :) 여기에서는 우리가 글을 쓸 때 컴퓨터와 Java 머신 내부에서 일어나는 일에 대해 이야기하겠습니다. 예를 들면 다음과 같습니다.

Cat cat = new Cat();
이전에 이에 대해 이야기했지만 만일을 대비하여 다음을 상기시켜 드리겠습니다.
  • 먼저 객체를 저장하기 위한 메모리가 할당됩니다.
  • 다음으로 Java 머신은 객체에 대한 참조를 생성합니다(이 경우 참조는 Cat cat입니다).
  • 마지막으로 변수가 초기화되고 생성자가 호출됩니다(이 프로세스를 자세히 살펴보겠습니다).
또한 개체 수명 주기 에 대한 단원에서 개체에 대한 참조가 하나 이상 있는 한 개체가 지속된다는 것을 기억할 것입니다. 아무것도 남지 않으면 개체는 가비지 수집기의 먹잇감이 됩니다. 개체 생성 중 작업 순서 - 2이 처음 두 항목은 특별한 질문을 제기해서는 안 됩니다. 메모리 할당은 간단한 프로세스이며 가능한 결과는 메모리가 있거나 없거나 두 가지뿐입니다. :) 그리고 링크를 생성하는 것은 드문 일이 아닙니다. 그러나 세 번째 항목은 엄격한 순서로 실행되는 전체 작업 집합을 나타냅니다. 저는 벼락치기 시험을 좋아하지 않지만 이 과정을 잘 이해하고 이 일련의 작업을 외워야 합니다.. 이전 강의에서 객체 생성 과정에 대해 이야기했을 때, 여러분은 아직 상속에 대해 전혀 알지 못했기 때문에 몇 가지를 설명하는 것이 문제가 되었습니다. 이제 꽤 많은 것을 알게 되었고 마침내 이 질문을 완전히 고려할 수 있습니다 :) 그래서 세 번째 요점은 " 마지막으로 변수가 초기화되고 생성자가 호출됩니다. "라고 말합니다. 하지만 이 모든 일이 어떤 순서로 발생합니까? 더 나은 이해를 위해 부모와 자식이라는 매우 간단한 두 클래스를 만들어 보겠습니다.

public class Vehicle { 

   public static int vehicleCounter = 0; 

   private String description = "Vehicle"; 
   public Vehicle() { 
   } 

   public String getDescription() { 
       return description; 
   } 
} 

public class Truck extends Vehicle { 

   private static int truckCounter = 0; 

   private int yearOfManufacture; 
   private String model; 
   private int maxSpeed; 

   public Truck(int yearOfManufacture, String model, int maxSpeed) { 
       this.yearOfManufacture = yearOfManufacture; 
       this.model = model; 
       this.maxSpeed = maxSpeed; 

       Vehicle.vehicleCounter++; 
       truckCounter++; 
   } 
}
Truck클래스는 연도, 모델 및 최대 속도를 나타내는 필드가 있는 트럭을 구현한 것입니다. 이제 우리는 그러한 객체를 하나 만들고 싶습니다.

public class Main { 

   public static void main(String[] args) throws IOException { 

       Truck truck = new Truck(2017, "Scania S 500 4x2", 220); 
   } 
}
Java 시스템에서 프로세스는 다음과 같습니다.
  1. 가장 먼저 일어나는 일은 클래스 의 정적 변수가 Vehicle초기화되는 것 입니다 . 네, 수업 Vehicle이 아니라 Truck. 정적 변수는 생성자가 호출되기 전에 초기화되며 이는 부모 클래스에서 시작됩니다. 이것을 확인해보자. vehicleCounter클래스 의 필드를 Vehicle10으로 설정하고 VehicleTruck생성자 모두에 표시하려고 합니다.

    
    public class Vehicle { 
    
       public static int vehicleCounter = 10; 
       private String description = "Vehicle"; 
    
       public Vehicle() { 
           System.out.println(vehicleCounter); 
       } 
    
       public String getDescription() { 
           return description; 
       } 
    } 
    
    public class Truck extends Vehicle { 
    
       private static int truckCount = 0;
    
       private int yearOfManufacture; 
       private String model; 
       private int maxSpeed; 
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) { 
           System.out.println(vehicleCounter); 
           this.yearOfManufacture = yearOfManufacture; 
           this.model = model; 
           this.maxSpeed = maxSpeed; 
    
           Vehicle.vehicleCounter++; 
           truckCount++; 
       } 
    }
    

    가 표시될 Truck때 트럭의 필드가 아직 초기화되지 않았음을 확인하기 위해 의도적으로 생성자의 맨 처음에 println 문을 넣습니다 .vehicleCounter

    결과는 다음과 같습니다.

    
    10 
    10
    
  2. 부모 클래스의 정적 변수가 초기화된 후 자식 클래스의 정적 변수가 초기화됩니다. 우리의 경우 이것은 클래스 truckCounter의 필드 입니다 Truck.

    다른 필드가 초기화되기 전에 생성자 truckCounter내부 의 값을 표시하는 또 다른 실험을 해봅시다 .Truck

    
    public class Truck extends Vehicle { 
    
       private static int truckCounter = 10; 
    
       private int yearOfManufacture; 
       private String model; 
       private int maxSpeed; 
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) { 
           System.out.println(truckCounter); 
           this.yearOfManufacture = yearOfManufacture; 
           this.model = model; 
           this.maxSpeed = maxSpeed; 
    
           Vehicle.vehicleCounter++; 
           truckCounter++; 
       } 
    }
    

    보시 다시피 생성자가 시작될 때 값 10이 이미 정적 변수에 할당되었습니다Truck .

  3. 아직 생성자를 위한 시간이 아닙니다! 변수 초기화가 계속됩니다. 부모 클래스의 비정적 변수는 세 번째로 초기화됩니다. 보시다시피 상속은 객체를 생성하는 과정을 상당히 복잡하게 만들지만 이에 대해 할 수 있는 일은 없습니다. 프로그래밍에서 몇 가지만 기억하면 됩니다. :)

    실험으로 클래스 description의 변수 에 초기 값을 할당한 Vehicle다음 생성자에서 변경할 수 있습니다.

    
    public class Vehicle { 
    
       public static int vehicleCounter = 10; 
    
       private String description = "Initial value of the description field"; 
    
       public Vehicle() { 
           System.out.println(description); 
           description = "Vehicle"; 
           System.out.println(description); 
       } 
    
       public String getDescription() { 
           return description; 
       } 
    }
    

    main()트럭을 생성하는 메서드를 실행해 보겠습니다 .

    
    public class Main { 
    
       public static void main(String[] args) throws IOException { 
    
           Truck truck = new Truck(2017, "Scania S 500 4x2", 220); 
       } 
    }
    

    다음 결과를 얻습니다.

    
    Initial value of the description field 
    Vehicle
    

    이는 Vehicle생성자가 시작할 때 description필드에 이미 값이 할당되었음을 증명합니다.

  4. 마지막으로 생성자를 위한 시간입니다! 보다 정확하게는 기본 클래스 생성자를 위한 시간입니다. 개체 생성 프로세스의 네 번째 단계에서 호출됩니다.

    이것은 또한 확인하기가 매우 쉽습니다. 콘솔에 두 줄을 출력해 봅시다. 하나는 Vehicle기본 클래스 생성자 내부이고 다른 하나는 Truck생성자 내부입니다. Vehicle내부 줄이 먼저 표시되는지 확인해야 합니다 .

    
    public Vehicle() { 
    
       System.out.println("Hello from the Vehicle constructor!"); 
    } 
    
    public Truck(int yearOfManufacture, String model, int maxSpeed) { 
    
       System.out.println("Hello from the Truck constructor!"); 
       this.yearOfManufacture = yearOfManufacture; 
       this.model = model; 
       this.maxSpeed = maxSpeed; 
    
       Vehicle.vehicleCounter++; 
       truckCounter++; 
    }
    

    우리는 우리의 방법을 실행 main()하고 결과를 볼 것입니다:

    
    Hello from the Vehicle constructor! 
    Hello from the Truck constructor! 
    

    훌륭한. 그것은 우리가 틀리지 않았다는 것을 의미합니다 :) 계속 진행하겠습니다.

  5. 이제 하위 클래스, 즉 우리 클래스의 비정적 필드를 초기화할 시간입니다 Truck. 인스턴스화되는 클래스 내의 필드는 다섯 번째 단계까지 초기화되지 않습니다! 놀랍지만 사실입니다 :) 다시 한 번 간단한 검사를 수행합니다. 부모 클래스와 마찬가지로 변수에 초기 값을 지정하고 생성자 maxSpeed에서 Truck생성자가 시작되기 전에 값이 할당되었는지 확인합니다.

    
    public class Truck extends Vehicle { 
    
       private static int truckCounter = 10; 
    
       private int yearOfManufacture; 
       private String model; 
       private int maxSpeed = 150; 
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) { 
    
           System.out.println("Initial value of maxSpeed = " + this.maxSpeed); 
           this.yearOfManufacture = yearOfManufacture; 
           this.model = model; 
           this.maxSpeed = maxSpeed; 
    
           Vehicle.vehicleCounter++; 
           truckCounter++; 
       } 
    }
    

    콘솔 출력:

    
    Initial value of maxSpeed = 150
    

    보시   다시피 생성자가 시작되면 이미  150입니다!TruckmaxSpeed

  6. 자식 클래스 의 생성자 Truck가 호출됩니다.

    그리고 이 시점에서 마지막으로 인스턴스화하는 클래스의 생성자가 호출됩니다!

    여섯 번째 단계에서만 트럭에 인수로 전달하는 값이 필드에 할당됩니다.

    보시다시피 트럭을 "구축"하는 것, 즉 객체 생성 프로세스는 간단하지 않습니다. 그러나 우리는 그것을 가장 작은 부분으로 나눈 것 같습니다 :)

개체 생성 중 작업 순서 - 3 이 과정을 잘 이해하는 것이 왜 그렇게 중요한가요? "내부"에서 무슨 일이 일어나고 있는지 정확히 알지 못한다면 일반 개체를 생성한 결과가 얼마나 예상치 못한 결과가 될 수 있는지 상상해 보십시오 :) 이제 코스로 돌아가서 몇 가지 작업을 완료할 시간입니다! 행운을 빌며 곧 뵙겠습니다! :)