1. Java
    1. 자바의 컴파일 과정

      1. *.java 파일을 빌드(build)하면. 어떻게 될까요?
      2. *.class 파일로 변환
        1. 자바 바이트 코드(.class)파일로 아직 컴퓨터가 읽을 수 없는 자바 가상 머신이 이해할 수 있는 코드가 된다.
      3. 컴파일된 코드를 JVM의 클래스 로더라는 곳에 전달한다.
      4. 클래스 로더는 동적로딩(Dynamic Loading)을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역(Runtime Data area), 즉 JVM의 메모리에 로드한다.
      5. 실행엔진(Execution Engine)은 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행한다.

      Untitled

      숙제

      • 이러한 점을 통해서 자바(or JVM 언어)는 어떤 이점을 가질 수 있는가?
      • 오늘 배운 내용을 더 상세하게 정리해서 자신의 블로그에 블로깅 하기!
    2. 자바의 Stack과 Heap 메모리

      1. Stack 메모리
        1. Heap 영역에 생성된 Object 타입의 데이터의 참조(메모리 주소, address) 값이 할당된다.
        2. 원시타입의 데이터가 값과 함께 할당된다.
        3. 지역변수들은 scope에 따른 visibility를 가진다.
        4. 각 Thread는 독립적인 stack을 가진다.
      2. Heap 메모리
        1. 주로 긴 생명주리를 가지는 데이터들이 저장된다. 대부분 오브젝트는 크기가 크고, 서로 다른 코드 블록에서 공유되는 경우가 많다.
        2. 애플리케이션의 모든 메모리 중 stack에 저장되어 있는 데이터를 제외한 모든 데이터가 저장되는 곳이다.
        3. 모든 Object 타입(Integer, String, ArrayList, ...)은 heap 영역에 생성된다.
        4. 모든 Thread가 공통으로 하나의 Heap 메모리를 사용한다.
    3. 자바 세상의 객체지향 원리

      1. 접근 제한자

        1. public
          • 다른 클래스에서도 접근 할 수 있는
        2. protected
          • 같은 패키지와 상속받은 하위클래스에서 접근 가능
        3. default
          • 같은 패키지내에서는 모두 가능
        4. private
          • 해당 클래스에 내에서만 접근 가능
        5. 왜 우리는 접근 제한자를 사용하는가?
          • 왜 우리는 항상 클래스의 멤버 변수는 꼭 private 으로 선언하는가?

            • 다른 클래스에서 조작을 막기 위해서 → 왜 막아야 하는가? → 값의 유효성 지키기 위해서
          • public 접근 제한자로 선언하면 어떤 문제가 발생하는가?

            public class CodingTest {
                private String testResult;
                private int score; // 0 ~ 5;
            
                public void CodingTest(String result, int score) throws Exception {
                    setTestResult(result);
                    setScore(score);
                };
            
                public void setTestResult(String result) throws Exception{
                    if(result.equalsIgnoreCase("PASS") || result.equalsIgnoreCase("NOT PASS")){
                        this.testResult = result;
                    }
                    else throw new Exception();
                };
            
                public void setScore(int score) throws Exception{
                    if(score >= 0 && score < 6)
                        this.score = score;
                    else throw new Exception();
                };
            }
            
      2. 캡슐화

        상태(변수 or 데이터)와 행동(함수 or 메서드)을 하나의 단위로 묶는 것을 말한다. 객체지향 프로그래밍을 지원하는 대부분의 언어에서 제공하는 클래스를 통해서 캡슐화를 제공한다. 그런데 상태와 행동을 한 덩어리로 묶는 것이 왜 정보 은닉화 연관이 있는걸까? 그리고 객체지향은 캡슐화 기능을 왜 제공하는걸까?

        먼저 우리는 2가지 중요한 사실을 알아야 한다. 위에서 이야기 한 것처럼 객체가 상태와 행동을 함께 가지는 복합적인 존재이고, 객체가 스스로 판단하고 행동하는 자율적인 존재라는 것이다. 객체가 자율적인 존재로써 적절한 행동(더하기)을 통해 문제(a와 b의 합을 구하라)를 해결하려면 객체가 어떤 생각을 하고 있는지 외부에서 알고 간섭할 수 없도록 해야, 객체가 스스로 올바른 판단을 하고 행동을 할 수 있는 것이다. 그래서 우리는 클래스의 상태(변수)를 정의할 때 대부분 private 접근 제한자를 사용했던 것이다.

        단순히 캡슐화 정분 은닉화를 해주는 것이 아니다. 캡슐화 + 접근 제한자를 통해서 정보 은닉화가 이루어지는 것이다. 그리고 정보 은닉화를 하는 이유는! 객체의 행동이 올바르게 동작할 수 있도록 하기 위함이다.

        public class Calculator {
        	private Long calculatedResult;
        
          public Long getCalculatedResult(){
              return this.calculatedResult;
          }
        
          public void sum(int a, int b) {
             this.calculatedResult = Long.valueOf(a + b);
          }
        }
        
        public class Calculator2 {
        	public Long calculatedResult;
        
          public Long getCalculatedResult(){
              return this.calculatedResult;
          }
        
          public void sum(int a, int b) {
             this.calculatedResult = Long.valueOf(a + b);
          }
        }
        
        public class Main {
          public static void main(String[] args) {
            Calculator c = new Calculator();
            Calculator c2 = new Calculator2();
            c.sum(1,2);
            c2.sum(1,2);
        		c.calculatedResult = 100L; // occur Error
        		c2.calculatedResult = 100L; // 
            System.out.println(c.getCalculatedResult()); // output: 3
            System.out.println(c2.getCalculatedResult()); // output: 100
          }
        }
        
      3. 상속

        1. 부모 클래스 또는 상위 클래스를 상속 받는 것을 말한다. 상속 받은 클래스를 자식 클래스 또는 하위 클래스라고 지칭한다. 자식 클래스는 부모 클래스의 메서드 또는 접근 제한자에 따라 멤버 변수(필드)에도 직접 접근을 할 수 있다.
        2. 그렇다면 우리는 왜 객체지향 세상 속에서 상속이라는 것을 사용하는 걸까? 첫번째로, 상속을 이용하면 기존의 클래스(부모 클래스)를 **“재사용”**하여 아주 적은 코드만으로도 새로운 클래스(자식 클래스)를 작성할 수 있다. 두번째로, 코드를 공통적으로 관리할 수 있기 때문에 유지보수가 쉬워진다.
        3. 즉, 상속은 코드의 재사용성을 높여주고, 중복을 제거해서 생산성과 유지보수에 크게 기여한다.
      4. 오버라이딩/오버로딩

        1. 오버라이딩

          1. 부모 클래스로 부터 상속 받은 메소드를 재정의하는 것.

          2. 예제 코드

            @Getter
            @Setter
            public class Parent {
            	private String sex;
            	private String name;
            
            	public void sayHello(){
            		System.out.println("안녕하세요.");
            	}
            }
            
            @Getter
            @Setter
            public class Child extends Parent {
            
            	public Child(){
            		super();
            	}
            
            	@Overriding
            	public void sayHello(){
            		System.out.println("ㅎ2");
            	}
            }
            
            
        2. 오버로딩

          1. ‘과적하다’라는 의미를 가진다.

          2. 동일한 메서드명으로 메서드를 정의하는 것. 그래서 과적 또는 과부하라는 Overloading이라는 명칭 붙음.

          3. 단, 인수(parameter)의 타입이 다르거나, 개수가 달라야 한다. 리턴 타입만 달라서는 안된다.

          4. 예제 코드

            public class Student {
            	private int grade;
            	private String sex;
            	private String name;
            
            	public void play(String gameName){
            		System.out.printf("Playing %s", gameName);
            	}
            
            	public void play(String gameName, int grade){
            		if(grade > 3)
            			System.out.printf("Playing %s, and enable chat", gameName);
            		else
            			System.out.printf("Playing %s, and disable chat", gameName);			
            	}
            	
            }
            
      5. 추상화/인터페이스

        1. 추상화

          1. 복잡한 자료, 모듈, 시스템등으로 부터 핵심적인(=공통적인) 개념 또는 기능을 간추려 내는 것을 추상화라고 한다.

          2. 예를 들어, 독일 3사 브랜드의 특정 모델(C클래스, 3시리즈, A6)을 클래스화 한다고 생각해보자. 이것들을 모두 독립적인 클래스로 정의해도 되지만, 그렇게 된다면 중복된 코드가 생겨나고, 그로 인해 생산성은 떨어지고, 유지보수는 어려워지게 된다.

          3. 여기서 “자동차”라는 추상화 클래스를 만들고 핵심적인 개념 및 기능을 구현 또는 정의한다면 이것을 구현하도록 한다면 생산성은 높아지고 유지보수에도 용이한 구조가 될 것이다.

            1. 장점
              1. 공통적인 부분에 대한 중복 코드 제거, 코드 재사용성 증대 (=객체지향의 원리를 추구하는 설계)
              2. 구현의 강제성을 통한 기능 보장
                1. 추상 클래스를 상속 받은 자식 클래스는 추상 메서드를 무조건 적으로 구현해야 한다.(추상화 클래스 규칙1.)
              3. 규격에 맞는 설계
          4. 자동차라는 추상화 통해 정의한 추상화 클래스이다.

            추상화 클래스 규칙2.

            추상화 클래스는 new 키워드를 이용해서 인스턴스화 할 수 없다. 무조건 자식(=하위)클래스를 통해서 인스턴스화 될 수 있고, 자식 클래스의 생성자 함수 안에서 super() 메소드를 이용해 추상 클래스의 생성자 호출이 가능하다.

          public abstract class Car {
            private boolean isDoorLock;
            private String brand;
            private String engine;
            private String color;
            private int speed;
            private int wheel;
          
            public Car(boolean door, String brand, String engine, String color, int speed, int wheel){
              this.isDoorLock = door;
              this.brand = brand;
              this.engine = engine;
              this.color = color;
              this.speed = speed;
              this.wheel = wheel;
            };
          
            public void pushDoorLockButton(){
              this.isDoorLock = !this.isDoorLock;
            }
          
            public abstract void stepOnAccelerator();
            public abstract void stepReleaseAccelerator();
            public abstract void stepOnBreak();
            public abstract void stepReleaseBreak();
          }
          
        2. 인터페이스

          1. 다른 클래스를 작성할 때 기본이 되는 틀? 규격서? 같은 역할을 제공하면서 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상 클래스를 의미한다.
          2. 추상 클래스와 다르게, 인터페이스는 추상메서드와 상수만을 정의할 수 있다.
          3. 장점
            1. 소스의 가독성과 유지보수가 항상 된다.
            2. 코드 종속성을 낮출 수 있다.
              1. 코드 종속성은 각각의 메서드 간의 결합도를 의미하며 인터페이스를 활용하면 한 메서드를 수정하였을 때, 다른 메서드도 수정해야 하는 상황을 줄여준다는 의미입니다.  인터페이스로 추상 메서드를 지정하면 메서드의 input값과 output값이 고정되어 있습니다. 예를 들자면  public abstract String myName(String name) 이라는 메서드는 input값, output값 모두 String으로 고정되어 있죠. 이 메서드를 구현하는 객체에서 아무리 수정하더라도 input값과 output 값은 String으로 고정되어 있어 변경에 대한 영향도가 작습니다. 그래서 인터페이스는 "변경에 강하다", "확장에는 열려있고 변경에는 닫혀있다" 라고 말하는 것입니다.
    4. Garbage Collector의 역할, 원리

      1. 정의

        프로그램을 개발하다 보면 유효하지 않은 메모리 공간(Heap)이 발생한다. 그 공간을 개발자가 직접 삭제하여 유효 공간으로 만드는 언어들도 있는데, JVM 기반의 JAVA는 JVM 가비지 컬렉터가 불필요한 메모리를 알아서 찾고, 그것들을 정리 해준다. 그것을 우리는 가비지 컬렉터(Garbage Collector, GC)라고 한다.

      2. 구조

        Untitled

        • Young 영역(Young Generation)
          • 새롭게 생성된 객체가 할당(Allocation)되는 영역
          • 대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라진다.
          • Young 영역에 대한 가비지 컬렉션(Garbage Collection)을 Minor GC라고 부른다.
        • Old 영역(Old Generation)
          • Young영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
          • Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.
          • Old 영역에 대한 가비지 컬렉션(Garbage Collection)을 Major GC 또는 Full GC라고 부른다.
      3. 동작 방식

        1. Stop The World
          1. 가비지 컬렉션을 실행하기 위해 JVM이 애플리케이션의 실행을 멈추는 작업이다. GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단되고, GC가 완료되면 작업이 재개된다.
          2. 말 그대로 일시적으로 어플리케이션 멈추는 현상을 말한다.
        2. Mark and Sweep
          1. Mark : 사용되는 메모리와 사용되지 않는 메모리를 식별하는 작업
          2. Sweep: Mark 단계에서 사용되지 않음으로 식별된 메모리를 해체하는 작업
          3. Stop The World를 통해 모든 작업을 중단시키면, GC는 스택의 모든 변수 또는 Reachable 객체를 스캔하면서 각각이 어떤 객체를 참고하고 있는지를 탐색하게 된다. 그리고 사용되고 있는 메모리를 식별하는데, 이러한 과정을 Mark라고 한다. 이후에 Mark가 되지 않은 객체들을 메모리에서 제거하는데, 이러한 과정을 Sweep라고 한다.
    5. Linked List vs Array List(=Array) 정의와 차이점

      스크린샷 2023-03-14 오후 10.07.22.png

      1. ArrayList는 데이터들이 순서대로 쭉 늘어선 배열의 형식을 가지고 있다.
        1. 장점
          1. 무작위 접근이 가능하다. ArrayList는 Index 정보를 이용하여 데이터의 접근이 용이하다.
        2. 단점
          1. 데이터를 추가하거나 삭제해야하는 경우 O(N)만큼 소요된다. 데이터를 추가하는 경우, 새로운 메모리 공간을 할당 받고 기존에 있던 데이터를 옮겨야 하기 때문에 O(N)만큼 소요된다.
      2. LinkedList는 순서대로 늘어선 배열의 형식이 아니라, 데이터가 저장되어 있는 메모리 공간의 주소 값으로 서로 연결되어 있는 구조를 가지고 있다.
        1. 장점
          1. 데이터 추가/삭제가 빠르다. 몇 개의 참조자만 바꿈으로써 새로운 데이터의 추가나 기존 데이터의 위치에 상관 없이 빠르게 삭제가 가능하다.
        2. 단점
          1. 데이터 접근 시, 순차적으로 접근해야 한다.

      숙제