<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>bill_0285.log</title>
        <link>https://velog.io/</link>
        <description>새로운 여정은 언제나 두렵고 동시에 흥미로 가득 차 있다.</description>
        <lastBuildDate>Thu, 11 May 2023 12:49:27 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>bill_0285.log</title>
            <url>https://velog.velcdn.com/images/bill_0285/profile/af806929-3724-44a2-9a2e-195a19f2e922/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. bill_0285.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bill_0285" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[내부 클래스]]></title>
            <link>https://velog.io/@bill_0285/%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@bill_0285/%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Thu, 11 May 2023 12:49:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="내부-클래스란">내부 클래스란?</h1>
<hr>
<ul>
<li><p>클래스 내부에 선언한 클래스로 이 클래스를 감싸고 있는 외부 클래스와 밀접한 연관이 있는 경우가 많고,</p>
</li>
<li><p>다른 외부 클래스에서 사용할 일이 거의 없는 경우에 내부 클래스로 선언해서 사용함</p>
</li>
<li><p>중첩 클래스라고도 함</p>
</li>
<li><p>내부 클래스의 종류</p>
<p><code>인스턴스(instance)</code> 내부 클래스, 
<code>정적(static)</code> 내부 클래스, 
<code>지역(local)</code> 내부 클래스, 
<code>익명(anonymous)</code> 내부 클래스</p>
</li>
</ul>
<h1 id="인스턴스-내부-클래스">인스턴스 내부 클래스</h1>
<hr>
<ul>
<li><p>내부적으로 사용할 클래스를 선언 (private으로 선언하는 것을 권장)</p>
</li>
<li><p>외부 클래스가 생성된 후 생성됨 ( 정적 내부 클래스는 외부클래스명으로 바로 접근 가능 )</p>
</li>
<li><p>private이 아닌 내부 클래스는 다른 외부 클래스에서 생성할 수 있음</p>
</li>
</ul>
<pre><code class="language-java">OutClass outClass = new OutClass();
//아웃 클래스 객체 하나 만들고
OutClass.InClass inClass = outClass.new InClass();
//그 객체를 통해 인클래스 객체 생성가능</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[동적 로딩]]></title>
            <link>https://velog.io/@bill_0285/%EB%8F%99%EC%A0%81-%EB%A1%9C%EB%94%A9</link>
            <guid>https://velog.io/@bill_0285/%EB%8F%99%EC%A0%81-%EB%A1%9C%EB%94%A9</guid>
            <pubDate>Thu, 11 May 2023 08:34:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="동적-로딩">동적 로딩</h1>
<hr>
<ul>
<li><p>컴파일 시에 데이터 타입이 binding 되는 것이 아닌, <strong>실행(runtime) 중에 데이터 타입을 <code>binding</code> 하는 방법</strong></p>
</li>
<li><p>프로그래밍 시에는 문자열 변수로 처리했다가 런타임시에 원하는 클래스를 로딩하여 <strong><code>binding</code></strong> 할 수 있다는 장점</p>
</li>
<li><p>컴파일 시에 타입이 정해지지 않으므로 동적 로딩시 오류가 발생하면 프로그램의 심각한 장애가 발생가능</p>
</li>
</ul>
<p>ex)</p>
<p>JDBC를 사용할떄 JDBC DB 라이브러리(Oracle,MySQL,MSSQL) 모두 Static하게 링크되어 컴파일이 되는 방식이 아닌, 라이브러리가 설치된 상태에서 필요시 호출이 된다.</p>
<p> <br><br></p>
<h2 id="class-클래스-사용하기">Class 클래스 사용하기</h2>
<hr>
<ul>
<li><p>자바의 모든 클래스와 인터페이스는 <strong>컴파일 후 .class 파일이 생성됨</strong></p>
</li>
<li><p><strong>Class 클래스</strong>는 컴파일 된 class 파일을 로드하여 <strong>객체를 동적 로드하고, 정보를 가져오는 메서드가 제공됨</strong></p>
</li>
</ul>
<ol>
<li>Class.forName(&quot;클래스 이름&quot;) 메서드로 클래스를 동적으로 로드 함<pre><code class="language-java">Class c = Class.forName(&quot;java.lang.String&quot;);</code></pre>
</li>
</ol>
<ol start="2">
<li>클래스 이름으로 직접 Class 클래스 가져오기</li>
</ol>
<pre><code class="language-java">Class c = String.class;
</code></pre>
<ol start="3">
<li>생성된 인스턴스에서 Class 클래스 가져오기</li>
</ol>
<pre><code class="language-java">String s = new String();
Class c = s.getClass();  //Object 메서드</code></pre>
<ul>
<li>Class의 newInstance()메서드로 인스턴스 생성
=&gt; new 키워드를 사용하지 않고 클래스 정보를 활용하여 인스턴스를 생성할 수 있음 </li>
</ul>
<h2 id="예제">예제</h2>
<p>DynamicLoadingTest.java</p>
<pre><code class="language-java">public class DynamicLoadingTest {

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

        Class c3 =  Class.forName(&quot;java.lang.String&quot;);
        //Class.forName 메서드는 클래스 이름을 인수로 사용하고
        //해당 클래스의 Class 개체를 반환한다.
        Constructor&lt;String&gt;[] cons =  c3.getConstructors();
        // getConstructors() 메서드는 Class 개체에 대한 
        // 모든 생성자를 포함하는 Constructor[] 배열을 반환한다.
        for(Constructor con: cons) {
            System.out.println(con);
        }//String의 모든 생성자들이 출력될 것이다.

        System.out.println();

        Method[] methods = c3.getMethods();
        //getMethods() 메서드는 Class 개체에 대한 
        // 모든 메서드를 포함하는 Method[] 배열을 반환한다.
        for(Method  method : methods) {
            System.out.println(method);
        }//String의 모든 메서드들이 출력될 것이다.
    }

}</code></pre>
<p>메서드 출력 결과 (너무 많아서 짤림)
<img src="https://velog.velcdn.com/images/bill_0285/post/98fe006c-173d-4344-b52c-fac5fd1efd0e/image.png" alt=""></p>
<p>생성자 출력 결과 </p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/3c699d89-6d81-4c0d-8f7e-ba593ed7df70/image.png" alt=""></p>
<h1 id="reflection-프로그래밍">reflection 프로그래밍</h1>
<hr>
<h2 id="설명">설명</h2>
<ul>
<li><p><strong>Class 클래스를 사용하여 클래스의 정보(생성자, 변수, 메서드)등을 알 수 있고 인스턴스를 생성하고, 메서드를 호출하는 방식의 프로그래밍</strong></p>
</li>
<li><p>로컬 메모리에 객체가 없는 경우, 원격 프로그래밍, 객체의 타입을 알 수 없는 경우에 사용</p>
</li>
<li><p>java.lang.reflect 패키지에 있는 클래스를 활용하여 프로그래밍</p>
</li>
<li><p>일반적으로 자료형을 알고 있는 경우엔 사용하지 않음</p>
</li>
</ul>
<h2 id="예제-1">예제</h2>
<p>Person.java (예제로 쓰일 객체)</p>
<pre><code class="language-java">public class Person {
    private String name;
    private int age;

    public Person() {};

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

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return name;
    }
}</code></pre>
<p>ClassTest.java</p>
<pre><code class="language-java">public class ClassTest {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
                        ClassNotFoundException, NoSuchMethodException, SecurityException {
        //1. 일반적인 객체 생성 방법
        Person person = new Person(&quot;James&quot;);
        System.out.println(person);
        //James가 출력된다.


        //2. Class 클래스를 이용한 방법

        //ch04패키지에 있는 Person이라는 클래스를 찾아서 
        //Class 자료형으로 반환
        Class personClass = Class.forName(&quot;ch04.Person&quot;);

        // String 클래스 찾아서 Class 자료형으로 반환
        Class parameterType = Class.forName(&quot;java.lang.String&quot;);

        //Class 클래스의 getConstructor() 메서드는 지정된 매개변수 유형 목록과 
        //일치하는 클래스의 생성자를 반환한다.
        Constructor cons = personClass.getConstructor(parameterType);

        Object initargs = &quot;DIGIMON&quot;;
        //newInstance() 메서드는 해당 생성자로 인스턴스를
        //생성할떄 사용되고, 매개변수는 Object자료형으로 넣어주면 된다.
        //Object 자료형을 반환하기에, Person 자료형으로 명시적 형변환(다운캐스팅)을 한다.
        //Object 클래스는 모든 클래스의 최상위 클래스이다.
        Person personLee = (Person) cons.newInstance(initargs);
        System.out.println(personLee);
        //DIGIMON이 출력된다.


    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[String, StringBuilder, StringBuffer, text block]]></title>
            <link>https://velog.io/@bill_0285/String-StringBuilder-StringBuffer-text-block</link>
            <guid>https://velog.io/@bill_0285/String-StringBuilder-StringBuffer-text-block</guid>
            <pubDate>Thu, 11 May 2023 07:21:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="string-클래스">String 클래스</h1>
<hr>
<h2 id="string-선언하기">String 선언하기</h2>
<p>힙 메모리에 인스턴스로 생성되는 경우와 상수 풀(constant pool)에 있는 주소를 참조하는 두 가지 방법이 있다.</p>
<pre><code>   ```java
String str1 = new String(&quot;abc&quot;); //인스턴스로 생성
String str2 = &quot;abc&quot;; //상수 풀(constant pool)에 있는 주소를 참조</code></pre><pre><code>


힙 메모리는 생성될때마다 다른 주소 값을 가지지만, 상수 풀의 문자열은 모두 같은 주소 값을 가짐


```java
public class StringTest {

    public static void main(String[] args) {
        String str1 = new String(&quot;abc&quot;);
        String str2 = new String(&quot;abc&quot;);

        System.out.println(str1 == str2);//false
        System.out.println(System.identityHashCode(str1));//2055281021
        System.out.println(System.identityHashCode(str2));//1554547125
        //즉 해쉬코드가 다르므로 생성될때 마다 서로 다른 주소를 가짐을 확인 가능.

        String str3 = &quot;abc&quot;;
        String str4 = &quot;abc&quot;;

        System.out.println(str3 == str4);//true
        System.out.println(System.identityHashCode(str3));//617901222
        System.out.println(System.identityHashCode(str4)); //617901222
        //즉 해쉬코드가 같으므로 상수 풀의 문자열은 모두 같은 주소값을 가짐 
    }
}</code></pre><p>왜그런지 알려면, 상수 풀이 무엇인지 알아야한다.</p>
<h2 id="string-constant-pool">String Constant Pool</h2>
<ul>
<li><p><strong>String literal로 생성한 객체는 &quot;String Constant Pool&quot;에 들어간다.</strong></p>
</li>
<li><p><strong>&quot;String Constant Pool&quot;은 Heap 영역 내 존재한다.</strong></p>
</li>
<li><p>new 연산자로 생성한 String 객체는 같은 값이 String Pool에 이미 존재하더라도, Heap 영역 내 별도의 객체를 가리키게 된다.</p>
</li>
</ul>
<p>즉,</p>
<p>자바에서 String 자료형 변수를 String literal로 생성하면 해당 String 값은 Heap 영역 내 &quot;String Constant Pool&quot;에 저장되어 재사용되지만,</p>
<p>new 연산자로 생성하면 같은 내용이라도 여러 개의 객체가 각각 Heap 영역을 차지한다. =&gt; 일반적인 객체의 동적할당 과정과 동일.</p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/f99eb577-daa9-4430-bdc3-1e3ec0242cfb/image.png" alt=""></p>
<p><strong>String literal로 생성한 객체의 값(위그림에선 &quot;Cat&quot;)이 이미 String Pool에 존재한다면, 해당 변수는 String Pool의 메모리 주소를 참조한다.</strong></p>
<p>위 그림에서 변수 s1과 s2가 같은 곳을 가리키고 있는 것도 이 때문이다.</p>
<h2 id="문자열-합치기">문자열 합치기</h2>
<ul>
<li><p>한번 생성된 String은 불변(immutable)하다</p>
</li>
<li><p>String을 연결하면 기존의 String에 연결되는 것이 아닌 새로운 문자열이 생성됨 ( 메모리 낭비가 발생할 수 있다.)</p>
</li>
</ul>
<pre><code class="language-java">public class StringTest2 {

    public static void main(String[] args) {
        String java = new String(&quot;java&quot;);
        String android = new String(&quot;android&quot;);
        System.out.println(System.identityHashCode(java));
        java = java.concat(android);
        System.out.println(System.identityHashCode(java));
        //java변수의 해쉬코드와, 거기에 android를 이어붙인 변수의 해쉬코드는 다르다.
    }
}</code></pre>
<h1 id="stringbuilder-stringbuffer">StringBuilder, StringBuffer</h1>
<hr>
<ul>
<li>내부적으로 가변적인 char[]를 멤버 변수로 가짐</li>
</ul>
<ul>
<li>문자열을 여러번 연결하거나 변경할 때 사용하면 유용함</li>
</ul>
<ul>
<li><p>새로운 인스턴스를 생성하지 않고 char[] 를 변경함</p>
</li>
<li><p>StringBuffer는 멀티 쓰레드 프로그래밍에서 동기화(synchronization)을 보장 =&gt; 공유자원 동시접근시, 순서가 정해짐</p>
</li>
<li><p>단일 쓰레드 프로그램에서는 StringBuilder 사용을 권장</p>
</li>
<li><p>toString() 메서드로 String반환</p>
<pre><code class="language-java">public class StringBuilderTest {
//StringBuffer도 문법이 똑같음.
//StringBuffer buffer = new StringBuffer(java);

  public static void main(String[] args) {
      String java = new String(&quot;java&quot;);
      String android = new String(&quot;android&quot;);

      StringBuilder buffer = new StringBuilder(java);
      System.out.println(System.identityHashCode(buffer));
      buffer.append(&quot;android&quot;);
      System.out.println(System.identityHashCode(buffer));
      //출력한 두 해쉬코드는 동일한 16진수를 출력함
      java = buffer.toString();
  }
}</code></pre>
</li>
</ul>
<h1 id="text-blockafter-java-15">text block(after Java 15)</h1>
<hr>
<p>Java 15부터는 &quot;&quot;&quot; (큰따옴표 3개)로 시작하여 그 뒤에 선택적 공백과 줄 바꿈이 오는 텍스트 블록을 사용할 수 있다. </p>
<p>html, json 문자열을 만드는데 유용하게 사용할 수 있음</p>
<pre><code class="language-java">public class StringTextBlock {

    public static void main(String[] args) {

        String strBlock = &quot;&quot;&quot;
                This 
                is 
                text
                block
                test.&quot;&quot;&quot;;
        System.out.println(strBlock);

        System.out.println(getBlockOfHtml());

    }

    public static String getBlockOfHtml() {
            return &quot;&quot;&quot;
                    &lt;html&gt;

                        &lt;body&gt;
                            &lt;span&gt;example text&lt;/span&gt;
                        &lt;/body&gt;
                    &lt;/html&gt;&quot;&quot;&quot;;

    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[추상클래스 vs 인터페이스 (w. IS-A vs HAS-A)]]></title>
            <link>https://velog.io/@bill_0285/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-vs-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@bill_0285/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-vs-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Wed, 10 May 2023 14:53:29 GMT</pubDate>
            <description><![CDATA[<h2 id="추상클래스와-인터페이스는-뭐가-달라요">추상클래스와 인터페이스는 뭐가 달라요?</h2>
<p>다음과 같이 gpt chat에게 물어봤다</p>
<blockquote>
<p>추상클래스와 인터페이스 따로 쓰는 이유가 뭐야? 추상클래스가 인터페이스의 기능을 모두 할 수 있을거 같은데?</p>
</blockquote>
<p>답변은 아래와 같다.</p>
<blockquote>
<p>추상 클래스와 인터페이스는 모두 추상화된 개념입니다. 하지만 두 개념은 사용하는 목적이나 특징이 다르기 때문에 따로 쓰이는 경우가 있습니다. </p>
</blockquote>
<blockquote>
<p>추상 클래스는 일부 메서드를 구현하고 나머지는 하위 클래스에서 구현하도록 하는 추상 메서드를 가지고 있습니다. 또한 일반적인 멤버 변수와 메서드를 가질 수 있습니다. 이러한 특징으로 인해 추상 클래스는 상속 관계에서 하위 클래스에게 공통된 속성과 메서드를 물려주는 역할을 하면서도 상속받은 클래스에서 반드시 구현해야 할 메서드가 무엇인지 알려주는 역할을 합니다.</p>
</blockquote>
<blockquote>
<p>반면에 인터페이스는 추상 메서드와 상수만을 가질 수 있습니다. 따라서 인터페이스는 클래스가 반드시 구현해야 할 메서드 목록을 정의하는 용도로 주로 사용됩니다. 인터페이스는 클래스가 아닌 다른 인터페이스를 구현할 수 있기 때문에, 다중 상속을 구현하는 데 사용될 수도 있습니다.</p>
</blockquote>
<blockquote>
<p>따라서, 추상 클래스는 공통된 구현 코드를 공유하는 클래스들 사이에서 공통된 속성과 메서드를 물려주는 데 사용되고, 인터페이스는 클래스가 구현해야 할 메서드를 정의하는 데 사용됩니다. 추상 클래스와 인터페이스는 둘 다 추상화된 개념이지만, 사용하는 목적과 특징이 다르기 때문에 따로 쓰이는 경우가 있습니다.</p>
</blockquote>
<hr>
<p>결론은, </p>
<p><strong>추상 클래스는 공통된 구현 코드를 공유하는 클래스들 사이에서 공통된 속성과 메서드를 물려주는 데 사용되고,</strong> </p>
<p><strong>인터페이스는 클래스가 구현해야 할 메서드를 정의하는 데 사용된다.</strong></p>
<hr>
<p>뭐, 틀린 말은 아니고 정론이긴 하다.</p>
<p>하지만 아직 확실히 용도가 와닿진 않는다.</p>
<p>추상클래스도 구현해야할 메서드를 정의하는데 사용되는데?? 
너무 광범위한 설명 아닌가?</p>
<p>그래서 더 찾아보고 공부한 결과,</p>
<p>내가 낸 결론은,</p>
<p><strong>사용의도에서 차이점이 있다고 본다.</strong></p>
<p>즉, 항상 그렇다는건 아니지만, 보통</p>
<p><strong>추상클래스는 IS - A 관계</strong>일때 주로 사용된다.</p>
<p>=&gt; 사과는 과일이다. 즉, 사과는 과일의 한 종류이다. 이런 관계를 표현할 때는 추상 클래스를 사용한다.</p>
<p><strong>인터페이스는 HAS - A 관계</strong>일때 주로 사용한다.</p>
<p>=&gt; 자동차는 엔진을 가지고 있다. 즉, 자동차는 엔진이라는 요소(기능)을 가지고 있다. 이런 관계를 표현할 때는 인터페이스를 사용한다.</p>
<p>다음과 같은 예시를 보자</p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/94131447-c6d2-468a-a38d-691df33d430c/image.png" alt=""></p>
<h2 id="추상-클래스">추상 클래스</h2>
<p>위에서 Creature, Human, Animal 같은 추상클래스는 구체화된 클래스의 상위 클래스로서, *<em>하위 클래스들의 기본적으로(다른말로, 공통적으로) 가져야 되는 속성과 기능을 정의했다. *</em> </p>
<p>즉 추상클래스가 하위클래스의 근본(is-a, ~는 ~이다)이 된다는 의미를 가지고있다.</p>
<p>=&gt; IS-A 관계에 대입하면 적절한 문장이 된다는 것이다.</p>
<p>ex)
Kevin은 Human이다(Kevin is Human) =&gt; O (케빈의 근본은 사람)
Turtle 은 Animal이다(Turtle is Animal) =&gt; O (거북이의 근본은 동물)
Pigeon은 Animal이다(Pigeon is Animal) =&gt; O (비둘기의 근본은 동물)</p>
<p>예를들어 </p>
<pre><code class="language-java">public abstract class Creature {
  public abstract void eat();


  }
}

public class Kevin extends Creature {
  @Override
  public void eat() {
    System.out.println(&quot;Kevin eats Kimchi!&quot;);
  }
}

public class Turtle extends Creature {
  @Override
  public void walk() {
    System.out.println(&quot;Turtle eats fish!&quot;);
  }
}

public class Pigeon extends Creature {
  @Override
  public void walk() {
    System.out.println(&quot;Pigeon eats bug!&quot;);
  }
}</code></pre>
<p>위처럼 추상클래스인 Creature에는 생명체의 기본이 되는 eat()메서드만 선언해놓고, 하위 클래스들은 기본이되는 해당 메서드를 재정의 해서 각 클래스마다 고유한 기능을 하도록 하였다.</p>
<h2 id="인터페이스">인터페이스</h2>
<p>Talkable, Flyable, Swimable 같은 인터페이스들은, 어떤 클래스들의 조상 클래스가 되기에는 적절지 않지만,</p>
<p>&quot;말할 수 있음&quot;,&quot;날 수 있음&quot;,&quot;수영할 수 있음&quot; 등의 <strong>어떠한 기능에 대한 가이드(규칙) 제공하고</strong>, Kevin이나 Turtle, Pigeon같은 클래스들이 그런 기능들을 가질 수 있게(HAS - A 관계)해준다.</p>
<p>예를 들어 </p>
<pre><code class="language-java">public interface Flyable {
  void fly();
}</code></pre>
<pre><code class="language-java">public interface Swimable {
  void swim();
}</code></pre>
<pre><code class="language-java">public interface Talkable {
  void talk();
}</code></pre>
<p>이렇게 만들어 놓고, 어떠한 클래스가 위 기능들이 필요하다면(have, 가지고 싶다면) implemnets로 구현해서 바로 기능을 제공해주면 된다.</p>
<h2 id="추상클래스와-인터페이스-모두-활용">추상클래스와 인터페이스 모두 활용</h2>
<p>이제 모두 활용한 예를 들면</p>
<pre><code class="language-java">abstract class Animal {
  public abstract void walk();

  public abstract void talk();
}

interface AblityToEat {
  public void eat(Creature creature);
}

interface ToBeEaten {
  public void toBeEatenBy(Creature creature);
}

class Turtle extends Animal implements AblityToEat {
  @Override
  public void walk() {
    System.out.println(&quot;I am walking!&quot;);
  }

  @Override
  public void talk() {
    System.out.println(&quot;I can talk!&quot;);
  }

  @Override
  public void eat(Creature creature) {
    System.out.println(&quot;I am eating&quot;+ creature+&quot;!&quot;);
  }
}

class Fish extends Animal implements ToBeEaten {
  @Override
  public void walk() {
    System.out.println(&quot;I cannot walk!&quot;);
  }

  @Override
  public void talk() {
    System.out.println(&quot;I cannot talk!&quot;);
  }

  @Override
  public void toBeEatenBy() {
    System.out.println(&quot;I am being eaten by a&quot;+creature+&quot;!&quot;);
  }
}</code></pre>
<p><del>거북이가 말할수 있다는게 이상하지만 넘어가도록하자</del></p>
<p>위의 예시에서, </p>
<ol>
<li><p>거북이와 물고기 모두 근본은 Animal이기때문에 Animal 클래스를 상속했고, </p>
</li>
<li><p>거북이와 물고기는 각각 먹을 수있고, 먹힐 수 있기 때문에
(다른말로, 먹을 수 있고 먹힐 수 있는 기능을 가지고 있기 떄문에) 
AblityToEat, ToBeEaten 인터페이스를 구현하도록 하였다.</p>
</li>
</ol>
<h2 id="정리">정리</h2>
<ul>
<li><strong>추상클래스는 IS - A 관계</strong>일때 주로 사용된다.</li>
</ul>
<p>이떄 추상클래스는 이 클래스를 상속할 하위 클래스들의 기초(근본)가 되어 어떠한 클래스인지를 나타내는 속성(멤버변수)과 기능(메서드)을 제공한다.</p>
<ul>
<li><strong>인터페이스는 HAS - A 관계</strong>일때 주로 사용한다.</li>
</ul>
<p>객체에 어떠한 기능이 추가될때마다 해당클래스에 메서드를 추가하는건 너무 번거롭다.</p>
<p>객체에서 연관된 특정 기능들을 분리한 다음,</p>
<p>어떠한 기능들을 제공하는지를 정의해서 인터페이스로서 제공하면, </p>
<p>후에 다른 모든 클래스한테도 해당 기능이 필요하다면 구현을 통해 사용하게 가능하다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터페이스]]></title>
            <link>https://velog.io/@bill_0285/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@bill_0285/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Mon, 08 May 2023 12:25:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="인터페이스란">인터페이스란?</h1>
<hr>
<p>인터페이스(Interface)는 클래스 또는 객체의 기능을 외부에 노출시키는 방법 중 하나이다. </p>
<p>즉, <strong>인터페이스는 객체 간의 상호작용을 돕는 규약이나 계약, 틀이라고 볼 수 있다.</strong></p>
<p>인터페이스는 일종의 추상화된 클래스로, 클래스와 비슷한 형태를 갖지만 <strong>실제로는 구현된 코드가 없다.</strong></p>
<p>대신 인터페이스는 메소드, 상수 등의 특정 요소를 선언하여, 해당 인터페이스를 구현한 클래스가 반드시 가져야 하는 <strong>특정한 기능이나 속성을 정의한다.</strong></p>
<p>이를 통해 객체 간의 상호작용에서 <strong>규격화된 방식으로 데이터를 주고받을 수 있다.</strong></p>
<p>ex)
ClickAble 이라는 인터페이스를 상속한 클래스는 외부에서 상호작용 할떄,</p>
<p>이 클래스는 클릭이 가능한 기능을 가지고있고, 그 기능(메서드)의 인풋(매개변수) 과 아웃풋(결과) 를 통해 대략적으로 어떠한 기능인지 알 수 있다.</p>
<h2 id="요약">요약</h2>
<ul>
<li><p>클래스나 프로그램이 제공하는 기능을 명시적으로 선언</p>
</li>
<li><p>일종의 클라이언트 코드와의 약속이며 클래스나 프로그램이 제공하는 <strong>명세(specification)</strong></p>
</li>
<li><p>클라이언트 프로그램은 <strong>인터페이스에 선언된 메서드 명세만 보고 이를 구현한 클래스를 사용할 수 있음</strong></p>
</li>
<li><p>어떤 객체가 하나의 인터페이스 타입이라는 것은 그 <strong>인터페이스가 제공하는 모든 메서드를 구현했다는 의미임</strong></p>
</li>
<li><p>인터페이스를 구현한 다양한 객체를 사용함 - 다형성</p>
</li>
</ul>
<h2 id="구현">구현</h2>
<ul>
<li><p>모든 메서드가 추상 메서드로 선언됨 public abstract</p>
</li>
<li><p>모든 변수는 상수로 선언됨 public static final</p>
</li>
<li><p>인터페이스를 클래스가 상속할 경우, 그 인터페이스의 모든 추상메소드를 구현해야함.</p>
<pre><code class="language-java">interface 인터페이스 이름{

  public static final float pi = 3.14F;
  public void makeSomething();
}
</code></pre>
</li>
</ul>
<pre><code>- 자바 8 부터 디폴트 메서드(default method)와 정적 메서드(static method) 기능의 제공으로 일부 구현 코드가 있음


## 예시

![](https://velog.velcdn.com/images/bill_0285/post/20427a00-dbaf-4b58-8ec4-e9559fa70b4a/image.png)

1. 사칙연산 기능이 있음을 알리는 calc 인터페이스 구현

2. 1차 기능인 더하기 ,빼기 기능만 구현된 Calculator 추상 클래스 구현
=&gt; 인터페이스를 상속했는데 전부 구현하지 않아서 추상 클래스임

3. calc의 모든 기능이 구현된 CompleteCalc 클래스 구현
=&gt; CompleteCalc 클래스는 추상클래스가 아니라서 인스턴스 생성가능

&lt;br&gt;&lt;br&gt;

Calc.java
```java
public interface Calc {

    double PI = 3.14;
    int ERROR = -99999999;
    //사칙연산의 기능이 있음을 알리는 추상 메서드 선언
    //외부에 다른 클래스와 상호작용할때 이 인터페이스를 상속한
    //클래스가 어떤 기능이 있는지 1차적으로 이해가 가능
    int add(int num1, int num2);
    int substract(int num1, int num2);
    int times(int num1, int num2);
    int divide(int num1, int num2);

}</code></pre><p>Calculator.java</p>
<pre><code class="language-java">public abstract class Calculator implements Calc{

    @Override
    public int add(int num1, int num2) {
    //인터페이스의 메서드 구현
        return num1 + num2;
    }

    @Override
    public int substract(int num1, int num2) {
     //인터페이스의 메서드 구현
        return num1 - num2;
    }
}
</code></pre>
<p>CompleteCalc.java</p>
<pre><code class="language-java">public class CompleteCalc extends Calculator{

    @Override
    public int times(int num1, int num2) {
    //인터페이스의 메서드 구현
        return num1 * num2;
    }

    @Override
    public int divide(int num1, int num2) {
    //인터페이스의 메서드 구현
        if( num2 == 0 )
            return ERROR;
        else 
            return num1 / num2;
    }

    public void showInfo() {
        System.out.println(&quot;모두 구현하였습니다.&quot;);
    }
}</code></pre>
<p>CalculatorTest.java</p>
<pre><code class="language-java">public class CalculatorTest {

    public static void main(String[] args) {
        Calc calc = new CompleteCalc();
        int num1 = 10;
        int num2 = 2;

        System.out.println(num1 + &quot;+&quot; + num2 + &quot;=&quot; + calc.add(num1, num2));
        System.out.println(num1 + &quot;-&quot; + num2 + &quot;=&quot; +calc.substract(num1, num2));
        System.out.println(num1 + &quot;*&quot; + num2 + &quot;=&quot; +calc.times(num1, num2));
        System.out.println(num1 + &quot;/&quot; + num2 + &quot;=&quot; +calc.divide(num1, num2));
    }
}</code></pre>
<p>결과
<img src="https://velog.velcdn.com/images/bill_0285/post/f91ada5f-a38e-49af-8897-4851a38b11bd/image.png" alt=""></p>
<h1 id="인터페이스-구현과-형-변환">인터페이스 구현과 형 변환</h1>
<hr>
<ul>
<li>인터페이스를 구현한 클래스는 인터페이스 형으로 선언한 변수로 형 변환 할 수 있음</li>
</ul>
<p>위의 계산기 예시에서 
Calc calc = new CompleteCalc();</p>
<ul>
<li><strong>상속에서의 형 변환과 동일한 의미</strong>
=&gt; 가상메서드원리(인스턴스의 가상 메서드 테이블 따름)그대로 적용!</li>
</ul>
<ul>
<li>클래스 상속과 달리 구현 코드가 없으므로 여러 인터페이스를 구현할 수 있음 ( cf. extends)</li>
</ul>
<ul>
<li>형 변환되는 경우 인터페이스에 선언된 메서드만을 사용가능함</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/6df3ee27-7738-4b49-b130-f0a0db1ce540/image.png" alt=""></p>
<h2 id="인터페이스와-다형성">인터페이스와 다형성</h2>
<p>하나의 인터페이스를 여러 객체가 구현하게 되면 클라이언트 프로그램은 인터페이스의 메서드를 활용하여 여러 객체의 구현을 사용할 수 있음 (다형성)</p>
<h2 id="예제">예제</h2>
<p>인터페이스를 이용한 DAO(data access object)를 구현 해보자.
<img src="https://velog.velcdn.com/images/bill_0285/post/d284a0b5-cdd9-4f29-a993-035d19ce5220/image.png" alt=""></p>
<ul>
<li><p>DB에 회원 정보를 넣는 dao(data access object)를 여러 DB 제품이 지원될 수 있게 구현함</p>
</li>
<li><p>환경파일(db.properties) 에서 database의 종류에 대한 정보를 읽고 그 정보에 맞게 dao 인스턴스를 생성하여 실행될 수 있게 함</p>
</li>
<li><p>source hierachy</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/16ac6d3d-f2bc-49d8-b379-c615d19a1118/image.png" alt=""></p>
<ol>
<li><p>우선 유저 정보 Model 클래스인 UserInfo클래스를 만들고,</p>
</li>
<li><p>UserInfoDao인터페이스를 구현해서 db종류에 맞게 구체화시킨 오라클Dao, MySqlDao 파일을 각각 구현한다.</p>
</li>
<li><p>마지막으로 서버(이번 예시에는 단순 UserInfoDao 파일)와 상호작용하는 클라이언트인 UserInfoClient 파일로 테스트를 해본다.</p>
</li>
</ol>
<h2 id="구현-1">구현</h2>
<p>1.유저 정보 Model 클래스인 UserInfo클래스를 만들자. </p>
<p>UserInfo.java (사용자정보 모델 클래스)</p>
<pre><code class="language-java">public class UserInfo {

    private String userId;
    private String passwd;
    private String userName;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}</code></pre>
<ol start="2">
<li>UserInfoDao인터페이스를 구현해서 db종류에 맞게 구체화시킨 오라클Dao, MySqlDao 파일을 각각 구현하자.</li>
</ol>
<p>UserInfoDao.java 
( dao 에서 제공되어야 할 메서드를 선언한 기본 인터페이스 )</p>
<pre><code class="language-java">public interface UserInfoDao {

    void insertUserInfo(UserInfo userInfo);
    void updateUserInfo(UserInfo userInfo);
    void deleteUserInf(UserInfo userInfo);
}</code></pre>
<p>UserInfoMySqlDao.java (UserInfoDao 인터페이스를 구현한 MySql 버전 dao)</p>
<pre><code class="language-java">public class UserInfoMySqlDao implements UserInfoDao{

    @Override
    public void insertUserInfo(UserInfo userInfo) {
        System.out.println(&quot;insert into MYSQL DB userId =&quot; + userInfo.getUserId() );        
    }

    @Override
    public void updateUserInfo(UserInfo userInfo) {
        System.out.println(&quot;update into MYSQL DB userId = &quot; + userInfo.getUserId());        
    }

    @Override
    public void deleteUserInf(UserInfo userInfo) {
        System.out.println(&quot;delete from MYSQL DB userId = &quot; + userInfo.getUserId());

    }

}</code></pre>
<p>UserInfoOracleDao.java (UserInfoDao 인터페이스를 구현한 Oracle 버전 dao)</p>
<pre><code class="language-java">public class UserInfoOracleDao implements UserInfoDao{

    public void insertUserInfo(UserInfo userInfo){
        System.out.println(&quot;insert into ORACLE DB userId =&quot; + userInfo.getUserId() );
    }

    public void updateUserInfo(UserInfo userInfo){
        System.out.println(&quot;update into ORACLE DB userId = &quot; + userInfo.getUserId());
    }

    public void deleteUserInf(UserInfo userInfo){
        System.out.println(&quot;delete from ORACLE DB userId = &quot; + userInfo.getUserId());
    }
}</code></pre>
<ol start="3">
<li>마지막으로  UserInfoDao와 상호작용하는 클라이언트인 UserInfoClient 클래스를 만들자.</li>
</ol>
<p>UserInfoClient.java (UserInfoDao 인터페이스를 활용하는 클라이언트 프로그램)</p>
<pre><code class="language-java">public class UserInfoClient {

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

        FileInputStream fis = new FileInputStream(&quot;db.properties&quot;);
        //파일입출력 스트림에 db.properties파일을 추가
        Properties prop = new Properties();
        //프로퍼티 자료형을 하나 선언해서
        prop.load(fis);
        // 위에 선언한 fis 파일을 로드한다.
        String dbType = prop.getProperty(&quot;DBTYPE&quot;);
        // 그 fis파일, 즉 db.properties 파일의 
        // DBTYPE 을 dbType변수에 저장
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(&quot;12345&quot;);
        userInfo.setPasswd(&quot;!@#$%&quot;);
        userInfo.setUserName(&quot;이순신&quot;);
        //위에 처럼 더미 유저정보를 넣어주고

        UserInfoDao userInfoDao = null;

        //아래와 같이 dbType에 따라 다른 Dao를 실행시킨다.
        // =&gt; 다형성 을 보여줌.
        if(dbType.equals(&quot;ORACLE&quot;)){
            userInfoDao = new UserInfoOracleDao();
        }
        else if(dbType.endsWith(&quot;MYSQL&quot;)){
            userInfoDao = new UserInfoMySqlDao();
        }
        else{
            System.out.println(&quot;db support error&quot;);
            return;
        }

        userInfoDao.insertUserInfo(userInfo);
        userInfoDao.updateUserInfo(userInfo);
        userInfoDao.deleteUserInf(userInfo);
    }
}</code></pre>
<p>결과</p>
<p>db.properties 환경파일이 MYSQL 일때</p>
<blockquote>
<p>&quot;DBTYPE=MYSQL&quot;</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/52ecdd48-c945-4c84-98bc-f761c1374c4c/image.png" alt=""></p>
<p>db.properties 환경파일이 ORACLE 일때</p>
<blockquote>
<p>&quot;DBTYPE=ORACLE&quot;</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/7a49698e-1596-4e6f-aeb8-765d2d6a4db4/image.png" alt=""></p>
<h1 id="인터페이스의-여러가지-메서드">인터페이스의 여러가지 메서드</h1>
<hr>
<h2 id="디폴트-메서드-자바-8이후">디폴트 메서드 (자바 8이후)</h2>
<ul>
<li><p>구현을 가지는 메서드, 인터페이스를 구현하는 클래스들에서 공통으로 사용할 수 있는 기본 메서드</p>
</li>
<li><p><strong>인터페이스를 상속한 인터페이스가 부모 인터페이스를 오버라이딩하려면 디폴트 메서드를 이용하면 된다.</strong></p>
<p>=&gt; 밑에 인터페이스의 인터페이스 다중 상속 항목에서 예제의 MyInterface.java 참조</p>
</li>
<li><p>default 키워드 사용</p>
</li>
</ul>
<pre><code class="language-java">default void description() {
    System.out.println(&quot;정수 계산기를 구현합니다.&quot;);
    myMethod();
}</code></pre>
<ul>
<li>구현 하는 클래스에서 재정의 할 수 있음</li>
</ul>
<pre><code class="language-java">@Override
public void description() {
    System.out.println(&quot;CompleteCalc에서 재정의한 default 메서드&quot;);
    //super.description();
}</code></pre>
<ul>
<li><strong>인터페이스를 구현한 클래스의 인스턴스가 생성 되어야 사용 가능함</strong></li>
</ul>
<h2 id="디폴트메서드의-다이아몬드-상속-문제">디폴트메서드의 다이아몬드 상속 문제</h2>
<ul>
<li>부모 인터페이스 A,B를 자식 인터페이스 C가 상속한다고 할때
=&gt;
A,B 모두 이름이 같은 디폴트메서드가 중복될경우 C에서 반드시 오버라이드 해서,
<strong>메서드 호출시 모호함을 해결해야함</strong></li>
</ul>
<ol>
<li>A.super.디폴트메서드명 으로 A의 메서드를 불러오거나</li>
<li>B.super.디폴트메서드명 으로 B의 메서드를 불러오거나</li>
<li>그냥 새로 재정의하면 된다.</li>
</ol>
<p>A.java</p>
<pre><code class="language-java">public interface A {
    void Test(){
    System.out.println(&quot;A의 디폴트 메서드&quot;);
    }
}</code></pre>
<p>B.java</p>
<pre><code class="language-java">public interface B {
    void Test(){
    System.out.println(&quot;B의 디폴트 메서드&quot;);
    }
}</code></pre>
<p>C.java</p>
<pre><code class="language-java">public interface C extends A, B{
    //1. A의 메서드 불러옴
    @Override
    void Test(){
    A.super.Test();
    }

    //2. B의 메서드 불러옴
    @Override
    void Test(){
    B.super.Test();
    }

    //3. 새로 재정의 함.
    @Override
    void Test(){
    System.out.println(&quot;C의 디폴트 메서드&quot;);
    }

    //4. 당연히, 1,2,3 조합도 가능. 어차피 재정의 하는거니까.
    @Override
    void Test(){
    A.super.Test();
    B.super.Test();
    System.out.println(&quot;C의 디폴트 메서드&quot;);
    }
}</code></pre>
<h2 id="정적-메서드-자바-8이후">정적 메서드 (자바 8이후)</h2>
<ul>
<li><p>인스턴스 생성과 상관 없이 <strong>인터페이스 타입으로 사용할 수 있는 메서드</strong></p>
</li>
<li><p>클래스명으로 접근</p>
</li>
<li><p>인스턴스 안만들고 접근 가능</p>
</li>
</ul>
<pre><code class="language-java">static int total(int[] arr) {
    int total = 0;

    for(int i: arr) {
        total += i;
    }
    mystaticMethod();
    return total;
}</code></pre>
<h2 id="private-메서드-자바-9이후">private 메서드 (자바 9이후)</h2>
<ul>
<li><p>인터페이스를 구현한 클래스에서 사용하거나 재정의 할 수 없음</p>
</li>
<li><p><strong>인터페이스 내부에서만 사용하기 위해 구현하는 메서드</strong></p>
</li>
<li><p>default 메서드나 static 메서드에서 사용함
=&gt; 당연하지. 왜냐면 이 두 유형의 메서드만 구현부가 있으니까.</p>
</li>
</ul>
<pre><code class="language-java">private void myMethod() {
    System.out.println(&quot;private method&quot;);
}

private static void mystaticMethod() {
    System.out.println(&quot;private static method&quot;);
}</code></pre>
<h1 id="인터페이스-상속">인터페이스 상속</h1>
<hr>
<h2 id="클래스의-인터페이스-다중-구현">클래스의 인터페이스 다중 구현</h2>
<ul>
<li><p>자바에서 클래스와 달리 인터페이스는 한 클래스가 다중 구현 할 수 있음</p>
</li>
<li><p>디폴트 메서드가 중복 되는 경우는 구현 하는 클래스에서 재정의 하여야 함</p>
</li>
<li><p>여러 인터페이스를 구현한 클래스는 인터페이스 타입으로 형 변환 되는 경우 해당 인터페이스에 선언된 메서드만 사용 가능 함</p>
</li>
</ul>
<h2 id="예제-1">예제</h2>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/91cd20e8-6009-47c8-8b65-7c44546596cf/image.png" alt=""></p>
<p>Sell.java</p>
<pre><code class="language-java">public interface Sell {
    void sell();
}</code></pre>
<p>Buy.java</p>
<pre><code class="language-java">public interface Buy {
    void buy();
}</code></pre>
<p>Customer.java</p>
<pre><code class="language-java">public class Customer implements Buy, Sell{

    @Override
    public void sell() {
        System.out.println(&quot;customer sell&quot;);
    }

    @Override
    public void buy() {
        System.out.println(&quot;customer buy&quot;);        
    }

    public void sayHello() {
        System.out.println(&quot;Hello&quot;);
    }
}</code></pre>
<p>CustomerTest.java</p>
<pre><code class="language-java">public class CustomerTest {

    public static void main(String[] args) {

        Customer customer = new Customer();
        customer.buy();
        customer.sell();
        customer.sayHello();
        //Customer 클래스의 모든 메서드 실행가능


        Buy buyer = customer;
        buyer.buy();
        //Buy 클래스에 buy메서드만 선언돼 있어서 buy메서드만 실행가능
        //가상메서드 원리에 의해 Customer의 buy메서드 로직 실행

        Sell seller = customer;
        seller.sell();
         //Buy 클래스에 sell메서드만 선언돼 있어서 sell메서드만 실행가능
        //가상메서드 원리에 의해 Customer의 sell메서드 로직 실행

    }
}</code></pre>
<h2 id="인터페이스의-인터페이스-다중-상속">인터페이스의 인터페이스 다중 상속</h2>
<ul>
<li><p>인터페이스 사이에도 상속을 사용할 수 있음</p>
</li>
<li><p>extends 키워드를 사용</p>
</li>
<li><p>인터페이스는 다중 상속이 가능하고 구현 코드의 상속이 아니므로 타입 상속 이라고 함</p>
</li>
</ul>
<h2 id="예제-2">예제</h2>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/be277eee-7fb8-4a05-babc-356e687a3940/image.png" alt=""></p>
<p>X.java</p>
<pre><code class="language-java">public interface X {
    void x();
}</code></pre>
<p>Y.java</p>
<pre><code class="language-java">public interface Y {
    void y();
}</code></pre>
<p>MyInterface.java</p>
<pre><code class="language-java">public interface MyInterface extends X, Y{
    void myMethod();

       @Override
       default void x(){
       //default 키워드로 통해 인터페이스X의 메서드 오버라이딩
    //유의미한 행위는 아님. 어차피 Myinterface 를 구현하는 클래스에서 x메서드를 구현할텐데
    //키워드 의미 그대로 해당 인터페이스를 구현할떄 기본값으로 두기위해 사용할 수도? 
       System.out.println(&quot;this is MyInterFace X);
   };
}</code></pre>
<p>MyClass.java</p>
<pre><code class="language-java">public class MyClass implements MyInterface{



    @Override
    public void y() {
        System.out.println(&quot;y()&quot;);        
    }

    @Override
    public void myMethod() {
        System.out.println(&quot;myMethod()&quot;);        
    }
}</code></pre>
<p>MyClassTest.java</p>
<pre><code class="language-java">public class MyClassTest {

    public static void main(String[] args) {

        MyClass mClass = new MyClass();

        X xClass = mClass;
        xClass.x();
        //this is MyInterFace X 출력됨


        Y yClass = mClass;
        yClass.y();
        //y() 출력됨

        MyClass iClass = mClass;
        iClass.x();
         //this is MyInterFace X 출력됨
        iClass.y();
        //y() 출력됨
        iClass.myMethod();
        //myMethod()
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[추상클래스와 템플릿 메서드 패턴]]></title>
            <link>https://velog.io/@bill_0285/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@bill_0285/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Sun, 07 May 2023 11:13:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="추상-클래스">추상 클래스</h1>
<hr>
<h2 id="추상-클래스란">추상 클래스란?</h2>
<ul>
<li><p>구현 코드 없이 <strong>메서드의 선언</strong>만 있는 추상 메서드(abstract method)를 포함한 클래스</p>
</li>
<li><p>메서드 선언(declaration) : 반환타입, 메서드 이름, 매개변수로 구성 =&gt; 선언부만 가짐
구현부(body) 안가짐</p>
</li>
<li><p>메서드 정의(definition) : 메서드 구현(implementation)과 동일한 의미
구현부(body) 를 가짐 ({ })</p>
</li>
<li><p>예) </p>
<pre><code class="language-java">int add(int x, int y); 
// 메서드 선언. 선언부만 있음. 추상 메서드임
int add(int x, int y){ } 
// 메서드 정의(구현). 구현부와 선언부가 있음. 추상 메서드아님</code></pre>
</li>
<li><p>abstract 예약어를 사용</p>
</li>
<li><p><strong>추상 클래스는 new 할 수 없음 ( 인스턴스화 할 수 없음 )</strong></p>
</li>
</ul>
<h2 id="추상-클래스-구현하기">추상 클래스 구현하기</h2>
<ul>
<li><p>메서드에 구현 코드가 없으면 abstract 로 선언</p>
</li>
<li><p><strong>abstract로 선언된 메서드를 가진 클래스는 abstract로 선언</strong></p>
</li>
<li><p>모든 메서드가 구현 된 클래스라도 <strong>abstract로 선언되면 추상 클래스로 인스턴스화 할 수 없음</strong></p>
</li>
<li><p>추상 클래스의 <strong>추상 메서드는 하위 클래스가 상속 하여 구현</strong></p>
</li>
<li><p>추상 클래스 내의 추상 메서드 : 하위 클래스가 구현해야 하는 메서드</p>
</li>
<li><p>추상 클래스 내의 구현 된 메서드 : 하위 클래스가 공통으로 사용하는 메서드 ( 필요에 따라 하위 클래스에서 재정의 함 )</p>
</li>
</ul>
<h2 id="예제">예제</h2>
<p>다음과 같은 예제 시나리오를 구현 해보자.</p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/30d42cb0-1e31-459d-bf55-9c75e315a67f/image.png" alt=""></p>
<p>위 사진에서 이탤릭체로 되어 있는 메소드는 추상메서드 이다. </p>
<p>컴퓨터는 크게 데스크탑과, 노트북 으로 나눌 수 있고, 모든 컴퓨터 기기가 기본적으로 반드시 제공되야할 기능들(전원 키고 끄기, 글자 입력, 화면 보이기)을 최상위 클래스인 컴퓨터에 선언한다.</p>
<p>이때 전원을 키고 끄는거는 컴퓨터마다 똑같이 떄문에 구현부까지 선언하고, 그외 타이핑하는거나 디스플레이하는 거는 기기마다 다를 수 있기에 추상 메서드로 선언했다.</p>
<p>Computer.java</p>
<pre><code class="language-java">public abstract class  Computer {

    abstract void display(); 
    //하위 클래스에서 구현하도록 추상 메서드로 선언
    abstract void typing(); 
    //하위 클래스에서 구현하도록 추상 메서드로 선언

    public void turnOn() { 
    //기기가 분화되도 기능은 변함없기 때문에 최상위 클래스에서 구현. 
    //물론 하위 클래스에서 재정의 가능
        System.out.println(&quot;전원을 켭니다.&quot;);
    }

    public void turnOff() { 
    //기기가 분화되도 기능은 변함없기 때문에 최상위 클래스에서 구현.
    //물론 하위 클래스에서 재정의 가능
        System.out.println(&quot;전원을 끕니다.&quot;);
    }
}</code></pre>
<p>DeskTop.java</p>
<pre><code class="language-java">public class DeskTop extends Computer{

    @Override
    void display() {
    //가상 메서드 구현
        System.out.println(&quot;DeskTop display&quot;);
    }

    @Override
    void typing() {
     //가상 메서드 구현
        System.out.println(&quot;DeskTop typing&quot;);
    }

    @Override
    public void turnOff() {
    //상위클래스의 구현된 메서드 재정의
        System.out.println(&quot;Desktop turnoff&quot;);
    }
}</code></pre>
<p>NoteBook.java</p>
<pre><code class="language-java">public abstract class NoteBook extends Computer{
//Computer 클래스의 추상 메서드 2개중 1개만 구현했기 때문에, 
//반드시 추상클래스로 선언해야함.
//추상클래스이므로 인스턴스 생성 불가.
    @Override
    public void typing() 
    //가상 메서드 구현
        System.out.println(&quot;NoteBook typing&quot;);        
    }
}</code></pre>
<p>MyNoteBook.java</p>
<pre><code class="language-java">public class MyNoteBook extends NoteBook{
//Computer 클래스의 추상 메서드 모두를 구현 완료. 
    @Override
    void display() {
    //가상메서드 구현
        System.out.println(&quot;MyNoteBook display&quot;);        
    }
}</code></pre>
<p>ComputerTest.java</p>
<pre><code class="language-java">public class ComputerTest {

    public static void main(String[] args) {
        Computer computer = new DeskTop();
        computer.display();
        computer.turnOff();

        NoteBook myNote = new MyNoteBook();
        //NoteBook baseNote = new NoteBook(); 는 오류가남, 
        // 추상클래스 를 구현하려 했기 때문
    }
}</code></pre>
<p><br><br></p>
<h1 id="템플릿-메서드-패턴">템플릿 메서드 패턴</h1>
<hr>
<h2 id="템플릿-메서드">템플릿 메서드</h2>
<p>알고리즘의 골격을 정의한 메서드를 의미한다. </p>
<p>시나리오의 흐름을 step별로 정의한 메서드 이기도 하다.</p>
<h2 id="설명">설명</h2>
<p>템플릿 메서드 패턴은 부모 클래스에서 코드의 흐름(시나리오)을 스텝(단계)별로 정의하고,</p>
<p>해당 시나리오의 흐름을 변경하지 않고 필요시 자식 클래스들이 알고리즘의 특정 단계들을 오버라이드​(재정의)​해서 시나리오를 구체화 하는 설계 패턴을 말한다. </p>
<ul>
<li><p>보통 시나리오(템플릿 메서드)는 변경되지 않기위해 final로 선언하여 하위 클래스에서 재정의 할 수 없게 함</p>
</li>
<li><p>프레임워크에서 많이 사용되는 설계 패턴</p>
</li>
<li><p>추상 클래스로 선언된 상위 클래스에서 템플릿 메서드를 활용하여 전체적인 흐름을 정의 하고,</p>
</li>
<li><p>하위 클래스에서 다르게 구현되어야 하는 부분은 추상 메서드로 선언하여 하위 클래스에서 구현 하도록 함</p>
</li>
</ul>
<h2 id="예시">예시</h2>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/55f08e15-8a2e-4d2f-8c0c-5cc0208f81bb/image.png" alt="">
위 와 같은 시나리오를 템플릿 메서드 패턴을 이용해 설계 해보자.</p>
<p>차의 시동을 키고 끄는 것은 공통적인 성능이므로 구현까지하고, 
운전이나 차가 멈추는건 차의 종류에따라 다르므로 추상메서드로 선언하고 하위클래스에서 구체화 하도록한다.</p>
<p>Car.java</p>
<pre><code class="language-java">public abstract class Car {

    public abstract void drive();
    //추상 메서드로 선언
    public abstract void stop();
    //추상 메서드로 선언

    public void startCar() {
    //구현 해놓는다.
        System.out.println(&quot;시동을 켭니다.&quot;);
    }

    public void turnOff() {
    //구현 해놓는다.
        System.out.println(&quot;시동을 끕니다.&quot;);
    }

    final public void run() {
    //템플릿 메서드 구현
    //final 키워드로 변경 불가능하게 해놓는다. 
        startCar();
        drive();
        stop();
        turnOff();
    }
}</code></pre>
<p>ManualCar.java</p>
<pre><code class="language-java">public class ManualCar extends Car{

    @Override
    public void drive() {
    //부모의 가상 메서드 구현
        System.out.println(&quot;사람이 운전합니다.&quot;);
        System.out.println(&quot;사람이 핸들을 조작합니다.&quot;);        
    }

    @Override
    public void stop() {
      //부모의 가상 메서드 구현
        System.out.println(&quot;브레이크를 밟아서 정지합니다.&quot;);        
    }

}</code></pre>
<p>AICar.java</p>
<pre><code class="language-java">public class AICar extends Car{

    @Override
    public void drive() {
      //부모의 가상 메서드 구현
        System.out.println(&quot;자율 주행합니다.&quot;);
        System.out.println(&quot;자동차가 스스로 방향을 바꿉니다.&quot;);
    }

    @Override
    public void stop() {
      //부모의 가상 메서드 구현
        System.out.println(&quot;스스로 멈춥니다.&quot;);        
    }
}</code></pre>
<p>CarTest.java</p>
<pre><code class="language-java">public class CarTest {

    public static void main(String[] args) {
    // 다형성을 볼수 있는 부분
    // 각자 자식클래스를 부모클래스자료형에 넣어서 구현
    // (업캐스팅)
        Car aiCar = new AICar();
        aiCar.run();
          // 템플릿메서드인 run을 통해 일관된 시나리오 작동
        System.out.println(&quot;=================&quot;);
        Car manualCar = new ManualCar();
        manualCar.run();
          // 템플릿메서드인 run을 통해 일관된 시나리오 작동
    }
}</code></pre>
<p>결과는 아래와 같다.
<img src="https://velog.velcdn.com/images/bill_0285/post/be345570-00e2-4f23-ac70-1ac2d3884604/image.png" alt=""></p>
<h1 id="final-예약어">final 예약어</h1>
<hr>
<p>final 변수 : 값이 변경될 수 없는 상수</p>
<p>   public static final double PI = 3.14;</p>
<p>final 메서드 : 하위 클래스에서 재정의 할 수 없는 메서드</p>
<p>final 클래스 : 상속할 수 없는 클래스</p>
<h2 id="예시-1">예시</h2>
<ul>
<li>여러 자바 파일에서 사용하는 상수 값 정의</li>
</ul>
<p>Define.java</p>
<pre><code class="language-java">public class Define {

    public static final int MIN = 1;
    public static final int MAX = 999999;
    public static final double PI = 3.14;
    public static final String GREETING = &quot;Good Morning!&quot;;
    public static final int MATH_CODE = 1001;
    public static final int CHEMISTRY_CODE = 1002;

}</code></pre>
<p>UsingDefine.java</p>
<pre><code class="language-java">public class UsingDefine {

    public static void main(String[] args) {

        System.out.println(Define.GREETING);
        System.out.println(Define.MIN);
        System.out.println(Define.MAX);
        System.out.println(Define.MATH_CODE);
        System.out.println(Define.CHEMISTRY_CODE);
        System.out.println(&quot;원주률은&quot; + Define.PI + &quot;입니다.&quot;);
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[상속과 다형성]]></title>
            <link>https://velog.io/@bill_0285/%EC%83%81%EC%86%8D%EA%B3%BC-%EB%8B%A4%ED%98%95%EC%84%B1-1r6946to</link>
            <guid>https://velog.io/@bill_0285/%EC%83%81%EC%86%8D%EA%B3%BC-%EB%8B%A4%ED%98%95%EC%84%B1-1r6946to</guid>
            <pubDate>Wed, 03 May 2023 10:47:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="상속">상속</h1>
<hr>
<h2 id="설명">설명</h2>
<ul>
<li><p>상속은 하나의 클래스가 다른 클래스의 속성과 동작을 가져와 그대로 사용할 수 있도록 하는 기능이다.</p>
</li>
<li><p>새로운 클래스를 정의 할 때 이미 구현된 클래스를 상속(inheritance) 받아서 속성이나 기능을 확장하여 클래스를 구현함</p>
</li>
<li><p>이미 구현된 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야 할때 기존 클래스를 상속함</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/f9f6324e-b16a-42a4-836d-65b29ebfb470/image.png" alt="클래스 상속"></p>
<ul>
<li><p>상속하는 클래스 : 상위 클래스, parent class, base class, super class</p>
</li>
<li><p>상속받는 클래스 : 하위 클래스, child class, derived class, subclass</p>
</li>
<li><p>상위 클래스는 하위 클래스 보다 더 일반적인 개념과 기능을 가짐</p>
</li>
<li><p>하위 클래스는 상위 클래스 보다 더 구체적인 개념과 기능을 가짐</p>
</li>
<li><p>하위 클래스가 상위 클래스의 속성과 기능을 확장 (extends)한다는 의미</p>
</li>
</ul>
<h2 id="문법">문법</h2>
<pre><code class="language-java">class B extends A{
} //클래스 B가 클래스 A를 상속한다는 의미.</code></pre>
<ul>
<li><p>extends 키워드 뒤에는 <strong>단 하나의 클래스</strong>만 올 수 있음</p>
</li>
<li><p><strong>자바는 단일 상속(single inheritance)만을 지원함</strong></p>
</li>
</ul>
<h2 id="예시">예시</h2>
<p>예시는 구체적인 시나리오가 있으면 더욱 좋다. 다음과 같은 예시를 들겠다.</p>
<h3 id="멤버십-시나리오">멤버십 시나리오</h3>
<blockquote>
<p>회사에서 고객 정보를 활용한 맞춤 서비스를 하기 위해 일반고객(Customer)과 이보다 충성도가 높은 우수고객(VIPCustomer)에 따른 서비스를 제공하고자 한다.<br></p>
</blockquote>
<ol>
<li>물품을 구매 할때 적용되는 할인율과 적립되는 보너스 포인트의 비율이 다름<br></li>
<li>여러 멤버십에 대한 각각 다양한 서비스를 제공할 수 있음<br></li>
</ol>
<h3 id="클래스-상속을-활용하여-구현해보기">클래스 상속을 활용하여 구현해보기</h3>
<ol>
<li>일반 고객(Customer) 클래스 구현</li>
</ol>
<ul>
<li><p>고객의 속성 : 고객 아이디, 고객 이름, 고객 등급, 보너스 포인트, 보너스 포인트 적립비율</p>
</li>
<li><p>일반 고객의 경우 물품 구매시 1%의 보너스 포인트 적립</p>
</li>
</ul>
<p>Customer.java</p>
<pre><code class="language-java">package ch01;

public class Customer {

    private int customerID;
    private String customerName;
    private String customerGrade;
    int bonusPoint;
    double bonusRatio;

    public Customer() {
        customerGrade = &quot;SILVER&quot;;
        bonusRatio = 0.01;
    }

    public int calcPrice(int price) {
        bonusPoint += price * bonusRatio;
        return price;
    }

    public String showCustomerInfo() {
        return customerName + &quot;님의 등급은 &quot; + customerGrade + 
                &quot;이며, 보너스 포인트는&quot; + bonusPoint + &quot;입니다&quot;;

    }
}</code></pre>
<ol start="2">
<li>우수 고객(VIPCustomer) 구현<blockquote>
</blockquote>
매출에 더 많은 기여를 하는 단골 고객
제품을 살때 10%를 할인해 줌
보너스 포인트는 제품 가격의 5%를 적립해 줌
담당 전문 상담원이 배정됨</li>
</ol>
<ul>
<li><p>Customer 클래스에 추가해서 구현하는 것은 좋지 않음</p>
</li>
<li><p>VIPCustomer 클래스를 따로 구현</p>
</li>
<li><p>이미 Customer에 구현된 내용이 중복되므로 Customer를 확장하여 구현함(상속)</p>
<h3 id="😏ㅋㅋ바본가-그냥-if절-추가하셈😏">😏ㅋㅋ바본가 그냥 if절 추가하셈😏</h3>
<p>마자마자. 내말이 그말임 ㅎ. 그냥 VIP 고객만 추가된건데, 굳이 전용 클래스 까지 만들어야하는 이유가 있음? 코드 낭비, 시간 낭비인듯..</p>
</li>
</ul>
<p>=&gt; 그래, 위에 <strong>시나리오가 더이상 확장될 여지 없이 고정됐고, 추가적인 요구사항이 절대 없다면</strong> 당연히 그게 훨씬 간단하고 가시적이지.</p>
<p>=&gt; 하지만, 대부분의 프로젝트는 그런식으로 흘러가지 않는다. 초기 계획과 완전히 다르게 진행되는 프젝도 있고, 중간중간 요구사항, 수정사항이 끝없이 들어온다.</p>
<p>=&gt; 당장 고객등급만 봐도, VIP 고객만 있어서 그렇지, 나중에 Gold 고객 Silver, Bronze 고객같이 등급을 세분화 해달라고 요구사항이 추가 될수 있잖아?</p>
<p>=&gt; 당장 가격계산 메서드만 봐도</p>
<pre><code class="language-java">public int calcPrice(int price) {
    if (customerGrade==&quot;Silver&quot;) {
        bonusPoint += price * bonusRatio;
        return price;
    }
    else if (customerGrade==&quot;Gold&quot;) {
            //blablabla
    }
    else if (customerGrade==&quot;Vip&quot;) {
            //blablabla
    }
      ...
    /// 고객 등급이 추가될때마다 모든 메서드마다 등급분류하는 if절 추가해줘야함 ;;

    }</code></pre>
<p>위처럼 고객 등급이 추가될떄마다 메서드에 if절 추가할껀가? 등급별 다르게 기능해야될 메서드가 저거 말고도 무수히 많을 텐데?</p>
<p>=&gt; 아 맞네, 추후 확장성, 유연성을 위해 상속을 하는 거구나</p>
<p>=&gt; 그래서 나는 만약 Gold등급을 추가해야한다면, GoldCustomer클래스를 정의할 것이다. </p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/546759bf-5de1-4c2f-80b7-f93e89d2a742/image.png" alt=""></p>
<p>그리고 VIP, Gold 고객 클래스는 기본 고객 클래스와 <strong>IS-A관계</strong>이기 때문에 상속을 사용하기 더할나위없이 좋은 케이스이다.
(IS-A 관계 뒤에 설명)</p>
<p>이제 이어서,</p>
<p>우수 고객 클래스를 구현하면</p>
<p>VIPCustomer.java</p>
<pre><code class="language-java">public class VIPCustomer extends Customer{

    private int agentID;
    double salesRatio;

    public VIPCustomer() {
        customerGrade = &quot;VIP&quot;;    //오류 발생
        bonusRatio = 0.05;
        salesRatio = 0.1;
    }

    public int getAgentID() {
        return agentID;
    }
}</code></pre>
<p>다음과 같다. 여기서 오류 발생이라고 한 부분을 보면,</p>
<ul>
<li><p>상위 클래스에 선언된 private 멤버 변수는 하위 클래스에서 접근 할 수 없다 =&gt; customerGrade 변수사용시 오류 발생</p>
</li>
<li><p>외부 클래스는 접근 할 수 없지만, 하위 클래스는 접근 할 수 있도록 protected 접근 제어자를 사용</p>
</li>
<li><p>그리고 외부에서 접근을 위한 getter/setter 선언</p>
</li>
</ul>
<p>Customer.java</p>
<pre><code class="language-java">    protected int customerID;
    protected String customerName;
    protected String customerGrade; 
    //이제 VIPCustomer에서 오류안뜸

    //getter, setter 구현
    ...
    public int getCustomerID() {
        return customerID;
    }

    public void setCustomerID(int customerID) {
        this.customerID = customerID;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getCustomerGrade() {
        return customerGrade;
    }

    public void setCustomerGrade(String customerGrade) {
        this.customerGrade = customerGrade;
    }</code></pre>
<p>Customer와 VIPCustomer 테스트하기</p>
<pre><code class="language-java">public class CustomerTest {

    public static void main(String[] args) {
        Customer customerLee = new Customer();
        customerLee.setCustomerName(&quot;이순신&quot;);
        customerLee.setCustomerID(10010);
        customerLee.bonusPoint = 1000;
        System.out.println(customerLee.showCustomerInfo());


        VIPCustomer customerKim = new VIPCustomer();
        customerKim.setCustomerName(&quot;김유신&quot;);
        customerKim.setCustomerID(10020);
        customerKim.bonusPoint = 10000;
        System.out.println(customerKim.showCustomerInfo());
    }
}</code></pre>
<p>출력결과 
<img src="https://velog.velcdn.com/images/bill_0285/post/4abacc50-2b06-4a12-b87a-7b3275f589f9/image.png" alt=""></p>
<h2 id="상속에서-클래스-생성-과정">상속에서 클래스 생성 과정</h2>
<h3 id="하위-클래스가-생성-되는-과정">하위 클래스가 생성 되는 과정</h3>
<ul>
<li><p>하위 클래스를 생성하면 상위 클래스가 먼저 생성 됨</p>
</li>
<li><p>new VIPCustomer()를 호출하면 Customer()가 먼저 호출 됨</p>
</li>
<li><p><strong>클래스가 상속 받은 경우 하위 클래스의 생성자에서는 반드시 상위 클래스의 생성자를 호출 함</strong></p>
</li>
</ul>
<p>Customer 생성자</p>
<pre><code class="language-java">public Customer() {
        customerGrade = &quot;SILVER&quot;;
        bonusRatio = 0.01;

        System.out.println(&quot;Customer() 생성자 호출&quot;);
}</code></pre>
<p>VIPCustomer 생성자</p>
<pre><code class="language-java">public VIPCustomer() {
        customerGrade = &quot;VIP&quot;;
        bonusRatio = 0.05;
        salesRatio = 0.1;

        System.out.println(&quot;VIPCustomer() 생성자 호출&quot;);
}</code></pre>
<p>위 경우에서 VIPCustomer 인스턴시 생성시 출력은</p>
<pre><code class="language-java">&quot;Customer() 생성자 호출&quot;
&quot;VIPCustomer() 생성자 호출&quot;</code></pre>
<p>이렇게 출력될 것이다.</p>
<h3 id="super-키워드">super 키워드</h3>
<ul>
<li><p>하위 클래스에서 가지는 <strong>상위 클래스에 대한 참조 값</strong></p>
</li>
<li><p>super()는 상위 클래스의 <strong>기본 생성자를 호출</strong> 함</p>
</li>
<li><p>하위 클래스에서 명시적으로 상위 클래스의 생성자를 호출하지 않으면 컴파일러가 자동으로 super()를 호출</p>
<p>=&gt; 자식생성자 호출 시 반드시 부모생성자를 호출해야되기 때문</p>
</li>
<li><p>이때 반드시 <strong>상위 클래스의 기본[디폴트] 생성자가 존재 해야 함</strong></p>
<p>=&gt; 상위 클래스의 기본 생성자가 없는데 super() 호출하면 오류가 생김</p>
</li>
<li><p>상위 클래스의 기본 생성자가 없는 경우 ( 다른 생성자가 있는 경우 ) 하위 클래스의 생성자에서는 super를 이용하여
명시적으로 상위 클래스의 생성자를 호출 함</p>
</li>
</ul>
<p>ex) 
Customer.java</p>
<pre><code class="language-java">// 디폴트 생성자 없애고 매개 변수가 있는 생성자 추가
public Customer(int customerID, String customerName) {
        this.customerID = customerID;
        this.customerName = customerName;

        customerGrade = &quot;SILVER&quot;;
        bonusRatio = 0.01;
        System.out.println(&quot;Customer(int, String) 생성자 호출&quot;);
}</code></pre>
<p>VIPCustomer.java</p>
<pre><code class="language-java">// super를 이용하여 상위 클래스의 생성자 명시적으로 호출
public VIPCustomer(int customerID, String customerName) {        
        super(customerID, customerName);// 이렇게 해줘야함
        // super()를 호출할 경우 오류가남
        // =&gt; Customer 클래스가 기본생성자가 없기때문에
        // =&gt; 자바에서 클래스는 생성자를 따로 정의할경우, 
        // 기본 생성자는 자동으로 생성되지 않음
        customerGrade = &quot;VIP&quot;;
        bonusRatio = 0.05;
        salesRatio = 0.1;

        System.out.println(&quot;VIPCustomer(int, String) 생성자 호출&quot;);
}</code></pre>
<p>super는 생성된 <strong>상위 클래스 인스턴스의 참조 값</strong>을 가지므로 super를 이용하여 상위 클래스의 메서드나 멤버 변수에 접근할 수 있음</p>
<p>ex)</p>
<pre><code class="language-java">super.bounusRatio  //변수
super.getCustomerGrade()  //메서드</code></pre>
<p>위에 방식대로 사용가능</p>
<h3 id="상속에서-인스턴스-메모리의-상태">상속에서 인스턴스 메모리의 상태</h3>
<ul>
<li>항상 <strong>상위 클래스의 인스턴스가 먼저 생성되고, 하위 클래스의 인스턴스가 생성 됨</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/e51b8580-9b25-4518-8080-1ad63fc3426a/image.png" alt=""></p>
<h3 id="형-변환업캐스팅">형 변환(업캐스팅)</h3>
<ul>
<li>상위 클래스로 변수를 선언하고 하위 클래스의 생성자로 인스턴스를 생성</li>
</ul>
<p>ex) </p>
<pre><code class="language-java">Customer customerLee = new VIPCustomer();</code></pre>
<p>상위 클래스 타입의 변수에 하위 클래스 변수가 대입;</p>
<pre><code class="language-java">VIPCustomer vCustomer = new VIPCustomer();
//자식클래스로 변수 선언

int addCustomer(Customer customer){
}
//부모 클래스를 매개변수로 받는 함수 선언

addCustomer(vCustomer);
//매개변수로 자식 클래스 자료형 넣어도 오류안남
//=&gt; 묵시적 형 변환 일어났기 떄문. </code></pre>
<p>하위 클래스는 상위 클래스의 타입을 내포하고 있으므로 상위 클래스로의 묵시적 형 변환이 가능함</p>
<p>상속 관계에서 모든 하위 클래스는 상위 클래스로 형 변환(업캐스팅)이 됨 
( 그 역은 성립하지 않음) =&gt; 그 역은 다운캐스팅이라함.</p>
<p>쉽게 말해 원래 대입연산자가 오른쪽을 왼쪽에 대입, 즉 rv를 lv에 넣는 과정이라생각하면 쉽다.</p>
<p>포유류=사람 (사람은 포유류이다)
탈것=비행기(비행기는 탈것이다)</p>
<p>근데 반대는 이상하잖아 =&gt; 그게 다운캐스팅 명시적형변환 해줘야함</p>
<h3 id="형-변환과-메모리-접근">형 변환과 메모리 접근</h3>
<ul>
<li><p>Customer vc = new VIPCustomer(); 에서 vc가 가리키는 것은?</p>
</li>
<li><p>VIPCustomer() 생성자에 의해 VIPCustomer 클래스의 모든 멤버 변수에 대한 메모리는 생성되었지만,</p>
</li>
<li><p>변수의 타입이 Customer 이므로 실제 접근 가능한 변수나 메서드는 Customer의 변수와 메서드임</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/82956eed-ab9d-4c49-bcb8-6f9f8457b9c2/image.png" alt=""></p>
<ul>
<li><p>(주의! VIPCustomer 클래스의 멤버들이 생성이 안된게 아님! 
메모리에 로드 돼있음! 접근을 못할 뿐...)</p>
</li>
<li><p>vc 변수의 타입은 Customer지만 인스턴스의 타입은 VIPCustomer 임</p>
</li>
<li><p>자바에서는 항상 <strong>인스턴스의 메서드가 호출 됨 (가상메서드의 원리)</strong></p>
</li>
<li><p>자바의 <strong>모든 인스턴스 메서드는 가상 메서드(virtual method) 임</strong></p>
</li>
</ul>
<h2 id="가상메서드">가상메서드</h2>
<h3 id="메서드는-어떻게-호출되고-실행-되는가">메서드는 어떻게 호출되고 실행 되는가?</h3>
<ul>
<li><p>메서드(함수)의 이름은 주소값을 나타냄</p>
</li>
<li><p>메서드는 명령어의 set 이고 프로그램이 로드되면 메서드 영역(코드 영역)에 명령어 set이 위치</p>
</li>
<li><p>해당 메서드가 호출 되면 명령어 set 이 있는 주소를 찾아 명령어가 실행됨</p>
</li>
<li><p>이때 메서드에서 사용하는 변수들은 스택 메모리에 위치 하게됨</p>
</li>
<li><p>따라서 다른 인스턴스라도 같은 메서드의 코드는 같으므로 같은 메서드가 호출됨</p>
</li>
<li><p>인스턴스가 생성되면 변수는 힙 메모리에 따로 생성되지만, <strong>메서드 명령어 set은 처음 한번만 로드 됨</strong></p>
</li>
</ul>
<p>쉽게 말해서 code영역에서 우리가 짠 메서드가 </p>
<p>⇒ 기계어(명령어집합(인스트럭션 셋))로 코드 영역에 저장 </p>
<p>⇒그리고 함수 호출시 해당 명령어 셋이있는 주소로가서 cpu가 읽는다</p>
<p>⇒ 그 메서드에서도 지역변수가 쓰인다? 그럼 stack영역에 메모리 점유했다가 메서드 블록이 끝나면 소멸되겠지;; 앞에서 배웠잖아!</p>
<p>그리고 당연히, 인스턴스마다 메서드를 호출하면 그 메서드가 복제되서 주소가 생기는게 아니라, </p>
<p>그냥 A라는 메서드를 호출하면 그 A에 담겨있는 로직이 이 위치해있는 주소로 가는거임.</p>
<p>배열의 이름이 주소인것과 마찬가지로, <strong>함수 명도 그 함수의 로직이 담겨있는 주소</strong>라고 생각하면된다.</p>
<p>ex)</p>
<pre><code class="language-java">public class TestMethod {

    int num;

    void aaa() {
        System.out.println(&quot;aaa() 호출&quot;);
    }

    public static void main(String[] args) {

        TestMethod a1 = new TestMethod();
        a1.aaa();

        TestMethod a2 = new TestMethod();
        a2.aaa();
    }

}</code></pre>
<p>위 코드에서 a1, a2 는 참조 &#39;지역변수&#39; 로서 stack영역에 할당,
a1,a2 가 각각 가리키는 멤버변수 num은 각각 heap영역에 할당,
인스턴스 메서드인 aaa는 인스턴스 a1,a2가 생성될떄마다 추가되는게아니고, 메서드영역에 한번만 할당됨.
<img src="https://velog.velcdn.com/images/bill_0285/post/b04ac05a-428c-4be4-bf23-f6e038acc2f0/image.png" alt=""></p>
<h3 id="가상-메서드의-원리">가상 메서드의 원리</h3>
<ul>
<li><p>클래스마다 가상 메서드 테이블이 있다.</p>
</li>
<li><p>가상 메서드 테이블(vitual method table)에서 해당 메서드에 대한 address를 가지고 있음</p>
</li>
<li><p>재정의된 경우는 재정의 된 메서드의 주소를 가리킴</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/e2fa43d8-99de-419f-9702-a2333f966b45/image.png" alt=""></p>
<p>그럼 이제설명이 가능하다</p>
<p>부모클래스 변수명=new 자식클래스(); 했을떄, </p>
<p>변수 타입은 부모클래스가 맞지만, 인스턴스 타입은 자식클래스이다. </p>
<p>따라서 자바는 <strong>인스턴스 타입의 가상메서드 테이블을 따르므로</strong>, 호출한 함수가 자식클래스에서 오버라이딩한 함수라면 재정의된 함수가 실행된다!<img src="https://velog.velcdn.com/images/bill_0285/post/38084e06-6c54-4527-81f8-1f56de9035e8/image.png" alt=""></p>
<h3 id="클래스-메서드는-가상-메서드">클래스 메서드는 가상 메서드?</h3>
<p>클래스 메서드(Static method)는 가상 메서드가 아니다!</p>
<p>클래스 메서드는 객체의 인스턴스와는 무관하게 클래스의 이름을 통해 호출되며, <strong>정적 바인딩(Static binding)으로 호출 대상이 결정</strong>된다.</p>
<p>따라서, 클래스 메서드는 가상 메서드가 아니며, 호출 대상 객체의 실제 타입에 따라 실행되는 메서드가 아닙니다.</p>
<h3 id="다운-캐스팅과-instanceof">다운 캐스팅과 instanceof</h3>
<h4 id="다운-캐스팅downcasting">다운 캐스팅(downcasting)</h4>
<ul>
<li><p>업캐스팅된 클래스를 다시 원래의 타입으로 형 변환</p>
</li>
<li><p>하위 클래스로의 형 변환은 명시적으로 해야 함</p>
</li>
<li><p>Customer vc = new VIPCustomer();              //묵시적</p>
</li>
<li><p>VIPCustomer vCustomer = (VIPCustomer)vc;      //명시적</p>
</li>
</ul>
<h4 id="instanceof를-이용하여-인스턴스의-형-체크">instanceof를 이용하여 인스턴스의 형 체크</h4>
<ul>
<li>원래 인스턴스의 형이 맞는지 여부를 체크하는 키워드 맞으면 true 아니면 false를 반환 함</li>
</ul>
<h2 id="상속은-언제-사용할까">상속은 언제 사용할까</h2>
<h3 id="is-a-관계-is-a-relationship--inheritance">IS-A 관계 (is a relationship : inheritance)</h3>
<ul>
<li><p>일반적인(general) 개념과 구체적인(specific) 개념과의 관계</p>
</li>
<li><p>상위 클래스 : 하위 클래스보다 일반적인 개념 ( 예: Employee )</p>
</li>
<li><p>하위 클래스 : 상위 클래스보다 구체적인 개념들이 더해짐 ( 예: Engineer, Manager...)</p>
</li>
<li><p>상속은 클래스간의 결합도가 높은 설계</p>
</li>
<li><p>상위 클래스의 수정이 많은 하위 클래스에 영향을 미칠 수 있음</p>
</li>
<li><p>계층구조가 복잡하거나 hierarchy가 높으면 좋지 않음</p>
</li>
</ul>
<p>ex) Customer 라는 일반적인 개념
VIPCustomer, GoldCustomer , SilverCustomer 라는 구체적인 개념</p>
<h3 id="has-a-관계-composition">HAS-A 관계 (composition)</h3>
<ul>
<li><p>클래스가 다른 클래스를 포함하는 관계 ( 변수로 선언 )</p>
</li>
<li><p>코드 재사용의 가장 일반적인 방법</p>
</li>
<li><p><strong>상속하지 않음</strong>
=&gt; 인터페이스를 이용해서 HAS-A 관계 표현</p>
</li>
</ul>
<p>ex)</p>
<ul>
<li><p>Student가 Subject를 포함함</p>
</li>
<li><p>Library를 구현할 때 ArrayList 생성하여 사용</p>
<p>=&gt; 우리가 클래스안에 ArrayList를 사용한다고 해서 ArrayList를 상속하지는 않음</p>
<ul>
<li>보통 HAS-A 관계는 <strong>인터페이스로</strong> 구현함
(velog에 인터페이스 정리한 곳 참고)</li>
</ul>
</li>
</ul>
<h3 id="결론">결론</h3>
<p>IS-A 관계면 상속을 사용하고, HAS-A 관계이면 인터페이스로 구현 권장</p>
<h1 id="다형성">다형성</h1>
<hr>
<h2 id="다형성polymorphism-이란">다형성(polymorphism) 이란?</h2>
<ul>
<li><p><strong>하나의 코드가 여러 자료형으로 구현되어 실행되는 것</strong></p>
</li>
<li><p>같은 코드에서 여러 다른 실행 결과가 나옴</p>
</li>
<li><p>정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 특징 중 하나임</p>
</li>
<li><p>다형성을 잘 활용하면 유연하고 확장성있고, 유지보수가 편리한 프로그램을 만들수 있음</p>
</li>
</ul>
<h2 id="다형성의-예">다형성의 예</h2>
<pre><code class="language-java">class Animal{

    public void move() {
        System.out.println(&quot;동물이 움직입니다.&quot;);
    }

    public void eating() {

    }
}

class Human extends Animal{
    public void move() {
        System.out.println(&quot;사람이 두발로 걷습니다.&quot;);
    }

    public void readBooks() {
        System.out.println(&quot;사람이 책을 읽습니다.&quot;);
    }
}

class Tiger extends Animal{

    public void move() {
        System.out.println(&quot;호랑이가 네 발로 뜁니다.&quot;);
    }

    public void hunting() {
        System.out.println(&quot;호랑이가 사냥을 합니다.&quot;);
    }
}


class Eagle extends Animal{
    public void move() {
        System.out.println(&quot;독수리가 하늘을 날아갑니다.&quot;);
    }

    public void flying() {
        System.out.println(&quot;독수리가 날개를 쭉 펴고 멀리 날아갑니다&quot;);
    }
}



public class AnimalTest {

    public static void main(String[] args) {
        Animal hAnimal = new Human();
        Animal tAnimal = new Tiger();
        Animal eAnimal = new Eagle();

        ArrayList&lt;Animal&gt; animalList = new ArrayList&lt;Animal&gt;();
        animalList.add(hAnimal);
        animalList.add(tAnimal);
        animalList.add(eAnimal);

        for(Animal animal : animalList) {
            animal.move();
        }
    }    

}</code></pre>
<p>출력은 다음과 같다.</p>
<pre><code class="language-java">사람이 두발로 걷습니다.
호랑이가 네 발로 뜁니다.
독수리가 하늘을 날아갑니다.</code></pre>
<p>Animal 자리에 어떤 동물 타입이 들어가냐에 따른 다른 출력이 나온다. 
=&gt; 다형성 보여줌</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[static, this 키워드와 싱글톤 패턴]]></title>
            <link>https://velog.io/@bill_0285/static-%ED%82%A4%EC%9B%8C%EB%93%9C%EC%99%80-this-%ED%82%A4%EC%9B%8C%EB%93%9C</link>
            <guid>https://velog.io/@bill_0285/static-%ED%82%A4%EC%9B%8C%EB%93%9C%EC%99%80-this-%ED%82%A4%EC%9B%8C%EB%93%9C</guid>
            <pubDate>Mon, 01 May 2023 03:26:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="this-키워드">This 키워드</h1>
<hr>
<h2 id="설명">설명</h2>
<ul>
<li><strong>인스턴스 자신의 메모리주소</strong>를 가리키는 키워드</li>
<li>참조연산자(.) 를 통해 자신의 멤버 변수와 인스턴스 메서드 접근 가능</li>
<li>생성자에서 또 다른 생성자를 호출 할때 사용</li>
<li>리턴 값은 자신의 주소(참조값)을 반환 함</li>
</ul>
<h2 id="생성자에서-다른-생성자를-호출-하는-this">생성자에서 다른 생성자를 호출 하는 this</h2>
<ul>
<li>클래스에 생성자가 여러 개 인경우, this를 이용하여 생성자에서 다른 생성자를 호출할 수 있음</li>
</ul>
<ul>
<li>생성자에서 다른 생성자를 호출하는 경우, 인스턴스의 생성이 완전하지 않은 상태이므로 this() statement 이전에 다른 statement를 쓸 수 없음</li>
</ul>
<pre><code class="language-java">public class Person {

    String name;
    int age;

    public Person() {
    //여기에 어떠한 로직이 들어가면 안된다는 의미 
    // =&gt; 인스턴스가 아직 완성되지 않았기 떄문
        this(&quot;이름없음&quot;, 1);
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}</code></pre>
<h1 id="static">Static</h1>
<hr>
<h2 id="설명-1">설명</h2>
<p>인스턴스 변수처럼 객체가 new(인스턴스화) 될때 생성되는 변수가 아닌,</p>
<p><strong>프로세스가 메모리에 로드되는 순간 데이터 영역에 생성되는 변수</strong>이고, </p>
<p>이는 <strong>프로세스가 끝날때까지 메모리에 상주하게 되는 변수</strong>이다.</p>
<p>따라서 인스턴스의 생성과 상관 없이 사용할 수 있는 변수이며, 여러번 생성되는 변수가 아닌 한번만 생성되는 변수이다.</p>
<p>클래스 변수, 정적변수라고도 한다.</p>
<p>인스턴스 생성과 상관 없이 사용 가능하므로 <strong>클래스 이름으로 직접 참조</strong></p>
<p><em>static 사용 고려 상황 예시</em></p>
<ul>
<li><p>여러 인스턴스가 공유하는 기준 값이 필요한 경우</p>
</li>
<li><p>학생마다 새로운 학번 생성</p>
</li>
<li><p>카드회사에서 카드를 새로 발급할때마다 새로운 카드 번호를 부여</p>
</li>
<li><p>회사에 사원이 입사할때 마다 새로운 사번이 필요한 경우<img src="https://velog.velcdn.com/images/bill_0285/post/73c8e8db-a833-45b9-9657-9d5b576e6a92/image.png" alt=""></p>
</li>
</ul>
<h2 id="사용-및-예시">사용 및 예시</h2>
<p>Employee.java</p>
<pre><code class="language-java">public class Employee {

    public static int serialNum = 1000;
    //static 변수 선언

    private int employeeId;
    private String employeeName;
    private String department;

    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }

}</code></pre>
<p>EmployeeTest.java</p>
<pre><code class="language-java">public class EmployeeTest {

    public static void main(String[] args) {
        Employee employeeLee = new Employee();
        employeeLee.setEmployeeName(&quot;이순신&quot;);
        System.out.println(employeeLee.serialNum);


        Employee employeeKim = new Employee();
        employeeKim.setEmployeeName(&quot;김유신&quot;);
        employeeKim.serialNum++;

        System.out.println(employeeLee.serialNum);
        System.out.println(employeeKim.serialNum);

    }
}</code></pre>
<p>출력 결과
<img src="blob:https://velog.io/6c577637-e93d-4963-ab00-2f5a3d139a87" alt="업로드중.."></p>
<p>두 인스턴스 employeeLee 와 employeeKim 이 serialNum 변수를 공유함을 알 수 있다.</p>
<p>여기서는 공유함을 보여주기 위해 인스턴스로부터 참조해서 접근했지만 그냥
Employee.serialNum 으로 클래스로부터 바로 접근 가능하다.</p>
<h2 id="static-메서드">static 메서드</h2>
<h3 id="설명-2">설명</h3>
<p>변수와 마찬가지로 메서드의 반환 값 앞에 static키워드가 붙은 메서드가 static 메서드 이다. </p>
<p>주로 static 변수에 대한 기능을 제공하는데 사용하지만, 인스턴스가 생성되지 않더라도 호출이 필요한 메서드는 static으로 선언한다.</p>
<p>역시 인스턴스 생성과 무관하게 <strong>클래스 이름으로 호출하여 사용</strong>할수 있으므로 클래스 메서드라고도 한다.</p>
<h3 id="예시">예시</h3>
<p>serialNum 변수를 private으로 선언하고 getter/setter 구현</p>
<pre><code class="language-java">private static int serialNum = 1000;

 ...
public static int getSerialNum() {
    return serialNum;
}

public static void setSerialNum(int serialNum) {
    Employee.serialNum = serialNum;
}</code></pre>
<p>클래스 이름으로 호출 가능 ( 클래스 메서드, 정적 메서드 )</p>
<pre><code class="language-java">System.out.println(Employee.getSerialNum());</code></pre>
<h3 id="static-vs-인스턴스">static vs 인스턴스</h3>
<p><strong>static 메서드(클래스 메서드)에서는 인스턴스 변수를 사용할 수 없다.</strong></p>
<ul>
<li><p>static 메서드는 인스턴스 생성과 무관하게 클래스 이름으로 호출 될 수 있음</p>
</li>
<li><p>인스턴스 생성 전에 호출 될 수 있으므로 static 메서드 내부에서는 인스턴스 변수를 사용할 수 없음</p>
</li>
<li><p>당연하지만 static 메서드 안에서 지역변수가 사용되는건 가능하다. 어차피 지역변수는 스택에 쌓이고 함수호출끝나면 사라지기 때문.</p>
</li>
</ul>
<p><strong>인스턴스 메서드 에서는 static변수 사용 가능하다</strong></p>
<ul>
<li><p>어차피 인스턴스 메서드는 반드시 인스턴스가 생성되고 쓰이는 메서드이고, static 변수는 인스터스 만들어지기도 전에 data영역에 할당돼있기 때문</p>
</li>
<li><p>즉, 메모리적으로 이슈가 없기때문에 사용가능하다.</p>
</li>
</ul>
<p><strong>정리</strong></p>
<ul>
<li>static 메서드 -&gt; 지역변수, static변수 사용가능 / 멤버변수불가능 왜냐면 static 메서드가 인스턴스생성이전에 사용될수 있으므로</li>
<li>인스턴스 메소드-&gt; 지역변수, static변수, 멤버변수모두사용가능 왜냐면 static 변수는 프로그램 실행시 이미 메모리에 로드돼있기 때문</li>
</ul>
<h1 id="싱글톤-패턴">싱글톤 패턴</h1>
<hr>
<h2 id="싱글톤-패턴이란">싱글톤 패턴이란?</h2>
<ul>
<li>프로그램에서 인스턴스가 단 한 개만 생성되어야 하는 경우 사용하는 디자인 패턴</li>
</ul>
<ul>
<li>static 변수, 메서드를 활용하여 구현 할 수 있음</li>
</ul>
<h2 id="구현-예시">구현 예시</h2>
<ol>
<li>생성자는 private으로 선언</li>
</ol>
<pre><code class="language-java">private Company() {}</code></pre>
<ol start="2">
<li>클래스 내부에 유일한 private 인스턴스 생성</li>
</ol>
<pre><code class="language-java">private static Company instance = new Company();</code></pre>
<ol start="3">
<li><p>외부에서 유일한 인스턴스를 참조할 수 있는 public 메서드 제공</p>
<pre><code class="language-java">public static Company getInstance() {

 if( instance == null) {
     instance = new Company();
 }
 return instance;
}</code></pre>
</li>
</ol>
<p>CompanyTest.java</p>
<pre><code class="language-java">public class CompanyTest {

    public static void main(String[] args) {
        Company company1 = Company.getInstance();

        Company company2 = Company.getInstance();

        System.out.println(company1);
        System.out.println(company2);

    }
}</code></pre>
<p>두 출력 모두 같은 주소값을 출력한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체와 캡슐화]]></title>
            <link>https://velog.io/@bill_0285/%EA%B0%9D%EC%B2%B4-%EC%99%80-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@bill_0285/%EA%B0%9D%EC%B2%B4-%EC%99%80-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Fri, 28 Apr 2023 12:36:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<h1 id="객체">객체</h1>
<hr>
<h2 id="의미">의미</h2>
<ul>
<li>의사나 행위가 미치는 대상 ( 사전적 의미 )</li>
</ul>
<ul>
<li>구체적, 추상적 데이터의 단위 ( 학생, 회원, 생산, 주문, 배송 )</li>
</ul>
<br>

<h2 id="객체-지향--절차-지향">객체 지향 / 절차 지향</h2>
<h4 id="ex-아침에-일어나-학교를-가는-과정을-예를-들자">ex) 아침에 일어나 학교를 가는 과정을 예를 들자.</h4>
<br>

<h3 id="절차-지향-프로그래밍">절차 지향 프로그래밍</h3>
<ul>
<li><p>시간이나 사건의 흐름에 따른 프로그래밍</p>
<p>일어난다 -&gt; 씻는다 -&gt; 밥을 먹는다 -&gt; 버스를 탄다-&gt; 요금을 지불한다 -&gt; 학교에 도착</p>
</li>
</ul>
<h3 id="객체-지향-프로그래밍">객체 지향 프로그래밍</h3>
<ul>
<li>프로그램에 사용되는 &#39;객체&#39;를 기준으로 하는 프로그래밍</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/139b1b51-94df-4f0a-8652-c0086f856e3e/image.png" alt="객체지향 프로그래밍"></p>
<ul>
<li><p>객체 지향 프로그램은 어떻게 구현하는가?</p>
<ol>
<li><p>객체를 정의 하고</p>
</li>
<li><p>각 객체의 속성을 멤버 변수로, 역할을 메서드로 구현하고</p>
</li>
<li><p>각 객체가 제공하는 기능들 간의 소통(메세지 전달)을 통하여 객체간의 협력을 구현</p>
</li>
</ol>
</li>
</ul>
<h2 id="클래스-코딩하기">클래스 코딩하기</h2>
<ul>
<li>클래스는 대문자로 시작하는것이 좋음</li>
</ul>
<ul>
<li>java 파일 하나에 클래스는 여러 개가 있을 수 있지만, public 클래스는 하나이고, public 클래스와 .java 파일의 이름은 동일함</li>
</ul>
<ul>
<li>camel notation 방식으로 명명</li>
</ul>
<h2 id="참조-자료형">참조 자료형</h2>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/392d7ea9-c257-4c64-9d4c-6cae07eccde0/image.png" alt=""></p>
<ul>
<li><p>기본 자료형은 사용하는 메모리의 크기가 정해져 있지만, 참조 자료형은 클래스에 따라 다름</p>
</li>
<li><p>참조 자료형을 사용 할때는 해당 변수에 대해 생성하여야 함<br>(String 클래스는 예외적으로 생성하지 않고 사용할 수 있음)
<br><br></p>
<h1 id="인스턴스-생성과-힙-메모리">인스턴스 생성과 힙 메모리</h1>
</li>
</ul>
<hr>
<h2 id="인스턴스-instance">인스턴스 (instance)</h2>
<p>클래스는 객체의 속성을 정의 하고, 기능을 구현하여 만들어 놓은 코드 상태</p>
<p>실제 클래스 기반으로 생성된 객체(인스턴스)는 각각 다른 멤버 변수 값을 가지게 됨</p>
<p>가령, 학생의 클래스에서 생성된 각각의 인스턴스는 각각 다른 이름, 학번, 학년등의 값을 가지게 됨</p>
<p>new 키워드를 사용하여 인스턴스 생성</p>
<h2 id="힙-메모리">힙 메모리</h2>
<p>완성된 <strong>인스턴스는 동적 메모리(heap memory) 에 할당됨</strong></p>
<p>C나 C++ 언어에서는 사용한 동적 메모리를 프로그래머가 해제 시켜야 함
( C에서는 free() / C++에서는 delete 이용)</p>
<p>자바에서 <strong>Gabage Collector 가 주기 적으로 사용하지 않는 메모리를 수거</strong></p>
<p>하나의 클래스로 부터 여러개의 인스턴스가 생성되고 각각 다른 메모리 주소를 가지게 됨.</p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/e88c3d0e-7392-49b1-8850-f880a20566cf/image.png" alt="heap"></p>
<pre><code class="language-java">Student studentLee=new Student();</code></pre>
<p>여기서 studentLee는 <strong>참조변수</strong>라고 하고,
생성된 인스턴스의 메모리 주소 값을 참조 값이라함.</p>
<p>=&gt; studentLee가 가르키는게 heap영역에 저장된 <strong>인스턴스의 메모리 주소를 가르키기때문</strong>
<br><br></p>
<h1 id="생성자">생성자</h1>
<hr>
<h2 id="설명">설명</h2>
<ul>
<li>생성자 기본 문법<blockquote>
</blockquote>
&lt;클래스 명&gt;([매개변수])
{
원하는 멤버변수의 초기 셋팅 또는 메서드 실행
}</li>
</ul>
<p>ex)</p>
<pre><code class="language-java">public Student(int studentNumber, String studentName, int grade) {
        this.studentNumber = studentNumber;
        this.studentName = studentName;
        this.grade = grade;
    }</code></pre>
<ul>
<li>객체를 생성할 때 new 키워드와 함께 사용   - new Student();</li>
</ul>
<ul>
<li>생성자는 일반 함수처럼 기능을 호출하는 것이 아니고 객체를 생성하기 위해 new 와 함께 호출 됨</li>
</ul>
<ul>
<li>객체가 생성될 때 변수나 상수를 초기화 하거나 다른 초기화 기능을 수행하는 메서드를 호출 함</li>
</ul>
<ul>
<li>생성자는 반환 값이 없고, 클래스의 이름과 동일</li>
</ul>
<ul>
<li><p>대부분의 생성자는 외부에서 접근 가능하지만, 필요에 의해 private 으로 선언되는 경우도 있음</p>
</li>
<li><p>멤버변수는 생성자호출되면서 값을 초기화 하지 않아도 자동으로 초기화됨(0, false, null 등등)</p>
</li>
</ul>
<h2 id="기본-생성자-default-constructor">기본 생성자 (default constructor)</h2>
<ul>
<li>클래스에는 반드시 적어도 하나 이상의 생성자가 존재</li>
</ul>
<ul>
<li><p>클래스에 생성자를 구현하지 않아도 new 키워드와 함께 생성자를 호출할 수 있음</p>
</li>
<li><p>디폴트 생성자는 생성자선언을 안햇을때 자동 생성됨</p>
</li>
<li><p>클래스에 생성자를 따로 구현하면 기본 생성자는 제공되지 않음</p>
<p>=&gt; 기본 생성자가 필요하다면 마찬가지로 선언해주면됨</p>
</li>
<li><p>매개 변수가 없음, 구현부가 없음</p>
</li>
</ul>
<h1 id="캡슐화">캡슐화</h1>
<hr>
<h2 id="설명-1">설명</h2>
<p>캡슐화란 클래스 안에 서<strong>로 연관있는 속성과 기능들을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호</strong>하는 것을 말한다. =&gt; 이때 캡슐은 클래스를 의미</p>
<h2 id="목적">목적</h2>
<ul>
<li><p>데이터 보호(data protection) – 외부로부터 클래스에 정의된 속성과 기능들을 보호</p>
</li>
<li><p>데이터 은닉(data hiding) – 내부의 동작을 감추고 외부에는 필요한 부분만 노출</p>
<p>=&gt; 참조연산자(.)로 직접 접근 지양.</p>
</li>
</ul>
<h2 id="효과">효과</h2>
<p>캡슐화를 통해 객체 동작의 구현 세부 정보를 숨기고 객체와 상호 작용하기 위한 <strong>공용 인터페이스(메서드)만 클라에 제공</strong>한다.</p>
<p>객체를 이용하는 <strong>클라이언트는 객체가 어떤 데이터와 코드를 가지고 있는지 몰라도</strong> 인터페이스를 통해 <strong>객체의 기능을 사용할 수 있다.</strong> </p>
<p>즉, 객체 내부의 데이터와 코드를 외부에 노출하지 않고도 객체의 기능을 사용할 수 있다. </p>
<p>이는 *<em>객체의 내부 구현을 변경하더라도 외부 코드에 영향을 미치지 않게 만들어준다. *</em></p>
<p>또한, 객체 내부에 캡슐화된 데이터를 보호하고, 잘못된 접근으로 인한 오류를 방지하는 효과도 있다.</p>
<p>(실제로 우리가쓰는 대부분 언어의 내장함수는 캡슐화가 잘 되어있다.)</p>
<h2 id="구현-방법">구현 방법</h2>
<h3 id="1-접근-제어-지시자">1. 접근 제어 지시자</h3>
<p>클래스 외부에서 클래스의 멤버 변수, 메서드, 생성자를 사용할 수 있는지 여부를 지정하는 키워드</p>
<ul>
<li>private : 같은 클래스 내부에서만 접근 가능 ( 외부 클래스, 상속 관계의 클래스에서도 접근 불가)</li>
</ul>
<ul>
<li>아무것도 없음 (default) : 같은 패키지 내부에서만 접근 가능 ( 상속 관계라도 패키지가 다르면 접근 불가)</li>
</ul>
<ul>
<li>protected : 같은 패키지나 상속관계의 클래스에서 접근 가능하고 그 외 외부에서는 접근 할 수 없음</li>
</ul>
<ul>
<li>public : 클래스의 외부 어디서나 접근 할 수 있음</li>
</ul>
<h3 id="2-getset-메서드">2. get/set 메서드</h3>
<p>private 으로 선언된 멤버 변수 (필드)에 대해 접근, 수정할 수 있는 메서드를 public으로 제공하는 방식. 각각 getter, setter라고도함</p>
<p>get() 메서드만 제공 되는 경우 read-only 필드</p>
<p>몇몇 IDE에서는 getter,setter를 생성해주는 기능있음 </p>
<p>=&gt; ex(이클립스)</p>
<pre><code class="language-java">public class Test1Test {
    private int studentNumber;
    private String studentName;

    public int getStudentNumber() { //Eclipse 에서 자동 generate 기능 이용
        return studentNumber;
    }

    public void setStudentNumber(int studentNumber) { //Eclipse 에서 자동 generate 기능 이용
        this.studentNumber = studentNumber;
    }

    public String getStudentName() { //Eclipse 에서 자동 generate 기능 이용
        return studentName;
    }

    public void setStudentName(String studentName) { //Eclipse 에서 자동 generate 기능 이용
        this.studentName = studentName;
    }

}</code></pre>
<h3 id="3-은닉화-구현-방법">3. 은닉화 구현 방법</h3>
<p>클래스에 멤버변수들을 private하게 선언하고,</p>
<p>get, set 메서드를 이용헤서 멤버변수의 변화를 주거나 가져오는게 은닉화에 전형적인 방법이다.</p>
<p>이렇게하면 <strong>멤버변수의 직접 접근을 막음</strong>으로서 객체를사용할떄 예상치 못한 오류를 막을수있고,</p>
<p>나중에 디버깅할떄도 어디서 잘못되었는지를 볼떄 메서드의 로직을 보면되기 떄문에 편리하다.</p>
<p>즉 객체를 사용하는 쪽에서 잘못 사용할 확률을 줄이는것이다.</p>
<p>그렇다고 안전을 위해 <strong>&#39;모든 변수들을 private해야한다&#39;는 아니다.</strong></p>
<p><strong>상황과 주어진 자원에 따라 멤버의 접근제어정도를 조절해야한다.</strong></p>
<p> 정책상으로 오픈해야되거나 오픈함으로써 더 유용한 멤버들은 public이나 다른 접근제어자로 접근허용 해주는게 좋다.</p>
<h3 id="4-캡슐화-고려하지-않은-코드">4. 캡슐화 고려하지 않은 코드</h3>
<pre><code class="language-java">public class MakeReport {

    StringBuffer buffer = new StringBuffer();

     private String line = &quot;===========================================\n&quot;;
     private String title = &quot;  이름\t   주소 \t\t  전화번호  \n&quot;;
     void makeHeader()
    {
        buffer.append(line);
        buffer.append(title);
        buffer.append(line);
    }

     void generateBody()
    {
        buffer.append(&quot;James \t&quot;);
        buffer.append(&quot;Seoul Korea \t&quot;);
        buffer.append(&quot;010-2222-3333\n&quot;);

        buffer.append(&quot;Tomas \t&quot;);
        buffer.append(&quot;NewYork US \t&quot;);
        buffer.append(&quot;010-7777-0987\n&quot;);
    }

     void makeFooter()
    {

        buffer.append(line);
    }


}</code></pre>
<p>위 MakeReport라는 코드를</p>
<pre><code class="language-java">public class TestMakeReport {

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


        report.makeHeader();
        report.generateBody();
        report.makeFooter();

        StringBuffer builder = report.buffer


        System.out.println(builder);

    }
}</code></pre>
<p>이렇게 하면 정상적을 출력이 될것이다. 것보기엔 문제가 없다. </p>
<p>하지만 이것은 캡슐화가 제대로 되지 않은 코드이다.  </p>
<p>캡슐화가 잘된 코드라면 report클래스에 쓰는 멤버변수와 메서드들은 최대한 그 클래스 내부에서 사용되서 캡슐처럼 닫혀있어야 하기 떄문이다. </p>
<p>멤버 변수중 buffer도 은닉화 되어 있지 않고,</p>
<p>MakeReport클래스안에서 report를 완성시키기 위해 만든 3가지 메서드를 TestMakeReport클래스 안에서 사용하고 있다. 이는 <strong>캡슐화가 제대로 이뤄지지 않았고, 두 클래스간 결합도가 높다고 할 수 있다.</strong></p>
<p>이런 경우, report를 만드는 로직이 바뀌면 TestMakeReport에서도 많은 부분이 수정해야 될 수 있다. </p>
<p>예를 들어, report를 만드는 순서가 makeHeader -&gt; makeFooter -&gt; generateBody 로 바꼈다고 해보자. 그러면 우리는 TestMakeReport 클래스에서 로직을 다음과 같이 바꿔야 한다.</p>
<pre><code class="language-java">public class TestMakeReport {

    public static void main(String[] args) {
        report report = new report();
        report.makeHeader();
        report.makeFooter();
        report.generateBody(); 

        StringBuffer builder = report.buffer
        System.out.println(builder);

    }
}</code></pre>
<p>지금 예시에서야 순서만 바뀐거지, 로직이나 함수명 등이 바뀌면 또 그걸 다 적용시켜줘야한다.</p>
<p>하지만 위 3가지 로직은 원래 MakeReport클래스의 기능이였으므로, <strong>3가지 로직을 은닉화 시키고 완성된 report 결과물 만을 TestMakeReport클래스가 사용하게 하면 어떨까?</strong></p>
<h3 id="5-캡슐화된-코드">5. 캡슐화된 코드</h3>
<pre><code class="language-java">public class MakeReport {

    private StringBuffer buffer = new StringBuffer();

     private String line = &quot;===========================================\n&quot;;
     private String title = &quot;  이름\t   주소 \t\t  전화번호  \n&quot;;
     private void makeHeader()
    {
        buffer.append(line);
        buffer.append(title);
        buffer.append(line);
    }

     private void generateBody()
    {
        buffer.append(&quot;James \t&quot;);
        buffer.append(&quot;Seoul Korea \t&quot;);
        buffer.append(&quot;010-2222-3333\n&quot;);

        buffer.append(&quot;Tomas \t&quot;);
        buffer.append(&quot;NewYork US \t&quot;);
        buffer.append(&quot;010-7777-0987\n&quot;);
    }

    private  void makeFooter()
    {

        buffer.append(line);
    }

    public String getReport()
    {
     void makeHeader();
     void generateBody();
     void makeFooter();
     return buffer.toString();
    }


}</code></pre>
<p>위 처럼 구현하면</p>
<pre><code class="language-java">public class TestMakeReport {

    public static void main(String[] args) {
        report report = new report();
        String builder = report.getReport();
        System.out.println(builder);
    }
}
</code></pre>
<p>이렇게 사용 가능하다.</p>
<p>여기서 핵심은 </p>
<ol>
<li><p>노출될 필요 없는 멤버 변수들을 모두 private하게 은닉화 시켰고</p>
</li>
<li><p>report를 만드는데 사용했던 3가지 로직을 은닉화 시킨 후, getReport라는 메서드만을 통해
외부에서 결과물을 받도록 하고 있다.</p>
</li>
</ol>
<p>이렇게 하면 report를 만드는 로직, 설정값등이 바껴도, 그 <strong>바뀐내용은 MakeReport클래스라는 캡슐안에서 내부적으로 수정</strong>될 것이고, 외부클래스인 <strong>TestMakeReport는 MakeReport내부가 바뀌든 말든 신경안쓰고 여전히 getReport 메서드를 통해서 원하는 결과물을 받을 수 있다!</strong></p>
<h3 id="6-결론">6. 결론</h3>
<p>이렇게 캡슐화를 활용하면, 객체 내부의 속성과 동작을 외부로의 노출을 최소화하여 각 객체의 자율성을 높이고, 이를 통해 객체 간 결합도를 낮추어 앞서 설명한 객체 지향의 핵심적인 이점을 잘 살리는 방법으로 프로그램을 설계하는 일이 가능하다.</p>
<h1 id="참고-자료">참고 자료</h1>
<ul>
<li><a href="https://www.codestates.com/blog/content/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A7%95">https://www.codestates.com/blog/content/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A7%95</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[카카오 테크 캠퍼스 1주차(진수, 데이터 영역, 인코딩, Switch)]]></title>
            <link>https://velog.io/@bill_0285/%EC%B9%B4%EC%B9%B4%EC%98%A4-%ED%85%8C%ED%81%AC-%EC%BA%A0%ED%8D%BC%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EC%A0%95%EB%A6%ACstatic%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%98%81%EC%97%AD-java-switch-expression2816%EC%A7%84%EC%88%98oop%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@bill_0285/%EC%B9%B4%EC%B9%B4%EC%98%A4-%ED%85%8C%ED%81%AC-%EC%BA%A0%ED%8D%BC%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EC%A0%95%EB%A6%ACstatic%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%98%81%EC%97%AD-java-switch-expression2816%EC%A7%84%EC%88%98oop%EA%B0%9C%EB%85%90</guid>
            <pubDate>Wed, 26 Apr 2023 13:23:30 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<p>1주차 동안 java 기초강의와 중급강의 1장을 들었다.</p>
<p>기본적으로 알고있는 내용이였지만, 헷갈리거나 확실히 몰랐던 내용들 위주로 블로그에 정리하기로 하였다.</p>
<p>다음 주차부터는 주차별 정리보단, 기술별, 주제별로 글을 포스트하는게 보는사람도, 스스로도 좋을거 같다.</p>
<h1 id="2-8-16진수">2, 8, 16진수</h1>
<hr>
<p><img src="blob:https://velog.io/ae8ee7e5-c2b8-427c-ba20-c357faef010f" alt="2,8,16 진수"></p>
<h2 id="설명">설명</h2>
<p>2, 8, 16진수의 개념과 그 표현방법은 기본적으로 알고 있을거라 생각한다. </p>
<p>자바에서는 2진수를 0b(또는 0B), 8진수를 0, 16진수를 0x(또는 0X)를 앞에 붙여 표현한다.</p>
<pre><code class="language-java">int binaryNum = 0b0101;  // 1*2^2  +   1*2^0  = 5
int octalNum = 0171; // 1*8^2   + 7*8^1 +   1*8^0 = 121
int decimalNum = 0x89; // 8*16^1   +   9*16^0 = 137
System.out.println(binaryNum); //5
System.out.println(octalNum); //121
System.out.println(decimalNum); //137</code></pre>
<p><br><br><br><br></p>
<h1 id="문자세트-및-인코딩">문자세트 및 인코딩</h1>
<hr>
<h2 id="문자세트">문자세트</h2>
<p>문자를 숫자로 변환한 값의 세트</p>
<p>ex): ASKII code, UNICODE</p>
<h3 id="아스키코드">아스키코드</h3>
<p> <img src="https://velog.velcdn.com/images/bill_0285/post/4465327f-8388-4226-a2c0-844a14988b24/image.gif" alt="아스키코드"></p>
<h4 id="설명-1">설명</h4>
<blockquote>
<p>아스키 코드는 알파벳과 숫자 특수 문자등을 1바이트에 표현하는데 사용하는 대표적인 문자세트이다. 1바이트로 구성되어 있는 아스키 코드는 8비트(==1바이트) 중 7개의 비트만 사용한다. 나머지 1비트는 <strong>Parity Bit이라고 불리는 오류 체크를 위한 비트로</strong>  통신 에러 검출을 위한 용도로 비워두었기 때문이다. Parity Bit를 제외한 7개의 비트 중 <strong>1의 개수가 홀수면 1, 짝수면 0</strong>으로 하는 식의 패리티 비트를 붙여서, 전송 도중 신호가 변질된 것을 수신측에서 검출해낼 수 있도록 하였다. </p>
</blockquote>
<p>위 설명중 패리티 비트는 옛날에 방식이다.</p>
<p>gpt chat에게 물어본 결과 현재는 아래와 같다고 한다.</p>
<blockquote>
<p>아스키 코드는 영문 알파벳을 사용하는 대표적인 문자세트가 맞습니다. 하지만, 1바이트로 구성되어 있는 아스키 코드는 8비트(==1바이트) 중 7개의 비트만 사용하며, 나머지 1비트는 Parity Bit가 아닌, <strong>보통 0으로 채워져 있습니다.</strong> Parity Bit는 통신 에러 검출을 위한 용도로 사용되긴 했지만, 아스키 코드에는 적용되지 않습니다. Parity Bit를 제외한 7개의 비트 중 1의 개수가 홀수면 1, 짝수면 0으로 하는 식의 패리티 비트를 붙여서, 전송 도중 신호가 변질된 것을 수신측에서 검출해낼 수 있도록 하는 방식이 있었습니다. 하지만, 현재는 대부분의 통신 장비에서 에러 검출을 위한 CRC 방식 등이 사용되며, <strong>패리티 비트는 거의 사용되지 않습니다.</strong></p>
</blockquote>
<p>즉  현재는 대부분의 통신 프로토콜이 오류 검출 및 수정 기능을 제공하기 때문에 패리티 비트는 거의 사용되지 않는다고 한다.</p>
<h3 id="유니코드">유니코드</h3>
<h4 id="설명-2">설명</h4>
<p>유니코드(Unicode)는 <strong>전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 처리하기 위한 국제표준 문자셋</strong>이다.</p>
<p>이는 기존의 문자셋인 ASCII, ISO-8859 등이 영어와 유럽언어만을 지원하는 제한적인 문자셋이었다는 문제점을 해결하기 위해 제정되었다.</p>
<p>유니코드는 다양한 언어와 문자체계를 지원하기 위해 <strong>1바이트에서 4바이트까지</strong> 다양한 크기의 코드 포인트를 사용한다. </p>
<p><strong>이를 통해 전 세계의 모든 문자를 표현할 수 있다.</strong> 유니코드에서는 한글, 중국어, 일본어와 같은 아시아권 문자부터 아랍어, 히브리어와 같은 우리나라에서는 쉽게 접하지 못하는 언어들까지 모두 지원한다.</p>
<h2 id="인코딩">인코딩</h2>
<h3 id="인코딩-1">인코딩</h3>
<p>인코딩(Encoding)은 컴퓨터에서 텍스트 데이터를 이진 데이터(바이너리 데이터)로 변환하는 과정</p>
<h3 id="디코딩">디코딩</h3>
<p>디코딩(Decoding)은 이진 데이터를 텍스트 데이터로 변환하는 과정</p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/aebd2cf4-c28f-4788-8d12-126c98159002/image.png" alt="인코딩 디코딩"></p>
<h3 id="종류">종류</h3>
<ol>
<li><h4 id="utf-8">UTF-8</h4>
<p>UTF-8은 <strong>가변 길이 문자 인코딩 방식</strong>이다.</p>
<p>UTF-8은 1바이트에서 4바이트까지 다양한 길이의 코드 포인트를 사용하여 전 세계의 모든 문자를 표현할 수 있다.</p>
<p><strong>ASCII 문자는 1바이트</strong>로 표현하고, <strong>한글과 같은 다국어 문자는 3바이트</strong>로 표현한다. </p>
<p>UTF-8은 <strong>유니코드의 가장 일반적인 인코딩 방식</strong>이며, 인터넷에서도 널리 사용된다.</p>
</li>
<li><h4 id="utf-16">UTF-16</h4>
<p>UTF-16 또한 유니코드의 인코딩 방식이며, <strong>고정 길이 문자 인코딩 방식이다.</strong> </p>
<p>UTF-16은 2바이트 또는 4바이트로 구성된 코드 포인트를 사용하여 문자를 표현한다. <strong>기본적으로 모든 문자가 2바이트로 표현</strong>되지만, <strong>SMP</strong>에 속한 문자는 4바이트로 표현된다.</p>
</li>
</ol>
<h3 id="smp와-하위인코딩-문제">SMP와 하위인코딩 문제</h3>
<ul>
<li><h4 id="smp">SMP</h4>
<p>Supplementary Multilingual Plane은 유니코드(Unicode)에서 제공하는 문자 집합 중 하나로, 0x10000(65,536)부터 0x10FFFF(1,114,111)까지의 문자를 포함한다. </p>
<p>이 영역은 Basic Multilingual Plane(BMP) 이외의 문자들을 포함하고 있으며, 주로 <strong>이모지, 한자, 히브리어, 아랍어, 한글</strong> 등을 포함하고 있다</p>
<p>SMP은 BMP에 비해 상대적으로 적은 문자를 포함하지만, 이 모든 문자를 BMP와 같은 방식으로 처리할 경우 코드 유닛이 4바이트를 차지하게 된다.</p>
<p>이는 <strong>메모리 공간과 처리 속도에서 비효율적</strong>일 수 있기 때문에, 보통 UTF-16 인코딩에서 SMP의 문자를 처리할 때는 <strong>surrogate pair</strong>라는 방식을 사용한다.</p>
</li>
<li><h4 id="surrogate-pair">Surrogate Pair</h4>
<p>Surrogate pair는 <strong>2개의 2바이트 코드 유닛을 사용하여 4바이트 문자를 표현</strong>하는 방식이다.</p>
<p>첫 번째 코드 유닛은 0xD800에서 0xDBFF 사이의 값 중 하나를 사용하고, 두 번째 코드 유닛은 0xDC00에서 0xDFFF 사이의 값 중 하나를 사용한다. </p>
<p>이렇게하면 SMP의 문자를 2개의 코드 유닛으로 표현할 수 있다.</p>
</li>
<li><h4 id="하위인코딩-문제">하위인코딩 문제</h4>
<p>하위 인코딩 문제는 UTF-16에서 SMP에 속한 문자를 인코딩 할떄 <strong>surrogate pair</strong>방식에서 문제가 생기는 걸 의미한다. </p>
<p>위에서 말했듯이 2개의 2바이트 코드 유닛을 사용할떄, 2개의 코드 유닛이 쌍(pair)을 이루어야 하며, 이 <strong>순서가 바뀌게 되면 잘못된 문자를 표현</strong>할 수 있다. </p>
<p>또한, 이 surrogate pair 방식을 올바르게 사용하지 않거나 처리하지 않을 경우 하위 인코딩 문제가 발생할 수 있다.</p>
<p>이러한 하위 인코딩 문제는 UTF-16을 다룰 때 주의해야 할 문제 중 하나이다. </p>
<p>이를 방지하기 위해서는 surrogate pair 방식을 올바르게 처리하는 코드가 필요하며, 최신 버전의 프로그래밍 언어나 라이브러리는 이러한 문제를 해결하기 위한 함수나 메서드를 제공하고 있다.</p>
</li>
</ul>
<h3 id="하위인코딩-왜-하필-utf-16에서만">하위인코딩, 왜 하필 UTF-16에서만?</h3>
<h4 id="-utf-16은-고정-길이방식이기-때문이다">=&gt; UTF-16은 고정 길이방식이기 때문이다!</h4>
<p>고정적으로 문자 표현을 2바이트로 사용하기 때문에, SMP의 문자를 처리할 때 surrogate pair 방식을 사용한다.</p>
<p>하지만 이 surrogate pair 방식에서 일부 구현에서는 하위 인코딩을 허용하면서 다양한 문제를 일으키게 된다.</p>
<p>예를 들어, 첫 번째 코드 유닛으로 0xDC00에서 0xDFFF 사이의 값을 사용하는 등의 문제가 있다.</p>
<p>반면에 UTF-8은 가변 길이 인코딩 방식으로, 1바이트에서 4바이트까지 다양한 길이의 코드 유닛을 사용한다.</p>
<p>SMP의 문자를 표현할 때에도 4바이트로 인코딩하며, 이 때 surrogate pair 방식을 사용하지 않기 때문에 하위 인코딩 문제가 발생하지 않는다.
<br><br><br><br></p>
<h1 id="java-switch-expression">Java Switch Expression</h1>
<hr>
<h2 id="설명-3">설명</h2>
<p>Java 12부터 Switch Expression이라는 새로운 기능이 추가되어, switch문을 좀 더 간결하게 사용할 수 있게 되었다. 이전의 switch문과는 다르게, 값을 반환할 수 있는 형태로 사용할 수 있다!</p>
<p>Switch Expression의 기본 문법은 다음과 같다.</p>
<pre><code class="language-java">result = switch (value) {
    case value1, value2, value3 -&gt; result1;
    case value4 -&gt; result2;
    case value5 -&gt; result3;
    ...
    default -&gt; useless_result;
};</code></pre>
<p>원래 switch문과 크게 다른건 없고, 화살표(-&gt;)를 통해서 조건과 결과를 이어주면 된다. 
간단하게 <strong>쉼표(,)로 조건을 구분하고 나열할 수 있다.</strong></p>
<p>또한, Switch Expression에서는 yield 키워드를 사용하여 값을 반환할 수 있다. </p>
<pre><code class="language-java">    public static void main(String[] args) {

        int month = 3;

        int day = switch (month) {
            case 1, 3, 5, 7, 8, 10,12 -&gt; {
                System.out.println(&quot;한 달은 31일입니다.&quot;); 
                yield 31;
            }
            case 4,6,9,11 -&gt; {
                System.out.println(&quot;한 달은 30일입니다.&quot;); 
                yield 30;
            }
            case 2 -&gt;{
                System.out.println(&quot;한 달은 28일입니다.&quot;);
                yield 28;
            }
            default-&gt;{
                System.out.println(&quot;존재하지 않는 달 입니다.&quot;); 
                yield 0;
            }
        };

    }
//출력 결과는 &quot;한 달은 31일 입니다&quot; 가 출력된다.</code></pre>
<p> 위 경우 month=3이므로 &quot;한 달은 31일 입니다&quot;가 출력되고, 
 31을 yield하기 떄문에 day=31이 된다.</p>
<p><br><br><br><br></p>
<h1 id="data-영역">Data 영역</h1>
<hr>
<h2 id="설명-4">설명</h2>
<p>데이터 세그먼트는 컴퓨터 프로그램의 메모리 구조 중 하나로, <strong>다양한 종류의 데이터가 저장되는 영역.</strong> </p>
<p>데이터 세그먼트에는 크게 스택 영역, 힙 영역, 데이터 영역, 코드 영역이 있다.</p>
<h2 id="영역의-구분">영역의 구분</h2>
<h3 id="스택-영역">스택 영역</h3>
<p>스택 영역은 함수 호출 시 생성되는 <strong>지역 변수, 함수의 매개변수</strong>등이 저장되는 메모리 영역이다.</p>
<p>스택은 메모리의 높은 주소에서 낮은 주소로 증가하는 방향으로 할당된다. </p>
<p>함수가 호출되면 스택 프레임이 생성되어 스택에 할당되고, 함수가 종료되면 스택 프레임이 제거된다.</p>
<p>재귀 함수 호출과 같은 경우 스택의 깊이가 깊어져 스택 오버플로우가 발생할 수 있다.</p>
<h3 id="힙-영역">힙 영역</h3>
<p>힙 영역은 프로그램 실행 중 동적으로 할당되는 메모리 영역이다.</p>
<p>우리가 <strong>객체를 동적할당</strong>하면 힙 영역에 할당된다.</p>
<p>힙은 스택과는 달리 메모리의 낮은 주소에서 높은 주소로 할당된다.</p>
<p>프로그램이 실행되는 동안 필요한 만큼 메모리를 할당하고, 사용이 끝난 후 해제해야 한다. =&gt; Java에 경우는 가비지콜렉터가 자동 관리해줌.</p>
<p>동적 메모리 할당을 통해 필요한 메모리만 사용할 수 있어 효율적인 메모리 관리가 가능하다.</p>
<h3 id="데이터-영역">데이터 영역</h3>
<p>데이터 영역은 전역 변수와 정적 변수를 저장하는 메모리 영역이다.</p>
<p>전역 변수와 정적 변수는 프로그램이 실행될 때 초기값이나 0으로 초기화되며, 전역 변수는 프로그램 전체에서 공유된다.</p>
<p><strong>프로그램의 시작과 함께 할당되며 프로그램이 종료되면 소멸한다.</strong></p>
<p>=&gt; Java는 전역 변수 개념 없음</p>
<h3 id="코드-영역메서드-영역">코드 영역(메서드 영역)</h3>
<p>코드 영역은 실행 파일에 포함된 기계어 코드가 저장되는 메모리 영역이다.</p>
<p>우리가 에디터나 다른 IDE 에서 코드를 작성한 후, </p>
<p>그 코드를 컴파일하여 <strong>실행 파일을 만들때</strong> 코드 영역에 <strong>우리가 작성한 코드가 기계어로 저장</strong>된다. </p>
<p>그리고 프로그램이 실행될 때, 코드 영역에 저장된 기계어 코드가 CPU에 의해 실행된다.</p>
<p>이 영역은 <strong>컴파일 타임에 결정되고 중간에 코드를 바꿀 수 없게 Read-Only 로 지정돼있다.</strong></p>
<p>메서드의 로직이 들어가는 영역이기도 해서 <strong>메서드 영역</strong>이라고도 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[성장,도피,두려움(w. 테오님의 공부론)]]></title>
            <link>https://velog.io/@bill_0285/%ED%83%9C%EC%98%A4%EB%8B%98%EC%9D%98-%EA%B0%9C%EB%B0%9C%EA%B3%B5%EB%B6%80%EB%A1%A0%EC%9D%84-%EB%B3%B4%EA%B3%A0</link>
            <guid>https://velog.io/@bill_0285/%ED%83%9C%EC%98%A4%EB%8B%98%EC%9D%98-%EA%B0%9C%EB%B0%9C%EA%B3%B5%EB%B6%80%EB%A1%A0%EC%9D%84-%EB%B3%B4%EA%B3%A0</guid>
            <pubDate>Sun, 02 Apr 2023 19:16:27 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@teo/computational-thinking">태오님의 개발론</a></p>
<p>이글을 보고 여태까지 스스로 했던 개발 공부 방식을 되돌아 보게 되었다. </p>
<p>특히 가슴에 큰 대못을 찔렸던 부분은 다음과 같다.</p>
<blockquote>
<h4 id="사람은-목적이-있을-때와-목적이-없을-때는-사고하는-뇌-구조가-다릅니다-그렇기에-내가-특정한-목적이-있을-때-공부했던-것들은-정말로-빠르게-내-지식이-됩니다">사람은 목적이 있을 때와 목적이 없을 때는 사고하는 뇌 구조가 다릅니다. 그렇기에 내가 특정한 목적이 있을 때 공부했던 것들은 정말로 빠르게 내 지식이 됩니다.</h4>
<h4 id="그런-부분들만-골라내서-일부만-학습을-하는게-효과가-있는지-모르겠다-나는-처음부터-다-알고-놓치는게-없이-깊이-알고-싶다-그래야만-다음으로-넘어갈-수-있다">&#39;그런 부분들만 골라내서 일부만 학습을 하는게 효과가 있는지 모르겠다. 나는 처음부터 다 알고 놓치는게 없이 깊이 알고 싶다. 그래야만 다음으로 넘어갈 수 있다.&#39;</h4>
<h4 id="라고-하는-문제의-유혹에-빠지지-마세요">라고 하는 문제의 유혹에 빠지지 마세요.</h4>
<h4 id="띄엄-띄엄-공부하는-것은-전혀-아무런-문제가-되지-않습니다-오히려-한-번에-다-이해를-해야만-넘어가겠다고-하는-생각-자체가-개발-실력을-키우는-데-굉장히-큰-방해-요소가-됩니다">띄엄 띄엄 공부하는 것은 전혀 아무런 문제가 되지 않습니다. 오히려 한 번에 다 이해를 해야만 넘어가겠다고 하는 생각 자체가 개발 실력을 키우는 데 굉장히 큰 방해 요소가 됩니다.</h4>
</blockquote>
<p>최근까지도 개발공부를 했던 나의 방식이 전면 부정? 당하는거 같아서 충격 반, 부끄러움 반을 느꼈다. 돌이켜 보면, 수험생활 부터 그랬던거 같다. </p>
<p>고딩때 수능 공부를 할때부터, 공부를 한다고 하면 두꺼운 이론 책 한권을 사서 처음 부터 끝까지 하나도 빠짐없이 정독을하고,</p>
<p>그다음에야 문제풀이에 들어가야 실력이 향상된다고 생각했다.</p>
<p>물론 수능은 언어,수리,영어,탐구영역의 문제해결능력을 보는 것이기 때문에, 학문을 공부하는 방식으로 접근하는게 맞을수도 있다.</p>
<p>하지만 개발은 다르지 않은가. <strong>개발은 학문이 아니다.</strong> 애초에 나는 왜 개발자가 되려했나. </p>
<p>나는 개발자 == 창조자, 즉 자기가 만들고 싶은 것은 무엇이든 만들 수 있는, <strong>무에서 유를 창조하려는 사람들이</strong>라고 생각했고, 나 또한 그런 사람이 되고 싶었기에 물리과에서 컴공과로 전과를 하고, 개발공부를 한것이 아닌가. </p>
<p>그리고 그때는 이론부터 파고든게 아니라 </p>
<p>&#39;나만의 공학용 계산기 만들어보자, 모바일 게임순위 사이트를 만들어서 광고를 붙여 수익창출을 해보자든가&#39; 등의</p>
<p>건설적이든 않든 간에 <strong>어떠한 목적을 가지고 구현에 초점</strong>을 두며 개발공부를 했었다.</p>
<p>그리고 그때는 확실히 개발실력이 지수적인 그래프를 그리며 늘었던거 같다. </p>
<p>그런데 왜 요즘은 오히려 이론부터 마스터하고 개발을 들어가야지 라는 생각을 하고있나.</p>
<p>사실 스스로 돌아보니 답은 나와있었다. <strong>머리가 커질수록 오히려 두려웠기 때문이다.</strong></p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/b1d148e3-9542-46ad-82b8-bffd6ff73954/image.jpg" alt="두려움"></p>
<h3 id="뒤처짐의-두려움-재능없음의-두려움-스스로의-한계에-대한-두려움">뒤처짐의 두려움, 재능없음의 두려움, 스스로의 한계에 대한 두려움</h3>
<p> 암것도 모르는 처음에야 원하는대로 하나하나식 만들어지는게 재밋고 모르는 것 투성이라 배우는 재미가 있었다. </p>
<p>하지만 지금은 (여전히 모르는 것은 많지만) 알면 알수록 배워야 할게, 배울 수 있는것들이 너무 많이 보였다.</p>
<p>예전에는 그냥 돌아가기만 하면된다는 마인드로 구현에 초점을 뒀다면, 이제는 6개월동안의 it기업에 인턴생활과 2개의 협업 프로젝트를 진행 해보면서 </p>
<p>디자인패턴, 클린아키텍처, 비즈니스 로직과 view의 분리, 협업에서의 객체지향적 개발의 실전방식, 트렐로, 팀즈, 노션, 슬랙, 피그마 , erdCloud, aws 등등 무수히많은 협업툴 등 많은것을 배웠고 이용해 봤지만,</p>
<p>오히려 배울수록 나 자신이 너무 부족함이 느껴졌고, 언제 이런것들을 마스터해서 완숙미를 가질 수 있을까, 그렇게 되기에는 너무 오랜시간이 걸리지않을까란 생각이 들었다.</p>
<p>처음에는 시간이라는 인풋이 너무 많이 들어갈까봐 귀찮아서 안하는 거라 생각했는데, 더 깊이들어가면 <strong>사실은 인풋이 들어가도 이해를 못할까봐, 나의 한계일까봐, 개발자로서의 나의 역량을 체감할까봐</strong> 지레짐작으로 두려워서 정작 개발은 하지않고 이론공부만 파고들면서 도피했던거 같다.</p>
<p>그리되면 이제는 <strong>새로운 개념과 구현방식에 대해 알게 되어도</strong> &#39;아 새로운 거네? 재밋겠다! 바로 적용해봐야지!&#39; 라는 생각보단 &#39;아, 또 뭐 새로운거 나왔네, 뭐라는지 봐도 바로 모르겠는데, 하.. 젠장 언제 또 공부하냐.. 할 거 많은데..&#39; 라는 <strong>부정적인 생각이 먼저 언습</strong>해오는거 같다.... </p>
<p><strong>개발자가 새로운 지식에 두려움을 갖는 순간 끝이라던데,</strong> 시작도 제대로 못한 개발자인채로 끝나는게 아닐까 싶은 생각도 들었다.</p>
<p>그렇게 항상 저딴 쓸데없는 스트레스를 받으며 개발 공부를 하던 중 테오님의 개발공부론을 보게 된 것이다. </p>
<p>글에 달린 댓글처럼, 정말 저 글을 쓰기위해 노력과 고민을 많이한 흔적이 내용에 그대로 드러났다고 생각한다. </p>
<p>그리고 개발실력을 늘리기위한 구체적인 방법론도 제시해주고 있었다. </p>
<p>나는 이글을 토대로 내 개발공부 방식을 바꿔보기로 하였다. </p>
<p>당연히 이 글이 무슨 마법처럼 내 고민을 해결해 주지는 않을 것이다. </p>
<p>당장 공부를 시작하면 나는 또 다시 새로운 지식에대한 스트레스를 받을 것이다.</p>
<p>하지만 이제는 어렴풋이 안다.  </p>
<p>한번에 모든 문제를 해결하려는 것은 사실 망상에 불과하다는 것을. </p>
<p>꾸준히 한다면 결국 바뀔수 밖에 없다는 것을. </p>
<p>그래서 앞으로는 velog도 지식을 습득하고 깨달을 때 마다 반드시 기록할 것이다.</p>
<blockquote>
<h4 id="진리는-뻔하고-단순하지만-명쾌합니다">진리는 뻔하고 단순하지만 명쾌합니다.</h4>
<h4 id="이-글이-새로운-인사이트가-되지는-않을지언정-그래-나도-이렇게-일단-한번-해보자-하는-마음을-가지고-당장은-이게-맞는-공부법이라고-믿고-한번-해보시길-바랍니다">이 글이 새로운 인사이트가 되지는 않을지언정 &quot;그래! 나도 이렇게 일단 한번 해보자!&quot; 하는 마음을 가지고 당장은 이게 맞는 공부법이라고 믿고 한번 해보시길 바랍니다.</h4>
<h4 id="화이팅입니다">화이팅입니다!</h4>
</blockquote>
<p>테오님 글의 마지막 문단이다. </p>
<p>덕분에 나도, <strong>일단 한번 해볼 &#39;용기&#39;</strong>를 가지고 나아가 보기로 하였다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바(Java, JRE, JVM, JDK) + 카테캠 1기 합격 후기]]></title>
            <link>https://velog.io/@bill_0285/%EC%9E%90%EB%B0%94%EC%9D%98-%EB%AA%A8%EB%93%A0%EA%B2%83JavaJREJVMJDKGC</link>
            <guid>https://velog.io/@bill_0285/%EC%9E%90%EB%B0%94%EC%9D%98-%EB%AA%A8%EB%93%A0%EA%B2%83JavaJREJVMJDKGC</guid>
            <pubDate>Mon, 27 Mar 2023 17:14:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>본 포스트는 카카오 테크 캠퍼스 1기에서 제공하는 패스트캠퍼스 강의에서 배운 내용을 토대로 정리하였습니다.</p>
</blockquote>
<p><a href="https://www.kakaotechcampus.com/user/index.do">카카오 테크 캠퍼스</a></p>
<p>서류전형과 코테를 통과하여 카카오 테크 캠퍼스 1기에 최종합격하였다!
(๑˃̵ᴗ˂̵)ﻭ </p>
<p>대략 9개월 동안의 과정에서 1파트는 강의제공, 2파트는 협업 클론 코딩,  3파트는 <strong>신규서비스 개발 프로젝트(대박 대박!)</strong>로 진행한다. 오늘부터 매주, 매일 꾸준하게 velog에 배웠던 내용 중 몰랐던 내용, 필요한 내용을 기록할 예정이다.</p>
<p>앞으로도 java에 관한 내용은 java 태그를, spring관련 내용은 spring태그로 velog에 관리할 생각이다. </p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/ad204841-c5f8-468b-981b-08ee8fcc6f23/image.gif" alt="">
(시작이 반이라지만.... 반만 하지말고 완주해보자!)</p>
<h1 id="java">Java</h1>
<hr>
<h2 id="필요성">필요성</h2>
<p> 자바는 c언어에서 시작된 언어이다.
c언어는 포인터로 직접 메모리에 접근해서 핸들링 하기떄문에 의도하지않은 시스템 다운이 종종 일어날 위험을 내포하고있다고 한다.</p>
<p>좀더 안정적인 언어가 없을까? =&gt; Java</p>
<p>모호하고 불안한요소들을 과감히 없애버림 =&gt; 안정적인 언어다.</p>
<p>안정적이다 =&gt; 웬만해선 죽지않는다.</p>
<h2 id="장점">장점</h2>
<h3 id="플랫폼-독립성">플랫폼 독립성</h3>
<p>   자바는 운영체제나 하드웨어 종속성을 최소화하고, &quot;Write once, run anywhere&quot;라는 모토를 가지고 개발되었다.</p>
<p> 자바는 C 언어와는 달리, Java 가상 머신(JVM)을 통해 Java 코드를 실행할 수 있기 때문에 운영체제나 하드웨어에 종속되지 않는다.</p>
<p>이를 통해 Java 언어로 작성된 프로그램은 여러 플랫폼에서 동작할 수 있다.</p>
<p>  c언어는 운영체제가 </p>
<p>  리눅스 =&gt; 리눅스 컴파일러로 리눅스실행파일 생성
  윈도우 =&gt; 윈도우 컴파일러로 윈도우실행파일 생성</p>
<p>각각은 상호호환되지 않는다.</p>
<p>   <img src="https://velog.velcdn.com/images/bill_0285/post/e25dc731-a049-44f5-b1fc-fa83ad102b39/image.png" alt=""></p>
<h3 id="그-이유가-뭘까">그 이유가 뭘까</h3>
<p>  c 언어로 작성된 프로그램은 운영체제에 의존하기 떄문이다. </p>
<p>  운영체제는 프로그램을 실행하기 위해 필요한 라이브러리, 시스템 호출, 컴파일러, 런타임 환경 등을 제공한다.</p>
<p> 리눅스와 윈도우는 서로 다른 운영체제이기 때문에, 컴파일러는 해당 운영체제에 맞게 프로그램을 컴파일한다. </p>
<p> 이때, 컴파일러가 사용하는 라이브러리, 시스템 호출 등은 해당 운영체제에서 지원하는 것을 사용한다.</p>
<p> 그 결과로 컴파일된 실행 파일은 해당 운영체제에서만 정상적으로 작동할 수 있다</p>
<p>   따라서, 리눅스에서 컴파일된 실행 파일은 리눅스에서만 실행 가능하고, 윈도우에서 컴파일된 실행 파일은 윈도우에서만 실행 가능하다. </p>
<p>   또는, 호환성을 위해 크로스 컴파일러를 사용하여 여러 운영체제에서 실행 가능한 실행 파일을 생성할 수도 있다.</p>
<p>   ** 하지만 Java는 javac 컴파일러를 통해 .java 소스코드가 .class 확장자명을 사용하는 바이트코드로 바뀌고, 이를 각 jvm에 가상머신에 실행시키면 어느 운영체제에서든 실행이 된다는 장점이있다. **  </p>
<p>   즉 </p>
<p>   <strong>플랫폼에 영향을 받지 않으므로 다양한 환경에서 사용할 수 있다.</strong></p>
<h3 id="객체지향-프로그래밍">객체지향 프로그래밍</h3>
<p>프로그램의 구현을 시간의 흐름순이 아닌 객체간의 관계와 협력을 기반으로 프로그램 하는 것</p>
<p>  Object oriented programming(OOP)  이라고 함 ( cf. 절차 지향 프로그래밍 procedural programming )</p>
<p> 사용 하는 언어 : Java, C++, C#, Python, JavaScript, Ruby 등 다수</p>
<h3 id="vs-절차지향-프로그래밍">vs 절차지향 프로그래밍</h3>
<p> 절차지향 프로그래밍이란 물이 위에서 아래로 흐르는 것처럼 <strong>순차적인 처리</strong>가 중요시 되며 프로그램 전체가 유기적으로 연결되도록 만드는 프로그래밍 기법이다.</p>
<p>   자동차 제조를 예로 들자면, 자동차는 엔진, 차체, 핸들, 의자, 바퀴 순으로 차례대로 만들어져야 한다. </p>
<p>   ** 서로 분리되어도 안 되고 , 순서가 틀려도 안 된다. ** 절차지향 프로그래밍 역시 이와 같다. </p>
<p>  절차지향언어의 구조는 <strong>컴퓨터의 처리구조</strong> 와 유사하다. 따라서 실행 속도가 빠르다는 것이 장점이다.</p>
<p>  핸들이 고장났다고 엔진부터 바퀴까지 전부 수리해야 한다면 얼마나 비효율적일까 -&gt; 유지보수가 어려움</p>
<p>  실행 순서가 정해져 있으므로 코드의 순서가 바뀌면 동일한 결과를 보장하기 어려움</p>
<h2 id="단점">단점</h2>
<h3 id="각-운영체제에-맞는-jvm을-설치해줘야-한다">각 운영체제에 맞는 JVM을 설치해줘야 한다.</h3>
<p>   윈도우라면 윈도우전용 JVM을, 리눅스라면 리눅스전용 JVM을 설치해줘야한다.</p>
<p>   컴파일된 바이트코드를 재컴파일 할 필요없이 바로 JVM에서 돌려서 실행이 가능하다는 것이 위에서 말한 장점인데,</p>
<p>   그렇다고해서 JVM을 하나의 통일된 것을 사용하는 건 불가능하다.</p>
<p>   각 운영체제에 맞는 JVM이 필요하다는 점은 맞지만, 일반적으로 자바 프로그래머가 직접 JVM을 설치할 필요는 없다. </p>
<p>   보통 JDK(Java Development Kit)를 설치하면 해당 운영체제에 맞는 JVM도 함께 설치되기 때문이다.</p>
<h3 id="느리다">느리다?</h3>
<p>   자바 언어의 가상머신이라는 과정을 한번더 거쳐야 하는 실행 방식은 과거에는 상대적으로 느리다는 이슈가 있었지만,</p>
<p>   현재는 <strong>JIT(Just-In-Time) 컴파일러</strong> 등의 기술이 적용되어 성능이 크게 개선되었다. </p>
<p>   따라서 이제는 속도 차이를 느끼지 못할 정도로 빠른 속도로 자바 프로그램이 실행된다.</p>
<h3 id="jit-컴파일러란">JIT 컴파일러란?</h3>
<p>   프로그램을 실행하기 전(<em>컴파일 타임</em>)에 처음 한 번 컴파일하는 대신, 프로그램을 실행하는 시점(<em>런 타임</em>)에서 필요한 부분을 즉석으로 컴파일하는 방식을 말한다.</p>
<p>보통 인터프리터 방식의 언어 구현들이 성능 향상을 목적으로 도입하는 경우가 많다.</p>
<p>Java에서 JIT 컴파일러는 바이트코드를 기계어로 번역할 때 사용한다. 이런 과정에서 JIT 컴파일러는 <strong>반복적으로 실행되는 코드를 실시간으로 분석하여 미리 기계어로 컴파일한 뒤 캐싱한다.</strong> </p>
<p>이를 통해 같은 코드가 반복해서 실행될 때마다 반복적인 컴파일 작업을 수행하지 않고, 미리 캐싱된 기계어 코드를 사용하여 실행속도를 높일 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/3512a034-9379-4641-af3c-4466bae59e8d/image.png" alt="엑!박!"></p>
<p><br><br><br></p>
<h1 id="jvm">JVM</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/bill_0285/post/6c3bc742-1773-4ccc-9d41-e5d295c34c69/image.png" alt=""></p>
<h2 id="설명">설명</h2>
<p>JVM(Java Virtual Machine)은 약자 그대로 Java 프로그램이 실행되는 가상 머신이다.  JVM을 사용하면 <strong>Java 프로그램이 다양한 운영 체제와 하드웨어에서 실행될 수 있다.</strong></p>
<p>JVM은 Java <strong>바이트 코드(bytecode)를 실행한다.</strong> Java 바이트 코드는 Java 컴파일러에서 생성되며, Java 소스 코드를 컴파일한 결과물이다. 이 바이트 코드는 운영 체제나 하드웨어와는 독립적이며, JVM이 이를 해석하여 실행한다.</p>
<h2 id="기능">기능</h2>
<p>JVM은 다음과 같은 기능을 수행한다.</p>
<ol>
<li><p>클래스 로더(Class Loader)
JVM은 클래스를 로드하기 위해 클래스 로더를 사용한다. 클래스 로더는 <strong>클래스 파일을 JVM 메모리에 로드</strong>하고, 이를 실행할 수 있는 형태로 변환한다.</p>
</li>
<li><p>바이트 코드 검증(Bytecode Verifier)
클래스 파일이 로드되면, JVM은 <strong>바이트 코드 검증 과정을 수행</strong>한다. 이 과정에서, 코드가 안전한지, 적법한지, 스택에 올바른 값이 있는지 등을 검증한다.</p>
</li>
<li><p>인터프리터(Interpreter)
JVM은 <strong>바이트 코드를 읽어들이고 실행하기 위해 인터프리터를 사용</strong>한다. 인터프리터는 바이트 코드를 한 줄씩 읽어들이고, 이를 기계어로 변환하여 실행한다.</p>
</li>
<li><p>JIT 컴파일러(JIT Compiler)
인터프리터가 바이트 코드를 실행할 때, 같은 코드를 반복적으로 실행하는 경우에는 성능 저하가 발생한다. 이를 해결하기 위해 JIT 컴파일러가 사용된다. <strong>JIT 컴파일러는</strong> 인터프리터가 실행하는 코드를 분석하여, <strong>자주 실행되는 코드는 기계어로 변환한다.</strong> 그리고 이후에는 기계어를 바로 실행하여 성능을 개선한다.</p>
</li>
<li><p>가비지 컬렉터(Garbage Collector)
Java는 자동 메모리 관리를 지원하기 때문에, <strong>메모리를 자동으로 해제하기 위해 가비지 컬렉터가 사용된다.</strong> 가비지 컬렉터는 더 이상 사용되지 않는 객체를 탐지하고, 이를 메모리에서 해제한다. </p>
<p>가비지 컬렉터는 <strong>주로 자바의 동적메모리 할당 영역인 힙(heap) 영역에서 실행되고,</strong> 자동으로 메모리 관리를 하기때문에 개발자가 메모리를 수동으로 할당하거나 해제할 필요가 없다.</p>
</li>
<li><p>네이티브 메서드 라이브러리(Native Method Libraries)
자바의 네이티브 메서드 라이브러리는 <strong>자바 언어와는 다른 언어로 작성된 코드를 자바에서 사용할 수 있도록 해주는 라이브러리이다.</strong> 이러한 라이브러리는 주로 C, C++, 어셈블리 등과 같은 다른 프로그래밍 언어로 작성된 코드를 자바에서 사용할 수 있도록 제공한다.</p>
<p><br><br><br></p>
<h1 id="jre">JRE</h1>
<hr>
<h2 id="설명-1">설명</h2>
<p>JRE (Java Runtime Environment)은 JVM과 Java 애플리케이션을 실행하는 데 필요한 <strong>클래스 라이브러리</strong> 및 구성 요소를 포함하는 소프트웨어 패키지이다. JRE는 <strong>Java 애플리케이션을 실행하기 위한 런타임 환경을 제공하기 위해 설계되었다.</strong></p>
</li>
</ol>
<p>JRE를 사용하면 사용자는 Java 애플리케이션을 실행할 수 있으며, 개발자는 Java 애플리케이션을 개발할 때 사용할 수 있는 Java 클래스 라이브러리를 포함한 필수 구성 요소를 사용가능함. JRE는 Java SE(Standard Edition) 및 Java EE(Enterprise Edition) 버전에 따라 다양한 패키지로 있음.</p>
<h2 id="자바-클래스-라이브러리">자바 클래스 라이브러리</h2>
<p>Java 프로그램에서 자주 사용되는 기본 클래스와 인터페이스의 집합.</p>
<h3 id="종류">종류</h3>
<p>크게 3가지 유형이 있다.</p>
<ul>
<li><p>Java SE API: Java Standard Edition API는 자바 개발자들이 대부분 사용하는 기본 라이브러리. 입출력, 데이터베이스 연결, 그래픽 등 다양한 기능을 제공한다.</p>
</li>
<li><p>Java EE API: Java Enterprise Edition API는 엔터프라이즈 환경에서 사용되는 라이브러리로, 분산 시스템, 웹 어플리케이션, 데이터베이스 액세스 등을 지원한다.</p>
</li>
<li><p>Java ME API: Java Micro Edition API는 모바일 기기에서 사용하는 라이브러리로, 자바 개발자들이 모바일 애플리케이션을 개발할 때 사용된다.</p>
</li>
</ul>
<p><br><br><br></p>
<h1 id="jdk">JDK</h1>
<hr>
<h2 id="설명-2">설명</h2>
<p>JDK(Java Development Kit)는 자바 언어로 개발을 할 때 필요한 컴파일러, 디버깅 툴, 실행 환경 등을 포함한 개발 도구 모음이다.</p>
<p>자바 개발을 위해 필요한 컴파일러(javac), 자바 실행 환경(java), 자바 디버깅 툴(jdb) 등이 포함되어 있다.</p>
<p>JDK는 개발자가 자바 애플리케이션을 <strong>개발하고, 컴파일하고, 실행하고, 디버깅하는 데 필요한 모든 도구를 제공</strong>한다. 또한 JDK는 자바 클래스 라이브러리, 자바 API 문서 등도 함께 제공하므로 개발자는 이를 활용하여 보다 쉽게 개발할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[옹알이(1)]]></title>
            <link>https://velog.io/@bill_0285/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1%EB%8B%A8%EA%B3%84</link>
            <guid>https://velog.io/@bill_0285/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1%EB%8B%A8%EA%B3%84</guid>
            <pubDate>Sun, 26 Mar 2023 14:57:18 GMT</pubDate>
            <description><![CDATA[<p>프로그래머스 0단계 문제인 옹알이(1)를 풀어보았다.</p>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/120956">프로그래머스 옹알이 (1)</a></p>
<p>당연히 0단계니 알고리즘을 공부할필요도 없이 기본적인 언어별 문법만 숙지하면 풀 수 있겠지 하고 바로 문제풀이로 들어갔다. </p>
<p>문제를 좀 풀고 나니까 너무 쉬운 문제였는데, 처음 풀떄는 replace라는 내장함수도 몰라서 정말 어렵게 생각해서 itertools패키지에 permutations, 즉 순열 함수를 사용해서 풀었다.</p>
<h2 id="코드">코드</h2>
<p>아래는 파이썬으로 해결한 풀이 코드 이다.</p>
<pre><code class="language-python">from itertools import *

def doPermutations(num):
    return permutations([&quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot;],num)



def solution(babbling):
    answer = 0
    for oneBabbling in babbling:
        length=len(oneBabbling)
        if(length&lt;=3):
            permutated=doPermutations(1)
            breakSign=False
            for i in permutated: #(a,b,c) (c,b,a)
                if(breakSign==True):break
                temp=&quot;&quot;
                for j in i:
                    temp+=j
                    if(temp==oneBabbling):
                        answer+=1
                        print(temp)
                        breakSign=True
                        break
        elif(4&lt;=length&lt;=6):
            permutated=doPermutations(2)
            breakSign=False
            for i in permutated: #(a,b,c) (c,b,a)
                if(breakSign==True):break
                temp=&quot;&quot;
                for j in i:
                    temp+=j
                    if(temp==oneBabbling):
                        answer+=1

                        breakSign=True
                        break

            permutated=doPermutations(3)
            if(breakSign==True): pass
            else:  breakSign=False

            for i in permutated: #(a,b,c) (c,b,a)
                if(breakSign==True):break
                temp=&quot;&quot;
                for j in i:
                    temp+=j
                    if(temp==oneBabbling):
                        answer+=1
                        print(temp)
                        breakSign=True
                        break

        elif(7&lt;=length&lt;=9):
            permutated=doPermutations(3)
            breakSign=False
            for i in permutated: #(a,b,c) (c,b,a)
                if(breakSign==True):break
                temp=&quot;&quot;
                for j in i:
                    temp+=j
                    if(temp==oneBabbling):
                        answer+=1
                        print(temp)
                        breakSign=True
                        break

            permutated=doPermutations(4)
            if(breakSign==True): pass
            else:  breakSign=False
            for i in permutated: #(a,b,c) (c,b,a)
                if(breakSign==True):break
                temp=&quot;&quot;
                for j in i:
                    temp+=j
                    if(temp==oneBabbling):
                        answer+=1
                        print(temp)
                        breakSign=True
                        break       
        elif(10&lt;=length):
            permutated=doPermutations(4)
            breakSign=False
            for i in permutated: #(a,b,c) (c,b,a)
                if(breakSign==True):break
                temp=&quot;&quot;
                for j in i:
                    temp+=j
                    if(temp==oneBabbling):
                        answer+=1
                        print(temp)
                        breakSign=True
                        break       

    return answer
</code></pre>
<p>ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 가관이다.... 해결은했는데 코드가 길어지고 코테 첨해본 놈이 작성한 코드 다웠다. </p>
<h2 id="설명">설명</h2>
<p>설명하자면, 어차피 &quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot; 이 4가지 문자열만으로 조합된 결과물만을 서칭해야하니, 저 4가지에서 1가지,2가지,3가지,4가지를 각각 가져와서 조합한다고 생각하였다. </p>
<p>그런데 그냥 조합이 아니고 순서에 상관있는, 즉 ayaye와 yeaya를 다르게 취급해야하므로 순열로 생각하고 
4p1, 4p2, 4p3, 4p4 까지 해서 개수를 구하면 되겠다고 접근하였다.</p>
<p>그걸위해서 기본 패키지인 itertools에 permutations을 사용하였다. </p>
<p>검사할 문자열을 길이를 기준으로 분기를 나눌껀데,
길이가 3이하면 무조건 4p1 밖에 안된다. 왜냐면 당장 4p2만되도 가장 길이가 작은 ye,ma를 가져온다해도 길이가 4이상이기떄문이다</p>
<p>같은이유로 길이가 4이상 6이하면 4p2, 4p3 밖에 안된다.(4p1은 최대길이가 3이고, 4p4는 최소길이가 8이기 떄문이다)</p>
<p>그 이상의 길이들도 마찬가지로 분기를 나눌수 있는데, 정리하자면</p>
<p>** len&lt;=3   ---&gt; 4p1 **
** 4&lt;=len&lt;=6 ---&gt; 4p2 4p3 **
** 7&lt;=len&lt;=9 ---&gt; 4p3 4p4 **
** 10&lt;=len   ---&gt; 4p4 **</p>
<p>이렇게 정리할 수있다.</p>
<h2 id="개선점">개선점</h2>
<p>** 당연하지만, 전혀 위에처럼 복잡하게 생각할 필요없다. ** </p>
<p>그냥 문자열 하나식 가져와서 맨처음 인덱스를 조사하기시작해서 aya,ye,woo,ma중에 하나라도 있으면 &quot;&quot;로 치환하는걸 반복해서 최종적으로 치환이 더이상 안될때 문자열==&quot;&quot;여야만 정답이므로 정답에 +1을 더하면 된다. 아래는 파이썬으로 작성한 코드이다.
굳이 처음인덱스만 검사하는이유는, wyeoo 이런것들도 ye검사해서 &quot;&quot;로치환하면 woo가 되고 이거를 woo를 검사하면 정답이 되기 떄문이다. 그래서 항상 검사한 문자열에 첫번쨰인덱스만 검사한다.</p>
<pre><code class="language-python">def solution(babbling):
    answer=0
    available=[ &quot;aya&quot;, &quot;ye&quot;, &quot;woo&quot;, &quot;ma&quot;]
    for index,onebabbl in enumerate(babbling):
        while True:
            index=-1
            for one in available:
                if(onebabbl.find(one)==0):
                    index=0
                    onebabbl=onebabbl.replace(one,&quot;&quot;)
                    break
            if(index==-1):break
            if(onebabbl==&quot;&quot;):
                answer+=1
                break

    return answer</code></pre>
]]></description>
        </item>
    </channel>
</rss>