<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sj.kim</title>
        <link>https://velog.io/</link>
        <description>기술로 세상을 이롭게</description>
        <lastBuildDate>Wed, 10 Jan 2024 14:21:10 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sj.kim</title>
            <url>https://velog.velcdn.com/images/sj_kim/profile/5e1a0a60-3b1d-4d20-93d3-c6bd0553a2f2/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sj.kim. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sj_kim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[모던 자바 인 액션] 동작 파라미터화 코드 전달하기]]></title>
            <link>https://velog.io/@sj_kim/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94-%EC%9D%B8-%EC%95%A1%EC%85%98-%EB%8F%99%EC%9E%91-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%ED%99%94-%EC%BD%94%EB%93%9C-%EC%A0%84%EB%8B%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sj_kim/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94-%EC%9D%B8-%EC%95%A1%EC%85%98-%EB%8F%99%EC%9E%91-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%ED%99%94-%EC%BD%94%EB%93%9C-%EC%A0%84%EB%8B%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 10 Jan 2024 14:21:10 GMT</pubDate>
            <description><![CDATA[<h2 id="동작-파라미터화를-이용하면-자주-바뀌는-요구사항에-효과적으로-대응할-수-있다">동작 파라미터화를 이용하면 자주 바뀌는 요구사항에 효과적으로 대응할 수 있다.</h2>
<pre><code class="language-java">package ex;

public enum Color {
    RED,
    GREEN

    ;
}
</code></pre>
<hr>

<pre><code class="language-java">package ex;

public class Apple {
    private Color color;

    public Apple(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }

    @Override
    public String toString() {
        return &quot;Apple{&quot; +
                &quot;color=&quot; + color +
                &#39;}&#39;;
    }
}
</code></pre>
<hr>

<h3 id="첫-번째-요구사항--녹색-사과만-필터링-해주세요">첫 번째 요구사항 : 녹색 사과만 필터링 해주세요.</h3>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/f749a7d5-aa08-4711-9284-b4289496c306/image.png" alt=""></p>
<hr>

<pre><code class="language-java">package ex;

import java.util.List;

public class Main {

    public static void main(String[] args) {
        List&lt;Apple&gt; apples = new Farm().filterGreenApples(List.of(new Apple(Color.GREEN), new Apple(Color.RED), new Apple(Color.GREEN)));

        apples.forEach(System.out::println);
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/2de282c3-ef04-40ed-90f9-b03e78b6607e/image.png" alt=""></p>
<h3 id="두-번째-요구사항--빨간색-사과만-필터링-해주세요">두 번째 요구사항 : 빨간색 사과만 필터링 해주세요.</h3>
<ul>
<li>색을 파라미터화하자.
<img src="https://velog.velcdn.com/images/sj_kim/post/959f53ca-80bd-4948-8922-ce3feff9874a/image.png" alt=""></li>
</ul>
<hr>

<pre><code class="language-java">package ex;

import java.util.List;

public class Main {

    public static void main(String[] args) {
        List&lt;Apple&gt; greenApples = new Farm().filterApplesByColor(List.of(new Apple(Color.GREEN), new Apple(Color.RED), new Apple(Color.GREEN)), Color.GREEN);
        List&lt;Apple&gt; redApples = new Farm().filterApplesByColor(List.of(new Apple(Color.GREEN), new Apple(Color.RED), new Apple(Color.GREEN)), Color.RED);

        greenApples.forEach(apple -&gt; System.out.println(&quot;green : &quot; + apple));
        System.out.println(&quot;---&quot;);
        redApples.forEach(apple -&gt; System.out.println(&quot;red : &quot; + apple));
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/feb7892b-c5e7-4abc-8ee0-ec6bf9206d06/image.png" alt=""></p>
<h3 id="세-번째-요구사항--무게로-사과를-구분할-수-있게-해주세요">세 번째 요구사항 : 무게로 사과를 구분할 수 있게 해주세요.</h3>
<ul>
<li>Apple 클래스 weight 필드 추가<pre><code class="language-java">package ex;
</code></pre>
</li>
</ul>
<p>public class Apple {
    private Color color;</p>
<pre><code>private int weight;

public Apple(Color color, int weight) {
    this.color = color;
    this.weight = weight;
}

public Color getColor() {
    return color;
}

public int getWeight() {
    return weight;
}

@Override
public String toString() {
    return &quot;Apple{&quot; +
            &quot;color=&quot; + color +
            &quot;, weight=&quot; + weight +
            &#39;}&#39;;
}</code></pre><p>}</p>
<p>```
<img src="https://velog.velcdn.com/images/sj_kim/post/b7354554-9e9e-4f54-8051-b4dd091b20bc/image.png" alt=""></p>
<ul>
<li>새로 추가한 무게 조건 필터링 코드가 기존의 색 조건 필터링 코드와 대부분 중복된다.
이는 소프트웨어 공학의 <code>DRY(Don&#39;t Repeat Yourself, 같은 것을 반복하지 말 것) 원칙</code>을 어긴다.</li>
</ul>
<h2 id="참고">참고</h2>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://search.shopping.naver.com/book/search?bookTabType=ALL&amp;pageIndex=1&amp;pageSize=40&amp;query=%EB%AA%A8%EB%8D%98%20%EC%9E%90%EB%B0%94%20%EC%9D%B8%20%EC%95%A1%EC%85%98&amp;sort=REL">모던 자바 인 액션</a>, 도서</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프록시 패턴(Proxy Pattern)]]></title>
            <link>https://velog.io/@sj_kim/%ED%94%84%EB%A1%9D%EC%8B%9C-%ED%8C%A8%ED%84%B4Proxy-Pattern</link>
            <guid>https://velog.io/@sj_kim/%ED%94%84%EB%A1%9D%EC%8B%9C-%ED%8C%A8%ED%84%B4Proxy-Pattern</guid>
            <pubDate>Tue, 02 Jan 2024 12:30:00 GMT</pubDate>
            <description><![CDATA[<ul>
<li>프록시(Proxy)는 &quot;대리&quot;의 의미로 특정 객체로의 접근을 제어하는 대리인을 제공한다.<h3 id="프록시-패턴-종류">프록시 패턴 종류</h3>
<h4 id="1-원격-프록시">1. 원격 프록시</h4>
</li>
<li>클라이언트 객체가 원격 객체<code>(다른 JVM의 힙 영역에 생성된 객체)</code>의 메소드를 호출하면 실제 원격 객체가 아닌 프록시 객체가 호출되고, 이 프록시 객체가 다른 원격 객체에게 메소드 호출을 전달해준다.<h4 id="2-가상-프록시">2. 가상 프록시</h4>
</li>
<li>생성 비용이 많이 드는 객체에 대한 접근를 제어한다.</li>
<li>프록시는 원본 객체 생성 전이나 생성 도중에 객체를 대신하며, 객체 생성이 끝나면 직접 요청을 전달한다.</li>
</ul>
<h3 id="예제-코드">예제 코드</h3>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/6e326de4-c8a4-4ec2-bb1e-36459120426a/image.png" alt=""></p>
<pre><code class="language-java">package pattern.ex02;

// Payment.java
public interface Payment {
    String request(int amount);
}

// Cash.java
public class Cash implements Payment{

    @Override
    public String request(int amount) {
        return &quot;결제 요청 - 금액 : &quot; + amount;
    }
}


// paymentProxy.java
public class paymentProxy implements Payment{
    private Cash cash;
    private String cashedData;

    @Override
    public String request(int amount) {
        if (cash == null) {
            cash = new Cash();
            cashedData = cash.request(amount);
            System.out.println(&quot;실제 객체 생성&quot;);
        } else {
            System.out.println(&quot;Proxy 객체 캐싱&quot;);
        }

        return cashedData;
    }
}

// Main.java
public class Main {
    public static void main(String[] args) {
        Payment paymentProxy = new paymentProxy();
        System.out.println(paymentProxy.request(1000));

        System.out.println(&quot;---&quot;);

        System.out.println(paymentProxy.request(1000));
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/bba044cb-22b7-480f-81f1-30580a5703a2/image.png" alt=""></p>
<ul>
<li>프록시 객체는 동일한 요청이 반복되는 경우 실제 객체에 대한 요청을 생략하고 저장된 결과를 반환한다.</li>
</ul>
<hr>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://search.shopping.naver.com/book/catalog/32473420628?cat_id=50010881&amp;frm=PBOKMOD&amp;query=%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8+%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4&amp;NaPm=ct%3Dlqs5h3xc%7Cci%3D3945a94133b998277c35fb4ba73e6a140e8774f0%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3D95ab673de426d06f4d439c0d6a3ebd6c85e07c34">헤드퍼스트 디자인패턴</a>, 도서</li>
<li><a href="https://sasca37.tistory.com/278">[디자인패턴] 프록시 (프록시 패턴, 데코레이터 패턴) 정리</a>, 블로그</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[템플릿 메서드 패턴(Template Method Design Pattern)]]></title>
            <link>https://velog.io/@sj_kim/%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4Template-Method-Design-Pattern</link>
            <guid>https://velog.io/@sj_kim/%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4Template-Method-Design-Pattern</guid>
            <pubDate>Sat, 30 Dec 2023 14:19:42 GMT</pubDate>
            <description><![CDATA[<ul>
<li>SOLID 원칙 중 <code>개방폐쇄원칙(OCP : Open/closed principle)</code><sup><a href="#footnote_1">1</a></sup>을 준수하는 디자인 패턴<h6 id="a-namefootnote_11a--확장에-대해-열려-있어야-하고-수정에-대해서는-닫혀-있어야-한다-즉-기능을-추가하거나-변경해야-할-때-이미-제대로-동작하고-있던-원래-코드를-변경하지-않아도-기존의-코드에-새로운-코드를-추가함으로써-기능의-추가나-변경이-가능하다"><a name="footnote_1">1</a>:  확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. <em>즉, 기능을 추가하거나 변경해야 할 때 이미 제대로 동작하고 있던 원래 코드를 변경하지 않아도, 기존의 코드에 새로운 코드를 추가함으로써 기능의 추가나 변경이 가능하다.</em></h6>
<h6 id="span-stylecolor04b486출처👉-위키백과span"><span style="color:#04B486"><em>출처👉 <a href="https://ko.wikipedia.org/wiki/%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84_%EC%9B%90%EC%B9%99">위키백과</a></em></span></h6>
</li>
<li>템플릿 메소드는 알고리즘의 각 단계를 정의하며, 서브클래스에서 일부 단계를 구현할 수 있도록 유도한다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;">즉, 어떤 기능에 대해서 실행 되어야 할 각 단계에 대한 순서만을 일단 정해두고, 각 단계에 대한 세부 구현을 상황에 따라 다르게 구현할 수 있도록 하는 디자인 패턴</span>*
<span style="color:#04B486"><em>출처👉 [［디자인 패턴］ - 03. 탬플릿 메서드（Template Method） 패턴]
(<a href="https://velog.io/@gyomni/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-03.-%ED%83%AC%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9CTemplate-Method-%ED%8C%A8%ED%84%B4">https://velog.io/@gyomni/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-03.-%ED%83%AC%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9CTemplate-Method-%ED%8C%A8%ED%84%B4</a>)</em></span></li>
</ul>
<blockquote>
<p>💡 <strong>디자인 패턴(Design Pattern)</strong></p>
</blockquote>
<ul>
<li>소프트웨어 개발자들이 소프트웨어 개발 과정에서 직면했던 일반적인 문제에 대해 재사용 가능한 해결책</li>
</ul>
<pre><code class="language-java">package pattern.ex01;

public abstract class Booking {

    // 서브클래스 오버라이드 방지
    final void book() {
        chooseRoute();
        chooseDateAndTime();
        pay();
    }

    void chooseRoute() {
        System.out.println(&quot;출발지와 목적지를 선택하다.&quot;);
    }

    abstract void pay();

    // 후크(Hook)
    void chooseDateAndTime() {}

}
</code></pre>
<blockquote>
<p>💡 <strong>후크(Hook)</strong></p>
</blockquote>
<ul>
<li>추상 클래스에서 선언되지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드</li>
</ul>
<pre><code class="language-java">package pattern.ex01;


// Taxi.java
public class Taxi extends Booking {
    @Override
    void pay() {
        System.out.println(&quot;택시 요금을 지불하다.&quot;);
    }
}

// Train.java
public class Train extends Booking {
    @Override
    void pay() {
        System.out.println(&quot;기차표를 예매하다.&quot;);
    }

    @Override
    void chooseDateAndTime() {
        System.out.println(&quot;출발 날짜와 시간을 선택하다.&quot;);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package pattern.ex01;

public class User {

    public static void main(String[] args) {

        Taxi taxi = new Taxi();
        taxi.book();

        System.out.println(&quot;------&quot;);

        Train train = new Train();
        train.book();
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/bbb1da09-5467-4f37-96ae-e8dccab9fa24/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/cca9534f-b595-4e6b-9ca2-14708c3264c5/image.png" alt=""></p>
<h2 id="장단점">장단점</h2>
<h3 id="장점">장점</h3>
<ul>
<li>공통된 코드를 부모 클래스에 정의하므로 코드 중복을 방지한다.</li>
<li>기존 코드에 영향을 주지 않고 새로운 알고리즘을 추가할 수 있어 확장이 용이하다.</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>추상 메서드의 수가 늘어나면 추상 클래스와 구현 클래스 간의 의존성이 높아져 유지보수가 어렵다.</li>
</ul>
<hr>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://search.shopping.naver.com/book/catalog/32473420628?cat_id=50010881&amp;frm=PBOKMOD&amp;query=%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8+%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4&amp;NaPm=ct%3Dlqs5h3xc%7Cci%3D3945a94133b998277c35fb4ba73e6a140e8774f0%7Ctr%3Dboknx%7Csn%3D95694%7Chk%3D95ab673de426d06f4d439c0d6a3ebd6c85e07c34">헤드퍼스트 디자인패턴</a>, 도서</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 09. 중첩 선언과 익명 객체]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-09.-%EC%A4%91%EC%B2%A9-%EC%84%A0%EC%96%B8%EA%B3%BC-%EC%9D%B5%EB%AA%85-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-09.-%EC%A4%91%EC%B2%A9-%EC%84%A0%EC%96%B8%EA%B3%BC-%EC%9D%B5%EB%AA%85-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Wed, 27 Dec 2023 09:47:13 GMT</pubDate>
            <description><![CDATA[<h1 id="91-중첩-클래스">9.1 중첩 클래스</h1>
<ul>
<li>클래스 내부에 선언한 클래스</li>
<li>중첩 클래스를 사용하면 클래스의 멤버를 쉽게 사용할 수 있고 외부에는 중첩 관계 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있다.</li>
<li>중첩 클래스도 컴파일하면 <code>바이트코드가 별도로 생성</code>된다.</li>
</ul>
<h1 id="92-인스턴스-멤버-클래스">9.2 인스턴스 멤버 클래스</h1>
<ul>
<li>A 객체를 생성해야만 B 객체를 생성할 수 있다.</li>
<li>클래스 내부에는 일반 클래스와 같이 <code>필드, 생성자, 메서드 선언</code>이 올 수 있다.</li>
<li>Java 17부터 정적 필드와 정적 메서드 선언이 가능하다.</li>
</ul>
<pre><code class="language-java">package ch09.sec02.ex;

public class A {
    class B {
        int field1 = 1;

        static int field2 = 2;

        B() {
            System.out.println(&quot;B 생성자 실행&quot;);
        }

         void method1() {
             System.out.println(&quot;B-method1() 실행&quot;);
         }

         static void method2() {
             System.out.println(&quot;B-static-method2() 실행&quot;);
         }
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch09.sec02.ex;

public class Main {
    public static void main(String[] args) {
        A.B.method2();  // B-static-method2() 실행

        A a = new A();
        A.B b = a.new B();  // B 생성자 실행

    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/2a7197ac-46ae-4010-bd75-a3c48c5ada2b/image.png" alt=""></p>
<h1 id="93-정적-멤버-클래스">9.3 정적 멤버 클래스</h1>
<ul>
<li>C 객체를 생성하지 않아도 D 객체를 생성할 수 있다.</li>
<li>다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다.</li>
<li>바깥 클래스와 함께 쓰일 때만 유용한 public 도우미로 쓰인다.</li>
<li>멤버 클래스에서 바깥 인스턴스에 접근할 일이 없다면 무조건 <code>static</code> 키워드를 붙여서 정적 멤버 클래스로 만든다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;">왜냐하면, 비정적 멤버 클래스는 바깥 클래스의 인스턴스와 암묵적으로 연결되어 바깥 인스턴스의 메서드를 호출하거나 참조를 가져올 수 있다. 
이 참조를 저장하려면 시간과 공간이 소비되어 가비지 컬렉션이 바깥 클래스의 인스턴스를 수거하지 못해 메모리 누수가 발생할 수 있다.</span>*</li>
</ul>
<pre><code class="language-java">package ch09.sec02.ex;

public class C {
   static class D {
       D() {
           System.out.println(&quot;D-생성자 실행&quot;);
       }
   }

   // 인스턴스 필드
    D field1 = new D();

   // 정적 필드
    static D filed2 = new D();

    C() {
        System.out.println(&quot;C-생성자 실행&quot;);
        D d = new D();
    }

    void method1() {
        D d = new D();
    }

    static void method2() {
        System.out.println(&quot;method2() Call!&quot;);
        D d = new D();
    }

}

</code></pre>
<hr>

<pre><code class="language-java">package ch09.sec02.ex;

public class Main {
    public static void main(String[] args) {
//        C.method2();                // D-생성자 실행
//        C.D filed2 = C.filed2;      // D-생성자 실행

        /*
            D-생성자 실행
            D-생성자 실행
            C-생성자 실행
            D-생성자 실행
        */
        C.D fieldA = new C().field1;    // 정적 필드 초기화 -&gt; 인스턴스 필드 초기화 -&gt; 생성자 호출

        System.out.println(&quot;-----&quot;);

        /*
            D-생성자 실행
            C-생성자 실행
            D-생성자 실행
        */
        C.D fieldB = new C().field1;    // 인스턴스 필드 초기화 -&gt; 생성자 호출

    }
}
</code></pre>
<ul>
<li>클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있다.</li>
</ul>
<blockquote>
<p>💡 <strong>클래스 로딩 시점</strong></p>
</blockquote>
<ul>
<li>클래스의 인스턴스가 생성될 때</li>
<li>클래스의 정적 변수가 사용될 때</li>
<li>클래스의 정적 메서드가 호출될 때</li>
</ul>
<p><span style="color:#04B486"><em>출처👉<a href="https://velog.io/@skyepodium/%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94-%EC%96%B8%EC%A0%9C-%EB%A1%9C%EB%94%A9%EB%90%98%EA%B3%A0-%EC%B4%88%EA%B8%B0%ED%99%94%EB%90%98%EB%8A%94%EA%B0%80">클래스는 언제 로딩되고 초기화되는가? (feat. 싱글톤)</a></em></span></p>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/f114b4e8-2ee4-4e74-b80d-1c6baab4135a/image.png" alt=""></p>
<h1 id="94-로컬-클래스">9.4 로컬 클래스</h1>
<ul>
<li>생성자 또는 메서드 내부에서 선언된 클래스</li>
<li>로컬 클래스는 생성자와 메서드가 실행될 동안에만 객체를 생성할 수 있다.</li>
<li>내부에 필드, 생성자, 메서드 선언이 올 수 있고, Java 17부터는 정적 필드와 정적 메서드를 지원한다.</li>
<li>로컬 변수는 Java 8 이후부터는 명시적으로 final 키워드를 붙이지 않아도 <code>final 특성을 가지고 있어 값을 읽을 수만 있고 수정할 수 없다.</code></li>
</ul>
<pre><code class="language-java">package ch09.sec02.ex;

public class E {
    public E() {
        System.out.println(&quot;E 객체 생성&quot;);
    }

    void method() {

        int var = 1;

        class F {
            int field = 1;
            public F() {
                System.out.println(&quot;F 객체 생성&quot;);
            }

            void method1() {
                // var = 2;    // Variable &#39;var&#39; is accessed from within inner class, needs to be final or effectively final
                field = 2;
                System.out.println(&quot;F객체 field 값: &quot; + field);
            }

            static void method2() {
                System.out.println(&quot;F객체 static 메서드 실행!&quot;);
            }
        }

        F f = new F();
        f.method1();

        F.method2();
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/84a972cc-ff6c-4870-a117-b86621b9cfd5/image.png" alt=""></p>
<hr>

<pre><code class="language-java">package ch09.sec02.ex;

public class Main {
    public static void main(String[] args) {
        E e = new E();  // E 객체 생성
        System.out.println(&quot; --- &quot;);
        e.method();     // F 객체 생성
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/cad3b850-0c26-47a3-b780-60e2bbb176ee/image.png" alt=""></p>
<hr>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://search.shopping.naver.com/book/search?bookTabType=ALL&amp;pageIndex=1&amp;pageSize=40&amp;query=%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C%20%EC%9E%90%EB%B0%94&amp;sort=REL">이펙티브 자바 Effective Java 3/E</a>, 도서</li>
</ul>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>






]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 08. 인터페이스]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-08.-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-08.-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Mon, 18 Dec 2023 09:40:07 GMT</pubDate>
            <description><![CDATA[<h1 id="81-인터페이스-역할">8.1 인터페이스 역할</h1>
<ul>
<li>인터페이스는 <code>두 객체를 연결</code>하는 역할을 한다.</li>
<li><strong>다형성</strong><sup><a href="#footnote_1">1</a></sup> 구현에 주된 기술로 이용된다.<h6 id="a-namefootnote_11a-사용-방법은-동일하지만-실행-결과가-다양하게-나오는-성질"><a name="footnote_1">1</a>: 사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질</h6>
</li>
</ul>
<h1 id="82-인터페이스와-구현-클래스-선언">8.2 인터페이스와 구현 클래스 선언</h1>
<h2 id="인터페이스-선언">인터페이스 선언</h2>
<ul>
<li>class 키워드 대신 <code>interface</code> 키워드 사용</li>
<li>접근제한자로는 <code>default</code>, <code>public</code>을 붙일 수 있다.<pre><code class="language-java">package ch08.sec02;
</code></pre>
</li>
</ul>
<p>public interface RemoteControl {</p>
<pre><code>public void turnOn();</code></pre><p>}</p>
<pre><code>
## 구현 클래스 선언
* `implements` 키워드를 사용해 인터페이스를 구현한다.
```java
package ch08.sec02;

public class Television implements RemoteControl{

    @Override
    public void turnOn() {
        System.out.println(&quot;Tv를 켜다.&quot;);
    }
}
</code></pre><h2 id="변수-선언과-구현-객체-대입">변수 선언과 구현 객체 대입</h2>
<ul>
<li>인터페이스 벽수는 객체를 참조하고 있지 않다는 뜻으로 <code>null을 대입</code>할 수 있다.</li>
<li>구현 객체를 사용하려면, 인터페이스 변수에 <code>구현 객체를 대입</code>해야 한다.
즉, 구현 객체의 번지를 대입해야 한다.</li>
</ul>
<pre><code class="language-java">package ch08.sec02;

public class RemoteControlEx {

    public static void main(String[] args) {
        RemoteControl remoteControl = null;
        remoteControl = new Television();
        remoteControl.turnOn(); // Tv를 켜다.
    }
}
</code></pre>
<h1 id="83-상수-필드">8.3 상수 필드</h1>
<ul>
<li>인터페이스에 선언된 필드는 모두 <code>public static final</code> 특성을 갖는다.
즉, 불변의 상수 필드로 <code>대문자</code>로 작성하되, 단어 간 연결은 <code>언더바（＿）</code>로 작성하는 것이 관례이다.<pre><code class="language-java">package ch08.sec02;
</code></pre>
</li>
</ul>
<p>public interface RemoteControl {</p>
<pre><code>// 상수 필드
int MAX_VOLUME = 10;
int MIN_VOLUME = 0;

// 추상 메서드
public void turnOn();</code></pre><p>}</p>
<pre><code>
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;https://velog.velcdn.com/images/sj_kim/post/337b2c9b-cc3e-4f4c-b6b6-e7aa3e008947/image.png&quot;&gt;
&lt;/p&gt;

&lt;hr&gt;

```java
package ch08.sec02;

public class RemoteControlEx {

    public static void main(String[] args) {
        System.out.println(RemoteControl.MAX_VOLUME);   // 10
        System.out.println(RemoteControl.MIN_VOLUME);   // 0
    }
}
</code></pre><h1 id="84-추상-메서드">8.4 추상 메서드</h1>
<ul>
<li>인터페이스는 public 추상 메서드<sup><a href="#footnote_2">2</a></sup>를 멤버로 가질 수 있다.<h6 id="a-namefootnote_22a-리턴-타입-메서드명-매개변수만-기술되고-중괄호｛｝를-붙이지-않는-메서드"><a name="footnote_2">2</a>: 리턴 타입, 메서드명, 매개변수만 기술되고 중괄호｛｝를 붙이지 않는 메서드</h6>
</li>
<li>인터페이스 구현 클래스에서는 <code>모든 추상 메서드를 재정의</code>해야 한다.</li>
</ul>
<h1 id="85-디폴트-메서드">8.5 디폴트 메서드</h1>
<ul>
<li><code>완전한 실행 코드를 가진 메서드</code>로 default 키워드가 리턴 타입 앞에 붙는다.</li>
<li>디폴트 메서드의 실행부에서는 상수 필드를 읽거나 추상 메서드를 호출하는 코드를 작성할 수 있다.<pre><code class="language-java">package ch08.sec02;
</code></pre>
</li>
</ul>
<p>public interface RemoteControl {</p>
<pre><code>int MAX_VOLUME = 10;
int MIN_VOLUME = 0;

void turnOn();

void setVolume(int volume);

default void setMute(boolean mute) {
    if (mute) {
        System.out.println(&quot;무음 처리&quot;);
        setVolume(MIN_VOLUME);
    } else {
        System.out.println(&quot;무음 해제&quot;);
    }
}

static void changeBattery() {
    // setMute();  // 컴파일 에러 : Non-static method &#39;setMute(boolean)&#39; cannot be referenced from a static context
    System.out.println(&quot;리모콘 건전지를 교환합니다.&quot;);
}</code></pre><p>}</p>
<pre><code>![](https://velog.velcdn.com/images/sj_kim/post/aafc53cd-d5db-4371-a470-6b22d8ea9142/image.png)

&lt;hr&gt;

* 구현 클래스는 디폴트 메서드를 재정의할 수 있다.
단, public 접근 제한자를 반드시 붙여야 하고, default 키워드를 생략해야 한다.

```java
package ch08.sec02;

public class Television implements RemoteControl{

    private int volume;
    private int memoryVolume;

    @Override
    public void turnOn() {
        System.out.println(&quot;Tv를 켜다.&quot;);
    }

    @Override
    public void setVolume(int volume) {
        if (volume &gt; RemoteControl.MAX_VOLUME) {
            this.volume = RemoteControl.MAX_VOLUME;
        } else if (volume &lt; RemoteControl.MIN_VOLUME) {
            this.volume = RemoteControl.MIN_VOLUME;
        } else {
            this.volume = volume;
        }

        System.out.println(&quot;현재 볼륨: &quot; + volume);
    }

    @Override
    public void setMute(boolean mute) {
        if (mute) {
            this.memoryVolume = this.volume;
            System.out.println(&quot;무음 처리합니다.&quot;);
            setVolume(RemoteControl.MIN_VOLUME);
        } else {
            System.out.println(&quot;무음 해제합니다.&quot;);
            setVolume(this.memoryVolume);
        }
    }
}
</code></pre><hr>

<pre><code class="language-java">package ch08.sec02;

public class Audio implements RemoteControl{

    private int volume;

    @Override
    public void turnOn() {
        System.out.println(&quot;오디오를 켜다.&quot;);
    }

    @Override
    public void setVolume(int volume) {
        if (volume &gt; RemoteControl.MAX_VOLUME) {
            this.volume = RemoteControl.MAX_VOLUME;
        } else if (volume &lt; RemoteControl.MIN_VOLUME) {
            this.volume = RemoteControl.MIN_VOLUME;
        } else {
            this.volume = volume;
        }

        System.out.println(&quot;현재 볼륨: &quot; + volume);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch08.sec02;

public class RemoteControlEx {

    public static void main(String[] args) {
        RemoteControl rc;

        rc = new Audio();
        rc.setMute(true);   // 무음 처리 현재 볼륨: 0
        rc.setMute(false);  // 무음 해제

        rc = new Television();
        rc.setVolume(7);    // 현재 볼륨: 7
        rc.setMute(true);   // 무음 처리합니다. 현재 볼륨: 0
        rc.setMute(false);  // 무음 해제합니다. 현재 볼륨: 7

        RemoteControl.changeBattery();  // 리모콘 건전지를 교환합니다.
    }
}
</code></pre>
<h1 id="86-정적-메서드">8.6 정적 메서드</h1>
<ul>
<li>정적 메서드는 구현 객체가 없어도 인터페이스만으로 호출할 수 있다.</li>
<li>정적 메서드 실행부에는 상수 필드를 제외한 추상 메서드, 디폴트 메서드, private 메서드 등을 호출할 수 없다.</li>
</ul>
<h1 id="87-private-메서드">8.7 private 메서드</h1>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>private 메서드</td>
<td>구현 객체가 필요한 메서드</td>
</tr>
<tr>
<td>privae 정적 메서드</td>
<td>구현 객체가 필요 없는 메서드</td>
</tr>
</tbody></table>
<h3 id="1-private-메서드">1) private 메서드</h3>
<ul>
<li>default 메서드에서만 호출 가능<h3 id="2-private-정적-메서드">2) private 정적 메서드</h3>
</li>
<li>default 메서드뿐 아니라 정적 메서드 안에서도 호출 가능</li>
</ul>
<pre><code class="language-java">package ch08.sec07;

public interface Service {

    default void defaultMethod() {
        System.out.println(&quot;default void defaultMethod() --- &quot;);
        privateMethod();
        privateStaticMethod();
        System.out.println(&quot;--- default void defaultMethod()&quot;);
    }

    private void privateMethod() {
        System.out.println(&quot;private void privateMethod() Call!!&quot;);
    }

    static void staticMethod() {
        System.out.println(&quot;static void staticMethod() ---&quot;);
        privateStaticMethod();
        // privateMethod();    // 컴파일 에러 :Non-static method &#39;privateMethod()&#39; cannot be referenced from a static context
        System.out.println(&quot;--- static void staticMethod()&quot;);
    }

    private static void privateStaticMethod() {
        System.out.println(&quot;private static void privateStaticMethod() Call!&quot;);
    }
}

</code></pre>
<hr>

<pre><code class="language-java">package ch08.sec07;

public class ServiceImpl implements Service{

}
</code></pre>
<hr>

<pre><code class="language-java">package ch08.sec07;

public class ServiceEx {
    public static void main(String[] args) {
        Service service = new ServiceImpl();
        service.defaultMethod();
        /*
            default void defaultMethod() ---
            private void privateMethod() Call!!
            private static void privateStaticMethod() Call!
            --- default void defaultMethod()
        */

        Service.staticMethod();
        /*
            static void staticMethod() ---
            private static void privateStaticMethod() Call!
            --- static void staticMethod()
        */
    }
}
</code></pre>
<h1 id="88-다중-인터페이스-구현">8.8 다중 인터페이스 구현</h1>
<ul>
<li>구현 객체는 <code>implements</code> 키워드를 사용해 여러 개의 인터페이스를 구현할 수 있다.<pre><code class="language-java">package ch08.sec08;
</code></pre>
</li>
</ul>
<p>public interface RemoteControl {</p>
<pre><code>void turnOn();
void turnOff();</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch08.sec08;

public interface Searchable {
    void search(String url);
}
</code></pre><hr>

<pre><code class="language-java">package ch08.sec08;

public class SmartTelevision implements RemoteControl, Searchable{
    @Override
    public void turnOn() {
        System.out.println(&quot;Tv를 켜다&quot;);
    }

    @Override
    public void turnOff() {
        System.out.println(&quot;Tv를 끄다&quot;);
    }

    @Override
    public void search(String url) {
        System.out.println(url + &quot;을 검색하다&quot;);
    }
}
</code></pre>
<hr>

<pre><code>package ch08.sec08;

public class MultiInterfaceImplEx {

    public static void main(String[] args) {
        RemoteControl rc = new SmartTelevision();
        rc.turnOn();    // Tv를 켜다
        rc.turnOff();   // Tv를 끄다

        Searchable searchable = new SmartTelevision();
        searchable.search(&quot;https://velog.io/&quot;);     // https://velog.io/을 검색하다
    }
}
</code></pre><p><img src="https://velog.velcdn.com/images/sj_kim/post/a40fd810-5c64-4b3a-ade4-025db4079552/image.png" alt=""></p>
<h1 id="89-인터페이스-상속">8.9 인터페이스 상속</h1>
<ul>
<li>인터페이스도 다른 인터페이스를 상속할 수 있으며, <code>클래스와 달리 다중 상속을 허용한다.</code><pre><code class="language-java">package ch08.sec09;
</code></pre>
</li>
</ul>
<p>public interface InterfaceC extends InterfaceA, InterfaceB{</p>
<pre><code>void methodC();</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

![](https://velog.velcdn.com/images/sj_kim/post/542a6548-a05c-4d53-8f03-6272ce422e05/image.png)

&lt;hr&gt;

```java
package ch08.sec09;

public class InterfaceCImpl implements InterfaceC{

    @Override
    public void methodA() {
        System.out.println(&quot;InterfaceCImpl - methodA() Call!&quot;);
    }

    @Override
    public void methodB() {
        System.out.println(&quot;InterfaceCImpl - methodB() Call!&quot;);
    }

    @Override
    public void methodC() {
        System.out.println(&quot;InterfaceCImpl - methodC() Call!&quot;);
    }
}
</code></pre><hr>

<pre><code class="language-java">package ch08.sec09;

public class ExtendsEx {

    public static void main(String[] args) {
        InterfaceCImpl impl = new InterfaceCImpl();

        InterfaceA ia = impl;
        ia.methodA();   // InterfaceCImpl - methodA() Call!

        InterfaceB ib = impl;
        ib.methodB();   // InterfaceCImpl - methodB() Call!

        InterfaceC ic = impl;
        ic.methodC();   // InterfaceCImpl - methodC() Call!
    }
}
</code></pre>
<h1 id="810-타입-변환">8.10 타입 변환</h1>
<ul>
<li>인터페이스의 타입 변환은 인터페이스와 구현 클래스 간에 발생한다.<h2 id="자동-타입-변환">자동 타입 변환</h2>
</li>
<li>부모 클래스가 인터페이스를 구현하고 있다면 자식 클래스도 인터페이스 타입으로 자동 타입 변환될 수 있다.<pre><code class="language-java">// A.java
public interface A {
}
</code></pre>
</li>
</ul>
<p>// B.java
public class B implements A{
}</p>
<p>// C.java
public class C extends B{
}</p>
<pre><code>![](https://velog.velcdn.com/images/sj_kim/post/d3fd1e4c-faa2-4729-8ac1-94bfa50a672b/image.png)

```java
public class PromotionEx {
    public static void main(String[] args) {
        B b = new B();
        C c = new C();

        A a;
        a = b;
        a = c;
    }
}</code></pre><h2 id="강제-타입-변환">강제 타입 변환</h2>
<ul>
<li>인터페이스 타입을 구현 클래스 타입으로 변환시킨다.<pre><code class="language-java">package sec10.exam02;
</code></pre>
</li>
</ul>
<p>public class CatingEx {</p>
<pre><code>public static void main(String[] args) {
    Vehicle vehicle = new Bus();
    vehicle.run();      // 버스가 달린다.
    // vehicle.checkFar();  // 컴파일 에러 : cannot find symbol

    // 강제 타입 변환
    Bus bus = (Bus) vehicle;
    bus.run();          // 버스가 달린다.
    bus.checkFare();    // 승차 요금을 확인한다.
}</code></pre><p>}</p>
<pre><code>
# 8.11 다형성
## 필드의 다형성
* 필드 타입으로 인터페이스를 선언하면 필드값으로 다양한 구현 객체를 대입할 수 있다.`(자동 타입 변환)`
```java
// Tire.java
public interface Tire {

    void roll();
}

// HankookTire.java
public class HankookTire implements Tire{

    @Override
    public void roll() {
        System.out.println(&quot;한국 타이어가 굴러갑니다.&quot;);
    }
}

// KumhoTire.java
public class KumhoTire implements Tire {

    @Override
    public void roll() {
        System.out.println(&quot;금호 타이어가 굴러갑니다.&quot;);
    }
}

// Car.java
public class Car {

    // 필드
    Tire  tire = new HankookTire();

    void run() {
        tire.roll();
    }
}
</code></pre><hr>

<pre><code class="language-java">public class CarEx {

    public static void main(String[] args) {
        Car car = new Car();
        car.run();  // 한국 타이어가 굴러갑니다.

        car.tire = new KumhoTire();
        car.run();  // 금호 타이어가 굴러갑니다.
    }
}
</code></pre>
<h2 id="매개변수의-다형성">매개변수의 다형성</h2>
<ul>
<li><p>매개변수 타입을 인터페이스로 선언하면 메서드 호출 시 다양한 구현 객체를 대입할 수 있다. <code>(자동 타입 변환)</code></p>
<pre><code class="language-java">// Vehicle.java
public interface Vehicle {

  void run();
}
</code></pre>
</li>
</ul>
<p>// Bus.java
public class Bus implements Vehicle{</p>
<pre><code>@Override
public void run() {
    System.out.println(&quot;버스가 달린다.&quot;);
}

public void checkFare() {
    System.out.println(&quot;승차요금을 확인한다.&quot;);
}</code></pre><p>}</p>
<p>// Taxi.java
public class Taxi implements Vehicle{
    @Override
    public void run() {
        System.out.println(&quot;택시가 달린다.&quot;);
    }
}</p>
<p>// Driver.java
public class Driver {</p>
<pre><code>void drive(Vehicle vehicle) {
    vehicle.run();
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
public class DriverEx {

    public static void main(String[] args) {
        Driver driver = new Driver();
        driver.drive(new Bus());    // 버스가 달린다.
        driver.drive(new Taxi());   // 택시가 달린다.
    }
}
</code></pre><h1 id="812-객체-타입-확인">8.12 객체 타입 확인</h1>
<ul>
<li><p><code>instanceof</code> 연산자로 객체 타입을 확인한다.</p>
<pre><code class="language-java">public class DriverEx {

  public static void main(String[] args) {
      Driver driver = new Driver();

      ride(new Bus());    // 승차요금을 확인한다.
  }

  public static void ride(Vehicle vehicle) {
      if (vehicle instanceof Bus) {
          Bus bus = (Bus) vehicle;
          bus.checkFare();
      }

      /* Java 12부터 사용 가능
      if (vehicle instanceof Bus bus) {
          bus.checkFare();
      }
      */
  }
}
</code></pre>
</li>
</ul>
<pre><code>
# 8.13 봉인된 인터페이스
* Java 15부터 도입된 봉인된(sealed) 인터페이스는 무분별한 자식 인터페이스 생성을 방지한다.
* sealed 키워드를 사용하면 permits 키워드 뒤에 상속 가능한 자식 인터페이스를 지정해야 한다.
* 자식 인터페이스는 non-sealed, selaed 중 하나의 유형으로 선언되어야 한다.
* non-sealed 키워드는 봉인을 해제한다는 뜻으로, 자식 인터페이스를 만들 수 있다.

![](https://velog.velcdn.com/images/sj_kim/post/89a555f4-a35c-4958-9fac-d20975416d5c/image.png)

```java
// InterfaceA.java
public sealed interface InterfaceA permits InterfaceB {
    void methodA();
}

// InterfaceB.java
public non-sealed interface InterfaceB extends InterfaceA {
    void methodB();
}

// InterfaceC.java
public interface InterfaceC extends InterfaceB {
    void methodC();
}

//    ImplClass.java
public class ImplClass implements InterfaceC {
    @Override
    public void methodA() {
        System.out.println(&quot;methodA() Call!!&quot;);
    }

    @Override
    public void methodB() {
        System.out.println(&quot;methodB() Call!!&quot;);
    }

    @Override
    public void methodC() {
        System.out.println(&quot;methodC() Call!!&quot;);
    }
}</code></pre><hr>

<pre><code class="language-java">public class SealedExample {

    public static void main(String[] args) {
        ImplClass implClass = new ImplClass();

        InterfaceA interfaceA = implClass;
        interfaceA.methodA();   // methodA() Call!!

        InterfaceB interfaceB = implClass;
        interfaceB.methodA();   // methodA() Call!!
        interfaceB.methodB();   // methodB() Call!!

        InterfaceC interfaceC = implClass;
        interfaceC.methodA();   // methodA() Call!!
        interfaceC.methodB();   // methodB() Call!!
        interfaceC.methodC();   // methodC() Call!!
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[ThreadLocal]]></title>
            <link>https://velog.io/@sj_kim/ThreadLocal</link>
            <guid>https://velog.io/@sj_kim/ThreadLocal</guid>
            <pubDate>Wed, 13 Dec 2023 05:16:24 GMT</pubDate>
            <description><![CDATA[<h1 id="threadlocal이란">ThreadLocal이란?</h1>
<ul>
<li>java.lang 패키지에 속한 클래스로 <strong>Thread별 독립적으로 초기화된 변수</strong>를 제공한다.</li>
<li>ThreadLocal 내부는 Thread의 정보를 Key 값으로 하여 값을 저장하는 Map 구조<code>(ThreadLocalMap)</code>를 가지고 있다.</li>
</ul>
<h2 id="주요-메서드">주요 메서드</h2>
<h3 id="1-get（）">1. get（）</h3>
<ul>
<li>현재 Thread의 ThreadLocal 변수 값 <code>반환</code><h3 id="2-set（）">2. set（）</h3>
</li>
<li>현재 Thread의 ThreadLocal 변수 값 <code>설정</code><h3 id="3-remove（）">3. remove（）</h3>
</li>
<li>현재 Thread의 ThreadLocal 변수 값 <code>제거</code><h3 id="4-withinitial（）">4. withInitial（）</h3>
</li>
<li>현재 Thread의 ThreadLocal 변수 생성 및 특정 값으로 <code>초기화</code></li>
</ul>
<h3 id="예제-코드-1-동시성-문제-발생">예제 코드 (1) 동시성 문제 발생</h3>
<pre><code class="language-java">public class MyRunnable implements Runnable {

    private static int var = 0;
    private int order;

    public MyRunnable(int order) {
        this.order = order;
    }

    @Override
    public void run() {
        for (int i = 0; i &lt; 5; i++) {
            var += 1;

            String str = i == 0 ? &quot; --init&quot; : &quot;&quot;;
            System.out.println(&quot;Thread - &quot; + order + &quot; / &quot; + &quot; [&quot; + i + &quot;] &quot; + &quot; - &quot; + var + str);
        }
    }

}

</code></pre>
<hr>

<pre><code class="language-java">public class ThreadLocalBefore {

    public static void main(String[] args) {
        for (int i = 0; i &lt; 2; i++) {
            Thread thread = new Thread(new MyRunnable(i));
            thread.start();
        }
    }

}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/a2de606f-eec9-47a4-be05-fdc4672457ab/image.png" alt=""></p>
<blockquote>
<p>💡 <strong>동시성 문제</strong></p>
</blockquote>
<ul>
<li>다수의 Thread가 하나의 공유 데이터<code>(동일한 자원)</code>를 조작할 때 발생하는 문제로 데이터 정합성 문제가 발생한다.</li>
</ul>
<h3 id="예제-코드-2-동시성-문제-해결---threadlocal-사용">예제 코드 (2) 동시성 문제 해결 - ThreadLocal 사용</h3>
<pre><code class="language-java">public class ThreadLocalMyRunnable implements Runnable {

    private static final ThreadLocal&lt;Integer&gt; var = ThreadLocal.withInitial(() -&gt; 0);
    private boolean removalStatus;
    private int order;

    public ThreadLocalMyRunnable(boolean removalStatus, int order) {
        this.removalStatus = removalStatus;
        this.order = order;
    }

    @Override
    public void run() {
        for (int i = 0; i &lt; 5; i++) {
            var.set(var.get() + 1);

            String str = i == 0 ? &quot; --init&quot; : &quot;&quot;;
            System.out.println(&quot;Thread - &quot; + order + &quot; / &quot; + &quot; [&quot; + i + &quot;] &quot; + &quot; - &quot; + var.get() + str);
        }

        if (removalStatus) {
            var.remove();
        }
    }
}

</code></pre>
<hr>

<pre><code class="language-java">public class ThreadLocalAfter {

    public static void main(String[] args) {
        for (int i = 0; i &lt; 2; i++) {
            Thread thread = new Thread(new ThreadLocalMyRunnable(false, i));
            thread.start();
        }
    }

}</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/06f51f70-a919-40c9-b64a-d3e059b372be/image.png" alt=""></p>
<h2 id="remove（）메서드-중요성">remove（）메서드 중요성</h2>
<ul>
<li>작업이 끝난 후 ThreadLocal 값을 제거하지 않으면, 추후 다시 ThreadLocal이 사용될 때 이전 값을 재사용하게 된다. 이를 방지하기 위해 remove（）메서드를 호출해 값을 지워주는 것이 좋다.</li>
</ul>
<h3 id="예제-코드-1-remove（）적용-전">예제 코드 (1) remove（）적용 전</h3>
<h4 id="newfixedthreadpool（）--고정된-크기의-스레드-풀-생성">newFixedThreadPool（） : 고정된 크기의 스레드 풀 생성</h4>
<pre><code class="language-java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadLocalRemoveBefore {

    private static final ExecutorService executorService = Executors.newFixedThreadPool(3);

    public static void main(String[] args) {
        for (int i = 0; i &lt; 5; i++) {
            Thread thread = new Thread(new ThreadLocalMyRunnable(false, i));
            executorService.execute(thread);
        }

        executorService.shutdown();
    }

}

</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/5e8eb095-bec5-4248-bdaf-2abc3e20b1f9/image.png" alt=""></p>
<blockquote>
<p>💡 <strong>Thread Pool</strong></p>
</blockquote>
<ul>
<li>스레드 풀은 작업처리에 사용되는 Thread를 제한된 개수만큼 정해놓고 작업큐 <code>(Queue)</code>에 들어오는 작업들을 하나씩 Thread가 맡아 처리하는 것</li>
<li>생성된 Thread는 작업을 마치면 즉시 종료되지 않고, 대신 풀에 반환되어 다음 작업을 수행할 수 있도록 재사용된다. *<span style="background-color: #ffffcc; color: #ff6666;">즉, 종료된 Thread는 풀로 반환되기에 바로 GC의 대상이 되지 않아 GC 동작에 따른 오버헤드<sup><a href="#footnote_1">1</a></sup>가 감소된다.</span>*</li>
<li>여러 번 Runtime Data Area에 Thread를 생성하지 않고, 특정 수의 Thread를 미리 생성해 재사용함으로써 Thread의 생성 및 소멸에 따른 오버헤드를 최소화하고, 성능을 향상시킨다.</li>
<li>Thread Pool을 사용하지 않고 필요 이상으로 Thread를 생성하면 메모리와 CPU 잠식<sup><a href="#footnote_2">2</a></sup> 문제가 발생할 수 있다.</li>
</ul>
<h6 id="a-namefootnote_11a-어떤-처리를-하기-위해-들어가는-간접적인-처리-시간-·-메모리-등을-말한다-span-stylecolor04b486출처👉위키백과span"><a name="footnote_1">1</a>: 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등을 말한다. <span style="color:#04B486"><em>출처👉<a href="https://ko.wikipedia.org/wiki/%EC%98%A4%EB%B2%84%ED%97%A4%EB%93%9C">위키백과</a></em></span></h6>
<h6 id="a-namefootnote_22a-빈번한-컨텍스트-스위칭-context-switching-기존-프로세스의-context를-저장하고-다음-프로세스를-실행할-수-있도록-context를-교체하는-작업이-발생하여-cpu-자원을-사용하고-잠식하는-현상이-초래한다"><a name="footnote_2">2</a>: 빈번한 컨텍스트 스위칭 (Context Switching, 기존 프로세스의 Context를 저장하고, 다음 프로세스를 실행할 수 있도록 Context를 교체하는 작업)이 발생하여 CPU 자원을 사용하고 잠식하는 현상이 초래한다.</h6>
<h3 id="예제-코드-2-remove（）적용-후">예제 코드 (2) remove（）적용 후</h3>
<pre><code class="language-java">import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadLocalRemoveAfter {

    private static final ExecutorService executorService = Executors.newFixedThreadPool(3);

    public static void main(String[] args) {
        for (int i = 0; i &lt; 5; i++) {
            Thread thread = new Thread(new ThreadLocalMyRunnable(true, i));
            executorService.execute(thread);
        }

        executorService.shutdown();
    }

}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/019f94c7-1910-47ab-a831-6a3ec89e13ab/image.png" alt=""></p>
<hr>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://dev.gmarket.com/62">G마켓 기술블로그 - Thread의 개인 수납장 ThreadLocal</a></li>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html">Java™ Platform, Standard Edition 8 API Specification</a></li>
<li><a href="https://hwannny.tistory.com/95">Thread Local 개념과 내부 구조</a></li>
<li><a href="https://catsbi.oopy.io/3ddf4078-55f0-4fde-9d51-907613a44c0d#3ddf4078-55f0-4fde-9d51-907613a44c0d">Catsbi&#39;s DLog - ThreadLocal을 알아보자!</a></li>
<li><a href="https://binux.tistory.com/152">ThreadLocal 사용 시, remove를 잊지 맙시다</a></li>
<li><a href="https://cheershennah.tistory.com/170">[java] Thread Pool 쓰레드 풀이란 ?</a></li>
<li><a href="https://velog.io/@bagt/%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%8A%A4%EB%A0%88%EB%93%9C%EC%99%80-context-switching">[CS] 멀티 프로세스/스레드와 context switching</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 07. 상속]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-07.-%EC%83%81%EC%86%8D</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-07.-%EC%83%81%EC%86%8D</guid>
            <pubDate>Fri, 08 Dec 2023 08:08:21 GMT</pubDate>
            <description><![CDATA[<h1 id="71-상속-개념">7.1 상속 개념</h1>
<ul>
<li>상속은 <code>부모가 자식에게 물려주는 행위</code>로 중복 코드를 줄여 개발 시간을 단축시키고, 클래스 수정을 최소화할 수 있다.</li>
</ul>
<h1 id="72-클래스-상속">7.2 클래스 상속</h1>
<ul>
<li>자식이 extends 키워드를 사용해 부모를 선택한다. *<span style="background-color: #ffffcc; color: #ff6666;">단, 다중 상속은 허용하지 않는다.</span>*<pre><code class="language-java">package ch07.sec02;
</code></pre>
</li>
</ul>
<p>public class Phone {</p>
<pre><code>public String model;
public String color;

public Phone() {
    System.out.println(&quot;부모 생성자 호출&quot;);
}

public void bell() {
    System.out.println(&quot;[부모] 벨이 울린다.&quot;);
}

public void hangup() {
    System.out.println(&quot;[부모] 전화를 끊습니다.&quot;);
}

public void sendVoice(String message) {
    System.out.println(&quot;[부모] &quot; + message);
}</code></pre><p>}</p>
<pre><code>&lt;hr&gt;

```java
package ch07.sec02;

public class SmartPhone extends Phone{
    public boolean wifi;

    public SmartPhone(String model, String color) {
        this.model = model;
        this.color = color;
    }

    public void setWifi(boolean wifi) {
        this.wifi = wifi;
        System.out.println(&quot;[자식] 와이파이 상태를 변경했습니다.&quot;);
    }
}
</code></pre><hr>

<pre><code class="language-java">package ch07.sec02;

public class SmartPhoneEx {
    public static void main(String[] args) {
        SmartPhone smartPhone = new SmartPhone(&quot;Galaxy&quot;, &quot;Gary&quot;);  // 부모 생성자 호출

        System.out.println(smartPhone.model);                      // Galaxy
        System.out.println(smartPhone.color);                      // Gary

        System.out.println(smartPhone.wifi);                       // false

        smartPhone.bell();                                         // [부모] 벨이 울린다.
        smartPhone.sendVoice(&quot;Hi~&quot;);                               // [부모] Hi~
        smartPhone.hangup();                                       // [부모] 전화를 끊습니다.

        smartPhone.setWifi(true);                                  // [자식] 와이파이 상태를 변경했습니다.
    }
}
</code></pre>
<h1 id="73-부모-생성자-호출">7.3 부모 생성자 호출</h1>
<ul>
<li>자식 객체를 생성하면 부모 객체가 먼저 생성된 다음에 자식 객체가 생성된다.</li>
<li><strong>부모 객체에 기본 생성자가 있다면</strong>, 자식 생성자의 맨 첫 줄에 컴파일 과정에서 자동으로 <code>super（）</code>가 추가된다.
만약, <strong>부모 클래스에 기본 생성자가 없고</strong> 매개변수를 갖는 생성자만 있다면 개발자가 직접 자식 생성자에 <code>super（매개값, …）</code>를 추가해줘야 한다.</li>
</ul>
<h2 id="1-부모클래스에-매개변수-갖는-생성자-추가">1) 부모클래스에 매개변수 갖는 생성자 추가</h2>
<pre><code class="language-java">package ch07.sec02;

public class Phone {

    public String model;
    public String color;

 //    public Phone() {
 //        System.out.println(&quot;부모 생성자 호출&quot;);
 //    }

    public Phone(String model, String color) {
        this.model = model;
        this.color = color;
        System.out.println(&quot;[부모] Phone(String model, String color) 생성자 호출&quot;);
    }

    // 코드 생략…

}
</code></pre>
<h5 id="컴파일-에러-발생--span-stylebackground-color-ffffcc-color-ff6666java-constructor-phone-in-class-ch07sec02phone-cannot-be-applied-to-given-typesspan">컴파일 에러 발생 : *<span style="background-color: #ffffcc; color: #ff6666;">java: constructor Phone in class ch07.sec02.Phone cannot be applied to given types;</span>*</h5>
<div align="center">
  <img src="https://velog.velcdn.com/images/sj_kim/post/7a37e643-d3b9-4f7e-96a4-de61470c88dd/image.png">
</div>

<h5 id="해결-방법">해결 방법</h5>
<pre><code class="language-java">    public SmartPhone(String model, String color) {
        super(model, color);
        this.model = model;
        this.color = color;
    }</code></pre>
<div align="center">
  <img src="https://velog.velcdn.com/images/sj_kim/post/83b90557-aeee-414a-8873-7044f76a03ff/image.png">
</div>

<h1 id="74-메서드-재정의">7.4 메서드 재정의</h1>
<h2 id="메서드-오버라이딩">메서드 오버라이딩</h2>
<ul>
<li><code>상속</code>된 메서드를 <code>자식 클래스에서 재정의</code>하는 것을 말한다.</li>
<li><strong>부모 메서드의 선언부(리턴 타입, 메서드명, 매개변수)와 동일해야 한다.</strong></li>
<li>접근 제한을 더 강하게 오버라이딩할 수 없다. <code>(public → private로 변경 불가)</code><ul>
<li>컴파일 에러 발생</li>
</ul>
</li>
<li><code>＠Override</code> 애노테이션을 붙이면 컴파일 단계에서 정확히 오버라이딩 되었는지 체크하고, 문제가 있다면 커파일 에러를 출력한다.<pre><code class="language-java">package ch07.sec02;
</code></pre>
</li>
</ul>
<p>public class SmartPhone extends Phone{
    public boolean wifi;</p>
<pre><code>public SmartPhone(String model, String color) {
    super(model, color);
    this.model = model;
    this.color = color;
}

public void setWifi(boolean wifi) {
    this.wifi = wifi;
    System.out.println(&quot;[자식] 와이파이 상태를 변경했습니다.&quot;);
}

@Override
public void bell() {
    super.bell();
    System.out.println(&quot;[자식] 벨이 울린다.&quot;);
}</code></pre><p>}</p>
<pre><code>&lt;hr&gt;

```java
package ch07.sec02;

public class SmartPhoneEx {
    public static void main(String[] args) {
        SmartPhone smartPhone = new SmartPhone(&quot;Galaxy&quot;, &quot;Gary&quot;);   // [부모] Phone(String model, String color) 생성자 호출
        smartPhone.bell();                                          // [자식] 벨이 울린다.
    }
}
</code></pre><h2 id="부모-메서드-호출">부모 메서드 호출</h2>
<ul>
<li><code>super</code> 키워드와 도트<code>.</code>연산자를 사용해 부모 클래스를 호출할 수 있다.<pre><code class="language-java">package ch07.sec02;
</code></pre>
</li>
</ul>
<p>public class SmartPhone extends Phone{
    // 코드 생략… </p>
<pre><code>@Override
public void bell() {
    super.bell();
    System.out.println(&quot;[자식] 벨이 울린다.&quot;);
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch07.sec02;

public class SmartPhoneEx {
    public static void main(String[] args) {
        SmartPhone smartPhone = new SmartPhone(&quot;Galaxy&quot;, &quot;Gary&quot;);   // [부모] Phone(String model, String color) 생성자 호출
        smartPhone.bell();                                          // [부모] 벨이 울린다. // [자식]벨이 울린다.
    }
}
</code></pre><h1 id="75-final-클래스와-final-메서드">7.5 final 클래스와 final 메서드</h1>
<h2 id="final-클래스">final 클래스</h2>
<ul>
<li>최종적인 클래스로 <code>더 이상 상속할 수 없다.</code> 즉, 부모 클래스가 될 수 없다.<pre><code class="language-java">package ch07.sec05.exam02;
</code></pre>
</li>
</ul>
<p>public final class Car {</p>
<p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch07.sec05.exam02;

public class SportsCar extends Car{   // 컴파일 에러 : Cannot inherit from final &#39;ch07.sec05.exam02.Car&#39;

}
</code></pre><h2 id="final-메서드">final 메서드</h2>
<ul>
<li>최종적인 메서드로 <code>오버라이딩할 수 없다.</code><pre><code class="language-java">package ch07.sec05.exam02;
</code></pre>
</li>
</ul>
<p>public class Car {</p>
<pre><code>public int speed;

public void SpeedUp() {
    speed += 1;
}

public final void stop() {
    System.out.println(&quot;차가 멈춥니다.&quot;);
    speed = 0;
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch07.sec05.exam02;

public class SportsCar extends Car{

    @Override
    public void SpeedUp() {
        speed += 10;
    }

    public final void stop() {  // 컴파일 에러 : &#39;stop()&#39; cannot override &#39;stop()&#39; in &#39;ch07.sec05.exam02.Car&#39;; overridden method is final
        System.out.println(&quot;차가 멈춥니다.&quot;);
        speed = 0;
    }
}
</code></pre><h1 id="76-protected-접근-제한자">7.6 protected 접근 제한자</h1>
<table>
<thead>
<tr>
<th>접근 제한자</th>
<th>제한 범위</th>
</tr>
</thead>
<tbody><tr>
<td><strong>public</strong></td>
<td>없음</td>
</tr>
<tr>
<td><strong>protected</strong></td>
<td>같은 패키지이거나 자식 객체만 사용 가능</td>
</tr>
<tr>
<td><strong>default</strong></td>
<td>같은 패키지</td>
</tr>
<tr>
<td><strong>private</strong></td>
<td>객체 내부</td>
</tr>
<tr>
<td>* 같은 패키지에서는 default처럼 접근이 가능하나, 다른 패키지에서는 자식 클래스만 접근을 허용한다.</td>
<td></td>
</tr>
<tr>
<td>```java</td>
<td></td>
</tr>
<tr>
<td>package ch07.sec06.package1;</td>
<td></td>
</tr>
</tbody></table>
<p>public class A {
    protected String field;</p>
<pre><code>protected A() {}

protected void method() {
    System.out.println(&quot;A 클래스입니다.&quot;);
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch07.sec06.package1;

public class B {

    public static void main(String[] args) {
        A a = new A();
        a.method(); // A 클래스입니다.
    }
}
</code></pre><hr>

<pre><code class="language-java">package ch07.sec06.package2;


import ch07.sec06.package1.A;

public class C extends A {

    public C() {
        super();    // 생략 가능
    }

    public void method1() {
        this.method();
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec06.package2;

public class D {

    public static void main(String[] args) {
        C c = new C();
        c.method1();    // A 클래스입니다.
    }
}
</code></pre>
<h1 id="77-타입-변환">7.7 타입 변환</h1>
<ul>
<li>클래스의 타입 변환은 <code>상속 관계</code>에 있는 클래스 사이에서 발생한다.</li>
</ul>
<h2 id="자동-타입-변환">자동 타입 변환</h2>
<ul>
<li>자식은 부모와 동일하게 취급될 수 있다.<pre><code class="language-java">package ch07.sec07.exam01;
</code></pre>
</li>
</ul>
<p>public class Parent {
    public Parent() {}</p>
<pre><code>public void method01() {
    System.out.println(&quot;Parent - method01()&quot;);
}

public void method02() {
    System.out.println(&quot;Parent - method02()&quot;);
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch07.sec07.exam01;

public class Child extends Parent {

    public Child() {}

    @Override
    public void method01() {
        System.out.println(&quot;@Override : Child - method01()&quot;);
    }

    public void method03() {
        System.out.println(&quot;Child - method03()&quot;);
    }
}
</code></pre><hr>

<pre><code class="language-java">package ch07.sec07.exam01;

public class Ex01 {

    public static void main(String[] args) {
        Parent parent = new Child();   // 자동 타입 변환

        parent.method01();             // @Override : Child - method01()
        // parent.method03();  // 컴파일 에러 : Cannot resolve method &#39;method03&#39; in &#39;Parent&#39;

        Child child = new Child();
        Parent parent1 = child;

        System.out.println(parent1 == child);   // true

    }
}

</code></pre>
<ul>
<li>부모타입으로 자동 타입 변환된 후에는 <strong>부모 클래스에 선언된 필드와 메서드만 접근이 가능하다.</strong></li>
<li><span style="background-color: #ffffcc; color: #ff6666;">단, 자식 클래스에서 오버라이딩된 메서드가 있다면 부모 메서드 대신 오버라이딩된 메서드가 호출된다.</span>*</li>
</ul>
<h2 id="강제-타입-변환">강제 타입 변환</h2>
<ul>
<li>부모 타입은 자식 타입으로 자동 변환되지 않기 때문에 강제 타입 변환을 해야 한다.
단, <code>자식 → 부모</code> 타입 변환 후 <strong>다시</strong> <code>부모 → 자식</code><strong>으로 변환할 때만</strong> 사용할 수 있다.<pre><code class="language-java">package ch07.sec07.exam01;
</code></pre>
</li>
</ul>
<p>public class Ex01 {</p>
<pre><code>public static void main(String[] args) {
    // Child child = (Child) new Parent(); // 런타임 에러 : ClassCastException Exception

    Parent parent = new Child();
    Child child = (Child) parent;
    child.method03();   // Child - method03()
}</code></pre><p>}</p>
<pre><code>
# 7.8 다형성
* 사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질
## 필드 다형성
* 필드 타입은 동일하지만 대입되는 객체가 달라져 실행 결과가 다양하게 나올 수 있는 것
```java
package ch07.sec08.exam;

public class Chef {

    public Menu menu;

    public void cook() {
        menu.make();
    }

    public void order(Menu menu) {
        menu.prepare();
    }
}

</code></pre><hr>

<pre><code class="language-java">package ch07.sec08.exam;

public class Menu {

    public void make() {
        System.out.println(&quot;요리하다&quot;);
    }

    public void prepare() {
        System.out.println(&quot;메뉴를 준비하다&quot;);
    }
}

</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec08.exam;

public class KoreanFood extends Menu {

    @Override
    public void make() {
        System.out.println(&quot;한식을 요리하다&quot;);
    }

    @Override
    public void prepare() {
        System.out.println(&quot;한식을 준비하다&quot;);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec08.exam;

package ch07.sec08.exam;

public class WesternFood extends Menu {

    @Override
    public void make() {
        System.out.println(&quot;양식을 요리하다&quot;);
    }

    @Override
    public void prepare() {
        System.out.println(&quot;양식을 준비하다&quot;);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec08.exam;

public class Ex {

    public static void main(String[] args) {
        Chef chef = new Chef();

        chef.menu = new Menu();
        chef.cook();                    // 요리하다

        chef.menu = new KoreanFood();
        chef.cook();                    // 한식을 요리하다

        chef.menu = new WesternFood();
        chef.cook();                    // 양식을 요리하다
    }
}


</code></pre>
<p>*<span style="background-color: #ffffcc; color: #ff6666;">어떤 객체가(e.g. Menu, KoreanFood, WesternFood) 대입됐는지에 따라 <strong>cook（）의 실행 결과가 달라지게 된다.</strong></span>*</p>
<h2 id="매개변수-다형성">매개변수 다형성</h2>
<ul>
<li>메서드가 클래스 타입의 매개변수를 가지고 있으면, 같은 타입의 객체뿐만 아니라 자식 객체를 제공할 수 있다.<pre><code class="language-java">package ch07.sec08.exam;
</code></pre>
</li>
</ul>
<p>public class Ex {</p>
<pre><code>public static void main(String[] args) {
    Chef chef = new Chef();

    Menu menu = new Menu();
    chef.order(menu);          // 메뉴를 준비하다

    KoreanFood koreanFood = new KoreanFood();
    chef.order(koreanFood);    // 한식을 준비하다

    WesternFood westernFood = new WesternFood();
    chef.order(westernFood);   // 양식을 준비하다
}</code></pre><p>}</p>
<pre><code>*&lt;span style=&quot;background-color: #ffffcc; color: #ff6666;&quot;&gt;어떤 객체가(e.g. Menu, KoreanFood, WesternFood) 대입됐는지에 따라 **order（）의 실행 결과가 달라지게 된다.**&lt;/span&gt;*

# 7.9 객체 타입 확인
* `instanceof` 연산자 사용
* 어떤 객체가 매개값으로 제공되었는지 확인하거나 변수가 참조하는 객체의 타입을 확인하고자 할 때 사용
```java
package ch07.sec08.exam;

public class Ex {

    public static void menuInfo(Menu menu) {
        if (menu instanceof KoreanFood food) {
            KoreanFood koreanFood = (KoreanFood) menu;
            koreanFood.prepare();
//            food.prepare(); // java 12부터
        } else if (menu instanceof WesternFood food) {
            WesternFood westernFood = (WesternFood) menu;
            westernFood.prepare();
//            food.prepare(); // java 12부터
        }
    }

    public static void main(String[] args) {
        Menu koreanMenu = new KoreanFood();
        Menu westernMenu = new WesternFood();

        System.out.println(koreanMenu instanceof KoreanFood);       // true
        System.out.println(westernMenu instanceof WesternFood);     // true

        System.out.println(koreanMenu instanceof  WesternFood);     // false
        System.out.println(westernMenu instanceof  KoreanFood);     // false

        menuInfo(koreanMenu);    // 한식을 준비하다
        menuInfo(westernMenu);   // 양식을 준비하다
    }
}
</code></pre><div>
  <img src="https://velog.velcdn.com/images/sj_kim/post/b1838955-9eb8-443c-ada8-d9cca28eedcd/image.png">
  <ul>
    <li>객체가 타입이면 true, 그렇지 않으면 false</li>
    <li>자바 12부터는 instanceof 연산의 결과가 true일 경우, 우측 타입 변수를 바로 사용할 수 있다. <br>따라서 강제 타입 변환이 필요 없다.</li>
  </ul>
</div>

<h1 id="710-추상-클래스">7.10 추상 클래스</h1>
<ul>
<li>객체를 생성할 수 있는 클래스들의 <code>공통적인 필드나 메서드를 추출</code>해서 선언한 클래스로 new 연산자를 사용해 객체를 직접 생성할 수 없다.</li>
<li>추상 클래스는 객체를 생성할 수 있는 <code>클래스의 부모 역할만</code>을 한다.</li>
</ul>
<h2 id="추상-클래스-선언">추상 클래스 선언</h2>
<ul>
<li>클래스 선언 시 <code>abstract 키워드</code>를 붙이면 추상 클래스가 된다.<pre><code class="language-java">package ch07.sec10.exam01;
</code></pre>
</li>
</ul>
<p>public abstract class Phone {
    // 필드 선언
    String owner;</p>
<pre><code>// 생성자 선언
public Phone(String owner) {
    this.owner = owner;
}

//메서드 선언
void turnOn() {
    System.out.println(&quot;전원 ON&quot;);
}

void turnOff() {
    System.out.println(&quot;전원 OPF&quot;);
}

public abstract  void sound();</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch07.sec10.exam01;

public class SmartPhone extends Phone{
    public SmartPhone(String owner) {
        super(owner);
    }

    void internetSearch() {
        System.out.println(&quot;인터넷 검색을 하다.&quot;);
    }

    @Override
    public void sound() {
        System.out.println(&quot;삐리리리~&quot;);
    }
}

</code></pre><hr>

<pre><code class="language-java">package ch07.sec10.exam01;

public class PhoneEx {

    public static void main(String[] args) {

        // Phone phone = new Phone();  // 컴파일 에러 : &#39;Phone&#39; is abstract; cannot be instantiated

        SmartPhone smartPhone = new SmartPhone(&quot;홍길동&quot;);
        smartPhone.turnOn();            // 전원 ON
        smartPhone.turnOff();           // 전원 OPF
        smartPhone.internetSearch();    // 인터넷 검색을 하다.
        smartPhone.sound();             // 삐리리리~
    }
}

</code></pre>
<h2 id="추상-메서드와-재정의">추상 메서드와 재정의</h2>
<ul>
<li>추상 메서드란 abstract 키워드가 붙고, 메서드 실행 내용인 중괄호가 <code>｛｝</code>가 없다.</li>
<li>추상 메서드는 자식 클래스의 공통 메서드라는 것만 정의할 뿐, 실행 내용을 가지지 않는다.</li>
<li>추상 메서드는 자식 클래스에서 반드시 재정의(오버라이딩)해서 실행 내용을 채워야 한다.</li>
</ul>
<h1 id="711-봉인된-클래스">7.11 봉인된 클래스</h1>
<ul>
<li>Java 15부터 도입된 봉인된(sealed) 클래스는 무분별한 자식 클래스 생성을 방지한다.</li>
<li><code>sealed</code> 키워드를 사용하면 <code>permits</code> 키워드 뒤에 상속 가능한 자식 클래스를 지정해야 한다.</li>
<li>자식 클래스는 final, non-sealed, selaed 중 하나의 유형으로 선언되어야 한다.</li>
</ul>
<pre><code class="language-java">package ch07.sec10.exam02;

public sealed class Person permits Employee, Manager, Owner{

    public void work() {
        System.out.println(&quot;하는 일이 결정되지 않았습니다.&quot;);
    }
}
</code></pre>
<hr>

<ul>
<li>final 키워드는 더 이상 상속할 수 없다.<pre><code class="language-java">package ch07.sec10.exam02;
</code></pre>
</li>
</ul>
<p>public final class Employee extends Person {</p>
<pre><code>@Override
public void work() {
    System.out.println(&quot;제품을 생산합니다.&quot;);
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

* non-sealed 키워드는 봉인을 해제한다는 뜻으로, 자식 클래스를 만들 수 있다.

```java
package ch07.sec10.exam02;

public non-sealed class Manager extends Person {
    @Override
    public void work() {
        System.out.println(&quot;생산을 관리합니다.&quot;);
    }
}
</code></pre><hr>

<pre><code class="language-java">package ch07.sec10.exam02;

public class SalesManager extends Manager{
    @Override
    public void work() {
        System.out.println(&quot;영업을 관리합니다.&quot;);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec10.exam02;

public sealed class Owner extends Person permits Company { // sealed, non-sealed or final modifiers expected

    @Override
    public void work() {
        System.out.println(&quot;회사를 운영합니다.&quot;);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec10.exam02;

public final class Company extends Owner {
    String name;

    public Company(String name) {
        this.name = name;
    }

    public void operate() {
        System.out.println(this.name + &quot; 회사가 운영 중입니다.&quot;);
    }
}
</code></pre>
<hr>

<pre><code class="language-java">package ch07.sec10.exam02;

public class SealedEx {

    public static void main(String[] args) {
        Person person = new Person();
        person.work();          // 하는 일이 결정되지 않았습니다.

        Employee employee = new Employee();
        employee.work();        // 제품을 생산합니다.

        Manager manager = new Manager();
        manager.work();         // 생산을 관리합니다.

        SalesManager salesManager = new SalesManager();
        salesManager.work();    // 영업을 관리합니다.

        Owner owner = new Owner();
        owner.work();           // 회사를 운영합니다.

        Company company = new Company(&quot;화장품&quot;);
        company.operate();      // 화장품 회사가 운영 중입니다.

    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/f778514e-78c1-418d-93a2-c5dfaf585231/image.png" alt=""></p>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JVM] Runtime Data Area]]></title>
            <link>https://velog.io/@sj_kim/JVM-Runtime-Data-Area</link>
            <guid>https://velog.io/@sj_kim/JVM-Runtime-Data-Area</guid>
            <pubDate>Mon, 04 Dec 2023 09:38:53 GMT</pubDate>
            <description><![CDATA[<h1 id="runtime-data-area-구조">Runtime Data Area 구조</h1>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/e0443927-5e0a-4bc1-aefd-4cfcb8fa1c47/image.png" alt=""></p>
<ul>
<li>JVM이 프로그램을 수행하기 위해 운영체제로부터 할당받은 메모리 영역으로 크게 5가지 영역으로 나뉜다.</li>
</ul>
<h2 id="1-method-area">1) Method Area</h2>
<ul>
<li><code>모든 스레드가 공유하는 메모리 공간</code>으로, *<span style="color: #ff6666">로드된 클래스와 인터페이스의 메타데이터</span><em>와 *<span style="color: #ff6666">런타임 상수풀</span></em>(Runtime Constant Pool), *<span style="color: #ff6666">정적 멤버</span>*(static)등이 저장된다.</li>
<li><code>Reflection API</code> 사용해 Method 영역에 있는 클래스 정보에 접근할 수 있다.</li>
</ul>
<blockquote>
<p>💡 <strong>Reflection</strong></p>
</blockquote>
<ul>
<li>구체적인 클래스 타입을 알지 못해도 클래스의 생성자, 메서드, 변수 등에 접근할 수 있도록 도와주는 Java 기본 API</li>
</ul>
<blockquote>
<p>💡 <strong>Runtime Constant Pool</strong></p>
</blockquote>
<ul>
<li>리터럴 상수뿐만 아니라 클래스와 인터페이스명, 메서드 및 필드명 등을 저장하고, 상수에 대한 참조를 나타낸다.</li>
<li>*<span style="background-color: #ffffcc; color: #ff6666;">즉, 프로그램이 실행되는 동안 변하지 않는 값들이 저장된다.</span>**</li>
<li>인덱스 1부터 시작해 상수에 대한 참조를 나타낸다.</li>
</ul>
<pre><code class="language-java">public class Example {

    public static void main(String []args) {
        System.out.println(&quot;Hello, world&quot;);
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/0b95ee3e-e779-4e9f-9ad5-88913702af0f/image.png" alt=""></p>
<ul>
<li><code>#n</code>은 상수 풀에 대한 참조를 나타낸다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;">3: ldc # 13 // String Hello, world</span> 라인에서 <code>ldc</code>는 <code>load constant</code>의 약자로,
상수풀에서 상수를 로드할 때 사용하는 명령어이다.</li>
</ul>
<h2 id="2-heap-area">2) Heap Area</h2>
<ul>
<li><p><code>모든 스레드가 공유하는 메모리 공간</code>으로 객체를 생성할 때마다 메모리 공간이 할당된다.</p>
</li>
<li><p><span style="background-color: #ffffcc; color: #ff6666; padding-bottom: 0;">따라서, dead code(실행되지 않는 코드)라면 힙 영역에 할당되지 않는다.</span>*</p>
</li>
<li><p><code>참조 타입(Reference type)</code>이 Heap 영역에 저장되는 이유는 객체가 동적으로 생성되고 내부 참조 크기가 동적으로 변하기 때문이다.</p>
<p>구분 | 32-bit JVM | 64-bit JVM</p>
</li>
<li><p>-- | --- | ---
내부 참조 크기<sup><a href="#footnote_1">1</a></sup> | 4 bytes | 8 bytes
최대 메모리 공간<sup><a href="#footnote_2">2</a></sup> | $$2^{32}$$ |$$2^{64}$$</p>
</li>
</ul>
<h6 id="a-namefootnote_11a-참조-타입-크기"><a name="footnote_1">1</a>: 참조 타입 크기</h6>
<h6 id="a-namefootnote_22a-전체-힙-메모리-크기"><a name="footnote_2">2</a>: 전체 힙 메모리 크기</h6>
<ul>
<li>GC(Garbage Collection)의 대상이 된다.</li>
<li>Heap 메모리 공간이 부족하면 <code>Java.lang.OutOfMemoryError : java heap space</code> 에러가 발생한다.
공간 부족의 원인은 <code>Heap 메모리 공간의 크기가 작거나</code> <code>애플리케이션 로직 문제</code>로 발생하는 경우가 있다.</li>
</ul>
<h4 id="oomejava-langoutofmemoryerror-해결-방법">OOME(java. lang.OutOfMemoryError) 해결 방법</h4>
<ul>
<li>Heap 메모리 공간은 <code>-Xms</code>(초기 힙 크기), <code>-Xmx</code>(최대 힙 크기) 옵션을 사용해 제어 가능하다.</li>
<li>OOME 발생 시점에 생성된 Heap Dump를 분석해 메모리 누수를 유발하는 로직을 수정한다.</li>
</ul>
<blockquote>
<p>💡 <strong>idea64.exe.vmoptions</strong></p>
</blockquote>
<ul>
<li>IntelliJ IDEA 실행 시 JVM 옵션을 주는 파일
<img src="https://velog.velcdn.com/images/sj_kim/post/d79fce18-40a3-4d31-aa89-5e5ddf345bc5/image.png" alt="IntelliJ IDEA 실행 시 JVM 옵션을 주는 파일" title="IntelliJ IDEA 실행 시 JVM 옵션을 주는 파일"></li>
</ul>
<h2 id="3-stack-area">3) Stack Area</h2>
<ul>
<li><code>메서드 호출 정보를 저장하는 공간</code>으로 각 스레드(Thread)별로 생성된다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;">단, 다른 스레드 간 접근은 불가하다.</span>*</li>
<li>스택(Stack)의 수명은 스레드의 수명에 따라 달라지며, 스레드가 살아있으면 스택도 살아있게 되고 그 반대의 경우도 마찬가지이다.</li>
<li>메서드가 호출될 때 마다 새로운 프레임(<code>Frame</code>)이 *<span style="background-color: #ffffcc; color: #ff6666;">호출 스택(Call Stack)<sup><a href="#footnote_3">3</a></sup></span>*에 추가(<code>Push</code>)되고, 메서드가 종료되면 해당 프레임이 스택에서 제거(<code>Pop</code>) 된다.</li>
</ul>
<h6 id="a-namefootnote_33a-메서드-호출을-기록하는-스택-자료구조"><a name="footnote_3">3</a>: 메서드 호출을 기록하는 스택 자료구조</h6>
<ul>
<li>지정한 Stack 메모리 크기보다 더 많은 메모리를 사용하게 되면 <code>Java.lang.StackOverFlowError</code> 에러가 발생한다.
원인은 <code>재귀함수</code>를 사용하거나 <code>상호 참조(본인참조 포함)</code> 문제로 발생하는 경우가 있다.</li>
</ul>
<h4 id="stack-overflow-해결-방법">Stack Overflow 해결 방법</h4>
<ul>
<li>재귀함수 호출 시 이전의 호출한 스택 메모리를 종료시킬 수 있도록 하면 된다. *<span style="background-color: #ffffcc; color: #ff6666;">즉, 다음 함수 호출시 현재 함수의 결과 값을 전달하면 된다.</span>*</li>
<li>참조 시 클래스 내에서 인스턴스를 직접 생성하지 않고 주입을 통해 인스턴스를 생성하면 된다.</li>
</ul>
<blockquote>
<p>💡 <strong>Thread</strong></p>
</blockquote>
<ul>
<li>프로세스(<code>process: 실행 중인 프로그램</code>) 내에서 실제로 작업을 수행하는 주체이자 실행 단위</li>
</ul>
<p><img src="https://github.com/suji3927/rrs/assets/47530310/b0afecf5-38ca-4504-8eb8-7a21fa272e35" alt=""></p>
<blockquote>
<p>💡 <strong>Frame</strong></p>
</blockquote>
<ul>
<li>메서드 호출에 대한 정보를 저장 (매개변수 및 지역변수, 리턴 값 등)</li>
</ul>
<h2 id="4-pc-registers">4) PC Registers</h2>
<ul>
<li><code>스레드의 현재 수행 중인 명령어의 주소를 저장하는 공간</code>으로, 각 스레드(Thread)별로 생성된다.</li>
</ul>
<h2 id="5-native-method-stacks">5) Native Method Stacks</h2>
<ul>
<li>자바이외의 언어로 작성된 네이티브 코드를 위한 스택으로, JNI(Java Native Interface)를 통해 호출하는 C, C++ 등의 코드를 수행하기 위한 스택</li>
</ul>
<blockquote>
<p>💡 <strong>JNI(Java Native Interface)</strong></p>
</blockquote>
<ul>
<li>JVM 위에서 실행되고 있는 <code>자바코드</code>가 <code>다른 언어들(C, C++ 등)로 작성된 라이브러리</code>들을 <code>호출</code>하거나 반대로 <code>호출되는 것을 가능하게</code> 하는 프로그래밍 프레임워크</li>
</ul>
<hr>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://www.baeldung.com/jvm-constant-pool">Baeldung - An Introduction to the Constant Pool in the JVM</a></li>
<li><a href="https://www.geeksforgeeks.org/difference-between-32-bit-and-64-bit-jvm-in-java/">Baeldung - Difference Between 32-bit and 64-bit JVM in Java</a></li>
<li><a href="https://devm.io/java/jvm-32-64-bit-163278-002">devmio - Does 32-bit or 64-bit JVM matter anymore?</a></li>
<li><a href="https://dataonair.or.kr/db-tech-reference/d-lounge/technical-data/?mod=document&amp;uid=235931">한국데이터산업진흥원 - OOME의 종류 및 분석</a></li>
<li><a href="https://inpa.tistory.com/entry/IntelliJ-%F0%9F%92%BD-JVM-%ED%9E%99-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%82%AC%EC%9D%B4%EC%A6%88-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0">IntelliJ - JVM 힙 메모리 사이즈 변경하기</a></li>
<li><a href="https://www.hackerearth.com/practice/notes/runtime-data-areas-of-java">hackerearth - Runtime Data Areas Of Java</a></li>
<li><a href="https://transferhwang.tistory.com/150">[JAVA] 자바 리플렉션(Java Reflection)</a></li>
<li><a href="https://incheol-jung.gitbook.io/docs/q-and-a/java/stw">스택 오버 플로우(SOF)</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 06. 클래스]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-06.-%ED%81%B4%EB%9E%98</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-06.-%ED%81%B4%EB%9E%98</guid>
            <pubDate>Tue, 28 Nov 2023 13:21:43 GMT</pubDate>
            <description><![CDATA[<h1 id="61-객체-지향-프로그래밍">6.1 객체 지향 프로그래밍</h1>
<ul>
<li><code>객체</code>를 먼저 만들고, 이 객체를 조립해 프로그램을 만드는 기법</li>
</ul>
<h2 id="1-객체란">1) 객체란?</h2>
<ul>
<li>다른 것과 식별 가능한 것</li>
<li>객체는 <code>속성(=필드)</code>과 <code>동작(=메서드)</code>으로 구성된다.</li>
<li><code>현실 세계</code>의 객체를 <code>소프트웨어 객체</code>로 설계하는 것을 <span style="background-color: #ffffcc; color: #ff6666;"><em>객체 모델링</em></span>이라고 한다.</li>
</ul>
<h2 id="2-객체의-상호작용">2) 객체의 상호작용</h2>
<ul>
<li>객체들은 다른 객체와 서로 상호작용하면서 동작한다.</li>
<li><code>메서드</code>는 객체들 사이의 상호작용 수단이다.
즉, 메서드 호출을 통해 객체들은 <code>데이터</code>를 서로 주고받는다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;"><em>매개값</em></span>은 메서드가 실행할 때 필요한 값이다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;"><em>리턴값</em></span>은 메서드의 실행 결과이며, 호출한 곳으로 돌려주는 값이다.</li>
</ul>
<h2 id="3-객체-간의-관계">3) 객체 간의 관계</h2>
<ul>
<li>관계의 종류에는 <code>집합 관계</code>, <code>사용 관계</code>, <code>상속관계</code>가 있다.</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>집합 관계</strong></td>
<td>완성품과 부품의 관계</td>
</tr>
<tr>
<td><strong>사용 관계</strong></td>
<td>다른 객체의 필드를 읽고 변경하거나 메서드를 호출하는 관계</td>
</tr>
<tr>
<td><strong>상속 관계</strong></td>
<td>부모와 자식 관계</td>
</tr>
</tbody></table>
<h2 id="4-객체-지향-프로그래밍의-특징">4) 객체 지향 프로그래밍의 특징</h2>
<h3 id="①-캡슐화">① 캡슐화</h3>
<ul>
<li>필드와 메서드를 하나로 묶고 <code>실제 구현 내용을 외부에 감추는 것</code></li>
<li>필드와 메서드를 보호하는 이유는 외부의 잘못된 사용으로 객체가 손상되는 것을 방지하기 위해서이다.</li>
<li>자바는 <span style="background-color: #ffffcc; color: #ff6666;"><em>접근제한자</em></span>를 사용해 캡슐화된 멤버의 노출 여부를 결정한다.</li>
</ul>
<h3 id="②-상속">② 상속</h3>
<ul>
<li>부모 역할의 상위 객체와 자식 역할의 하위 객체가 있다.</li>
<li>부모 객체는 자신의 <code>필드</code>와 <code>메서드</code>를 자식 객체에게 물려주어 사용할 수 있도록 한다.</li>
<li>부모 객체의 필드와 메서드를 그대로 사용할 수 있어 자식 객체에서는 중복 코딩을 하지 않아도 되어 <code>코드의 재사용성</code>을 높아준다.</li>
<li>부모 객체의 필드와 메서드를 수정하면 자식 객체들은 수정된 필드와 메서드를 그대로 사용할 수 있어 <code>유지 보수 시간을 최소화</code>시켜 준다.</li>
</ul>
<h3 id="③-다형성">③ 다형성</h3>
<ul>
<li>사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질</li>
<li>다형성을 구현하기 위해서는 <code>자동 타입 변환</code>과 <code>재정의</code> 기술이 필요한데, 상속과 인터페이스 구현으로 얻어진다.</li>
</ul>
<h1 id="62-객체와-클래스">6.2 객체와 클래스</h1>
<ul>
<li>객체를 생성할 때 <code>설계도</code>에 해당하는 <span style="background-color: #ffffcc; color: #ff6666;"><em>클래스</em></span>가 필요하다.</li>
<li>클래스로부터 생성된 객체를 해당 클래스의 <span style="background-color: #ffffcc;  color: #ff6666;"><em>인스턴스</em></span>라고 부른다.</li>
<li><span style="background-color: #ffffcc; color: #ff6666;"><em>인스턴스화</em></span>는 클래스로부터 객체를 만드는 과정을 뜻한다.
<img src="https://velog.velcdn.com/images/sj_kim/post/e29b636b-4207-466e-9a76-9b1733b79eca/image.png" alt=""></li>
</ul>
<h1 id="63-클래스-선언">6.3 클래스 선언</h1>
<ul>
<li>객체 생성을 위한 설계도를 작성하는 작업</li>
<li>클래스명은 <code>첫 문자를 대문자</code>로 하고 캐멀 스타일로 작성한다.</li>
<li>하나의 소스 파일에 복수 개의 클래스를 선언할 때 <code>소스 파일명과 동일한 클래스만 공개 클래스로</code> 선언할 수 있다. 따라서, Tire 클래스도 공개 클래스로 선언하고 싶다면 별도의 파일로 생성해야 한다.
<img src="https://velog.velcdn.com/images/sj_kim/post/bbd96450-5191-4240-bc7f-3b847a2fce04/image.png" alt=""></li>
</ul>
<h1 id="64-객체-생성과-클래스-변수">6.4 객체 생성과 클래스 변수</h1>
<ul>
<li>객체 생성 연산자인 <code>new</code> 연산자와 생성자 호출 코드인<code>&#39;클래스（）&#39;</code>를 통해 객체를 생성하고 객체의 주소를 리턴한다. 
<code>클래스 변수 = new 클래스（）</code></li>
</ul>
<h1 id="65-클래스의-구성-멤버">6.5 클래스의 구성 멤버</h1>
<blockquote>
</blockquote>
<div align="center">
  <img src="https://velog.velcdn.com/images/sj_kim/post/9303d224-a4d3-41e3-8ae0-09157f53fea7/image.png">
</div>

<p><span style="color:#04B486"><em>출처👉[이것이자바다] 6.5 클래스의 구성 멤버</em></span></p>
<h2 id="1-필드">1) 필드</h2>
<ul>
<li>객체의 데이터를 저장하는 역할</li>
</ul>
<h2 id="2-생성자">2) 생성자</h2>
<ul>
<li>new 연산자로 객체를 생성할 때 객체의 초기화 역할을 담당</li>
</ul>
<h2 id="3-메서드">3) 메서드</h2>
<ul>
<li>메서드는 객체가 수행할 동작</li>
</ul>
<h1 id="66-필드-선언과-사용">6.6 필드 선언과 사용</h1>
<ul>
<li><p><code>클래스 블록에서 선언</code>되어야만 필드 선언이 된다.</p>
</li>
<li><p>초기값을 제공하지 않을 경우 필드는 객체 생성 시 자동으로 기본값으로 초기화된다.</p>
<pre><code class="language-java">public class Car {
  String model = &quot;Hyundai&quot;;
  String color;

  int speed;
</code></pre>
</li>
</ul>
<p>}</p>
<pre><code>&lt;hr&gt;

```java
public class CarEx {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.model);  // Hyundai
        System.out.println(car.color);  // null
        System.out.println(car.speed);  // 0
    }
}
</code></pre><h2 id="1-필드-사용">1) 필드 사용</h2>
<ul>
<li><p>클래스로부터 객체가 생성된 후 필드 값을 읽고 변경하는 것이 가능하다.</p>
</li>
<li><p>도트<code>.</code> 객체 접근 연산자로 필드를 읽고 변경할 수 있다.</p>
<pre><code class="language-java">public class CarEx {
  public static void main(String[] args) {
      Car car = new Car();
      System.out.println(car.model);  // Hyundai

      car.model = &quot;Tesla&quot;;
      System.out.println(car.model);  // Tesla
  }
}
</code></pre>
</li>
</ul>
<pre><code>
# 6.7 생성자 선언과 호출
* `new 연산자`는 객체를 생성한 후 `생성자를 호출`해 객체를 초기화한다.
* `객체 초기화`란 객체를 사용할 준비를 하는 것

## 1) 기본 생성자
* 모든 클래스는 기본 생성자가 존재하며, 하나 이상 가질 수 있다.
* `클래스에 생성자 선언이 없으면`, `컴파일러`는 `기본 생성자`를 바이트 코드 파일에 `자동으로 추가`시킨다.
* 개발자가 명시적으로 선언한 생성자가 있다면 `기본생성자를 추가하지 않는다`.
![](https://velog.velcdn.com/images/sj_kim/post/a9d3101a-482f-4f46-b979-1d3715317ea8/image.png)
&lt;hr&gt;

![](https://velog.velcdn.com/images/sj_kim/post/a7b354b5-6852-4843-b5b7-20a5c8ac9e55/image.png)

## 2) 생성자 선언
* 생성자는 리턴 타입이 없고 클래스 이름과 동일하다.

## 3) 필드 초기화
* 필드 선언 시 초기값을 대입하는 것이 가능하다.
* 생성자의 매개변수명이 필드명과 동일하기 때문에 `this` 키워드를 필드명 앞에 붙여준다.
`this` 키워드는 `현재 객체`를 뜻한다.
```java
public class Car {
    String model = &quot;Hyundai&quot;;
    String color;

    int speed;

    public Car(String model, String color, int speed) {
        this.model = model;
        this.color = color;
        this.speed = speed;
    }
}
</code></pre><h2 id="4-생성자-오버로딩">4) 생성자 오버로딩</h2>
<ul>
<li><p><code>생성자 오버로딩</code>이란 매개변수를 달리하는 생성자를 여러 개 선언하는 것. (매개변수의 타입, 개수, 순서가 다르다.)
<span style="background-color: #ffffcc; color: #ff6666;"><em>단, 매개변수의 타입과 개수, 순서가 동일한데 매개변수명만 바꾸는 것은 생성자 오버로딩이 아니다.</em></span></p>
<pre><code class="language-java">public class Car {
  String model = &quot;Hyundai&quot;;
  String color;

  int speed;

  public Car() {
  }

  public Car(String model) {
      this.model = model;
  }

  public Car(String model, String color) {
      this.model = model;
      this.color = color;
  }

  public Car(String model, String color, int speed) {
      this.model = model;
      this.color = color;
      this.speed = speed;
  }
}
</code></pre>
</li>
</ul>
<pre><code>&lt;hr&gt;

```java
public class CarEx {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.model);  // Hyundai

        Car car3 = new Car(&quot;Chevrolet&quot;);
        System.out.println(car3.model); // Chevrolet
        System.out.println(car3.color); // null
        System.out.println(car3.speed); // 0

        Car car2 = new Car(&quot;BMW&quot;, &quot;green&quot;);
        System.out.println(car2.model); // BMW
        System.out.println(car2.color); // green
        System.out.println(car2.speed); // 0

        Car car1 = new Car(&quot;Kia&quot;, &quot;red&quot;, 120);
        System.out.println(car1.model); // Kia
        System.out.println(car1.color); // red
        System.out.println(car1.speed); // 120
    }
}

</code></pre><h2 id="5-다른-생성자-호출">5) 다른 생성자 호출</h2>
<ul>
<li><p>생성자 오버로딩이 많아지면 생성자 간 중복 코드가 발생한다.
이 경우에는 공통 코드를 한 생성자에 집중시키고, 나머지 생성자는 <code>this（）</code>를 사용해
공통 코드 생성자를 호출하는 방법으로 개선할 수 있다.</p>
</li>
<li><p><code>this</code>는 생성자의 첫 줄에 작성되며 다른 생성자를 호출하는 역할</p>
<pre><code class="language-java">public class Car {
  String model = &quot;Hyundai&quot;;
  String color;

  int speed;

  public Car() {
  }

  public Car(String model) {
      this(model, &quot;gray&quot;, 200);
  }

  public Car(String model, String color) {
      this(model, color, 170);
  }

  public Car(String model, String color, int speed) {
      this.model = model;
      this.color = color;
      this.speed = speed;
  }
}
</code></pre>
</li>
</ul>
<pre><code>
&lt;hr&gt;

```java
public class CarEx {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.model);  // Hyundai

        Car car3 = new Car(&quot;Chevrolet&quot;);
        System.out.println(car3.model); // Chevrolet
        System.out.println(car3.color); // gray
        System.out.println(car3.speed); // 200

        Car car2 = new Car(&quot;BMW&quot;, &quot;green&quot;);
        System.out.println(car2.model); // BMW
        System.out.println(car2.color); // green
        System.out.println(car2.speed); // 170

        Car car1 = new Car(&quot;Kia&quot;, &quot;red&quot;, 120);
        System.out.println(car1.model); // Kia
        System.out.println(car1.color); // red
        System.out.println(car1.speed); // 120
    }
}
</code></pre><h1 id="68-메서드-선언과-호출">6.8 메서드 선언과 호출</h1>
<ul>
<li><code>메서드 선언</code>은 객체의 동작을 실행 블록으로 정의하는 것</li>
<li><code>메서드 호출</code>은 실행 블록을 실제 실행하는 것
<img src="https://velog.velcdn.com/images/sj_kim/post/f2b0a8f0-6dea-4e5f-8b03-cafd7efbafdb/image.png" alt=""></li>
</ul>
<h2 id="1-리턴-타입">1) 리턴 타입</h2>
<ul>
<li>호출한 곳으로 전달하는 <code>결과값의 타입</code></li>
<li>리턴 타입이 있는 메서드는 반드시 실행 블록 안에 <code>return</code> 문을 지정해야 한다.</li>
<li>리턴 값이 없는 경우에는 <code>void</code>로 작성</li>
</ul>
<h2 id="2-메서드명">2) 메서드명</h2>
<ul>
<li>첫 문자는 소문자로 시작</li>
</ul>
<h2 id="3-매개변수">3) 매개변수</h2>
<ul>
<li>매개값을 받기 위해 사용</li>
<li>전달할 매개값이 없다면 매개변수 생략 가능</li>
</ul>
<h2 id="4-실행-블록">4) 실행 블록</h2>
<ul>
<li>메서드 호출 시 실행되는 부분</li>
</ul>
<h2 id="5-메서드-호출">5) 메서드 호출</h2>
<ul>
<li><span style="background-color: #ffffcc; color: #ff6666;">메서드는 객체가 존재하지 않으면 호출할 수 없다.</span> 즉, 클래스로부터 객체를 생성된 후 호출 가능</li>
<li><strong>객체 내부</strong>에서는 메서드명으로만 호출한다.</li>
<li><strong>외부 객체</strong>에서는 참조 변수와 도트<code>.</code>연산자를 이용해 호출한다.</li>
</ul>
<h2 id="6-가변길이-매개변수">6) 가변길이 매개변수</h2>
<ul>
<li><p>매개변수의 개수와 상관없이 매개값을 줄 수 있다.</p>
</li>
<li><p>매서드 호출 시 매개값을 쉼표로 구분해 개수와 상관없이 제공할 수 있다.</p>
</li>
<li><p>매개값들은 자동으로 배열 항목으로 변환되어 메서드에서 사용된다.</p>
<pre><code class="language-java">public class Computer {

  void count(int ... values) {
      System.out.println(values.length);
  }

  int sum(int ... values) {
      count(values);  // 객체 내부 호출

      int sum = 0;
      for (int i = 0; i &lt; values.length; i++) {
          sum += values[i];
      }

      return sum;
  }
</code></pre>
</li>
</ul>
<p>}</p>
<pre><code>
&lt;hr&gt;

```java
public class ComputerEx {
    public static void main(String[] args) {
        Computer computer = new Computer();
        int result = computer.sum(1, 3, 5, 7, 9, 10);     // 외부 객체 호출
        System.out.println(result);
        // 6
        // 35

        int result2 = computer.sum(new int[]{2, 4, 6});   // 직접 배열을 매개값으로 제공
        System.out.println(result2);
        // 3
        // 12
    }
}
</code></pre><h2 id="7-return문">7) return문</h2>
<ul>
<li>메서드의 실행을 <code>강제 종료</code>하고 호출한 곳으로 돌아간다는 의미</li>
<li>메서드 선언에 return 타입이 있는 경우 return문 뒤에 리턴 값을 지정해줘야 한다.</li>
</ul>
<h2 id="8-메서드-오버로딩">8) 메서드 오버로딩</h2>
<ul>
<li>메서드 이름은 같지만<code>(리턴타입은 무관)</code> 매개변수의 타입, 개수, 순서가 다른 메서드를 여러개 선언하는 것.</li>
<li><strong><span style="background-color: #ffffcc; color: #ff6666;">메서드 오버로딩의 목적은 다양한 매개값을 처리하기 위해서이다.</span></strong></li>
</ul>
<h1 id="69-인스턴스-멤버">6.9 인스턴스 멤버</h1>
<ul>
<li>필드와 메서드는 선언 방법에 따라 <code>인스턴스 멤버</code>와 <code>정적 멤버</code>로 구분할 수 있다.</li>
<li><strong>인스턴스 멤버</strong> 중 <code>필드</code>는 객체가 생성될 때마다 새로 <code>Heap 영역</code>에 생성되고,
<code>메서드</code>는 클래스가 로드될 때 <code>Method 영역</code>에 할당되며, 객체가 생성되면 객체에 소속되어 공유해서 사용한다.</li>
<li>*<span style="background-color: #ffffcc; color: #ff6666;">즉, 객체 없이는 사용하지 못하도록 제한이 걸려있다.</span>**</li>
<li><strong>정적 멤버</strong>는 <code>Method 영역</code>에 생성되어 모든 객체에 공유된다.</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>인스턴스(instance) 멤버</td>
<td>객체에 소속된 멤버로 객체를 생성해야만 사용할 수 있다.</td>
</tr>
<tr>
<td>정적(static) 멤버</td>
<td>클래스에 고정된 멤버로 객체 없이도 사용할 수 있다.</td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<div align="center">
  <img src="https://velog.velcdn.com/images/sj_kim/post/abc0037b-e95a-48f4-a187-5c93bf7c3020/image.png">
</div>

<p><span style="color:#04B486"><em>출처👉<a href="https://www.geeksforgeeks.org/java-memory-management/">geeksforgeeks</a></em></span></p>
<h2 id="1-this-키워드">1) this 키워드</h2>
<ul>
<li>객체 내부에서는 인스턴스 멤버에 접근하기 위해 <code>this</code>를 사용한다.</li>
<li>객체는 자신을 <code>this</code>라고 한다.</li>
</ul>
<h1 id="610-정적-멤버">6.10 정적 멤버</h1>
<ul>
<li><code>Method 영역</code>의 클래스에 고정적으로 <code>위치</code>하는 멤버로 <code>객체를 생성할 필요 없이</code> 클래스를 통해 바로 사용이 가능하다.</li>
</ul>
<h2 id="1-정적-멤버-선언">1) 정적 멤버 선언</h2>
<ul>
<li><code>static</code> 키워드를 사용해 정적 멤버를 선언한다.</li>
<li>객체마다 가지고 있을 필요가 없는 공용적인 필드는 <code>정적 필드</code>로 선언하는 것이 좋다.</li>
<li>인스턴스 필드를 이용하지 않는 메서드는 <code>정적 메서드</code>로 선언하는 것이 좋다.</li>
</ul>
<h2 id="2-정적-멤버-사용">2) 정적 멤버 사용</h2>
<ul>
<li>클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있다.</li>
<li>클래스명과 도트<code>.</code> 연산자로 접근하여 사용한다.</li>
</ul>
<h2 id="3-정적-블록">3) 정적 블록</h2>
<ul>
<li><strong><span style="background-color: #ffffcc; color: #ff6666;">일반적으로 정적 필드는 필드 선언과 동시에 초기값을 주지만 정적 블록을 이용해 초기화할 수도 있다.</span></strong></li>
<li>정적 블록은 클래스가 메모리로 로딩될 때 자동으로 실행된다.
<img src="https://velog.velcdn.com/images/sj_kim/post/2296dd15-82a2-4a3a-9443-2cafc55c1495/image.png" alt=""></li>
</ul>
<h2 id="4-인스턴스-멤버-사용-불가">4) 인스턴스 멤버 사용 불가</h2>
<ul>
<li><p>정적 메서드나 정적 블록은 내부에 인스턴스 필드나 인스턴스 메서드를 사용할 수 없다.</p>
</li>
<li><p>객체 자신의 참조인 this도 사용할 수 없다.</p>
</li>
<li><p>main（）메서드도 정적 메서드이므로 객체 생성 없이 인스턴스 필드와 메서드를 바로 사용할 수 없다.</p>
<pre><code class="language-java">public class Bird {
  String color;

  void fly() {
      System.out.println(&quot;날다&quot;);
  }

  public static void main(String[] args) {
      // color = &quot;red&quot;;  // 컴파일 에러 : non-static variable color cannot be referenced from a static context
      // fly();          // 컴파일 에러 : non-static method fly() cannot be referenced from a static context

      Bird bird = new Bird();
      bird.color = &quot;red&quot;;
      System.out.println(bird.color);   // red
      bird.fly();                       // 날다
  }
}
</code></pre>
</li>
</ul>
<pre><code>
# 6.11 final 필드와 상수
* `final` 필드와 상수를 선언해 `값 변경을 막고 읽기만 허용`할 수 있다.

## 1) final 필드 선언
* final 필드는 초기값이 저장되면 최종값이 된다. **&lt;span style=&quot;background-color: #ffffcc; color: #ff6666;&quot;&gt;즉, 실행 도중에 수정할 수 없다.&lt;/span&gt;**
* 필드에 초기값을 주는 방법은 2가지뿐이다.
① **필드 선언** 시 초기값 대입
② **생성자**에서 초기값 대입

```java
public class Korean {
    // 인스턴스 final 필드 선언
    final String nation = &quot;Korea&quot;;
    final String ssn;

    // 인스턴스 필드 선언
    String name;

    public Korean(String ssn, String name) {
        this.ssn = ssn;
        this.name = name;
    }
}
</code></pre><hr>

<pre><code class="language-java">public class KoreanEx {
    public static void main(String[] args) {
        Korean person = new Korean(&quot;111111-2222222&quot;, &quot;홍길동&quot;);
        // person.ssn = &quot;333333-4444444&quot;;      // 컴파일 에러 : cannot assign a value to final variable ssn
        System.out.println(person.nation);     // Korea
        System.out.println(person.ssn);        // 111111-2222222
        System.out.println(person.name);       // 홍길동

        person.name = &quot;김영희&quot;;
        System.out.println(person.name);       // 김영희
    }
}
</code></pre>
<h2 id="2-상수-선언">2) 상수 선언</h2>
<ul>
<li><p>불변의 값</p>
</li>
<li><p>상수는 <code>static이면서 final</code>인 특성을 가져야 한다. 즉, 상수는 객체마다 저장할 필요가 없고, 여러 개의 값을 가지면 안 된다.</p>
</li>
<li><p>상수 이름은 모두 대문자로 작성하는 것이 관례이다.</p>
</li>
<li><p><strong><span style="background-color: #ffffcc; color: #ff6666;">일반적으로 상수는 선언과 동시에 초기값을 주지만 정적 블록을 이용해 초기화할 수도 있다.</span></strong></p>
<pre><code class="language-java">public class KoreanEx {
  public static void main(String[] args) {
      System.out.println(Korean.city);        // Seoul
      System.out.println(Korean.nation);      // Korea

      // Korean.city = &quot;Busan&quot;;      // 컴파일 에러 : cannot assign a value to final variable city
  }
}
</code></pre>
</li>
</ul>
<pre><code>
# 6.12 패키지
* 패키지는 클래스 일부분이자 클래스를 `식별`하는 용도
* 주로 개발 회사의 도메인 이름의 역순으로 작성하고, 마지막에는 프로젝트 이름을 붙여주는 것이 일반적이다.
* 상위 패키지와 하위 패키지를 도트`.`로 구분한다.

## 1) 패키지 선언
* `package` 키워드와 함께 패키지 이름을 기술한 것으로, `소스 파일 최상단`에 위치해야 한다.
* 컴파일러는 클래스 패키지 선언을 보고 디렉토리를 자동 생성시킨다.
* 모두 소문자로 작성하는 것이 관례이다.

## 2) import 문
* 다른 패키지에 있는 클래스를 사용하려면 import 문을 이용해서 어떤 패키지를 사용하는지 명시해야 한다.
* 동일한 패키지에 포함된 다수의 클래스를 사용해야 한다면 클래스 이름을 생략하고 `*`를 사용할 수 있다.
* import 문은 하위 패키지를 포함하지 않는다.
![](https://velog.velcdn.com/images/sj_kim/post/646c49c2-4750-4b2f-9813-40cd662c1cc8/image.png)

```java
package ch06.sec12.hyundai;

import ch06.sec12.hankook.SnowTire;
import ch06.sec12.kumho.*;

public class Car {

    Tire tire1 = new Tire();
    ch06.sec12.hankook.Tire tire2 = new ch06.sec12.hankook.Tire();

    SnowTire tire3 = new SnowTire();

    AllSeasonTire allSeasonTire = new AllSeasonTire();

}
</code></pre><h1 id="613-접근-제한자">6.13 접근 제한자</h1>
<ul>
<li>필드와 메서드가 <code>외부로 노출되지 않도록</code> 해 객체의 무결성(결점이 없는 성질)을 유지하기 위해서
자바는 <code>접근 제한자</code>를 사용한다.</li>
<li><code>default</code>는 접근 제한자가 아니라 접근 제한자가 붙지 않은 상태를 말한다.</li>
</ul>
<table>
<thead>
<tr>
<th>접근 제한자</th>
<th>제한 범위</th>
</tr>
</thead>
<tbody><tr>
<td><strong>public</strong></td>
<td>없음</td>
</tr>
<tr>
<td><strong>protected</strong></td>
<td>같은 패키지이거나 자식 객체만 사용 가능</td>
</tr>
<tr>
<td><strong>default</strong></td>
<td>같은 패키지</td>
</tr>
<tr>
<td><strong>private</strong></td>
<td>객체 내부</td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<div align="center">
  <img src="https://www.codingeek.com/wp-content/uploads/2017/07/Access-Specifiers.png">
</div>

<p><span style="color:#04B486"><em>출처👉<a href="https://www.codingeek.com/java/java-access-modifiers-public-protected-private-and-default/">codingeek - Java Access Modifiers- public, protected, private and default</a></em></span></p>
<h1 id="614-getter와-setter">6.14 Getter와 Setter</h1>
<ul>
<li>객체의 필드를 외부에서 읽고 변경할 경우 객체의 <code>무결성(결점이 없는 성질)</code>이 깨질 수 있다.
따라서, 외부에서의 직접적인 필드 접근을 막고 Setter 메서드를 통해서만 필드 값을 변경할 수 있도록 한다.</li>
<li>외부에서 객체의 필드를 읽을 때에도 Getter 메서드를 통해서만 접근한다.<pre><code class="language-java">package ch06.sec14;
</code></pre>
</li>
</ul>
<p>public class Car {</p>
<pre><code>private int speed;
private boolean stop;

String model;

public int getSpeed() {
    return speed;
}

public void setSpeed(int speed) {
    if (speed &lt; 0) {
        this.speed = 0;
        return;
    }

    this.speed = speed;
}

public boolean isStop() {
    return stop;
}

public void setStop(boolean stop) {
    this.stop = stop;

    if (stop == true) {
        this.speed = 0;
    }
}

@Override
public String toString() {
    return &quot;Car{&quot; +
            &quot;speed=&quot; + speed +
            &quot;, stop=&quot; + stop +
            &quot;, model=&#39;&quot; + model + &#39;\&#39;&#39; +
            &#39;}&#39;;
}</code></pre><p>}</p>
<pre><code>&lt;hr&gt;

```java
package ch06.sec14;

public class CarEx {
    public static void main(String[] args) {
        Car car = new Car();
        car.model = &quot;hyundai&quot;;
        System.out.println(car);    // Car{speed=0, stop=false, model=&#39;hyundai&#39;}

        // car.speed = 2;           // 컴파일 에러 : java: speed has private access in ch06.sec14.Car
        car.setSpeed(3);
        System.out.println(car);    // Car{speed=3, stop=false, model=&#39;hyundai&#39;}

        car.setStop(true);
        System.out.println(car);    // Car{speed=0, stop=true, model=&#39;hyundai&#39;}

        System.out.println(car.getSpeed());     // 0
    }
}
</code></pre><h1 id="615-싱글톤-패턴">6.15 싱글톤 패턴</h1>
<ul>
<li>단 1개의 객체만 생성해서 사용하는 패턴</li>
<li><code>생성자를 private 접근 제한</code>해서 외부에서 new 연산자로 생성자를 호출할 수 없도록 막는 것이다.
대신 싱글톤 패턴이 제공하는 <code>정적 메소드</code>를 통해 간접적으로 객체를 얻을 수 있다.
일반적으로 정적 메서드명은 <code>getInstance</code>로 작성한다.<pre><code class="language-java">package ch06.sec14;
</code></pre>
</li>
</ul>
<p>public class SingletonEx {
    private static SingletonEx singletonEx = new SingletonEx();</p>
<pre><code>private SingletonEx() {}

public static SingletonEx getInstance() {
    return singletonEx;
}</code></pre><p>}</p>
<pre><code>
&lt;hr&gt;

```java
package ch06.sec14;

public class Ex {
    public static void main(String[] args) {
        SingletonEx instance1 = SingletonEx.getInstance();
        SingletonEx instance2 = SingletonEx.getInstance();

        System.out.println(instance1 == instance2); // true
    }
}
</code></pre><hr>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 05. 참조 타입]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-05.-%EC%B0%B8%EC%A1%B0-%ED%83%80</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-05.-%EC%B0%B8%EC%A1%B0-%ED%83%80</guid>
            <pubDate>Thu, 23 Nov 2023 13:32:33 GMT</pubDate>
            <description><![CDATA[<h1 id="51-데이터-타입-분류">5.1 데이터 타입 분류</h1>
<ul>
<li>자바의 데이터 타입은 기본 타입(primitive type)과 참조 타입(reference type)으로 분류된다.</li>
<li><code>기본 타입</code>은 <code>값 자체</code>를 저장하고, <code>참조 타입</code>은 객체가 생성된 <code>메모리 번지</code>를 저장한다.<ul>
<li>변수들은 모두 스택 메모리 영역에 생성되는데 <code>기본 타입</code>은 직접 <code>값</code>을 저장하고 있지만, <code>참조 타입</code>은 힙 메모리 영역의 <code>객체 번지</code>를 저장하고 이 번지를 통해 객체를 참조한다.<blockquote>
</blockquote>
<div align="center">
<img src="https://velog.velcdn.com/images/sj_kim/post/742ac6ee-298b-4b1d-999b-8a3ea06a2992/image.png">
</div>
<div align="center">
<img src="https://velog.velcdn.com/images/sj_kim/post/0088819f-350e-4600-b6de-e28af421423a/image.png">
</div>

</li>
</ul>
</li>
</ul>
<p><span style="color:#04B486"><em>출처👉[이것이자바다] 5.1 데이터 타입 분류</em></span></p>
<h1 id="52-메모리-사용-영역">5.2 메모리 사용 영역</h1>
<ul>
<li>java 명령어로 JVM이 구동되면 JVM은 운영체제에서 할당받은 메모리 영역(Runtime Data Area)을 <strong>메소드</strong>, <strong>힙</strong>, <strong>스택</strong>으로 구분해 사용한다.</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>메소드 영역</td>
<td>바이트코드 파일의 내용이 저장되는 영역, static 변수가 저장되며 모든 객체가 접근 가능하다.</td>
</tr>
<tr>
<td>힙 영역</td>
<td><strong>객체가 생성되는 영역</strong>, 가비지 컬렉션에 대상이 된다.<br>메소드 영역과 스택 영역의 상수와 변수에서 객체의 번지를 참조한다.</td>
</tr>
<tr>
<td>스택 영역</td>
<td>메소드를 호출할 때마다 생성되는 프레임이 저장되는 영역, 메소드 호출이 끝나면 프레임은 자동 제거된다.<br>프레임 내부에 로컬 변수 스택이 있는데, 여기에 기본 타입 변수와 참조 타입 변수가 생성되고 제거된다.</td>
</tr>
</tbody></table>
<h1 id="53-참조-타입-변수의---연산">5.3 참조 타입 변수의 ==, != 연산</h1>
<ul>
<li><p><code>==</code>와 <code>!=</code> 연산자는 변수의 값이 같은지 아닌지 비교한다.</p>
</li>
<li><p><code>기본 타입</code>은 <code>값</code>을 비교한다면, <code>참조 타입</code>은 객체의 <code>번지</code>를 비교한다.</p>
</li>
<li><p>참조 타입의 경우 같은 값이 저장되더라도 서로 다른 객체로 번지는 다르다.</p>
<pre><code class="language-java">public class ReferenceType {
  public static void main(String[] args) {
      int x = 5;
      int y = 5;
      System.out.println(x == y);                   // true

      int[] arrayX = {1, 3, 5 ,7};
      int[] arrayY = {1, 3, 5, 7};
      System.out.println(arrayX == arrayY);         // false
      System.out.println(arrayX.equals(arrayY));    // false

      int[] arrayZ = arrayY;
      System.out.println(arrayZ == arrayY);         // true
      System.out.println(arrayZ.equals(arrayY));    // true
  }
}
</code></pre>
</li>
</ul>
<pre><code>&gt; 💡 **Object객체 equals( )**
* 메서드 내부에서 `==`연산자를 사용해 객체의 번지가 같은지 비교한다. 
![](https://velog.velcdn.com/images/sj_kim/post/c1a96f7e-b210-495f-b07a-1f24b8d78903/image.png)

# 5.4 null과 NullPointerException
* 참조 타입 변수는 null 값을 가질 수 있다. 이 때, null로 초기화된 참조 변수는 `스택 영역`에 생성된다.
* 프로그램 실행 도중 발생한 오류를 예외(Exception)이라 부른다.
* 변수가 null인 상태에서 객체의 데이터나 메서드를 사용하려 할 때 `NullPointerException` 예외가 발생한다.
```java
public class ReferenceType {
    public static void main(String[] args) {
        int[] lotto = null;
        System.out.println(lotto.length);  // Exception in thread &quot;main&quot; java.lang.NullPointerException: Cannot read the array length because &quot;lotto&quot; is null
    }
}
</code></pre><h1 id="55-문자열string-타입">5.5 문자열(String) 타입</h1>
<ul>
<li>자바의 문자열은 String 객체로 생성된다.</li>
<li>String 객체는 <strong><code>문자열 리터럴이 동일하면 서로 공유하도록 설계</code></strong>되어있다. 즉, 동일한 String 객체의 번지가 저장된다.
단, <code>new 연산자</code>로 새로운 객체를 만들면 문자열 리터럴이 동일해도 <code>서로 다른 String 객체의 번지</code>를 가지게 된다.</li>
<li><code>&quot;&quot;</code>빈 문자열만으로도 String 객체를 생성할 수 있다.<h2 id="1-문자열-비교">1) 문자열 비교</h2>
</li>
<li>내부 문자열이 동일한지 비교하고 싶다면 <code>String 객체의 equals( ) 메서드</code>를 사용하면 된다.</li>
</ul>
<pre><code class="language-java">public class ReferenceType {
    public static void main(String[] args) {
        String food = &quot;&quot;;
        System.out.println(food.length());            // 0

        String color1 = &quot;red&quot;;
        String color2 = &quot;red&quot;;

        System.out.println(color1 == color2);         // true

        String color3 = new String(&quot;red&quot;);
        System.out.println(color1 == color3);         // false
        System.out.println(color2 == color3);         // false

        System.out.println(color1.equals(color3));    // true
    }
}
</code></pre>
<blockquote>
<p>💡 <strong>String객체 equals( )</strong></p>
</blockquote>
<ul>
<li>메서드 내부에서 조건문으로 <code>==</code>연산자를 사용해 객체의 번지가 같은지 비교한다.
같지 않다면,
<span style="background-color: #F2F5A9;"><strong>1)</strong></span> <code>instanceof</code>로 Argument(anObject)가 String 타입인지 확인(<strong>true</strong> 또는 <strong>false</strong> 반환)하고, 맞다면 해당 변수(aString)에 자동 캐스팅하여 할당한 값과
<span style="background-color: #F2F5A9;"><strong>2)</strong></span> COMPACT_STRINGS 상수 값과 coder(문자열 저장 방법 : <strong>0</strong>(UTF-16인코딩) 또는 <strong>1</strong>(Latin-1 인코딩))의 값을 비교하고,
<span style="background-color: #F2F5A9;"><strong>3)</strong></span> 두 문자열의 길이와 각 각의 글자를 비교한다.<div align="center">
<img src="https://velog.velcdn.com/images/sj_kim/post/9e77893c-8068-4e24-8f57-c4c10d8f1b1d/image.png">
</div>
<div align="center" margin-top="5px !important">
<img src="https://velog.velcdn.com/images/sj_kim/post/fab3b630-8f1b-4525-9991-e722feebe5bc/image.png">
</div>

</li>
</ul>
<h2 id="2-문자-추출">2) 문자 추출</h2>
<ul>
<li>문자열에서 특정 위치의 문자를 얻고 싶다면 <code>charAt( )</code> 메서드를 사용한다.
주어진 인덱스의 문자를 리턴하는데, <code>인덱스</code>란 0에서부터 시작해 &#39;문자열의 길이 - 1&#39;까지의 번호를 말한다.</li>
</ul>
<h2 id="3-문자열-길이">3) 문자열 길이</h2>
<ul>
<li>문자열에서 문자의 개수를 얻고 싶다면 <code>length( )</code> 메서드를 사용한다.</li>
</ul>
<h2 id="4-문자열-대체">4) 문자열 대체</h2>
<ul>
<li>문자열에서 특정 문자열을 다른 문자열로 대체하고 싶다면 <code>replace( )</code> 메서드를 사용한다.</li>
<li>새로운 String 객체를 생성한다.</li>
</ul>
<h2 id="5-문자열-잘라내기">5) 문자열 잘라내기</h2>
<ul>
<li>문자열에서 특정 위치의 문자열을 잘라내어 가져오고 싶다면 <code>substring( )</code> 메서드를 사용한다.</li>
<li>새로운 String 객체를 생성한다.</li>
<li><code>beginIndex ~ endIndex -1</code> 까지 문자열을 잘라낸다.<pre><code class="language-java">public String substring(int beginIndex, int endIndex) { ... }</code></pre>
</li>
</ul>
<h2 id="6-문자열-찾기">6) 문자열 찾기</h2>
<ul>
<li>문자열에서 특정 문자열의 위치를 찾고자 할 때에는 <code>indexOf( )</code> 메서드를 사용한다.
문자열이 있다면 <code>인덱스</code>를, 없다면 <code>&#39;-1&#39;</code>을 리턴한다.</li>
<li>문자열이 중복된 경우 <code>처음으로 나타나는 위치의 인덱스</code>를 리턴</li>
<li>문자열이 단순 포함되어 있는지만 알고 싶다면 <code>contains( )</code> 메서드를 사용한다.
문자열이 포함되어 있다면 <code>true</code>, 없다면 <code>false</code>를 리턴한다.</li>
</ul>
<h2 id="7-문자열-분리">7) 문자열 분리</h2>
<ul>
<li>문자열이 구분자를 사용해 여러 개의 구성되어 있을 경우 <code>split( )</code> 메서드를 사용하면 구분자 기준으로 분리된 문자열 <code>배열</code>을 얻을 수 있다.</li>
</ul>
<pre><code class="language-java">import java.util.Arrays;

public class StringEx {
    public static void main(String[] args) {
        String food = &quot;다코야키, 햄버거, 문어숙회, 해물누룽지탕, 문어튀김&quot;;

        System.out.println(food.length());                               // 29

        System.out.println(food.charAt(0));                              // 다
        System.out.println(food.charAt(3));                              // 키         
        System.out.println(food.charAt(29));                             // Exception in thread &quot;main&quot; java.lang.StringIndexOutOfBoundsException: index 29, length 29

        System.out.println(food.replace(&quot;문어&quot;, &quot;오징어&quot;));                // 다코야키, 햄버거, 오징어숙회, 해물누룽지탕, 오징어튀김
        System.out.println(food);                                        // 다코야키, 햄버거, 문어숙회, 해물누룽지탕, 문어튀김

        System.out.println(food.substring(3, 7));                        // 키, 햄
        System.out.println(food);                                        // 다코야키, 햄버거, 문어숙회, 해물누룽지탕, 문어튀김

        System.out.println(food.indexOf(&quot;문&quot;));                          // 11
        System.out.println(food.indexOf(&quot;문어&quot;));                        // 11

        System.out.println(food.contains(&quot;누룽지&quot;));                     // true

        System.out.println(Arrays.toString(food.split(&quot;,&quot;)));           // [다코야키,  햄버거,  문어숙회,  해물누룽지탕,  문어튀김]

    }
}
</code></pre>
<h1 id="56-배열array-타입">5.6 배열(Array) 타입</h1>
<ul>
<li>변수는 하나의 값만 저장할 수 있기에 저장해야 할 값이 많아지면 변수의 개수가 늘어난다.</li>
<li>배열은 인덱스(Index)를 부여해 놓은 자료구조로 각 인덱스에 값을 저장한다.</li>
<li><strong><span style="color: #DC143C">배열은 같은 타입의 값만 저장할 수 있고, 길이는 늘리거나 줄일 수 없다.</span></strong></li>
</ul>
<h2 id="1-배열-변수-선언-및-생성">1) 배열 변수 선언 및 생성</h2>
<ul>
<li>배열 변수는 참조 변수로 힙 영역에 생성되고 null로 초기화할 수 있다.</li>
<li>배열 변수를 미리 선언했다면 new 타입［］을 사용해 값을 대입할 수 있다.</li>
<li><code>new 연산자</code>를 사용하면 배열의 길이 지정이 가능하고, <code>데이터 타입의 기본값으로 초기화</code>된다.</li>
<li>메소드의 매개변수가 배열 타입이면, 매개값으로 중괄호｛｝로 감싼 값을 파라미터로 넘기면 컴파일 에러가 발생한다.<pre><code class="language-java">import java.util.Arrays;
</code></pre>
</li>
</ul>
<p>public class ArrayEx {
    public static void main(String[] args) {
        int[] age;
        //age = {15, 20, 45}; // 컴파일 에러 발생 : illegal start of expression
        age = new int[]{15, 20, 45};
        System.out.println(Arrays.toString(age));       // [15, 20, 45]</p>
<pre><code>    int[] year = {2021, 2022, 2023};
    String[] name = {&quot;철수&quot;, &quot;영희&quot;, &quot;순자&quot;};

    System.out.println(Arrays.toString(year));      // [2021, 2022, 2023]
    System.out.println(Arrays.toString(name));      // [철수, 영희, 순자]

    int[] height = new int[3];
    System.out.println(Arrays.toString(height));    // [0, 0, 0]

    String[] season = new String[4];
    season[0] = &quot;봄&quot;;
    System.out.println(season[0]);                  // 봄
    System.out.println(season[2]);                  // null
    System.out.println(season.length);              // 4

    int[] month = {1, 2, 3, 4, 5};
    System.out.println(Arrays.toString(month));     // [1, 2, 3, 4, 5]
    System.out.println(month.length);               // 5

    int[] printArr = {2, 4, 6};                     // (i : 0 -  array[i] : 2) (i : 1 -  array[i] : 4) (i : 2 -  array[i] : 6)
    print(printArr);

    //print({2,4,6});  //컴파일 에러 발생 : illegal start of expression
}

public static void print(int[] array) {
    for (int i = 0; i &lt; array.length; i++) {
        System.out.printf(&quot;(i : %d -  array[i] : %d) &quot;, i, array[i]);
    }
}</code></pre><p>}</p>
<pre><code> # 5.7 다차원 배열
 * 배열에 또 다른 배열이 대입되는 것을 다차원 배열이라 한다.
 * 2차원 배열이라면 타입 뒤에 대괄호`［］`2개를, 3차원 배열이라면 대괄호`［］`3개를 붙여 선언한다.
 * 다차원 배열 생성 시 차원의 수 만큼 `중괄호`를 중첩시키거나 `new 연산자`를 사용할 수 있다.

```java
import java.util.Arrays;

public class ArrayEx {
    public static void main(String[] args) {
        int[][] soccerScore = new int[3][4];                      // 3행 4열의 다차원 배열
        System.out.println(soccerScore.length);                   // 3
        System.out.println(soccerScore[0].length);                // 4
        System.out.println(soccerScore[1].length);                // 4
        System.out.println(soccerScore[2].length);                // 4
        // System.out.println(score[3].length);                   // 런타임 에러 발생 : Exception in thread &quot;main&quot; java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
        soccerScore[0][1] = 15;
        System.out.println(Arrays.toString(soccerScore[0]));      // [0, 15, 0, 0]
        System.out.println(Arrays.toString(soccerScore[1]));      // [0, 0, 0, 0]
        System.out.println(Arrays.toString(soccerScore[2]));      // [0, 0, 0, 0]
        // System.out.println(Arrays.toString(score[3]));         // 런타임 에러 발생 : Exception in thread &quot;main&quot; java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

        int[][] basketballScores = {
                {20, 30, 40},
                {1, 3}
        };

        System.out.println(basketballScores.length);                  // 2
        System.out.println(Arrays.toString(basketballScores[0]));     // [20, 30, 40]
        System.out.println(Arrays.toString(basketballScores[1]));     // [1, 3]
        System.out.println(basketballScores[0][1]);                   // 3
        System.out.println(basketballScores[1][1]);                   // 3
    }
}
</code></pre><hr>

<pre><code class="language-java">public class ArrayEx {
    public static void main(String[] args) {
        // Q. 주어진 배열 항목의 전체 합과 평균을 구해 출력하는 코드를 작성해보세요.(중첩 for문 이용)
        int[][] array = {
                {95, 86},
                {83, 92, 96},
                {78, 83, 93, 87, 88}
        };

        int count = 0;
        int sum = 0;
        for (int i = 0; i &lt; array.length; i++) {
            for (int j = 0; j &lt; array[i].length; j++) {
                sum += array[i][j];
                count++;
            }
        }
        System.out.printf(&quot;전체 합 : %d, 전체 평균 : %.1f&quot;, sum, (double) sum/count);      // 전체 합 : 881, 전체 평균 : 88.1
    }
}
</code></pre>
<h1 id="58-객체를-참조하는-배열">5.8 객체를 참조하는 배열</h1>
<ul>
<li>기본 타입 배열은 각 항목에 값을 직접 저장하지만, 참조 타입 배열은 각 항목에 대한 객체의 번지를 저장한다.</li>
<li>리터럴이 같다면 동일한 번지에 저장된다.
단, <code>new 연산자</code>로 새로운 배열을 생성하면 서로 다른 객체의 번지를 갖게 된다.<pre><code class="language-java">import java.util.Arrays;
</code></pre>
</li>
</ul>
<p>public class ArrayEx {
    public static void main(String[] args) {
        String[] fruits = new String[5];
        fruits[0] = &quot;apple&quot;;
        fruits[1] = &quot;avocado&quot;;
        fruits[2] = &quot;blackberry&quot;;
        fruits[3] = &quot;avocado&quot;;</p>
<pre><code>    String[] brand = {&quot;apple&quot;};

    String[] juice = new String[2];
    juice[0] = new String(&quot;apple&quot;);

    System.out.println(fruits.length);                 // 5
    System.out.println(Arrays.toString(fruits));       // [apple, avocado, blackberry, avocado, null]
    System.out.println(fruits[1] == fruits[3]);        // true
    System.out.println(fruits[0] == brand[0]);         // true
    System.out.println(fruits[0] == juice[0]);         // false
    System.out.println(brand[0] == juice[0]);          // false
    System.out.println(brand[0].equals(juice[0]));     // true
}</code></pre><p>}</p>
<pre><code>
# 5.9 배열 복사
* 배열은 한 번 생성하면 길이를 변경할 수 없다.
* 배열은 복사하면 기존 배열의 `번지가 그대로` 새로운 배열에 복사돼 저장된다.
```java
import java.util.Arrays;

public class ArrayEx {
    public static void main(String[] args) {
        int[] firstArray = {1, 3, 5};
        int[] secondArray = new int[5];

        for (int i = 0; i &lt; firstArray.length; i++) {
            secondArray[i] = firstArray[i];
        }

        System.out.println(Arrays.toString(secondArray));    // [1, 3, 5, 0, 0]
        System.out.println(firstArray[0] == secondArray[0]); // true

        int[] newArray = new int[5];
        System.arraycopy(firstArray, 0, newArray, 0, firstArray.length);
        System.out.println(Arrays.toString(newArray));      // [1, 3, 5, 0, 0]
        System.out.println(firstArray[0] == newArray[0]);   // true
    }
}
</code></pre><h1 id="510-배열-항목-반복을-위한-향상된-for-문">5.10 배열 항목 반복을 위한 향상된 for 문</h1>
<pre><code class="language-java">public class ArrayEx {
    public static void main(String[] args) {
        String[] colors = {&quot;FFFFFF&quot;, &quot;CCFFCC&quot;, &quot;FFCCFF&quot;, &quot;E5FFCC&quot;};
        for (String color : colors) {
            if (color.contains(&quot;5&quot;)) {
                System.out.println(color);  // E5FFCC
            }
        }

    }
}
</code></pre>
<ul>
<li><p>배열에서 가져올 항목(<span style="background-color: #ffffcc; font-weight: bold; color: #ff6666; font-style: italic;">colors</span>)이 있으면 변수(<span style="background-color: #ffffcc; font-weight: bold; color: #ff6666; font-style: italic;">String color</span>)에 항목을 저장하고,
실행문(<span style="background-color: #ffffcc; font-weight: bold; color: #ff6666; font-style: italic;">if (color.contains(&quot;5&quot;)) {...}</span>)을 실행한다.
다시 반복하면서, 배열에서 가져올 항목이 존재하면 변수에 저장하고 실행문을 실행한다.
더이상 가져올 항목이 없으면 for문을 종료한다.</p>
<pre><code class="language-java">public class ArrayEx {
  public static void main(String[] args) {
      // Q. 주어진 배열 항목에서 최대값을 출력하는 코드를 작성해보세요.(for문 이용)
      int[] array = {1, 5, 3, 8, 2};

      int max = 0;
      for (int num: array) {
          if (max &lt; num) {
              max = num;
          }
      }

      System.out.println(max);    // 8
  }
}
</code></pre>
</li>
</ul>
<pre><code>
# 5.11 main（）메서드의 String［］ 매개변수 용도
* main（）메서드는 자바 프로그램의 시작점이다.
* Java는 명령 프롬프트나 터미널에서 프로그램을 실행할 때 값을 요구할 수 있다.
전달된 값은 `문자열로 취급`되어 String［］ 배열의 항목 값으로 저장되고, main（）메서드 호출 시 매개값으로 전달된다.
```java
public class ArrayEx {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println(&quot;2개의 입력 값이 필요합니다.&quot;);
            System.exit(0);
        }

        System.out.println(Integer.parseInt(args[0]) + Integer.parseInt(args[1]));
    }
}
</code></pre><blockquote>
<p>💡 인텔리제이에서 입력값을 주고 실행하는 방법</p>
</blockquote>
<p>1) Edit Configurations... 클릭
<img src="https://velog.velcdn.com/images/sj_kim/post/b2923ba2-eaa7-4b97-b10b-25cff04591ff/image.png" alt="">
2) Run/Debug Configurations 대화상자에서 Program arguments 입력란에 값을 입력한다.
<img src="https://velog.velcdn.com/images/sj_kim/post/a8a0c4cd-4c9c-42e4-b909-8637529035a2/image.png" alt=""></p>
<h1 id="512-열거enum-타입">5.12 열거(Enum) 타입</h1>
<ul>
<li><code>한정된 값</code>을 갖는 타입</li>
<li><code>열거 상수</code>는 열거 타입으로 사용할 수 있는 <code>한정된 값</code>을 말하며, 관례적으로 모두 <code>대문자 알파벳</code>으로 정의한다.</li>
<li>열거 타입에는 <code>열거타입.열거상수</code> 형태로만 대입할 수 있다. 또한, 참조 타입이므로 <code>null</code>도 대입 가능하다.</li>
</ul>
<pre><code class="language-java">public enum Rainbow {
    RED,
    ORANGE,
    YELLOW,
    GREEN,
    BLUE,
    INDIGO,
    PURPLE
}
</code></pre>
<hr>

<pre><code class="language-java">public class EnumEx {
    public static void main(String[] args) {
        System.out.println(Rainbow.RED);    // RED

        Rainbow color = null;
        // color = &quot;red&quot;;   // 컴파일 에러 : java: incompatible types: java.lang.String cannot be converted to Rainbow
        color = Rainbow.INDIGO;
        System.out.println(color);          // INDIGO
    }
}
</code></pre>
<hr>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 04. 조건문과 반복문]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-04.-%EC%A1%B0%EA%B1%B4%EB%AC%B8%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-04.-%EC%A1%B0%EA%B1%B4%EB%AC%B8%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8</guid>
            <pubDate>Tue, 21 Nov 2023 13:30:40 GMT</pubDate>
            <description><![CDATA[<h1 id="41-코드-실행-흐름-제어">4.1 코드 실행 흐름 제어</h1>
<ul>
<li>자바 프로그램은 <code>main( )</code> 메서드의 시작 중괄호 <code>{</code>에서 끝 중괄호 <code>}</code>까지 위에서부터 아래로 실행하는 흐름을 가진다.</li>
<li><code>제어문</code>은 이러한 실행 흐름을 개발자가 원하는 방향으로 바꿀 수 있도록 해주며, 연산 결과에 따라 블록 내부의 실행 여부가 결정된다.
<img src="https://velog.velcdn.com/images/sj_kim/post/16a46379-b16b-4524-bb81-7bdd59276d20/image.png" alt="main메서드" title="main( ) 메서드"></li>
</ul>
<h1 id="42-if문">4.2 if문</h1>
<ul>
<li><p>if문은 조건식의 결과에 따라 블록 실행 여부가 결정된다.</p>
</li>
<li><p>조건식에는 true 또는 false 값을 산출할 수 있는 연산식이나 boolean 변수가 온다.</p>
</li>
<li><p>조건식이 true면 블록을 실행하고, false면 블록을 실행하지 않는다.</p>
</li>
<li><p><code>if문은 else블록과 함께 사용</code>되며, 조건식이 ture면 if문 블록이 실행되고, false면 else 블록이 실행된다.</p>
</li>
<li><p><code>조건문이 여러 개인 경우 else if 블록이 사용</code>되고,
상위 조건식부터 아래로 평가하며 true라면 else if 블록이 실행되고 전체 if문을 벗어나게 된다.
만약 <code>모든 조건식이 false</code>일 경우 <code>else 블록이 실행</code>되고 if문을 벗어나게 된다.</p>
</li>
<li><p>if문은 조건식의 결과가 true, false 두 가지밖에 없기 때문에 경우의 수가 많아질수록
else if를 반복적으로 추가해야 하무로 코드가 복잡하다.</p>
<pre><code class="language-java">public class IfEx {
  public static void main(String[] args) {
      int num = (int) (Math.random() * 20) + 1;

      if (num % 2 == 0) {
          System.out.println(&quot;1번째 조건식&quot;);
          System.out.printf(&quot;num : %d, 2의 배수입니다.\n&quot;, num);
      } else if (num % 3 == 0) {
          System.out.println(&quot;2번째 조건식&quot;);
          System.out.printf(&quot;num : %d, 3의 배수입니다.\n&quot;, num);
      } else if (num % 5 == 0) {
          System.out.println(&quot;3번째 조건식&quot;);
          System.out.printf(&quot;num : %d, 5의 배수입니다.\n&quot;, num);
      } else {
          System.out.println(&quot;2 또는 3 또는 5의 배수가 아닙니다. num : &quot; + num);
      }
  }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/248976c4-3195-4ce8-8682-b589c7d20db6/image.png" alt="실행결과" title="실행 결과"></p>
</li>
</ul>
<h1 id="43-switch문">4.3 switch문</h1>
<ul>
<li><p>변수값에 따라 실행문이 결정되기 때문에 if문 보다 코드가 간결하다.</p>
</li>
<li><p>변수값과 동일한 값을 갖는 case가 없으면 default로 가서 실행문을 실행시킨다. (default 생략 가능)</p>
</li>
<li><p><code>break는 다음 case를 실행하지 않고 switch문을 빠져나가게 해준다.</code>
만약, break가 없다면 다음 case가 연달아 실행되는데, 이때는 case 값과는 상관없이 실행된다.</p>
</li>
<li><p>switch 문의 괄호에는 정수타입과 문자열 타입 변수를 사용할 수 있다.</p>
</li>
<li><p>Java 12이후부터는 표현식(Expressions)을 사용해 break문 대신 화살표(<code>-&gt;</code>)와 중괄호로 사용한다.
또한, 단일 값일 경우에는 화살표 오른쪽에 값을 기술해 변수에 바로 대입할 수 있다.</p>
</li>
<li><p>Java 13이후부터는 중괄호를 사용할 경우 <code>yield 키워드</code>로 값을 지정해 변수에 바로 대입 가능하다.</p>
<pre><code class="language-java">public class SwitchEx {
  public static void main(String[] args) {
      String season = &quot;겨율&quot;;

      // Java 11 이전 문법
      String food = &quot;&quot;;
      switch (season) {
          case &quot;봄&quot; :
              food = &quot;딸기케이크&quot;;
              break;
          case &quot;여름&quot; :
              food = &quot;빙수&quot;;
              break;
          case &quot;가을&quot; :
              food = &quot;와플&quot;;
              break;
          default:
              food = &quot;떡볶이&quot;;
      }

      System.out.println(food);    // 떡볶이
  }
}</code></pre>
<pre><code class="language-java">public class SwitchEx {
  public static void main(String[] args) {
      String season = &quot;가을&quot;;

      // Java 12부터
      String food = switch (season) {
          case &quot;봄&quot; -&gt; &quot;딸기케이크&quot;;
          case &quot;여름&quot;, &quot;가을&quot; -&gt; &quot;빙수, 와플&quot;;
          default -&gt; &quot;떡볶이&quot;;
      };

      System.out.println(food);   // 빙수, 와플
  }
}
</code></pre>
</li>
</ul>
<pre><code>```java
public class SwitchEx {
    public static void main(String[] args) {
        String season = &quot;여름&quot;;

        // Java 13부터
        String food = switch (season) {
            case &quot;봄&quot; -&gt; &quot;딸기케이크&quot;;
            case &quot;여름&quot;, &quot;가을&quot; -&gt; {
                String summerFood = &quot;빙수&quot;;
                yield summerFood + &quot;,&quot; + &quot;와플&quot;;
            }
            default -&gt; &quot;떡볶이&quot;;
        };

        System.out.println(food);   // 빙수,와플
    }
}
</code></pre><h1 id="44-for문">4.4 for문</h1>
<ul>
<li><p>똑같은 실행문을 반복적으로 실행할 때 사용한다.</p>
<pre><code class="language-java">public class ForEx {
  public static void main(String[] args) {
      for (int i = 0; i &lt; 2; i++) {
          System.out.println(&quot;hello world, i의 값 : &quot; + i);
          // hello world, i의 값 : 0
          // hello world, i의 값 : 1
      }
  }
}</code></pre>
<blockquote>
<p>💡 실행순서</p>
</blockquote>
</li>
<li><p>１) 초기화식 <code>int i = 0;</code> 실행</p>
</li>
<li><p>２) 조건식<code>i &lt; 2;</code> 평가</p>
</li>
<li><p>２.１) <strong>true</strong>면 실행문 <code>System.out.println(&quot;hello world, i의 값 : &quot; + i);</code> 실행</p>
</li>
<li><p>２.１.１) 증감식 <code>i++</code> 실행 → 2) 부터 반복</p>
</li>
<li><p>２.２) <strong>false</strong>면 for문 종료</p>
</li>
<li><p>초기화식과 증감식이 둘 이상 있을 수 있다. 이런 경우에는 같이 쉼표<code>(,)</code>로 구분해 작성한다.</p>
</li>
<li><p>초기화식에서 선언된 변수는 for문 블록 안에서만 사용되는 로컬 변수이다.</p>
</li>
</ul>
<pre><code class="language-java">public class ForEx {
    public static void main(String[] args) {
        // Q. for문을 이용해 1부터 100까지의 정수 중 3의 배수의 총합을 출력하는 코드를 작성하세요.
        int total = 0;
        for (int i = 1; i &lt;= 100 ; i++) {
            if (i % 3 == 0) {
                total += i;
                System.out.println(i);
            }
        }

        System.out.println(&quot;3의 배수 총합 : &quot; + total);  // 3의 배수 총합 : 1683
    }
}
</code></pre>
<ul>
<li><p>for문 안에 또 다른 for문이 있는 형태를 <code>중첩된 for문</code>이라고 한다.
바깥 for문이 1번 실행될 때마다 중첩된 for문은 지정 횟수만큼 반복하고 다시 바깥 for문으로 돌아간다.</p>
<pre><code class="language-java">public class ForEx {
  public static void main(String[] args) {
      // Q. 중첩 for문을 이용해 방정식 4x + 5y = 60의 모든 해를 구해서 (x, y) 형태로 출력하여라. 단, x와 y는 10 이하의 자연수이다.
      for (int i = 1; i &lt;= 10 ; i++) {
          int resultX = 4 * i;
          for (int j = 1; j &lt; 10; j++) {
              int resultY = 5 * j;
              if (resultX + resultY == 60) {
                  System.out.printf(&quot;(%d, %d)\n&quot;, i, j);
                  // (5, 8)
                  // (10, 4)
              }
          }
      }
  }
}</code></pre>
<h1 id="45-while문">4.5 while문</h1>
</li>
<li><p>while문은 조건식이 true일 경우에 계속 반복하고, false가 되면 반복을 멈추고 while 문을 종료한다.</p>
<pre><code class="language-java">public class WhileEx {
  public static void main(String[] args) {
      /*
      Q. while문과 Math.random() 메소드를 이용해 두 개의 주사위를 던져 (눈1, 눈2)형태로 출력
         눈의 합이 5가 아니면 계속 주사위를 던지고, 눈의 합이 5이면 실행을 멈춘다.
      */
      while (true) {
          int firstDice = (int) (Math.random() * 6) + 1;
          int secondDice = (int) (Math.random() * 6) + 1;
          if (firstDice + secondDice == 5) {
              break;
          }

          System.out.printf(&quot;(%d, %d)\n&quot;, firstDice, secondDice);
          // (2, 2)
          // (5, 6)
          // (5, 3)
          // (2, 4)
          // (2, 5)
          // (5, 4)
          // (2, 6)
          // (3, 1)
          // (6, 4)
          // (2, 1)
          // (3, 6)
          // (1, 2)
          // (1, 3)
      }
  }
}

</code></pre>
</li>
</ul>
<pre><code>&gt; 💡 실행순서
* １) 조건식 `ture` 평가
* １.１) **true**면 실행문 `int firstDice 부터 if조건문 ~ System.out.printf까지` 실행 → 1) 부터 다시 반복
* １.２) **false**면 while문 종료

* `조건식에 ture 사용하면 무한 반복`하게 되는데, 이 경우 while문을 빠져나가기 위한 코드가 필요하다. 위 코드에서는 `if 조건문`이 해당된다.

# 4.6 do-while문
* 실행문을 먼저 실행시키고, 실행 결과에 따라 반복 실행 여부를 결정할 때 do-while문을 사용한다.
```java
import java.util.Scanner;

public class WhileEx {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int inputNumber;

        do {
            System.out.println(&quot;1 부터 9 까지의 숫자를 입력하세요.&quot;);
            inputNumber = scanner.nextInt();
            System.out.println(inputNumber);
        } while (inputNumber != 3);

        System.out.println(&quot;숫자 입력이 종료되었습니다.&quot;);
    }
}</code></pre><p><img src="https://velog.velcdn.com/images/sj_kim/post/2bdd3ad4-81b1-4086-b78d-d76141ab2038/image.png" alt="실행결과" title="do-while 실행 결과"></p>
<blockquote>
<p>💡 실행순서</p>
</blockquote>
<ul>
<li>１) 실행문 <code>do 블록</code> 실행</li>
<li>２) 조건식 <code>inputNumber != 3</code> 평가</li>
<li>２.１) <strong>true</strong>면 1) → 2) 반복 실행</li>
<li>２.２) <strong>false</strong>면 do-while문 종료</li>
</ul>
<h1 id="47-break문">4.7 break문</h1>
<ul>
<li><p><code>반복문</code>을 <code>실행 중지</code>하거나 <code>조건문</code>을 <code>종료</code>할 때 사용한다.</p>
</li>
<li><p><code>중첩된 반복문</code>에서 break문은 가장 가까운 반복문만 종료시킨다.</p>
<pre><code class="language-java">public class ForEx {
  public static void main(String[] args) {
      for (int i = 5; i &gt;= 1; i--) {
          for (int j = 1; j &lt;= i; j++) {
              System.out.print(&quot;*&quot;);

              if (j == 3) {
                  System.out.println(&quot;[ @ ]&quot;);
                  break;
              }
          }
          System.out.println();
          System.out.println(&quot;--- 바깥 for문 ---, i 값 : &quot; + i);
      }
  }
}

</code></pre>
</li>
</ul>
<pre><code>![break문 예제](https://velog.velcdn.com/images/sj_kim/post/c278e338-dcdd-465b-b015-9e4820f8f4b7/image.png &quot;break문 예제&quot;)

# 4.8 continue문
* 반복문에서만 사용되며, continue문이 실행되면 조건식으로 바로 이동한다.
* continue문은 break문과 다르게 반복문을 종료하지 않고 계속 반복 수행한다.
```java
public class ForEx {
    public static void main(String[] args) {
        for (int i = 5; i &gt;= 1; i--) {
            for (int j = 1; j &lt;= i; j++) {
                if (j == 3) {
                    continue;
                }

                System.out.print(&quot; &quot; + j + &quot; &quot;);
            }
            System.out.println();
            System.out.println(&quot;--- 바깥 for문 ---&quot;);
        }
    }
}
</code></pre><p><img src="https://velog.velcdn.com/images/sj_kim/post/dbd60cc4-9fbb-4e27-97ec-2287d9404ce7/image.png" alt="continue문 예제" title="continue문 예제"></p>
<hr>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 03. 연산자]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-03.-%EC%97%B0%EC%82%B0</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-03.-%EC%97%B0%EC%82%B0</guid>
            <pubDate>Fri, 17 Nov 2023 09:36:42 GMT</pubDate>
            <description><![CDATA[<h1 id="31-부호증감-연산자">3.1 부호/증감 연산자</h1>
<h2 id="311-부호-연산자">3.1.1 부호 연산자</h2>
<ul>
<li><p>부호 연산자는 변수의 부호를 유지하거나 변경한다.</p>
</li>
<li><p><code>+</code> 연산자는 잘 사용되지 않고, <code>-</code> 연산자만 부호를 변경할 때 사용한다.</p>
<pre><code class="language-java">public class OperatorEx {
  public static void main(String[] args) {
      byte maxValue = Byte.MAX_VALUE;
      byte minxValue = Byte.MIN_VALUE;

      System.out.println(&quot;max : &quot; + maxValue + &quot;, min : &quot; + minxValue);   // max : 127, min : -128

      // byte minusMaxValue = -maxValue;   // 컴파일 에러 발생 : possible lossy conversion from int to byte
      int minusMaxValue = -maxValue;
      System.out.println(minusMaxValue);   // -127
  }
}</code></pre>
</li>
<li><p>정수 타입(byte, short, int) 연산의 결과는 int 타입으로 반환된다.</p>
<h2 id="312-증감-연산자">3.1.2 증감 연산자</h2>
</li>
<li><p><code>++</code>, <code>--</code> 연산자는 변수의 값을 1 증가시키거나 1 감소시키는 연산자이다.</p>
<pre><code class="language-java">public class OperatorEx {
  public static void main(String[] args) {
      int x = 1;
      int y = 1;

      int result1 = ++x + 10;
      System.out.println(result1); // 12
      System.out.println(x); // 2

      int result2 = y++ + 10;
      System.out.println(result2); // 11
      System.out.println(y); // 2
  }
}</code></pre>
</li>
<li><p>증감연산자가 <code>변수 앞에 있으면 우선 변수 1 증가 또는 1 감소 시킨 후</code> 나머지 연산을 수행한다.</p>
</li>
<li><p>증감연산자가 <code>변수 뒤에 있으면 우선 연산 후</code> 변수 1 증가 또는 1 감소시킨다.</p>
<h1 id="32-산술-연산자">3.2 산술 연산자</h1>
<p>연산식 | 설명</p>
</li>
<li><p>-- | ---</p>
</li>
<li><p>| 덧셈</p>
</li>
<li><p>| 뺄셈</p>
</li>
<li><p>| 곱셈
/ | 나눗셈
% | 나눗셈의 나머지 산출</p>
<pre><code class="language-java">public class OperatorEx {
  public static void main(String[] args) {
      int x = 2;
      int y = 10;

      int plus = x + y;
      int subtraction = y - x;
      int multiplication = x * y;
      int division = y / x;
      int remainder = y % x;

      System.out.println(plus);               // 12
      System.out.println(subtraction);        // 8
      System.out.println(multiplication);     // 20
      System.out.println(division);           // 5 
      System.out.println(remainder);          // 0
  }
}
</code></pre>
</li>
</ul>
<pre><code>* 피연산자가 정수 타입이면 결과는 int 타입으로 반환된다.
단, 피연산자 중 하나가 long 타입이면 연산의 결과는 long 타입으로 반환된다.
* 피연산자 중 하나가 실수이면 연산의 결과는 실수으로 반환된다.
# 3.4 정확한 계산은 정수 연산으로
* 실수 타입을 사용해 산술 연산을 하면 결과 값이 정확하지 않다.
* 실수 연산이 필요한 경우 `BigDecimal` 클래스를 사용하면, 산술 연산 시 정확한 결과 값을 얻을 수 있다.
```java
import java.math.BigDecimal;

public class OperatorEx {
    public static void main(String[] args) {
        double x = 0.722;
        double y = 5.234;

        // 예상 값 : 5.956
        System.out.println(x + y); // 5.9559999999999995

        BigDecimal bigDecimalX = new BigDecimal(&quot;0.722&quot;);
        BigDecimal bigDecimalY = new BigDecimal(&quot;5.234&quot;);
        System.out.println(bigDecimalX);                        // 0.722
        System.out.println(bigDecimalY);                        // 5.234
        System.out.println(bigDecimalX.add(bigDecimalY));       // 5.956
    }
}
</code></pre><blockquote>
<p>💡 <strong>BigDecimal</strong></p>
</blockquote>
<ul>
<li>float 타입은 유효자릿수가 7자리로, 소수점 이하 7자리까지만 정확한 값이며 그 이후의 값은 오차가 발생한다.</li>
<li>double 타입은 유효자릿수가 16자리로, 소수점 이하 16자리까지만 정확한 값이며 그 이후의 값은 오차가 발생한다.</li>
<li>가장 넓은 범위의 부동소수점을 표현할 수 있는 BigDecimal 클래스를 사용하면 연산의 정밀도를 높일 수 있다.
단, 사칙연산 시 add( ), subtract( ), multiply( ), divide( ) 메서드를 사용하여야 한다. </li>
</ul>
<h1 id="35-나눗셈-연산-후-nan과-infinity-처리">3.5 나눗셈 연산 후 NaN과 Infinity 처리</h1>
<ul>
<li><p><strong>NaN(Not a Number)</strong> : 숫자가 아닌 값</p>
</li>
<li><p><strong>Infinity</strong> : 무한대</p>
</li>
<li><p>나눗셈 또는 나머지 연산에서 좌측 피연산자가 정수이고 우측 피연산자가 0일 경우 예외가 발생한다.</p>
</li>
<li><p>좌측 피연산자가 실수이거나 우측 피연산자가 0.0 또는 0.0f이면 예외가 발생하지 않고 Infinity 또는 NaN 값이 출력된다.</p>
</li>
<li><p><code>Double.isInfinite( )</code>와 <code>Double.isNaN( )</code>을 사용해 true값이 반환되면 변수값이 Infinity 또는 NaN이다. </p>
<pre><code class="language-java">public class OperatorEx {
  public static void main(String[] args) {
      int x = 5;
      int y = 0;
//        System.out.println(x / y);  // Exception in thread &quot;main&quot; java.lang.ArithmeticException: / by zero

      float z = 2.5f;
      System.out.println(z / y);                          // Infinity

      double zero = 0.0;
      double result = x / zero;
      System.out.println(result);                         // Infinity
      System.out.println(Double.isInfinite(result));      // true

      double result2 = x % zero;
      System.out.println(result2);                        // NaN
      System.out.println(Double.isNaN(result2));          // true
  }
}</code></pre>
<h1 id="36-비교-연산자">3.6 비교 연산자</h1>
<p>연산자 | 설명</p>
</li>
<li><p>-- | ---
==  | 두 값이 같은지 비교
!= | 두 값이 다른지 비교</p>
<blockquote>
<p>, &lt;  | 값이 큰지 또는 작은지 비교
=, &lt;= | 값이 크거나 같은지 또는 작거나 같은지 비교</p>
</blockquote>
</li>
<li><p>피연산자의 타입이 다를 경우 연산 전에 타입을 일치시킨다.
단, 피연산자 중 하나가 float나 double인 경우 두 타입은 부동 소수점 방식으로 인해 값의 정밀도 차이가 발생해 비교 연산 시 실수 타입으로 강제 변환해야 한다.</p>
</li>
<li><p>문자열의 경우 동등 비교 연산 시 <code>==</code>와 <code>!=</code>  대신 <code>equals( )</code> 또는 <code>!equals( )</code>를 사용한다.</p>
<h1 id="37-논리-연산자">3.7 논리 연산자</h1>
<p>구분 | 설명</p>
</li>
<li><p>-- | ---
＆＆ 또는 ＆ (논리곱) | 피연산자 모두가 true → true
││ 또는 │ (논리합) | 피연산자 중 하나만 true → true
＾ (배타적 논리합) | 피연자 중 하나가 true 이고 나머지가 false → true
！ (논리 부정) | 피연산자의 논리값을 바꿈 true ↔ false</p>
</li>
<li><p><code>&amp;&amp; 연산자</code>는 <code>앞의 피연산자가 false라면</code> 뒤의 피연산자를 평가하지 않고 <code>바로 결과 값을 산출</code>한다.
반면, <code>&amp; 연산자</code>는 피연산자 <code>모두 평가 후 값을 산출</code>하기에 &amp;&amp; 연산자가 더 효율적으로 동작한다.</p>
</li>
<li><p><code>|| 연산자</code>도 <code>앞의 피연산자가 true라면 바로 결과 값을 산출</code>한다.
반면, <code>| 연산자</code>도 피연산자 <code>모두 평가 후</code> 값을 산출하기에 || 연산자가 더효율적으로 동작한다.</p>
<pre><code class="language-java">public class OperatorEx {
  public static void main(String[] args) {
      boolean a = true;
      boolean b = false;

      System.out.println(a &amp;&amp; b);   // false
      System.out.println(a || b);   // true
      System.out.println(a ^ b);    // true
      System.out.println(!a);       // false
      System.out.println(!b);       // true
  }
}</code></pre>
<h1 id="38-비트-논리-연산자">3.8 비트 논리 연산자</h1>
</li>
<li><p><code>bit 단위</code>로 논리 연산을 수행한다.</p>
</li>
<li><p><code>2진수 0과 1로 저장되는 정수 타입만 피연산자</code>가 될 수 있고, 부동 소수점 방식으로 저장되는 실수 타입은 피연산자가 될 수 없다.</p>
</li>
<li><p><code>byte, short, char</code> 타입 피연산자를 <code>int 타입으로 자동 변환한 후 연산을 수행</code>한다.
따라서, 결과도 int 타입 변수에 대입해야 한다.</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>＆ (논리곱)</td>
<td>두 비트가 모두 1일 경우 → 1</td>
</tr>
<tr>
<td>│ (논리합)</td>
<td>두 비트 중 하나만 1이면 → 1</td>
</tr>
<tr>
<td>＾ (배타적 논리합)</td>
<td>두 비트 중 하나는 1이고, 다른 하나가 0인 경우 → 1</td>
</tr>
<tr>
<td>∼ (논리 부정)</td>
<td>보수</td>
</tr>
</tbody></table>
<pre><code class="language-java">public class OperatorEx {
    public static void main(String[] args) {
        byte x = 12;
        byte y = 27;

        System.out.println(&quot;2진수 : &quot; + Integer.toBinaryString(x));                   // 2진수 : 1100
        System.out.println(&quot;2진수 : &quot; + Integer.toBinaryString(y));                   // 2진수 : 11011

        int BitwiseAnd = x &amp; y;
        System.out.println(&quot;10진수 : &quot;  + BitwiseAnd);                                // 10진수 : 8
        System.out.println(&quot;2진수 : &quot; + Integer.toBinaryString(BitwiseAnd));          // 2진수 : 1000

        int BitwiseOr = x | y;
        System.out.println(&quot;10진수 : &quot; + BitwiseOr);                                  // 10진수 : 31
        System.out.println(&quot;2진수 : &quot; + Integer.toBinaryString(BitwiseOr));           // 2진수 : 11111

        int BitwiseXor = x ^ y;
        System.out.println(&quot;10진수 : &quot;  + BitwiseXor);                                // 10진수 : 23
        System.out.println(&quot;2진수 : &quot; + Integer.toBinaryString(BitwiseXor));          // 2진수 : 10111

        int BitwiseComplement = ~ x;
        System.out.println(&quot;10진수 : &quot;  + BitwiseComplement);                          // 10진수 : -13
        System.out.println(&quot;2진수 : &quot; + Integer.toBinaryString(BitwiseComplement));    // 2진수 : 11111111111111111111111111110011
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/cf6b5b83-b6d0-4692-a7aa-a037f38e6c92/image.png" alt="비트논리연산자"></p>
<h1 id="39-비트-이동-연산자">3.9 비트 이동 연산자</h1>
<ul>
<li>비트를 좌측 또는 우측으로 밀어서 이동시키는 연산을 수행한다.</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>ａ 〈〈 ｂ (left shift 연산)</td>
<td>a의 각 비트를 b만큼 <strong>왼쪽</strong>으로 이동 <br> <strong>a × 2ⁿ</strong>와 동일한 결과가 된다. <br> 오른쪽 빈자리는 <strong>0</strong>으로 채운다.</td>
</tr>
<tr>
<td>ａ 〉〉 ｂ (right shift 연산)</td>
<td>a의 각 비트를 b만큼 <strong>오른쪽</strong>으로 이동 <br> <strong>a / 2ⁿ</strong>와 동일한 결과가 된다. <br> 왼쪽 빈자리는 <strong>최상위 부호 비트와 같은 값</strong>으로 채운다.</td>
</tr>
<tr>
<td>ａ 〉〉〉 ｂ</td>
<td>a의 각 비트를 b만큼 <strong>오른쪽</strong>으로 이동 <br> 왼쪽 빈자리는 <strong>0</strong>으로 채운다.</td>
</tr>
</tbody></table>
<h1 id="310-대입-연산자">3.10 대입 연산자</h1>
<ul>
<li><p>우측 피연산자의 값을 좌측 피연산자인 변수에 대입하거나, 정해진 연산을 수행한 후 결과를 대입할 수 있다.</p>
<pre><code class="language-java">public class OperatorEx {
  public static void main(String[] args) {
      int x = 2;
      int y  = x;

      System.out.println(y);                          // 2
      System.out.println( (x += 1) + &quot;, x  : &quot; + x);  // 3, x  : 3
      System.out.println( (x -= 1) + &quot;, x  : &quot; + x);  // 2, x  : 2
      System.out.println( (x *= 2) + &quot;, x  : &quot; + x);  // 4, x  : 4
  }
}
</code></pre>
</li>
</ul>
<pre><code># 3.11 삼항(조건)연산자
* 조건식이 **true**이면 **콜론(`:`) 앞**의 피연산자가 선택되고, false이면 **콜론 뒤**의 피연산자가 선택된다.
![삼항연산자](https://velog.velcdn.com/images/sj_kim/post/c0345536-d935-4f22-92a9-cd907e15491c/image.png)

# 3.12 연산의 방향과 우선순위
* 대부분의 연산자는 `왼쪽에서부터 오른쪽으로` 연산을 수행한다. 먼저 처리해야 할 연산은 `괄호( )`를 사용한다.
반면, 대입 연산자는 `오른쪽에서 왼쪽으로` 연산을 수행한다.

---
&lt;p&gt;
  &lt;img src=&quot;https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg&quot;&gt;
&lt;/p&gt;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Wrapper Class 정리]]></title>
            <link>https://velog.io/@sj_kim/Wrapper-Class-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@sj_kim/Wrapper-Class-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 16 Nov 2023 08:56:28 GMT</pubDate>
            <description><![CDATA[<h1 id="1-wrapper-class-정의">1. Wrapper Class 정의</h1>
<ul>
<li>자바의 8가지 기본 타입을 객체화하기 위해 포장한 형태로, 다양한 메소드와 필드를 사용할 수 있다.</li>
</ul>
<h1 id="2-wrapper-class-종류">2. Wrapper Class 종류</h1>
<table>
<thead>
<tr>
<th>Primitive type</th>
<th>Wrapper class</th>
</tr>
</thead>
<tbody><tr>
<td>byte</td>
<td>Byte</td>
</tr>
<tr>
<td>short</td>
<td>Short</td>
</tr>
<tr>
<td>int</td>
<td>Integer</td>
</tr>
<tr>
<td>long</td>
<td>Long</td>
</tr>
<tr>
<td>float</td>
<td>Float</td>
</tr>
<tr>
<td>double</td>
<td>Double</td>
</tr>
<tr>
<td>char</td>
<td>Character</td>
</tr>
<tr>
<td>boolean</td>
<td>Boolean</td>
</tr>
</tbody></table>
<h1 id="3-박싱boxing과-언박싱unboxing">3. 박싱(Boxing)과 언박싱(UnBoxing)</h1>
<ul>
<li>박싱 : 기본 타입 → 래퍼 클래스 변환</li>
<li>언박싱 : 래퍼 클래스 → 기본 타입 변환</li>
</ul>
<h1 id="4-wrapper-class-최대값-최소값">4. Wrapper Class 최대값, 최소값</h1>
<pre><code class="language-java">public class WrapperClassEx {
    public static void main(String[] args) {
        byte byteMinValue = Byte.MIN_VALUE;
        byte byteMaxValue = Byte.MAX_VALUE;
        int intMinValue = Integer.MIN_VALUE;
        int intMaxValue = Integer.MAX_VALUE;
        long longMinValue = Long.MIN_VALUE;
        long longMaxValue = Long.MAX_VALUE;

        System.out.println(String.format(&quot;Byte 최소값 : %d, 최대값 : %d&quot;, byteMinValue, byteMaxValue));   // Byte 최소값 : -128, 최대값 : 127
        System.out.println(String.format(&quot;Integer 최소값 : %d, 최대값 : %d&quot;, intMinValue, intMaxValue));  // Integer 최소값 : -2147483648, 최대값 : 2147483647
        System.out.println(String.format(&quot;Long 최소값 : %d, 최대값 : %d&quot;, longMinValue, longMaxValue));   // Double 최소값 : -9223372036854775808, 최대값 : 9223372036854775807

        System.out.println(String.format(&quot;Byte 최소값 : %d, 값 비교 : %b&quot;, (int) -Math.pow(2, 7), Byte.MIN_VALUE == -Math.pow(2, 7)));                      // Byte 최소값 : -128, 값 비교 : true
        System.out.println(String.format(&quot;Integer 최소값 : %d, 값 비교 : %b&quot;, (int) -Math.pow(2, 31), Integer.MIN_VALUE == -Math.pow(2, 31)));              // Integer 최소값 : -2147483648, 값 비교 : true
        System.out.println(String.format(&quot;Integer 최대값 : %d, 값 비교 : %b&quot;, (int) (Math.pow(2, 31) - 1), Integer.MAX_VALUE == (Math.pow(2, 31) - 1)));    // Integer 최대값 : 2147483647, 값 비교 : true
    }
}
</code></pre>
<ul>
<li>MAX_VALUE, MIN_VALUE 필드는 최대값과 최소값을 표현한다.</li>
<li>Math.pow( )메서드를 통해서도 최대값과 최소값을 구할 수 있다.<h2 id="41-byte-최대값과-최소값">4.1 Byte 최대값과 최소값</h2>
</li>
<li><code>bit</code>는 컴퓨터가 이해할 수 있는 최소 단위로 0과 1로 구성되어 있다.</li>
<li><code>Byte</code>는 컴퓨터에서 사용되는 가장 일반적인 데위터 단위로 1Byte는 8bit로 구성되고,
정수 Byte 타입은 8bit의 메모리 크기를 가진다.
<img src="https://velog.velcdn.com/images/sj_kim/post/7f64200b-01ab-4d1b-9b75-d4c5d393d53a/image.png" alt=""></li>
<li>제일 왼쪽에 있는 비트는 부호비트로 음수를 나타낼 수 있다.</li>
<li>2진수는 0과 1로 표시하는데, 0은 전기 스위치의 on, 1은 전기 스위치 off에 기인한다.</li>
</ul>
<h1 id="5-오버플로우overflow와-언더플로우underflow">5. 오버플로우(overflow)와 언더플로우(underflow)</h1>
<ul>
<li><p><strong>오버플로우</strong> : 데이터 값의 최대 표현 범위에서 벗어나는 것</p>
</li>
<li><p><strong>언더플로우</strong> : 데이터 값의 최소 표현 범위에서 벗어나는 것</p>
</li>
<li><p>오버플로우와 언더플로우 발생 시 해당 타입의 최소값 또는 최대값으로 되돌아가기 때문에 연산 시 주의하여야 한다.</p>
<pre><code class="language-java">public class WrapperClassEx {
  public static void main(String[] args) {
      byte byteMinValue = Byte.MIN_VALUE;
      byte byteMaxValue = Byte.MAX_VALUE;
      int intMinValue = Integer.MIN_VALUE;
      int intMaxValue = Integer.MAX_VALUE;

      System.out.printf(&quot;byte 최소값 : %d, 언더플로우 : %d\n&quot;, byteMinValue, --byteMinValue);     // byte 최소값 : -128, 언더플로우 : 127
      System.out.printf(&quot;byte 최소값 : %d, 오버플로우 : %d\n&quot;, byteMaxValue, ++byteMaxValue);     // byte 최소값 : 127, 오버플로우 : -128
      System.out.printf(&quot;int 최소값 : %d, 언더플로우 : %d\n&quot;, intMinValue, --intMinValue);        // int 최소값 : -2147483648, 언더플로우 : 2147483647
      System.out.printf(&quot;int 최소값 : %d, 오버플로우 : %d\n&quot;, intMaxValue, ++intMaxValue);        // int 최소값 : 2147483647, 오버플로우 : -2147483648
  }
}</code></pre>
<h2 id="51-byte-오버플로우">5.1 Byte 오버플로우</h2>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/c1cea330-40f2-466b-b59e-efad4b1cebbe/image.png" alt=""></p>
</li>
<li><p>2진수 덧셈에서 1 + 1은 10이 된다. 왜냐하면 <code>10진수 2</code> → <code>2진수 10</code>으로 표현되기 때문이다.</p>
</li>
</ul>
<h2 id="52-byte-언더플로우">5.2 Byte 언더플로우</h2>
<p><img src="https://velog.velcdn.com/images/sj_kim/post/1478e304-dd5e-4c69-86a6-04c5bedee313/image.png" alt=""></p>
<ul>
<li>-1은 부호비트를 사용하여 <code>10000001</code> 표시할 수 있는데, 이는 +0과 -0이 존재하는 문제가 있고, 양수·음수 간 연산이 어렵다.
그래서 <code>-1</code>은 2의 보수를 이용해 계산한다. <code>2의 보수</code>란 1의 보수(자리 비트 값 반전)를 구한 값에 + 1 한 것이다.
즉, 1의 2진수 : <code>00000001</code> → 1의 보수 : <code>11111110</code> → 더하기 1 : <code>11111111</code>로,</li>
<li>1의 2진수는 <code>11111111</code>로 표현할 수 있다.(-128 + (64 + 32+ 16 + 8 + 4 + 2 + 1) = -1)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JIT(Just-In-Time) 컴파일러]]></title>
            <link>https://velog.io/@sj_kim/JITJust-In-Time-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC</link>
            <guid>https://velog.io/@sj_kim/JITJust-In-Time-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC</guid>
            <pubDate>Thu, 16 Nov 2023 05:15:25 GMT</pubDate>
            <description><![CDATA[<h1 id="1-컴파일러-정의">1. 컴파일러 정의</h1>
<blockquote>
<p>특정 프로그램밍 언어로 쓰여 있는 문서를 다른 프로그래밍 언어로 옮기는 언어 <code>번역 프로그램</code>
<span style="color:#04B486"><em>출처👉<a href="https://ko.wikipedia.org/wiki/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC">위키백과</a></em></span></p>
</blockquote>
<h2 id="1-자바-컴파일러">1) 자바 컴파일러</h2>
<ul>
<li>자바 소스 코드를 JVM이 이해할 수 있는 자바 바이트 코드로 변환
<img src="https://velog.velcdn.com/images/sj_kim/post/4800b92f-0ab9-4326-91db-9228358df6d3/image.png" alt=""></li>
</ul>
<blockquote>
<p>💡 <strong>javap 명령어</strong></p>
</blockquote>
<ul>
<li>클래스 파일을 역어셈블(Disassemble)하는 명령어</li>
<li>-c : 클래스 파일의 바이트 코드를 보여준다.</li>
</ul>
<h1 id="2-컴파일러-동작-방식">2. 컴파일러 동작 방식</h1>
<ul>
<li><code>전체 소스 코드 파일</code>을 가져와 사용되지 않는 코드나 중복된 코드 등을 <code>분석 후 최적화</code> 한다.</li>
<li>코드가 수정되면 컴파일을 다시 해야하는 단점이 있다.</li>
</ul>
<h1 id="3-jit-컴파일러-정의">3. JIT 컴파일러 정의</h1>
<ul>
<li><code>프로그램을 실행하는 동안 실시간으로 기계어로 번역하는 컴파일러</code>로
Just-In-Time이라 불리는 이유는 실행 시점에 코드를 컴파일하고 최적화하기 때문이다.</li>
</ul>
<h1 id="4-java에서-jit-컴파일러-동작-방식">4. Java에서 JIT 컴파일러 동작 방식</h1>
<blockquote>
</blockquote>
<p><img src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*ZAzYxBXnTKl6RGZ9jvZmvg.jpeg" alt="JIT Compiler"><span style="color:#04B486"><em>출처👉<a href="https://medium.com/nerd-for-tech/jit-java-just-in-time-jit-compiler-af1cc86fe53b">JIT Java|Just In Time (JIT) Compiler</a></em></span></p>
<blockquote>
</blockquote>
<p><img src="https://cdn-jndph.nitrocdn.com/kwZVykLDpYcpjbQfkelLdgBReCNswIAm/assets/images/optimized/wp-content/uploads/2019/12/1d6630d2cf173ef23ff5c9f605bb67e6.10-768x459.png" alt="Execution Engine"><span style="color:#04B486"><em>출처👉<a href="https://waytoeasylearn.com/learn/execution-engine/">Execution Engine</a></em></span></p>
<ul>
<li>Execution Engine이 동작하며 Java 바이트 코드를 실행하면,</li>
<li><em>JIT Compiler*</em>는 <code>Profiler</code>가 실행 중인 애플리케이션의 <code>hot spot(자주 사용되는 코드)</code>을 식별하고, 특정 메서드에 대한 <code>호출 횟수</code> 등을 <code>카운트</code>하여 알리면 이를 최적화하여 Native Code로 변환한다.
또한, 일부 코드 블럭이 많이 호출되면 이를 <code>code cache</code>로 옮겨 빠르게 액세스할 수 있도록 한다.</li>
<li>JVM은 인터프리터와 JIT 컴파일러를 함께 사용한다.</li>
</ul>
<h2 id="1-인터프리터-정의">1) 인터프리터 정의</h2>
<blockquote>
<p>프로그래밍 언어의 <code>소스 코드를 바로 실행</code>하는 컴퓨터 프로그램 또는 환경을 말한다.
<span style="color:#04B486"><em>출처👉<a href="https://ko.wikipedia.org/wiki/%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0">위키백과</a></em></span></p>
</blockquote>
<h2 id="2-인터프리터-동작-방식">2) 인터프리터 동작 방식</h2>
<ul>
<li><code>한 번에 한 줄씩</code>, 소스 코드 파일에서 라인을 읽고 프로세서가 실행할 수 있도록 전송하고, 그다음 라인을 읽고 전송하는 동작을 반복한다.</li>
<li>코드가 길어질수록 속도가 느려지는 단점이 있다.</li>
</ul>
<blockquote>
<p>🤔 <strong>코틀린과 자바가 100% 호환되는 이유</strong></p>
</blockquote>
<ul>
<li>코틀린과 자바는 JVM에서 실행되며, 코틀린 또한 컴파일러를 통해 자바 바이트 코드로 변환된다.</li>
</ul>
<hr>
<p>💡<strong>참고</strong></p>
<ul>
<li><a href="https://www.youtube.com/watch?v=GXUiEouK7DM">Java Program Execution Process in Detail | Working of JUST-IT-TIME Compiler (JIT) in Detail</a>, YouTube</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 02. 변수와 타입]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-02.-%EB%B3%80%EC%88%98%EC%99%80-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-02.-%EB%B3%80%EC%88%98%EC%99%80-%ED%83%80%EC%9E%85</guid>
            <pubDate>Wed, 15 Nov 2023 01:18:24 GMT</pubDate>
            <description><![CDATA[<h1 id="21-변수-선언">2.1 변수 선언</h1>
<ul>
<li>변수는 하나의 값을 저장할 수 있는 메모리 번지에 붙여진 이름으로, 프로그램은 메모리 번지에 값을 저장하고 읽을 수 있다.</li>
<li>변수 선언은 어떤 타입의 데이터를 저장할 것인지와 변수 이름이 무엇인지를 결정한다.</li>
<li>변수 이름은 첫 문자를 소문자로 시작하되 캐멀 스타일로 작성하는 것이 관례이다.</li>
<li>대입 연산자<code>(=)</code>를 사용해 선언된 변수에 값을 저장할 수 있다.</li>
<li>변수에 최초로 값(=초기값)이 대입될 때 메모리에 할당되고, 해당 메모리에 값이 저장되며 이를 <code>변수 초기화</code>라 한다.</li>
<li>변수는 또 다른 변수에 대입되어 메모리 간에 값을 <code>복사</code>할 수 있다.<p align="center" width="50%">
<img src="https://velog.velcdn.com/images/sj_kim/post/11923a67-6af9-4976-835c-542ef3761a06/image.png" width="450">
</p>

</li>
</ul>
<h1 id="22-정수-타입">2.2 정수 타입</h1>
<ul>
<li>자바는 정수, 실수, 논리값을 저장할 수 있는 기본(privitive)타입 8개를 제공한다.</li>
<li>기본적으로 컴파일러는 정수 리터럴(=프로그래머가 직접 입력한 값)을 <code>int 타입</code>으로 간주한다. 따라서, <code>long 타입 값</code>을 사용하고 싶다면 <code>소문자 &#39;l&#39; 또는 대문자 &#39;L&#39;</code>을 붙여 컴파일러에게 알려줘야 한다.</li>
</ul>
<table>
<thead>
<tr>
<th>데이터형</th>
<th>메모리크기</th>
</tr>
</thead>
<tbody><tr>
<td>byte</td>
<td>1byte(8bit)</td>
</tr>
<tr>
<td>short</td>
<td>2byte(16bit)</td>
</tr>
<tr>
<td>char</td>
<td>2byte(16bit)</td>
</tr>
<tr>
<td>int</td>
<td>4byte(32bit)</td>
</tr>
<tr>
<td>long</td>
<td>8byte(64bit)</td>
</tr>
</tbody></table>
<h1 id="23-문자-타입">2.3 문자 타입</h1>
<ul>
<li>하나의 문자를 작은 따옴표<code>&#39; &#39;</code>로 감싼 것을 문자 리터럴이라고 하며, 유니코드로 변환되어 저장된다. 따라서, <code>char 변수</code>에 유니코드 숫자를 직접 대입할 수도 있다.</li>
<li>char 변수는 <code>공백 하나(유니코드:32)를 포함해서 초기화</code>해야 한다.<blockquote>
<p>유니코드(Unicode)는 전 세계의 모든 문자를 다루도록 설계된 표준 문자 전산 처리 방식이다.
👉🏻<a href="https://namu.wiki/w/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C">나무위키 - 유니코드</a></p>
</blockquote>
</li>
</ul>
<h1 id="24-실수-타입">2.4 실수 타입</h1>
<ul>
<li>기본적으로 컴파일러는 실수 리터럴(=프로그래머가 직접 입력한 값)을 <code>double 타입</code>으로 간주한다. 따라서, <code>float 타입 값</code>을 사용하고 싶다면 <code>소문자 &#39;f&#39; 또는 대문자 &#39;F&#39;</code>을 붙여 컴파일러에게 알려줘야 한다.</li>
</ul>
<table>
<thead>
<tr>
<th>데이터형</th>
<th>메모리크기</th>
</tr>
</thead>
<tbody><tr>
<td>float</td>
<td>4byte(32bit)</td>
</tr>
<tr>
<td>double</td>
<td>8byte(64bit)</td>
</tr>
</tbody></table>
<h1 id="25-논리-타입">2.5 논리 타입</h1>
<ul>
<li>참과 거짓을 의미하는 논리 리터럴은 true와 false이다.</li>
</ul>
<table>
<thead>
<tr>
<th>데이터형</th>
<th>메모리크기</th>
</tr>
</thead>
<tbody><tr>
<td>boolean</td>
<td>1byte(8bit)</td>
</tr>
</tbody></table>
<h1 id="26-문자열-타입">2.6 문자열 타입</h1>
<ul>
<li><p>여러 개의 문자열을 큰 따옴표<code>&quot; &quot;</code>로 감싼 것으로, 유니코드로 변환되지 않는다.</p>
</li>
<li><p><code>String 타입</code>은 기본 타입에 속하지 않는 <code>참조 타입</code>이다.</p>
</li>
<li><p>문자열 내부에 <code>이스케이프 문자(=역슬래쉬가 붙은 문자)</code>를 사용해 특정 문자를 포함하거나 출력 방식을 수정할 수 있다.</p>
</li>
<li><p><code>자바 13부터는 텍스트 블록 문법</code>을 제공한다. 큰따옴표 3개<code>&quot;&quot;&quot; &quot;&quot;&quot;</code>로 감싸면 이스케이프하거나 라인피드할 필요 없이 작성된 그대로 문자열로 저장된다.</p>
<pre><code class="language-java">public class StringExample {

  public static void main(String []args) {
      System.out.println(&quot;----------&quot;);
      System.out.println(&quot;받아들이면 된다&quot;);
      System.out.println(&quot;\&quot;지는 해\&quot;를 깨우며 노력하지 말거라&quot;);
      System.out.print(&quot;너는\t달빛에\t더\t아름답다\n&quot;);
      String name = &quot;서혜진&quot;;
      String title = &quot;너에게&quot;;
      System.out.print(name);
      System.out.print(&quot;\\&quot;);
      System.out.println(title);

      System.out.println(&quot;----------&quot;);
      System.out.println(&quot;Java 13 이후&quot;);
      String poem = &quot;&quot;&quot;
              받아들이면 된다
              &quot;지는 해&quot;를 깨우며 노력하지 말거라
              너는 달빛에  더  아름답다
              서혜진\\너에게
              &quot;&quot;&quot;;
      System.out.println(poem);
  }
}</code></pre>
<p align="center" width="50%">
<img src="https://velog.velcdn.com/images/sj_kim/post/33abb307-dc77-4ee1-997f-648abdaf5ee0/image.png" width="200" title="실행결과">
</p>

</li>
</ul>
<h1 id="27-자동-타입-변환">2.7 자동 타입 변환</h1>
<ul>
<li>값의 허용 범위가 <code>작은 타입이 큰 타입으로 대입될 때</code> 발생</li>
<li>단, <code>byte 타입은 char 타입으로 자동 타입 변환이 될 수 없다.</code> 왜냐하면 char 타입의 허용 범위는 음수를 포함하지 않는데, byte 타입은 음수를 포함하기 때문이다. (자동 타입 변환 예외)</li>
</ul>
<h1 id="28-강제-타입-변환">2.8 강제 타입 변환</h1>
<ul>
<li>값의 허용 범위가 <code>큰 타입을 작은 타입으로 쪼개어 저장</code>하는 것을 강제 타입 변환(casting)이라고 한다.</li>
<li><code>강제 타입의 목적은 원래 값이 유지되면서 타입만 바꾸는 것</code>이므로, 작은 허용 범위 타입에 저장될 수 있는 값을 가지고 강제 타입 변환을 해야 한다.</li>
</ul>
<pre><code class="language-java">public class Example {

    public static void main(String []args) {
        int intValue = 10;
        char charValue = &#39;A&#39;;
        double doubleValue = 5.7;
        String strValue = &quot;A&quot;;

        System.out.println((byte) intValue);     // 10 출력
        System.out.println((int) doubleValue);   // 5 출력
        System.out.println((char) strValue);     // 컴파일 에러 발생 : Inconvertible types; cannot cast &#39;java.lang.String&#39; to &#39;char&#39;
    }
}</code></pre>
<h1 id="29-연산식에서-자동-타입-변환">2.9 연산식에서 자동 타입 변환</h1>
<ul>
<li>자바는 <code>컴파일 단계에서 연산을 수행</code>한다.
단, <code>정수 리터럴이 아닌 피연산자로 사용되면 실행 단계에서 연산을 수행</code>한다.</li>
<li>byte, short 타입의 변수는 <code>int 타입으로 자동 타입 변환</code>되어 연산을 수행한다.</li>
<li>피연산자 중 하나가 double 타입이면 다른 연산자도 double 타입으로 변환되어 연산된다.</li>
<li>피연산자 중 하나가 문자열 타입이면 나머지 연산자도 문자열로 자동 변환되어 문자열 결합 연산을 수행한다.</li>
</ul>
<h1 id="210-문자열을-기본-타입으로-변환">2.10 문자열을 기본 타입으로 변환</h1>
<pre><code class="language-java">public class Example {

    public static void main(String []args) {
        String str = &quot;5&quot;;

        System.out.println(Byte.parseByte(str));       // 5 출력
        System.out.println(Integer.parseInt(str));     // 5 출력
        System.out.println(Float.parseFloat(str));     // 5.0 출력
        System.out.println(Double.parseDouble(str));   // 5.0 출력
    }
}</code></pre>
<h1 id="211-변수-사용-범위">2.11 변수 사용 범위</h1>
<ul>
<li>중괄호<code>{ }</code> 블록 내에서 선언된 변수는 해당 블록 내에서만 사용 가능하고 밖에서는 사용할 수 없다.</li>
<li>블록 전체에서 사용하고 싶다면 메소드 블록 첫머리에 선언하는 것이 좋다.</li>
</ul>
<hr>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>


]]></description>
        </item>
        <item>
            <title><![CDATA[[이것이자바다] Chapter 01. 자바 시작하기]]></title>
            <link>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-01.-%EC%9E%90%EB%B0%94-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sj_kim/%EC%9D%B4%EA%B2%83%EC%9D%B4%EC%9E%90%EB%B0%94%EB%8B%A4-Chapter-01.-%EC%9E%90%EB%B0%94-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 14 Nov 2023 09:50:46 GMT</pubDate>
            <description><![CDATA[<h1 id="11-프로그래밍-언어와-자바">1.1 프로그래밍 언어와 자바</h1>
<ul>
<li>컴퓨터가 이해할 수 있는 <code>기계어는 0과 1로 이루어진 이진 코드</code>를 사용한다.</li>
<li>프로그래밍 언어는 사람의 언어와 기계어의 다리 역할을 한다.</li>
<li>프로그래밍 언어는 <code>고급 언어와 저급 언어</code>로 구분된다.<ul>
<li><code>고급 언어란 사람이 쉽게 이해할 수 있는 언어</code>로, 컴퓨터는 컴파일 과정을 통해 기계어로 변환 후 사용한다. 대표적으로 자바, C, 파이썬 등이 있다.</li>
<li>개발자가 고급 언어로 작성한 파일을 소스 파일이라고 부른다.</li>
<li><code>저급 언어란 기계어에 가까운 언어</code>이다.<h2 id="자바의-특징">자바의 특징</h2>
</li>
<li>모든 운영체제에서 실행 가능</li>
<li>객체 지향 프로그래밍</li>
<li>메모리 자동 정리</li>
</ul>
</li>
</ul>
<h1 id="12-운영체제별-jdk-설치">1.2 운영체제별 JDK 설치</h1>
<ul>
<li>자바 프로그램을 개발하고 실행하기 위해서는 JDK(Java Development Kit)를 설치해야 한다.
OpenJDK17 버전 다운로드👉 <a href="https://adoptium.net/">어답티움</a></li>
</ul>
<h1 id="13-윈도우-환경-변수-설정">1.3 윈도우 환경 변수 설정</h1>
<ul>
<li>운영체제는 프로그램들이 실행하면서 사용할 수 있는 값들을 환경 변수 이름으로 관리한다.
<img src="https://velog.velcdn.com/images/sj_kim/post/271c9ec6-836b-4c77-a1ef-4422f2c56bad/image.png" alt="" title="JAVA_HOME 환경변수 설정"></li>
<li>Path 환경 변수에 <code>%JAVA_HOME%\bin</code>을 첫 번째 항목으로 올려준다. 이렇게 하는 이유는 등록된 순서대로 명령어를 찾기 때문이다.
<img src="https://velog.velcdn.com/images/sj_kim/post/34e7ab64-1bc2-4459-9842-5558e493c9bd/image.png" alt=""></li>
<li>명령 프롬프트로 환경 변수가 올바르게 설정되었는지 확인한다.
<img src="https://velog.velcdn.com/images/sj_kim/post/85b5ada1-cb4d-4ffc-a942-cd27e73326fe/image.png" alt=""></li>
</ul>
<h1 id="15-바이트코드-파일과-자바-가상-머신">1.5 바이트코드 파일과 자바 가상 머신</h1>
<ul>
<li><code>.java</code> : 자바 소스 파일 확장명</li>
<li><code>.class</code> : 바이트코드 파일 확장명</li>
</ul>
<h2 id="자바-가상-머신">자바 가상 머신</h2>
<ul>
<li><code>java 명령어는</code> JDK와 함께 설치된 JVM(Java Virtual Machine)을 구동시켜 <code>바이트 코드 파일을 기계어로 번역하여 실행</code>시킨다.</li>
<li><code>바이트코드 파일</code>은 <code>운영체제와 상관없이 모두 동일</code>한 내용이지만, <code>자바 가상 머신은 운영체제별로 다르게 설치</code>된다.</li>
</ul>
<h1 id="16-소스-작성부터-실행까지">1.6 소스 작성부터 실행까지</h1>
<ul>
<li>콘솔에 <code>Hello, world!</code> 출력하기<p align="center">
<img src="https://velog.velcdn.com/images/sj_kim/post/ad2f0c9d-1f8a-4293-bc77-28441a042be1/image.png" width="200px">
</p>

</li>
</ul>
<blockquote>
<p>💡 javac 명령어 옵션</p>
</blockquote>
<ul>
<li>-d : directory 의미, 바이트코드파일이 저장될 대상 디렉터리 지정</li>
</ul>
<blockquote>
<p>💡 java 명령어 옵션</p>
</blockquote>
<ul>
<li>-cp : classpath 의미, 컴파일 대상인 바이트코드의 경로를 지정</li>
</ul>
<h1 id="110-코드-용어-이해">1.10 코드 용어 이해</h1>
<h2 id="클래스명">클래스명</h2>
<ul>
<li>숫자로 시작할 수 없고, 공백을 포함해서는 안 되며 대문자로 시작한다.</li>
</ul>
<h2 id="main-메소드">main( )메소드</h2>
<ul>
<li><code>프로그램 실행 진입점</code>, 바이트코드 파일을 실행하면 main( ) 메소드 블록이 실행된다.</li>
</ul>
<h1 id="112-실행문과-세미콜론">1.12 실행문과 세미콜론</h1>
<ul>
<li>실행문 끝에는 반드시 세미콜론(;)을 붙여야 한다.</li>
</ul>
<hr>
<p>
  <img src="https://velog.velcdn.com/images/sj_kim/post/fce4e881-0954-49be-8c04-2032000105f9/image.jpg">
</p>
]]></description>
        </item>
    </channel>
</rss>