<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>im_joonchul.log</title>
        <link>https://velog.io/</link>
        <description>지금, 새로운 문을 열자! 문 저편에 무엇이 있을지 두렵더라도!!</description>
        <lastBuildDate>Sun, 11 Apr 2021 08:06:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>im_joonchul.log</title>
            <url>https://images.velog.io/images/im_joonchul/profile/e7010516-00b9-4399-9738-6883d86aed18/1.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. im_joonchul.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/im_joonchul" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Design Pattern]]></title>
            <link>https://velog.io/@im_joonchul/DesignPattern</link>
            <guid>https://velog.io/@im_joonchul/DesignPattern</guid>
            <pubDate>Sun, 11 Apr 2021 08:06:49 GMT</pubDate>
            <description><![CDATA[<h1 id="디자인-패턴-design-patterns">디자인 패턴 (Design Patterns)</h1>
<ul>
<li>디자인 패턴이 어떤 것인지와 대표적으로 사용하는 패턴에 대한 사용법 정도만 정리했다.</li>
</ul>
<h2 id="디자인-패턴이란">디자인 패턴이란</h2>
<ul>
<li>자주 발생하는 문제를 쉽게 해결하기 위해 제시된 재사용 가능한 해결책<ul>
<li>Don&#39;t reinvent the Wheel (바퀴를 다시 발명하지 마라)</li>
</ul>
</li>
<li>이미 해결된 방식은 해결된 방식대로 해결하고, 새롭게 맞딱드린 문제를 해결하자</li>
<li>소프트웨어 설계 문제를 쉽게 해결할 수 있도록 패턴화된 설계 방식</li>
<li>팀원들과의 소통을 위해 디자인 패턴 학습이 필요하다.<ul>
<li>팀원들이 싱글톤 패턴으로 해결 해주세요 할 때 이 패턴에 대해서 알고 있어야 하겠지?</li>
</ul>
</li>
</ul>
<h2 id="디자인-패턴의-구조">디자인 패턴의 구조</h2>
<ul>
<li>문맥(Context)<ul>
<li>패턴이 적용될 수 있는 문제 상황을 기술</li>
</ul>
</li>
<li>문제(Problem)<ul>
<li>패턴이 적용되어 해결되어야 하는 여러 설계 이슈를 기술</li>
</ul>
</li>
<li>해결(Solution)<ul>
<li>문제를 해결하는 설계 구성 요소와 구성 요소 사이의 관계를 기술</li>
</ul>
</li>
</ul>
<h2 id="디자인-패턴의-종류">디자인 패턴의 종류</h2>
<ul>
<li>Gang of four 패턴<ul>
<li>생성 패턴 (Creational patterns)<ul>
<li>객체의 생성 방식에 관련된 패턴</li>
<li>Abstract Factory, Factory Method, Singleton ...</li>
</ul>
</li>
<li>구조 패턴 (Structural patterns)<ul>
<li>클래스/객체를 조합한 구조를 가지는 패턴</li>
<li>Composite, Decorator ...</li>
</ul>
</li>
<li>동작 패턴 (Behavioral patterns)<ul>
<li>클래스/객체 사이의 동작 분배에 관련된 패턴</li>
<li>Observer, State, Strategy, Template Method, Command ...</li>
</ul>
</li>
</ul>
</li>
<li>동시성 패턴 (Concurrency patterns)<ul>
<li>Scheduling, Monitor, Lock ...</li>
</ul>
</li>
<li>아키텍처 패턴 (Architecture patterns)<ul>
<li>Model-View-Controller, Model-View-Presenter, Model-View-ViewModel ...</li>
</ul>
</li>
<li>기타 패턴<ul>
<li>Dependency injection, Lazy loading, Mock object ...</li>
</ul>
</li>
</ul>
<h2 id="대표적인-디자인-패턴">대표적인 디자인 패턴</h2>
<h3 id="싱글톤-패턴">싱글톤 패턴</h3>
<ul>
<li><p>단 하나의 객체만 존재할 수 있는 클래스를 구현하는 패턴</p>
<pre><code class="language-java">class Singleton {
  private static Singleton instance;

  private Singleton() {}

  public static Singleton getInstance() {
      if(instance == null) {
          instance = new Singleton();
      }
      return instance;
  }
}</code></pre>
<h3 id="팩토리-패턴">팩토리 패턴</h3>
</li>
<li><p>구상 클래스 객체를 전담하여 생성하는 클래스를 구현하는 패턴</p>
</li>
<li><p>팩토리 메소드 패턴 (ref)</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/a79d6243-d9a2-4de9-881b-13c7497f0234/%ED%8C%A9%ED%86%A0%EB%A6%AC%ED%8C%A8%ED%84%B4.jpg" alt="팩토리패턴"></p>
<pre><code class="language-java">interface Shape {
    void draw();
}

class Rectangle implements Shape {
  @Override
  public void draw() {
      System.out.println(&quot;Inside Rectangle::draw() method.&quot;);
    }
}

class Square implements Shape {
  @Override
  public void draw() {
      System.out.println(&quot;Inside Square::draw() method.&quot;);
  }
}

class Circle implements Shape {
  @Override
  public void draw() {
      System.out.println(&quot;Inside Circle::draw() method.&quot;);
  }
}

class ShapeFactory {


Shape getShape(String shapeType){
    if(shapeType == null){
      return null;
    }        
    if(shapeType.equalsIgnoreCase(&quot;CIRCLE&quot;)){
      return new Circle();

    } else if(shapeType.equalsIgnoreCase(&quot;RECTANGLE&quot;)){
      return new Rectangle();

    } else if(shapeType.equalsIgnoreCase(&quot;SQUARE&quot;)){
      return new Square();
    }

    return null;
  }
}
class FactoryPatternDemo {
  public static void main(String[] args) {
    ShapeFactory shapeFactory = new ShapeFactory();

    Shape shape1 = shapeFactory.getShape(&quot;CIRCLE&quot;);
    shape1.draw();

    Shape shape2 = shapeFactory.getShape(&quot;RECTANGLE&quot;);

    shape2.draw();

    Shape shape3 = shapeFactory.getShape(&quot;SQUARE&quot;);

    shape3.draw();
  }
}</code></pre>
<h3 id="추상-팩토리-패턴">추상 팩토리 패턴</h3>
<p><img src="https://images.velog.io/images/im_joonchul/post/2cdf8b9e-eecb-41c2-b81f-371b66b9ff8c/%EC%B6%94%EC%83%81%ED%8C%A9%ED%86%A0%EB%A6%AC%ED%8C%A8%ED%84%B4.jpg" alt="추상팩토리패턴"></p>
<pre><code class="language-java">public interface Shape {
  void draw();
}

class RoundedRectangle implements Shape {
  @Override
  public void draw() {
      System.out.println(&quot;Inside RoundedRectangle::draw() method.&quot;);
  }
}

class RoundedSquare implements Shape {
  @Override
  public void draw() {
      System.out.println(&quot;Inside RoundedSquare::draw() method.&quot;);
  }
}

class Rectangle implements Shape {
  @Override
  public void draw() {
      System.out.println(&quot;Inside Rectangle::draw() method.&quot;);
  }
}

abstract class AbstractFactory {
  abstract Shape getShape(String shapeType) ;
}

class ShapeFactory extends AbstractFactory {
  @Override
  public Shape getShape(String shapeType){    
      if(shapeType.equalsIgnoreCase(&quot;RECTANGLE&quot;)){
        return new Rectangle();         
      }else if(shapeType.equalsIgnoreCase(&quot;SQUARE&quot;)){
        return new Square();
      }     
      return null;
  }
}

class RoundedShapeFactory extends AbstractFactory {
  @Override
  public Shape getShape(String shapeType){    
      if(shapeType.equalsIgnoreCase(&quot;RECTANGLE&quot;)){
        return new RoundedRectangle();         
      }else if(shapeType.equalsIgnoreCase(&quot;SQUARE&quot;)){
        return new RoundedSquare();
      }     
      return null;
  }
}

class FactoryProducer {
  public static AbstractFactory getFactory(boolean rounded){   
      if(rounded){
        return new RoundedShapeFactory();         
      }else{
        return new ShapeFactory();
      }
  }
}

class AbstractFactoryPatternDemo {
  public static void main(String[] args) {
      AbstractFactory shapeFactory = FactoryProducer.getFactory(false);

      Shape shape1 = shapeFactory.getShape(&quot;RECTANGLE&quot;);
      shape1.draw();
      Shape shape2 = shapeFactory.getShape(&quot;SQUARE&quot;);
      shape2.draw();

      AbstractFactory shapeFactory1 = FactoryProducer.getFactory(true);

      Shape shape3 = shapeFactory1.getShape(&quot;RECTANGLE&quot;);
      shape3.draw();
      Shape shape4 = shapeFactory1.getShape(&quot;SQUARE&quot;);
      shape4.draw();
  }
}</code></pre>
<h3 id="데코레이터-패턴">데코레이터 패턴</h3>
<ul>
<li>생성자를 이용해 객체에 일정한 기능을 추가하는 패턴</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/7f757f7d-31f1-4cf0-9c92-b826f8f7b3f9/%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0%20%ED%8C%A8%ED%84%B4.jpg" alt="데코레이터패턴"></p>
<pre><code class="language-java">interface Shape {
  void draw();
}

class Rectangle implements Shape {

  @Override
  public void draw() {
      System.out.println(&quot;Shape: Rectangle&quot;);
  }
}

class Circle implements Shape {

  @Override
  public void draw() {
      System.out.println(&quot;Shape: Circle&quot;);
  }
}

abstract class ShapeDecorator implements Shape {
  protected Shape decoratedShape;

  public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
  }

  public void draw(){
      decoratedShape.draw();
  }    
}

class RedShapeDecorator extends ShapeDecorator {

  public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);        
  }

  @Override
  public void draw() {
      decoratedShape.draw();           
      setRedBorder(decoratedShape);
  }

  private void setRedBorder(Shape decoratedShape){
      System.out.println(&quot;Border Color: Red&quot;);
  }
}

class DecoratorPatternDemo {
  public static void main(String[] args) {

      Shape circle = new Circle();

      Shape redCircle = new RedShapeDecorator(new Circle());

      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println(&quot;Circle with normal border&quot;);
      circle.draw();

      System.out.println(&quot;\nCircle of red border&quot;);
      redCircle.draw();

      System.out.println(&quot;\nRectangle of red border&quot;);
      redRectangle.draw();
  }
}</code></pre>
<h3 id="옵저버-패턴">옵저버 패턴</h3>
<ul>
<li>Observable 객체의 변화를 Observer에서 알 수 있도록 하는 패턴 </li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/044bc16e-97a0-4896-a03a-815edc84b081/%EC%98%B5%EC%A0%80%EB%B2%84%ED%8C%A8%ED%84%B4.jpg" alt=""></p>
<pre><code class="language-java">class Subject {
  private List&lt;Observer&gt; observers = new ArrayList&lt;Observer&gt;();
  private int state;

  public int getState() {
      return state;
  }

  public void setState(int state) {
      this.state = state;
      notifyAllObservers();
  }

  public void attach(Observer observer){
      observers.add(observer);        
  }

  public void notifyAllObservers(){
      for (Observer observer : observers) {
        observer.update();
      }
  }     
}

abstract class Observer {
  protected Subject subject;
  public abstract void update();
}

class BinaryObserver extends Observer{

  public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
  }

  @Override
  public void update() {
      System.out.println( &quot;Binary String: &quot; + Integer.toBinaryString( subject.getState() ) ); 
  }
}

class OctalObserver extends Observer{

  public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
  }

  @Override
  public void update() {
    System.out.println( &quot;Octal String: &quot; + Integer.toOctalString( subject.getState() ) ); 
  }
}

class HexaObserver extends Observer{

  public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
  }

  @Override
  public void update() {
      System.out.println( &quot;Hex String: &quot; + Integer.toHexString( subject.getState() ).toUpperCase() ); 
  }
}

class ObserverPatternDemo {
  public static void main(String[] args) {
      Subject subject = new Subject();

      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);

      System.out.println(&quot;First state change: 15&quot;);    
      subject.setState(15);
      System.out.println(&quot;Second state change: 10&quot;);    
      subject.setState(10);
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터페이스(Interface)]]></title>
            <link>https://velog.io/@im_joonchul/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-Interface</link>
            <guid>https://velog.io/@im_joonchul/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-Interface</guid>
            <pubDate>Sun, 11 Apr 2021 07:58:47 GMT</pubDate>
            <description><![CDATA[<h1 id="인터페이스란">인터페이스란</h1>
<ul>
<li>클래스를 사용하는 방식, 접점만을 선언하는 클래스와 유사한 틀</li>
<li>아무런 구현이 되어 있지 않으며, 모든 메소드가 추상 메소드</li>
<li>이름 짓는 방법<ol>
<li>interface IFOO &lt;- class Foo 상속을 하는 자식에서 부모 방향으로 / 앞에 i로 쓴다.</li>
<li>interface Printable(형용사 형태로 많이 씀) &lt;- Bar  사용 가능한 형용사 형태로 쓴다.</li>
</ol>
</li>
</ul>
<h2 id="인터페이스의-특징">인터페이스의 특징</h2>
<ul>
<li><code>class</code>가 아니고 <code>interface</code> 키워드를 사용한다.<ul>
<li><code>public</code> 또는 <code>default</code> 접근 제어자만 사용 가능.</li>
</ul>
</li>
<li>구현 코드가 들어가지 않아서 new(인스턴스화)될 수 없다.</li>
<li>생성자를 가질 수 없고, 객체 생성을 할 수 없다.</li>
<li>자식 객체는 참조할 수 있으나 메소드와 변수는 사용할 수 없다.</li>
<li>인터페이스명으로 클래스 메소드 호출이 가능하나, 자식클래스명으로 클래스 메소드 호출 불가능.</li>
<li>멤버 변수는 항상 <code>public static final</code> 이다. (생략 가능하다.)</li>
<li>멤버 메소드는 항상 <code>public abstract</code> 이며, 생략가능</li>
<li>(자바에서는) 클래스는 하나만 상속할 수 있으나, 인터페이스는 여러개 상속이 가능하다.</li>
<li>인터페이스의 상속은 implements 키워드 사용</li>
</ul>
<h2 id="인터페이스의-요소">인터페이스의 요소</h2>
<ul>
<li>상수: 선언된 모든 변수는 상수로 처리됨(static 멤버 변수는 가질 수 있지만, 인스턴스 멤버 변수는 가질 수 없다)<ul>
<li>인터페이스명.클래스 멤버 변수 접근이 가능하다.</li>
</ul>
</li>
<li>메소드 : 모든 메소드는 추상 메소드이다.</li>
<li>디폴트 메소드 : 기본 구현을 가지는 메소드 구현하는 클래스에서 재정의 할 수 있음(java 8)<ul>
<li>만약 이미 운영중인 프로그램에 새로운 기능을 추가하려고 할 때, 추상메소드로 구현을 하면 구현한 클래스들은 강제적으로 추상메소드를 구현해야하니 
구현하지 않았을 때 에러가 발생한다. 그래서 이미 운영되고 있는 시스템에서 추가 요건으로 인해 불가피하게 반영을 해야할 때 디폴트 메소드를 쓰면 효과적이다.</li>
</ul>
</li>
<li>정적 메소드 : 인스턴스 생성과 상관없이 인터페이스 타입으로 호출하는 메소드(java 8)</li>
<li>private 메소드 : 인터페이스 내에서 사용하기 위해 구현한 메소드
구현하는 클래스에서 재정의 할 수 없음(java9)</li>
</ul>
<h2 id="인터페이스-선언과-구현">인터페이스 선언과 구현</h2>
<p><img src="https://images.velog.io/images/im_joonchul/post/f0a5c308-b2e4-49c2-a03d-39c69a72793c/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4.jpg" alt="인터페이스"></p>
<h2 id="인터페이스에서-클래스로의-타입-상속">인터페이스에서 클래스로의 타입 상속</h2>
<pre><code class="language-java">Calc calc = new CompleteCacl();</code></pre>
<ul>
<li>인터페이스를 구현한 클래스는 인터페이스 타입으로 변수를 선언하여 인스턴스를 생성할 수 있다.</li>
<li>인터페이스는 구현 코드가 없기 때문에 타입 상속이라고 한다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/52eb07e5-27cf-4f95-bbad-99155ea370e5/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%ED%83%80%EC%9E%85%EC%83%81%EC%86%8D.jpg" alt="인터페이스타입상속"></p>
<ul>
<li><p>또 다른 구현코드(예문)</p>
<pre><code class="language-java">interface IFoo{
    public static final int MEMBER_VAR = 10; //변하지 않는 상수는 대문자_ 형식으로 사용하기 때문에 여기도 사용한다.
    int MEMBER_VAR2 = 20 ; //이렇게 사용해도됨 public static final;

    public abstract void methodA(int param);
    void methodB(int param); //public abstract

}

class Foo implements IFoo{

    @Override
    public void methodA(int param) {
        System.out.println(param);
    }

    @Override
    public void methodB(int param) {
        System.out.println(param);

    }
}</code></pre>
</li>
</ul>
<h2 id="인터페이스간의-상속">인터페이스간의 상속</h2>
<ul>
<li><p>인터페이스 간에도 상속이 가능하데, 이 경우 <code>extends</code> 키워드를 사용한다. (구현하는 것이 아니라서 extends 사용)</p>
<ul>
<li>클래스에서 인터페이스를 상속받는 경우에는 <code>implements</code> 키워드를 사용한다.</li>
</ul>
</li>
<li><p>클래스간의 상속과 달리 인터페이스간의 상속은 다중 상속 가능하다.</p>
<pre><code class="language-java">interface  Walkable{
  void walk();
}
interface  Runable{
  void run();
}

interface Jumpable extends  Walkable, Runable{
  void jump();
  //  워크, 런이 다 포함되어 있음
}

class Jumper implements Jumpable{
// 3개다 구현해야함  -?
  @Override
  public void walk() {
      System.out.println(&quot;걷다&quot;);
  }

  @Override
  public void run() {
      System.out.println(&quot;달리다&quot;);
  }

  @Override
  public void jump() {
      System.out.println(&quot;뛰다&quot;);

  }
}</code></pre>
<h2 id="인터페이스를-활용한-다형성-구현">인터페이스를 활용한 다형성 구현</h2>
<h3 id="인터페이스의-역할은">인터페이스의 역할은?</h3>
<ul>
<li>인터페이스는 클라이언트 프로그램에 어떤 메소드를 제공하는지 알려주는 명세 또는 약속이다.</li>
<li>한 객체가 어떤 인터페이스의 타입이라 함은 그 인터페이스의 메소드를 구현했다는 의미한다.</li>
<li>클라이언트 프로그램은 실제 구현 내용을 몰라도 인터페이스의 정의만 알면 그 객체를 사용할 수 있다.</li>
<li>인터페이스를 구현해 놓은 다양한 객체를 사용한다 - 다형성</li>
<li>JDBC를 구현한 오라클, MSSQL라이브러리 등 </li>
</ul>
</li>
<li><p>ORACLE, MySQL, MsSQL 같은 DB회사들이 구현을해서 라이브러리(.jar)를 준다.
그러면 우리가 오라클로 연결해서 쿼리문을 수행 하겠다 하면  라이브러리를 import해서 라이브러리를 가져다가 커넥션을 연결을 할 때 
오라클 소스를 뒤져보지 않는다 단지, 메소드들만 확인한다.(명세들만 확인을 한다.설계에서 중요하다.*) </p>
</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/14c1c094-6404-4851-ac3f-4c9e08f450fa/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%82%AC%EC%9A%A9%EC%98%88.jpg" alt="인터페이스상속예"></p>
<h3 id="다형성-구현-문제">다형성 구현 문제</h3>
<ul>
<li>고객센터에는 전화 상담을 하는 상담원들이 있습니다. 일단 고객 센터로 전화가 오면 대기열에 저장됩니다.</li>
<li>상담원이 지정되기 전까지 대기 상태가 됩니다. 각 전화가 상담원에게 배분되는 정책은 다음과 같이 여러 방식으로 구현될 수 있습니다.<ul>
<li>상담원 순서대로 배분하기</li>
<li>대기가 짧은 상담원 먼저 배분하기</li>
<li>우선순위가 높은(숙련도가 높은) 상담원에게 먼저 배분하기</li>
</ul>
</li>
<li>위와 같은 다양한 정책이 사용되는 경우 interface를 정의하고 다양한 정책을 구현하여 실행하세요.</li>
</ul>
<h4 id="구현-코드">구현 코드</h4>
<ul>
<li><p>Scheduler 인터페이스</p>
<pre><code class="language-java">public interface Scheduler {
  public void getNextCall();
  public void sendCallToAgent();
}</code></pre>
</li>
<li><p>RoundRobin 클래스</p>
<pre><code class="language-java">public class RoundRobin implements Scheduler{
  @Override
  public void getNextCall() {
      System.out.println(&quot;상담 전화를 순서대로 대기열에서 가져옵니다.&quot;);
  }

  @Override
  public void sendCallToAgent() {
      System.out.println(&quot;다음 순서의 상담원에게 배분합니다.&quot;);
  }
}</code></pre>
</li>
<li><p>PriorityAllocation 클래스</p>
<pre><code class="language-java">public class PriorityAllocation implements Scheduler{
  @Override
  public void getNextCall() {
      System.out.println(&quot;고객등급이 높은 고객의 call을 먼저 가져옵니다.&quot;);
  }

  @Override
  public void sendCallToAgent() {
      System.out.println(&quot;업무 숙련도가 높은 상담원에게 먼저 배분합니다.&quot;);
  }
}</code></pre>
</li>
<li><p>LeastJob 클래스</p>
<pre><code class="language-java">public class LeastJob implements Scheduler{
  @Override
  public void getNextCall() {
      System.out.println(&quot;상담 전화를 순서대로 대기열에서 가져옵니다.&quot;);
  }

  @Override
  public void sendCallToAgent() {
      System.out.println(&quot;현재 상담업무가 없거나 상담대기가 가장 적은 상담원에게 할당합니다.&quot;);
  }
}</code></pre>
</li>
<li><p>Test 클래스</p>
<pre><code class="language-java">public class SchedulerTest {
  public static void main(String[] args) throws IOException {
      System.out.println(&quot;전화 상담원 할당 방식을 선택하세요&quot;);
      System.out.println(&quot;R : 한명씩 차례대로&quot;);
      System.out.println(&quot;L : 대기가 적은 상담원 우선&quot;);
      System.out.println(&quot;P : 우선순위가 높은 고객우선 숙련도 높은 상담원&quot;);

</code></pre>
</li>
</ul>
<pre><code>    int ch = System.in.read(); //아스키코드 값이 입력된다.
    Scheduler scheduler = null;

    if(ch == &#39;R&#39; || ch == &#39;r&#39;){
        scheduler = new RoundRobin();
    }else if(ch == &#39;L&#39; || ch==&#39;l&#39;){
        scheduler = new LeastJob();
    }else if(ch == &#39;P&#39; || ch == &#39;p&#39;){
        scheduler = new PriorityAllocation();
    }else{
        System.out.println(&quot;지원되지 않는 기능입니다.&quot;);
        return; // 왜 리턴을 넣지?
    /**
     * return을 사용하는 이유
     * return은 값을 반환하거나 메소드를 호출한 곳으로 되돌아갈 때 사용하는 예약어이다
     * 만약 메소드 내부에서 return값이 void일때 return을 하면 여기서 메소드를 끝내겠다는 의미
     * return을 호출하면 나머지 로직을 실행하지 않고 함수를 종료하는 의미이다.
     */
    }

    scheduler.getNextCall();
    scheduler.sendCallToAgent();
}</code></pre><p>}</p>
<pre><code>## 인터페이스와 strategy pattern

![strategypattern](https://images.velog.io/images/im_joonchul/post/626c9190-e6da-4262-a0df-ba82f3d72adc/strtegypattern.jpg)

* 인터페이스를 활용하면 다양한 정책이나 알고리즘을 프로그램의 큰 수정 없이 적용, 확장할 수 있음

## JDK 1.8 이후의 인터페이스
  * 인터페이스에도 default 메소드를 구현할 수 있다. 접근제어자는 항상 `public` 키워드를 사용해야 한다.
    * 인터페이스는 원래 메소드를 구현할 수 없었는데 1.8버전 이후에 defualt 메소드가 생기면서 메소드를 구현할 수 있게 되었다.
  * 인터페이스 철학과 맞지 않으나, 기존에 사용하던 인터페이스가 개선되어,
   모든 자식 메소드에 동일하게 구현되어야 하는 메소드가 생긴 경우에 쉽게 기능을 추가하기 위해 만들어졌다.
  * 많은 클래스들이 인터페이스를 상속하는 경우 선택적으로 오버라이드해서 사용할 수 있다.
   ````java
  interface IFoo2{
      void abstractMethod();
      default void defaultMethod(){ //디폴트 메소드
          System.out.println(&quot;default method&quot;);
      }
  }

  class FooTwo implements IFoo2{
      @Override
      public void abstractMethod() {
          System.out.println(&quot;abstract method implemented&quot;);
      }

  //    @Override // overriding not necessary 반드시 오버라이딩 해야 하는 것은 아님.
  //    public void defaultMethod() {
  //        System.out.println(&quot;overriden default method&quot;);
  //    }

  }
  //처음부터 디폴트메소드를 구현하고 시작하는 것은 철학적으로 맞지않음 원래 abstract 메소드만 있음

  class SuperFoo{ //인터페이스가 있는데 부족한 부분이 있어서 메소드를 생성해서 사용하고 있었다
      public void defaultMethod(){
          System.out.println(&quot;default method in super class&quot;);
      }
  }


  class Foo3 extends SuperFoo implements IFoo2 {

      @Override
      public void abstractMethod() {
          System.out.println(&quot;abstract metho implemented&quot;);
      }

  }</code></pre><ul>
<li><p>인터페이스의 static 메소드 : 클래스 메소드와 동일하게 사용 가능하다.</p>
<ul>
<li>인터페이스 이름으로 호출 가능하다.</li>
<li>클래스 구현체의 이름으로도 호출 가능하다.<pre><code class="language-java">interface IFoo {
  static void staticMethod() {
      System.out.println(&quot;static method&quot;);
  }
}
</code></pre>
</li>
</ul>
<p>public class Main {</p>
<pre><code>public static void main(String[] args) {
    IFoo.staticMethod(); // static method
}</code></pre><p>}
````</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[제네릭(Generic)]]></title>
            <link>https://velog.io/@im_joonchul/%EC%A0%9C%EB%84%A4%EB%A6%ADGeneric</link>
            <guid>https://velog.io/@im_joonchul/%EC%A0%9C%EB%84%A4%EB%A6%ADGeneric</guid>
            <pubDate>Sun, 11 Apr 2021 07:52:18 GMT</pubDate>
            <description><![CDATA[<h1 id="제네릭이란">제네릭이란</h1>
<ul>
<li><p>타입을 파라미터화해서 컴파일시 구체적인 타입이 결정되도록 하는 것 컬렉션, 람다식(함수적 인터페이스), 스트림 ,NIO에서 널리 사용된다.</p>
</li>
<li><p>대상 객체의 타입을 입력받아서 사용하는 형식</p>
</li>
<li><p>실행시 타입에러가 나는 것보다 컴파일시에 미리 타입을 강하게 체크해서 에러를 사전에 방지할 수 있다, 타입 변환을 제거할 수 있다.</p>
<ul>
<li>일부 타입을 제한할 수 있는 기능이 있음.</li>
<li>입력을 <code>object</code> 로 할 수 있으나, 런타임에 <code>instanceof</code> 로 객체를 체크해야 함.<ul>
<li>원하는 객체가 들어왔는지 계속 확인해야 한다.</li>
</ul>
</li>
</ul>
</li>
<li><p>제네릭을 사용할 경우 간결하게 코드 작성을 할 수 있다.</p>
</li>
<li><p>클래스를 선언할 때에는 타입이 알려지지 않으며, 타입 파라미터를 사용한다.</p>
</li>
<li><p>생성자도 갖을 수 있다, 객체 참조 가능. 인터페이스, 추상클래스 상속 가능, 프리미티브 타입 불가능.</p>
</li>
<li><p>타입의 상속시 부모와 자식클래스의 타입을 맞추어 줘야 한다. 타입 파라미터도 모두 채워 주어야 한다. 
부모클래스/인터페이스의 동일한 타입 파라미터를 넘겨줄 수 있다.</p>
</li>
<li><p>static 멤버 변수, static 메소드는 타입 파라미터를 사용할 수 없다.</p>
<ul>
<li>static void staticMethod(T t)는 안되고 / static <P>p staticMethod(P p) 는 가능하다.</li>
<li>static 메소드도 사용이 가능하다. 다만, 클래스와 static 메소드의 타입 파라미터를 갖게 하면 안된다.</li>
<li>왜냐하면, static은 객체가 생성되기 전에 메모리에 할당되는데 메모리에 할당되려면 타입이 있어야 하고, </li>
<li>타입 파라미터는 객체를 생성할 때 값이 넘어오기 때문에</li>
</ul>
</li>
<li><p>new 키워드를 사용하여 객체를 참조할 수 없다.</p>
</li>
<li><p>instanceof의 피연산자로 사용할 수 없다.</p>
</li>
</ul>
<h2 id="제네릭-타입을-사용할-경우의-효과">제네릭 타입을 사용할 경우의 효과</h2>
<ul>
<li>비 제네릭을 사용할 경우 Object 타입을 사용하므로 빈번한 타입 변환생성 -&gt; 성능 저하</li>
<li>제네릭을 사용할 경우 클래스를 선언할 때 타입 파라미터를 기술한다. 컴파일시 타입 파라미터가 구체적인 클래스로 변경된다.
유연하게 타입을 선언하여 처리할 수 있다.</li>
</ul>
<h2 id="제네릭-클래스">제네릭 클래스</h2>
<h3 id="제네릭-타입">제네릭 타입</h3>
<ul>
<li><p>제네릭 타입이란 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.
타입을 파라미터로 가진다 -&gt; 선언시 클래스 또는 인터페이스 이름 뒤에 &lt;&gt; 부호가 붙는다.</p>
<ul>
<li>타입 파라미터 - 개발코드(실행하는 곳)에서는 타입 파라미터 자리에 구체적인 타입을 지정해야 한다.</li>
</ul>
</li>
<li><p>클래스와 인터페이스에 제네릭이 적용된 타입</p>
</li>
<li><p>클래스를 선언할 때에 타입이 알려지지 않으며, 타입 파라미터를 사용.</p>
<pre><code class="language-java">//일반 클래스
class Foo{

}

// 제네릭 클래스
// 클래스를 선언할 때에는 설정되지 않은 타입이 있으며, 이것을 타입 파라미터로 표현한다.
class GenericFoo&lt;T&gt; { // T: 타입 파라미터
    String name;
    T memberVar; // T를 자료형으로 사용.

    public GenericFoo(String name, T memberVar) {
        //생성자 생성 어떤 타입의 자료형이 들어오는지 모르는데 구현 가능.
        this.name = name;
        this.memberVar = memberVar;
    }
}
//제네릭 인터페이스
interface GenericInterface&lt;T&gt;{ //인터페이스도 제네릭이 가능

}
class HashMap&lt;k,w&gt;{ // 여러 개의 타입 파라미터로 쓸 수 있다.

}</code></pre>
</li>
<li><p>제네릭 타입은 실제로 사용될 때 타입 파라미터에 자료형을 입력받는다.</p>
<pre><code class="language-groovy">GenericFoo&lt;String&gt; foo = new GenericFoo&lt;String&gt;(&quot;name&quot;,&quot;var&quot;);
 //**생성할 때 자료형을 정해주게 되어 있음.**
 // &lt;&gt;안에 스트링으로 넣어줬기 때문에 T도 스트링으로 된다.

GenericFoo&lt;String&gt; foo1 = new GenericFoo&lt;&gt;(&quot;name&quot;,&quot;var&quot;);//뒤에 &lt;&gt;생략가능</code></pre>
<h3 id="주의-해야할-문법들">주의 해야할 문법들</h3>
</li>
<li><p>메소드의 중괄호 {} 안에서 타입 파라미터 변수로 사용 가능한 것은 상위 타입의 멤버(필드,메소드)로 제한된다.</p>
</li>
<li><p>하위 타입에만 있는 필드와 메소드는 사용할 수 없다. </p>
</li>
<li><p>static은 객체가 생성 전에 자료형이 결정되어야 하는데, </p>
</li>
<li><p>class GenericBar<T>의 타입 파라미터와 static 변수, 메소드는 같은 타입 파라미터를 갖고 있기 때문에 안됨!</p>
<pre><code class="language-java">class  GenericBar&lt;T&gt;{

 // 제네릭은 객체를 생성할때 자료형을 입력받기 때문에
 // 스태틱은 객체 생성 전에 자료형이 결정되어야 하기때문에 
 // 클래스에 속하기 때문에 T를 사용하면 자료형 알 수 없음.
 // static은 클래스에 속하기 때문에 애초에 T가 쓸수 없음 문법적 문제

 static T classVar; 
 // 안된다.. 클래스의 스테틱변수는 객체와 관계없이 클래스에 속해있기 때문에
 // 스태틱 변수가 생겨야하는 생성시점에는 T 자료형이 없기 때문에
 static void method(T var){} //이것도 마찬가지로 불가능.</code></pre>
<ul>
<li><p>문법적으로 문제가 없을 것 같으나, 안정성 문제로 금지. 암기해야 하는 됨!</p>
</li>
<li><p><code>instanceof</code>의 피연산자로 사용할 수 없다.</p>
</li>
<li><p><code>new</code> 키워드를 사용하여 객체 생성을 할 수 없다.</p>
<pre><code class="language-groovy">// T memberVar = new T(); t는 new 키워드를 쓸 수 없음. 안정성 문제 때문에 불가능하다.
// T라는 자료형이 결정되지 않기때문에 생성자가 어떻게 정의될지 모르기 때문에 불가능 자바에서 막혀있음.
// 타입파라미터의 객체를 생성하는 것은 불가능 하다.
 {
     Object obj = new Object();
     if(obj instanceof T){ 
// 어떤 객체가 있을 때 T에 속하는지 확인하기 불가능. 안정성 문제 때문에 그냥 막혀있음.

  }
}</code></pre>
<h3 id="제네릭-타입의-상속">제네릭 타입의 상속</h3>
</li>
</ul>
</li>
<li><p>부모 클래스 또는 인터페이스에 선언한 타입 파라미터는 반드시 자식에서도 선언해야 된다.</p>
</li>
<li><p>자식 클래스에서 추가적인 타입 파라미터를 선언할 수 있다.</p>
</li>
<li><p>부모 클래스와 인터페이스의 타입 파라미터가 같을 경우 상속받는 클래스에서 다르게 넣어주면 된다.</p>
<pre><code class="language-java">class Product&lt;T,M&gt; {
 private T kind;
 private M model;

 public T getKind() {
     return kind;
 }
 public void setKind(T kind) {
     this.kind = kind;
 }
 public M getModel() {
     return model;
 }
 public void setModel(M model) {
     this.model = model;
 }
}
class Tv{
}
class ChildProduct&lt;K,V,C&gt; extends Product&lt;K,V&gt;{
 private C company;

 public C getCompany() {
     return company;
 }

 public void setCompany(C company) {
     this.company = company;
 }
}
public class ChildProductAndStorageExam {

 public static void main(String[] args) {
     ChildProduct&lt;Tv,String,String&gt; childProduct = new ChildProduct&lt;Tv, String, String&gt;();
     childProduct.setKind(new Tv());
     childProduct.setModel(&quot;스마트티비&quot;);
     childProduct.setCompany(&quot;삼성&quot;);
 }
}</code></pre>
</li>
</ul>
<h3 id="파라미터-타입의-제한">파라미터 타입의 제한</h3>
<ul>
<li><p>extends를 이용하여 파라미터 타입을 제한할 수 있다.</p>
<ul>
<li>인터페이스의 경우에도 extends 키워드를 사용한다.</li>
<li>클래스와 인터페이스를 동시에 제약하려면 &amp;로 연결한다.</li>
</ul>
</li>
<li><p>제한한 자료형의 자식 클래스는 모두 사용할 수 있다.</p>
<pre><code class="language-java">//타입 제한을 하지 않으면 extends object와 동일하다.
class GenericNoTypeLimit&lt;T extends Object&gt;{
}

//extends를 이용해서 부모클래스를 제한 할 수 있음, 추상클래스를 상속하면서 인터페이스를 추가로 구현할 수 있음 
// 추상클래스+인터페이스를 구현해야한다
class GenericTypeLimitation&lt;T extends Number &amp; Cloneable&gt;{

}</code></pre>
</li>
</ul>
<h2 id="제네릭-메소드">제네릭 메소드</h2>
<ul>
<li>매개변수 타입과 리턴타입으로 타입 파라미터를 갖는 메소드를 말한다.
실제 메소드를 호출할 때 매개변수와 리턴 타입을 지정해서 사용한다.</li>
</ul>
<h3 id="메소드에-선언된-제네릭">메소드에 선언된 제네릭</h3>
<ul>
<li><p>메소드의 리턴 타입 앞에 타입 파라미터 변수를 선언하여 사용</p>
</li>
<li><p>public &lt;타입파라미터,...&gt; 리턴타입 메소드명 (매개변수){ ... }</p>
<pre><code class="language-java">class GenericMethod{
  public &lt;T&gt; T method(T x){
  // 여기서 &lt;T&gt; 는 제네릭 타입으로 선언을 하겠다라는 의미이다.
      return x;
  }
}</code></pre>
</li>
<li><p>메소드에 선언된 제네릭은 정적 메서드에도 사용 가능.</p>
<pre><code class="language-java">class GenericMethod&lt;T&gt; {
public static void method(T t) { // Error
  ...
}

public static &lt;P&gt; P method (P p) { // Possible
  ...
}
}</code></pre>
<h3 id="제네릭-메소드를-호출하는-두가지-방법">제네릭 메소드를 호출하는 두가지 방법</h3>
</li>
<li><p>리턴타입 변수 = &lt;구체적인 타입&gt; 메소드명(매개값);</p>
</li>
<li><p>리턴타입 변수 = 메소드명(매개값); // 주로 이방법을 더 많이 사용한다.</p>
<pre><code class="language-java">class Box&lt;T&gt; {
  private T t;
  public void set(T t) {
      this.t = t;
  }
  public T get() {
      return t;
  }
}
</code></pre>
</li>
</ul>
<p>class Util {
    public static <T> Box<T> boxing(T t){
        Box<T> box = new Box<T>();
        box.set(t);
        return box;
    }
}</p>
<p>public class BoxingMethodExam {</p>
<pre><code>public static void main(String[] args) {
    Box&lt;Integer&gt; box = Util.&lt;Integer&gt;boxing(123);
    Box&lt;String&gt; box2 = Util.boxing(&quot;홍길동&quot;);

    System.out.println(box.get());
    System.out.println(box2.get());
}</code></pre><p>}</p>
<pre><code>### 와일드 카드
  * 이미 선언되어 있는 제네릭 타입을 매개변수나 리턴타입으로 사용할 때 타입 파라미터를 제한할 목적
      * 비교 &lt;T extends 상위 또는 인터페이스&gt; 는 제네릭 타입과 제네릭 메소드를 선언할 때 제한한다.
  * 와일드카드 ?는 메소드의 입력 타입에 제네릭이 쓰일 경우, 제네릭의 타입 변수를 제한할 수 있다.
  * `&lt;?&gt;` =&gt; `&lt;? extends Object&gt;`와 동일
  * `&lt;? extends T&gt;` =&gt; 와일드카드의 상한을 제한
  * `&lt;? super T&gt;` =&gt; 와일드카드의 하한을 제한
 ````java
 // 와일드카드
class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {

        return name;
    }
}
class Worker extends Person {

    public Worker(String name) {
        super(name);
    }
}
class Student extends Person{

    public Student(String name) {
        super(name);
    }
}
class HighStudent extends Student{

    public HighStudent(String name) {
        super(name);
    }
}
public class Course&lt;T&gt; {
    private String name;
    private T[] students;

    public Course(String name, int capacity) {
        this.name = name;
        students = (T[])new Object[capacity];
        // T타입으로 new 로 생성을 못하니깐 오브젝트로 만든다음
        // 타입 변환을 해야 한다.
    }

    public String getName() {
        return name;
    }
    public T[] getStudents() {
        return students;
    }

    public void add(T t) {
        for(int i=0; i&lt;students.length; i++) {
            if (students[i] == null) {
                students[i] = t;
                break;
            }
        }
    }
}</code></pre><h3 id="출력">출력</h3>
<pre><code class="language-java">package sec02.exam06_generic_wildCard;

import java.util.Arrays;

public class WildCardExam {
    public static void registerCourse(Course&lt;?&gt; course) {
        System.out.println(course.getName()+&quot;수강생 : &quot;+Arrays.toString(course.getStudents()));
    }
    // Student, HightStudent 클래스 타입만 가능, 상한을 제한한다
    public static void registerCourseStudent(Course&lt;? extends Student&gt; course) {
        System.out.println(course.getName()+&quot;수강생 : &quot;+Arrays.toString(course.getStudents()));
    }

    // Person, Worker 클래스 타입만 가능, 하한을 제한한다.
    public static void registerCourseWorker(Course&lt;? super Worker&gt; course) {
        System.out.println(course.getName()+&quot;수강생 : &quot;+Arrays.toString(course.getStudents()));
      }

    public static void main(String[] args) {
        Course&lt;Person&gt; personCourse = new Course&lt;Person&gt;(&quot;일반인 과정&quot;,5);
        personCourse.add(new Person(&quot;일반인&quot;));
        personCourse.add(new Person(&quot;직장인&quot;));
        personCourse.add(new Person(&quot;학생&quot;));
        personCourse.add(new Person(&quot;고등학생&quot;));

        Course&lt;Worker&gt; workerCourse = new Course&lt;Worker&gt;(&quot;직장인 과정&quot;,5);
        workerCourse.add(new Worker(&quot;직장인&quot;));

        Course&lt;Student&gt; studentCourse = new Course&lt;Student&gt;(&quot;학생 과정&quot;,5);
        studentCourse.add(new Student(&quot;학생&quot;));
        studentCourse.add(new HighStudent(&quot;고등학생&quot;));


        Course&lt;HighStudent&gt; highStudentCourse = new Course&lt;HighStudent&gt;(&quot;고등학생 과정&quot;,5);
//        highStudentCourse.add(new Student(&quot;일반인&quot;)); //error
        highStudentCourse.add(new HighStudent(&quot;직장인&quot;));

        registerCourse(personCourse); // 일반인 과정수강생 : [일반인, 직장인, 학생, 고등학생, null]
        registerCourse(workerCourse); // 직장인 과정수강생 : [직장인, null, null, null, null]
        registerCourse(studentCourse); // 학생 과정수강생 : [학생, 고등학생, null, null, null]
        registerCourse(highStudentCourse); // 고등학생 과정수강생 : [직장인, null, null, null, null]


        //registerCourseStudent(personCourse); error
        //registerCourseStudent(workerCourse); error
        registerCourseStudent(studentCourse); // 학생 과정수강생 : [학생, 고등학생, null, null, null]
        registerCourseStudent(highStudentCourse); // 고등학생 과정수강생 : [직장인, null, null, null, null]


        registerCourseWorker(personCourse); // 일반인 과정수강생 : [일반인, 직장인, 학생, 고등학생, null]
        registerCourseWorker(workerCourse); // 직장인 과정수강생 : [직장인, null, null, null, null]
        //registerCourseWorker(studentCourse); error
        //registerCourseWorker(highStudentCourse); error
    }
}
</code></pre>
<h1 id="동적-바인딩">동적 바인딩</h1>
<ul>
<li>메소드가 생길 때 자료형이랑 정의되어 있어서 기계가 동작하게 만들어지게 정상적인데, 자료형이 정해져있지 않아서 들어오는거에 따라 동작이 달라짐.
실제로 런타임이 되지 않으면 컴파일 타임이 알 수 없음.( 컴파일 타임에는 동작이 완전히 정의가 되지 않음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[열거형(Enumeration)]]></title>
            <link>https://velog.io/@im_joonchul/%EC%97%B4%EA%B1%B0%ED%98%95-Enumeration</link>
            <guid>https://velog.io/@im_joonchul/%EC%97%B4%EA%B1%B0%ED%98%95-Enumeration</guid>
            <pubDate>Sun, 11 Apr 2021 07:40:28 GMT</pubDate>
            <description><![CDATA[<h1 id="열거형이란">열거형이란</h1>
<ul>
<li>반드시 하나의 값만 가지게 될 변수들을 모아놓은 요일, 직업등 정해진 값 외에 바뀌지 않는 것들의 집합을 말한다. 이런 것들을 열거해서 한꺼번에 묶어 놓은 형태를 열거형이라 한다.</li>
<li>enum 키워드로 표현하고, &#39;이넘&#39; 이라고 부른다.</li>
<li>내부적인 구현은 <code>enum</code> -&gt; <code>java.lang.Enum</code> 클래스를 상속 하는 것</li>
<li>이미 상속하는 클래스(java.lang.Enum)가 있기 때문에 enum은 다른 클래스를 상속하지 못한다. </li>
</ul>
<h2 id="열거형의-특징">열거형의 특징</h2>
<ul>
<li>열거형으로 선언된 순서에 따라 0부터 index 값을 가진다.(순차적으로 증가)</li>
<li>접근 제한자는 <code>public</code>과 <code>default</code>만 사용 가능하다.</li>
<li>열거형은 다른 클래스를 상속하지 못하지만, 인터페이스 구현은 가능하다.</li>
<li>클래스 변수와 마찬가지로 바로 사용이 가능하다.</li>
<li>열거형 타입에는 열거형 상수와 null 값 할당 가능.</li>
<li>일종의 클래스 자료형으로 쓸 수 있고, 열거형 상수도 객체로 사용 가능하다.</li>
<li>생성자가 있을 수 있는데 앞에 private만 쓸 수 있고 생략 가능하다.</li>
<li>생성자는 값을 입력 받게 되어 있는데, 만들 때 각 객체에 값을 넣어줘야 한다.</li>
</ul>
<h2 id="열거형의-구현">열거형의 구현</h2>
<ul>
<li><p>일반적인 구현</p>
<pre><code class="language-java">// 클래스의 일종 자료형으로 쓰일 수 있음.
enum Job{
//실제 값은 0인데 자바에서는 숫자 개념으로 사용하지 말라는 것이 권고이다. 각 상수는 0부터 숫자를 가지지만, 
// 심볼로만 사용하고 숫자는 사용하지 않음.

  STUDENT, MARKETING, DEVELOPER, CEO, CHIEF_EXECUTIONAL_OFFICER 
  // 열거형 상수 대문자 단어 구문은 _ 로 표현
}
public class Enumeration {
public static void main(String[] args) {
    Job job = Job.CHIEF_EXECUTIONAL_OFFICER; // 클래스 변수와 유사하게 사용

    if(job == Job.CHIEF_EXECUTIONAL_OFFICER){
        System.out.println(&quot;사장님 안녕하세요?&quot;);
    }

    char c = &#39;A&#39;;
    switch (c){
        case &#39;A&#39;:
            break;
        case &#39;B&#39;:
            break;
        case &#39;C&#39;:
            break;
        default:
            break;
    }

    switch (job){ // switch ~ case 문에는 열거형 자료형을 생략, 열거형 상수만 사용
        case STUDENT:
            System.out.println(&quot;you will be a great one&quot;);
            break;
        case MARKETING:
            System.out.println(&quot;you sells&quot;);
            break;
        case DEVELOPER:
            System.out.println(&quot;you make things&quot;);
            break;
        case CHIEF_EXECUTIONAL_OFFICER:
            System.out.println(&quot;you choose&quot;);
            break;
        default:
            System.out.println(&quot;who are you?&quot;);
    }

}
}</code></pre>
<ul>
<li><p>클래스 내부에서 열거형 구현</p>
<pre><code class="language-java">class Foo{
 enum Symbol{
     ONE,TWO,THREE;
 }
}
public class Enumeration {
public static void main(String[] args) {
    System.out.println(Foo.Symbol.ONE); 
    // 이넘이 그대로 출력됨 결과값 : ONE; 출력을하면 자동으로 toString()으로 변환되서 스트링으로 출력됨.
    // 숫자로서 사용되는게 굉장히 제한됨. 최대한 막혀 있음
}
}</code></pre>
</li>
<li><p>열거형에 메소드 구현</p>
<pre><code class="language-java">enum Symbol{
ONE,TWO,THREE,FOUR;
public Symbol nextSymbol(){
   if(this.equals(ONE)){ // 클래스 멤버변수와 마찬가지로 바로 사용 가능
       //각자가 객체로 사용됨
       return TWO;
   }else if(this.equals(TWO)){
       return THREE;
   }else if(this.equals(THREE)){
       return FOUR;
   }else{
       return ONE;
   }
}
}
public class Enumeration {
public static void main(String[] args) {
   Symbol sym = Symbol.ONE; //애는 객체
   Symbol nextSym = sym.nextSymbol(); 
   // 객체는 메소드를 실행할 수 있어서 사용가능 열거형 상수는 객체이다.
   // 그래서 메소드를 실행할 수 있다.
   System.out.println(nextSym); //TWO
   nextSym = nextSym.nextSymbol();
   System.out.println(nextSym); //THREE
}
}</code></pre>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>열거형에 생성자를 이용한 enum 초기화</p>
<ul>
<li><p>열거형의 생성자는 항상 <code>private</code>이며 생략 가능</p>
<pre><code class="language-java">enum Family{
FATHER(&quot;아버지&quot;), MATHER(&quot;어머니&quot;), SON(&quot;아들&quot;), DAUGHTER(&quot;딸&quot;); 
//열거형 상수(객체)
// 여기서 객체가 생성되는 것임. 처음 한번만 생성되는 거임

private String koreanWord; // 멤버변수(객체에 속하는 변수)

public String getKoreanWord() {
    return koreanWord;
}

public void setKoreanWord(String koreanWord) {
    this.koreanWord = koreanWord;
}

//private는 생략 가능 public 안됨 강제 private  / 안에서 생성되기 때문에
//객체의 생성자는 string을 입력받게 되어있는데 만들때 각 객체에 값을 넣어줘야한다. FATHER(&quot;아버지&quot;)
// 생성자를 사용해서 (&quot;아버지&quot;)처럼 &quot;&quot;안에 값을 변경할 수 있다.
private Family(String koreanWord){
    this.koreanWord = koreanWord;
}
}
public class Enumeration {
public static void main(String[] args) {
    Family fam = Family.SON;
   System.out.println(fam.getKoreanWord());
   fam.setKoreanWord(&quot;버린 자식&quot;);
   System.out.println(fam.getKoreanWord());
   System.out.println(Family.SON.getKoreanWord());
}
}</code></pre>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[추상클래스(Abstract class)]]></title>
            <link>https://velog.io/@im_joonchul/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4Abstract-class</link>
            <guid>https://velog.io/@im_joonchul/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4Abstract-class</guid>
            <pubDate>Sun, 11 Apr 2021 07:32:02 GMT</pubDate>
            <description><![CDATA[<h1 id="추상-클래스란">추상 클래스란</h1>
<ul>
<li>일부 메소드가 구현되지 않고, 선언만 되어있는 클래스<ul>
<li>자식 클래스에서 이것을 반드시 구현하게끔 강제하는 것</li>
<li>필요한 모든 클래스가 구현될 수 있도록 하여 안정성을 높이는 효과를 가져온다.</li>
</ul>
</li>
<li>일반 클래스의 공통적인 부분을 추출해 어느정도 규격(틀)을 잡아 놓는 추상적인 클래스이다.</li>
<li>일반 클래스는 실제 객체를 생성할 정도의 구체성을 가지는 반면, 추상클래스는 아직 메서드와 내용이 추상적이기 때문에
객체를 생성할 수 없다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/d4b494d8-eb99-401b-aa11-09b691e2b7ac/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4.jpg" alt="추상클래스"></p>
<h2 id="추상클래스-특징">추상클래스 특징</h2>
<ul>
<li>메소드와 클래스에 abstract 예약어를 사용한다.</li>
<li>추상클래스는 new(인스턴스화) 할 수 없다.</li>
<li>추상메소드가 없어도 abstract 키워드를 사용하면 추상클래스가 된다</li>
<li>생성자를 가질 수 있고, 일반 메소드도 가질 수 있다. </li>
<li>생성자를 갖지만, 객체 생성이 불가능하다. 그런데 구현된 자식클래스의 객체는 받을 수 있다.</li>
<li>추상클래스의 변수를 초기화 할 수 있다.(자동 초기화도 된다.)</li>
<li>공통적으로 사용할 수 있는 필드와 메서드를 공통적으로 추출해 만들어진 클래스이다.</li>
<li>구현해야하는 메소드들은 상위 클래스에서 선언을 해놓고,구현의 책임을 하위클래스에 위임한다.</li>
<li>하나의 추상메소드라도 포함을 하면 추상 클래스가 되야 한다.<ul>
<li>모든 메소드가 구현되있다고 해도 클래스에 abstract 키워드를 사용하면 추상 클래스가 된다.</li>
</ul>
</li>
<li>자기 자신의 객체를 생성하지 못하는 거 외에는 일반클래스와 비슷하다.</li>
<li>인터페이스와의 차이점은 멤버 변수를 갖고 있느냐 없느냐의 차이.</li>
</ul>
<h3 id="추상클래스-사용하기">추상클래스 사용하기</h3>
<ul>
<li><p>추상클래스는 단독으로 사용되는 것이 아니라 상위 클래스로서 사용된다.</p>
<ul>
<li>추상 메소드는 하위 클래스가 구현해야하는 메소드이다.</li>
<li>구현된 메소드는 하위 클래스가 공통으로 사용하는 기능의 메소드
하위 클래스에 따라 재정의할 수 있다.</li>
</ul>
</li>
<li><p>추상메소드는 하위클래스에서 강제적으로 구현을 해야하지만, 
구현된메소드(일반메소드)들은 하위 클래스에 따라 재정의할 수도 있고, 안해도 상관이 없다.</p>
</li>
</ul>
<h2 id="추상클래스의-사용-용도">추상클래스의 사용 용도</h2>
<ol>
<li><p>공통된 필드와 메소드를 통일할 목적으로 사용한다.</p>
<ul>
<li>추상클래스에서 미리 필드와 메서드를 정의해 놓는다면, 실체클래스(일반클래스)에서는
추상클래스의 필드와 메소드명을 변경할 수 없고 그대로 받아 사용해야 구현해야 한다.
따라서 필드와 메소드의 이름을 통일시켜주고 유지보수성을 높일 수 있다.</li>
</ul>
</li>
<li><p>실체클래스 구현시, 시간 절약이 가능하다.</p>
<ul>
<li>필드와 메소드를 정의해 놓은 추상클래스가 있다면, 예를 들어 자동차를 구현해야 할 때
추상클래스를 기반으로 필요한 부분은 추가해서 클래스를 구현할 수 있다.
(없다면 결국 내가 추상클래스를 구현해야 하는 것이 아니냐 하면 이미 회사에 이런 것들을 구현하는
아키텍쳐들이 설계를 해놓았을 것이다.)</li>
</ul>
</li>
<li><p>규격에 맞는 실체 클래스 구현</p>
<ul>
<li>추상클래스에서 사용해야 할 필드와 메소드들을 정의해 놓으니, 이것을 토대로 코드를 작성할 때,
통일성 있는 규격 안에서 실체 클래스를 구현할 수 있기 때문이다.</li>
</ul>
</li>
</ol>
<pre><code class="language-java">abstract class AbstractFoo{
    int x, y;

    public void method(){
        System.out.println(&quot;method&quot;);
    }
                                       //세미콜론을 잊지 말아야 합니다.
    public abstract void abstractMethod(); 
    // 선언만 하고 구현하지 않음. Virtual method call이여서 부모메소드는 비어있음.
}

class Foo extends AbstractFoo{

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

public class AbstractClass {
    public static void main(String[] args) {
       // AbstractFoo afoo = new AbstractFoo() 
       //추상 클래스는 객체 생성이 불가합니다. 구현이 안되있으니 인스턴스화가 안된다.
        Foo foo = new Foo();
        foo.abstractMethod();

        AbstractFoo afoo = (AbstractFoo)foo;
        afoo.abstractMethod(); // virtual method call
        //추상클래스는 객체 생성은 불가하지만, 구현된 자식클래스의 객체는 받을 수 있다.
    }
}</code></pre>
<h1 id="템플릿-메서드">템플릿 메서드</h1>
<ul>
<li>템플릿 : 틀이나 견본을 의미</li>
<li>템플릿 메소드 : 추상메소드나 구현된 메소드를 활용하여 전체의 흐름(시나리오)를 정의 해 놓은 메소드 final로 선언하여 재정의 할 수 없게 한다.</li>
</ul>
<h2 id="템플릿-매서드-패턴">템플릿 매서드 패턴</h2>
<ul>
<li>디자인 패턴의 일종으로 프레임워크에서 많이 사용되는 설계패턴이다</li>
<li>추상클래스로 선언된 상위클래스에서 추상메소드를 이용하여 전체 구현의 흐름을 정의하고
구체적인 각 메소드 구현은 하위클래스에 위임함 </li>
<li>하위클래스가 다른 구현을 했 다고 해서 템플릿 메소드에 정의된 시나리오대로 수행됨.</li>
</ul>
<h3 id="템플릿-메소드-예제">템플릿 메소드 예제</h3>
<ul>
<li><p>Car 클래스</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;);
  }
  public void washCar(){ }
  //아무 기능이 없어 여기서는 수행을 하지 않고 하위 클래스에서 재정의해서 사용.
  // 모든 하위클래스에서 구현을해야하는 거라면 abstract를 사용하지만
  // 모든 하위클래에서 사용하지 않으면 이렇게 사용한다.
  // 기능의 확장이 가능함

  //템플릿 메소드
  final public void run(){ //재정의할 수 없게 final 키워드 사용.
      startCar();
      drive();
      stop();
      turnOff();
      washCar();
  }
}</code></pre>
</li>
<li><p>AICar</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;);
  }

  @Override
  public void washCar(){
      System.out.println(&quot;자동 세차합니다.&quot;);
  }
}</code></pre>
</li>
<li><p>ManualCar</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>
</li>
<li><p>CarTest 클래스</p>
<pre><code class="language-java">public class CarTest {
  public static void main(String[] args) {
      Car aiCar = new AICar();
      aiCar.run();
      System.out.println(&quot;============&quot;);
      Car manualCarnuCar = new ManualCar();
      manualCarnuCar.run();
  }
}</code></pre>
<h2 id="final-예약어">final 예약어</h2>
</li>
<li><p>fianl 변수는 값이 변경될 수 없는 상수이다.</p>
</li>
<li><p>public static final double PI = 3.14;</p>
</li>
<li><p>오직 한번만 값을 할당 할 수 있음</p>
</li>
<li><p>final 메소드는 하위 클래스에서 재정의(overriding) 할 수 없음.
final 클래스는 더 이상 상속되지 않음</p>
</li>
<li><p>상속이 됬을 때 문제가 될 수 도 있고 고유한 기능이 있는 경우 상속할 일이 없다 하면 final을 붙이면 된다.
public static final 상수 값 정의하여 사용하기</p>
</li>
<li><p>프로젝트 구현 시 여러 파일에서 공유해야 하는 상수 값은 하나의 파일에 선언하여 사용하면 편리하다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/41be0794-e5b5-41fd-bc48-770f2437c817/final1.jpg" alt="final1"></p>
<p><img src="https://images.velog.io/images/im_joonchul/post/c63261a3-3efe-4396-8308-88599a48a523/final2.jpg" alt="final2"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[다형성(Polymorphism)]]></title>
            <link>https://velog.io/@im_joonchul/%EB%8B%A4%ED%98%95%EC%84%B1-Polymorphism</link>
            <guid>https://velog.io/@im_joonchul/%EB%8B%A4%ED%98%95%EC%84%B1-Polymorphism</guid>
            <pubDate>Sun, 11 Apr 2021 07:26:08 GMT</pubDate>
            <description><![CDATA[<h1 id="다형성이란">다형성이란?</h1>
<ul>
<li>하나의 객체가 여러가지 타입을 가질 수 있는 것을 말한다.</li>
<li>자바에서는 이러한 다형성을 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를
참조할 수 있도록 하여 구현하고 있다.</li>
<li>다형성은 상속, 추상화와 더불어 객체지향 프로그래밍을 구성하는 중요한 특징 중 하나이다.</li>
<li>객체지향 프로그래밍의 유연성, 재활용성, 유지보수성에 기본이 되는 특징이다.<h2 id="다형성의-장점">다형성의 장점</h2>
</li>
<li>다양한 여러 클래스를 하나의 자료형(상위 클래스)으로 선언하거나 형변환 하여
각 클래스가 동일한 메소드를 오버라이딩 한 경우, 하나의 코드가 다양한 구현을 실행 할 수 있다.</li>
<li>유사한 클래스가 추가되는 경우 유지보수에 용이하고, 각 자료형 마다 다른 메소드를 호출하지 않으므로 코드에서 많은 if문이 사라진다.</li>
</ul>
<h2 id="다형성의-다양한-특징">다형성의 다양한 특징</h2>
<ul>
<li><p>오버로딩에 의한 다형성, 오버라이딩에 의한 다형성(상속에 의한 다형성과 같다.)</p>
</li>
<li><p>부모 클래스 타입으로 자식 클래스 객체를 참조하는 특징</p>
</li>
<li><p>부모 클래스로 자식 클래스를 참조한 경우, 자식 클래스의 메소드는 사용할 수 없다.</p>
</li>
<li><p>반대로 자식 클래스 타입으로 부모 클래스 타입의 객체를 참조할 경우에는 문법적으로 오류는 나지 않지만, 런타임시 에러가 발생한다.</p>
<pre><code class="language-java">class Foo{
 public void methodA(){
 }
}
class Bar extends Foo{
 public void methodB(){
 }
}
public class Poly01 {
 public static void main(String[] args) {
     Bar bar = new Bar(); //new가 있어야 새로운 객체를 만듬 자식 객체를 생성한 것이다.
     Foo foo = (Foo)bar; // 부모 클래스 타입으로 자식 객체를 받음.
     // 여전히 힙영역에는 자식객체가 있는 것이다.

     foo.methodA(); // Foo객체로받아서 문법적으로 a만 사용 가능, b는 불가능
     //foo.methodB();//이 경우 자식 클래스 메소드는 사용이 불가능 문법적으로 불가능함. 문법적으로 제한을 한 것이다.

     Foo foo1 = new Foo();

     //Bar bar1 = (Bar)foo1; 
     // 자식 클래스 타입으로 부모 객체를 받음 이거 자체가 오류(문법 오류는 아님)
     // 문법 오류는 아니지만, 런타임 오류가 발생
     // 자식클래스 자료형으로 객체를 보려 하지만, 부모 객체 부분만 있기 때문에
     // 런타임에서 오류가 발생시킴.
     //bar1.methodA(); //문법오류x 성립하지 않음
    // bar1.methodB(); //문법오류x 성립하지 않음

     Bar bar1 = (Bar)foo; 
     // 원래 자식객체를 자식객체로 캐스팅함 자식클래스 타입으로 자식 객체를 받음
     // 힙 영역에는 계속 자식 객체가 있었던 것. 부모객체 자료형으로 있는것을 자료객체로 캐스팅할 때
     // foo변수에 자식객체가 담겨져있는지 부모객체가 담겨져있는지 문법적으로 알수없음
     bar1.methodA();
     bar1.methodB();
 }
}

</code></pre>
</li>
</ul>
<ul>
<li>자식클래스로 부모 클래스를 참조하려 하면 java.lan.ClassCastException 오류 발생</li>
</ul>
<pre><code class="language-java"> public class Main {
     public static void main(String args[]) {
         Foo foo = new Foo();
         Bar bar;

         // bar = (Bar)foo; // error
         if (foo instanceof Bar) { // returns false
             bar = (Bar)foo;
         }
     }
 }</code></pre>
<h3 id="형변환과-오버라이딩-메소드-호출">형변환과 오버라이딩 메소드 호출</h3>
<ul>
<li><p>멤버 변수의 재정의는<code>선언된 객체의 타입</code>을 따른다. (문법적으로 본다) 클래스 변수도 마찬가지 변수는 별도의 메모리에 저장됨.</p>
</li>
<li><p>메소드 오버라이딩은 <code>메모리상의 객체 타입</code>을 따른다. (실제 객체로 본다)</p>
</li>
<li><p>부모 와 자식 클래스가 같은 메소드를 가지고 있을 경우, 부모 타입으로 자식 객체를 생성하게 되면 메소드를 호출할 때 자식 클래스의 메소드로 호출되는 경우를 가상 메소드 호출이라고 한다. (Virtual Method Call)</p>
<pre><code class="language-java">class  Foo{
   static public String y = &quot;super class&quot;;
   public String x = &quot;Super&quot;;
   public  void methodA(){
       System.out.println(&quot;Super method&quot;); 
       // (가상 메소드 호출, virtual method call) 실제로 콜이 이루어지지 않지만 만들어줌 실제로 호출되지않음
       // 없으면 안됨 문법을 맞춰주기 위한 것 뿐 구현된 것 자체는 중요하지 않음..
   }
}

class Bar extends Foo{
   static public String y = &quot;sub class&quot;;
   public String x = &quot;sub&quot;;
   @Override
   public void methodA(){
       System.out.println(&quot;sub method&quot;);
   }
}

public class Poly02 {
   public static void main(String[] args) {
       Bar bar = new Bar();
       Foo foo = (Foo)bar; // new Bar();

       System.out.println(bar.x); //sub
       bar.methodA(); //sub

       System.out.println(foo.x); //super
       foo.methodA(); //sub virtural method call

       System.out.println(Foo.y);
       System.out.println(Bar.y);

//        System.out.println(foo.y); //super
//        System.out.println(bar.y); //sub
   }
}</code></pre>
</li>
<li><p>공변 변환 타입(Covariant return type)</p>
<pre><code class="language-java">class Foo{
  public Foo getInstance(){
      return this;
  }
}
class Bar extends Foo{
  @Override
  public Bar getInstance(){ 
  //오버라이딩이지만, 리턴 타입이 달라질 수 있다. 여기서는 예외적으로 반환값이 달라진다. 공변 반환 타입
      return this;
      //return (Foo)this; 이거와 같다.
  }
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향프로그래밍(OOP)]]></title>
            <link>https://velog.io/@im_joonchul/%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-OOP</link>
            <guid>https://velog.io/@im_joonchul/%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-OOP</guid>
            <pubDate>Sun, 11 Apr 2021 07:05:25 GMT</pubDate>
            <description><![CDATA[<h1 id="객체지향-프로그래밍object-oriented-programming-oop">객체지향 프로그래밍(Object Oriented Programming, OOP)</h1>
<h2 id="객체지향-프로그래밍이란">객체지향 프로그래밍이란?</h2>
<p>컴퓨터 프로그래밍 패러다임 중 하나로, 프로그램을 명령어의 목록으로 보는 시각에서 벗어나, 독립된 단위인 객체의 모임으로 파악하는 것이다. 
각각의 객체는 메세지를 주고받고, 데이터를 처리한다.
프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고,
그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법(객체 간의 협력을 구현)</p>
<p><img src="https://images.velog.io/images/im_joonchul/post/d1747650-04dc-4f75-8d9a-65735e16c3fa/%EA%B0%9D%EC%B2%B4%EA%B7%B8%EB%A6%BC.png" alt="객체간의협력"></p>
<h3 id="객체지향-프로그래밍의-장점">객체지향 프로그래밍의 장점</h3>
<ul>
<li>코드의 재사용성이 용이하다.</li>
<li>유지보수가 쉽다.</li>
<li>대규모 프로젝트에 적합하다.</li>
</ul>
<h3 id="객체지향-프로그래밍의-단점">객체지향 프로그래밍의 단점</h3>
<ul>
<li>처리속도가 상대적으로 느리다.</li>
<li>객체가 많으면 용량이 커질 수 있다.</li>
<li>설계시 많은 시간과 노력이 필요하다.</li>
</ul>
<h2 id="객체지향의-기본-구성-요소">객체지향의 기본 구성 요소</h2>
<ul>
<li><p>클래스(Class)</p>
<ul>
<li>같은 종류의 집단에 속하는 속성과 행위를 정의한 것</li>
<li>클래스는 다른 클래스 또는 외부 요소와 독립적으로 디자인해야 함</li>
</ul>
</li>
<li><p>객체(Object)</p>
<ul>
<li>클래스의 인스턴스로, 실제로 메모리상에 할당된 것</li>
<li>자신 고유의 속성을 가지며, 클래스에 정의된 행위를 수행</li>
<li>ex) 사람, 자동차, 주문, 생산, 관리</li>
</ul>
</li>
<li><p>메소드(Method)</p>
<ul>
<li>클래스로부터 생성된 객체를 사용하는 방법</li>
<li>메소드는 속성(변수)을 변화시키는 데에 사용한다.<ul>
<li>정적 메소드는 정적 변수들을 변화시키고, 인스턴스 메소드는 객체의 속성을 변화시킨다.</li>
</ul>
</li>
<li>꼭 속성을 변화시키는 것은 아니고, 주요 기능이 속성을 변화시키는 것이다.</li>
</ul>
</li>
</ul>
<h2 id="객체지향의-특징">객체지향의 특징</h2>
<ol>
<li><p>추상화(Abstraction)</p>
<ul>
<li>객체지향에서 추상화란 객체에서 공통된 속성과 행위를 추출하는 것을 의미한다.</li>
<li>예를 들어, 자동차의 종류 중에 소나타, 아반떼, 그랜져, 제네시스 등이 있을 때 
이것들을 자동차라는 클래스를 만들어 세부적인 기능들은 다 다르지만, 공통적인 속성과 행위에 대한 개념을 정의한 것이다.</li>
<li>객체를 클래스로 추상적인 개념으로 만드는 것 추상화, 클래스를 객체로 만드는 것이 인스턴스화라고 한다.</li>
</ul>
</li>
<li><p>캡슐화(Encapsulation)</p>
<ul>
<li>캡슐화는 연관 있는 변수와 메소드를 묶어주는 작업을 말한다.</li>
<li>접근 제어자(private)를 통해 외부로부터 접근을 제한하여 객체 내에서만 접근이 가능하도록 하며, 이를 정보은닉이라고 한다.</li>
<li>외부 클래스에서의 직접적인 접근으로 발생하는 변경이나 오류를 막음으로써 보안성이 높아진다.</li>
</ul>
</li>
<li><p>상속(Inheritance)</p>
<ul>
<li>현실에서 부모의 재산이나 특징들을 자식이 이어받는 상속의 개념을 프로그래밍적으로 적용한 개념으로, 
부모 클래스의 속성과 기능을 이어받아 자식 클래스에서 사용할 수 있는 것을 말한다.</li>
<li>코드의 중복성을 줄여주는 역할을 한다.</li>
</ul>
</li>
<li><p>다형성(Polymorphism)</p>
<ul>
<li><p>한 타입의 참조 자료로 여러 타입의 객체를 참조할 수 있도록 하는 것으로, 동일한 변수, 함수명 등이 다양한 형태로 정의되는 것을 말한다.</p>
</li>
<li><p>오버 로딩(Overloading)과 오버 라이딩(Overriding)이라는 형태로 다양하게 기능들을 정의할 수 있다.</p>
</li>
<li><p>오버로딩 : 같은 이름의 메소드 여러 개를 가지면서 매개 변수의 자료형과 개수를 다르게 구현한 것이다.</p>
<pre><code class="language-java"> class Anmimal{
    String name;
    int age;
    public Animal(){
         name = &quot;홍길동&quot;;
         age = 14;
    }
    public Animal(String name, int age){
          this.name = name;
          this.age = age;
    }
 }</code></pre>
</li>
<li><p>오버라이딩 : 부모 클래스가 가지고 있는 메소드를 하위 클래스가 재정의해서 사용하는 것을 말한다.</p>
<pre><code class="language-java"> class Anmimal{
    void move(){
      System.out.println(&quot;동물이 이동합니다&quot;);
    }
 }

 class Cat extends Anmimal{
     @Override
     void move(){
        System.out.println(&quot;고양이가 이동합니다.&quot;);
     }
 }</code></pre>
</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[제어자(Modifier)]]></title>
            <link>https://velog.io/@im_joonchul/%EC%A0%9C%EC%96%B4%EC%9E%90-Modifier</link>
            <guid>https://velog.io/@im_joonchul/%EC%A0%9C%EC%96%B4%EC%9E%90-Modifier</guid>
            <pubDate>Sun, 11 Apr 2021 06:59:45 GMT</pubDate>
            <description><![CDATA[<h1 id="제어자modifier">제어자(Modifier)</h1>
<h2 id="제어자란">제어자란</h2>
<ul>
<li><p>클래스, 변수, 메소드에 부가 기능을 부여하는 키워드</p>
</li>
<li><p>접근 제어자 (Access modifiers)</p>
<ul>
<li>변수, 메소드, 생성자에 대한 접근할 수 있는 범위를 정하는 키워드이다.</li>
<li>자바 파일명과 같은 public class 클래스명이 꼭 있어야 한다.</li>
<li>private – 같은 클래스에서만 사용가능, 내부 구현을 위해서만 사용한다.</li>
<li>default – package라고도 한다 제어자명은 생략하여 쓴다. (제어자명에 package,default를 사용하지 않는다.)<pre><code>       사용범위가 같은 패키지안에서 가능.</code></pre></li>
<li>protected – private와 비슷하게 사용이 되나, 상속한 경우 구현 시 접근이 필요할 때 사용.<pre><code>      자식이면 다른 패키지여도 접근할 수가 있다, 부모의 부모는 건들 수 없다.</code></pre></li>
<li>public – 모든 곳에서 사용가능.</li>
<li>클래스는 public 과 default만 사용 가능하다.</li>
</ul>
</li>
<li><p>그 외 제어자 (Other modifiers)</p>
<ul>
<li>특별한 기능을 부여하는 제어자</li>
<li>static, final, abstract, synchronized</li>
</ul>
</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/55409fec-6993-49d2-a835-dc2cfc739f84/%EC%A0%91%EA%B7%BC%EC%A0%9C%ED%95%9C%EC%9E%90%EC%A0%91%EA%B7%BC%EB%B2%94%EC%9C%84.jpg" alt="접근제어자의 접근범위"></p>
<ul>
<li><p><a href="https://stellan.tistory.com/entry/%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-%EC%A0%91%EA%B7%BC-%EC%A0%9C%ED%95%9C%EC%9E%90">이미지 출처</a></p>
<h3 id="접근-제어자">접근 제어자</h3>
<pre><code class="language-java">package com.company.s04.p05.subp01;
public class ClassA {
  public  int x;
  protected  int y;
  int z; // default (=package)
  private int w;

  public void methodA(){} //
  protected void methodB(){} //
  void methodC(){}//default (=package)
  private void methodD(){} //private - 내부 구현을 위해서만 사용.

  public void methodTest(){ //같은 클래스
      System.out.println(x);
      System.out.println(y);
      System.out.println(z);
      System.out.println(w);

      methodA();
      methodB();
      methodC();
      methodD();
  }
}
</code></pre>
</li>
</ul>
<p>class ClassATest{ // 같은 패키지인 경우.
    public static void main(String[] args) {
        ClassA obj = new ClassA();
        System.out.println(obj.x);
        System.out.println(obj.y);
        System.out.println(obj.z);
        //System.out.println(obj.w); 접근 불가</p>
<pre><code>    obj.methodA();
    obj.methodB();
    obj.methodC();
    //obj.methodD(); private 검색도 안됨
}</code></pre><p>}</p>
<pre><code>* 다른 패키지
````java
package com.company.s04.p05.subp02;
import com.company.s04.p05.subp01.ClassA;

class ClassAA extends ClassA{
    public void methodTest(){
        System.out.println(x);
        System.out.println(y); 
       // protected 자식이면 다른 패키지여도 ok 실제로 많이 씀. 
       // 하나의 자식 외에는 못봄. 부모의 부모는 건들 수 없음.(자바특성)
       // protected는 private처럼 쓰지만, 상속한 경우 구현 시 접근이 필요 할 때 사용.
       // System.out.println(z);
       // System.out.println(w); private - 상속해도 못봄

        methodA();//public
        methodB();//protected
        //methodC();
        //methodD();
    }
}

// public default만 사용 가능, 
// private은 쓸 수 없음 같은 클래스만 볼 수 있기 때문에 다른 클래스라는 개념이 없기 때문에. 
// protected도 사용 불가.
public class ClassB {
    public static void main(String[] args) {
        ClassA obj = new ClassA();
        System.out.println(obj.x); //다됨 public
       // System.out.println(obj.y); //protected 다른 패키지인경우 자식만됨.
        //System.out.println(obj.z); //default 다른 패키지이면 안됨.
        //System.out.println(obj.w); 접근 불가

        obj.methodA();
        //obj.methodB();//protected 다른 패키지인경우 자식만됨.
        //obj.methodC();//default 다른 패키지이면 안됨.
        //obj.methodD(); private 검색도 안됨
    }
}</code></pre><h3 id="public으로-open한거랑-private으로-닫아놓고-public-method를-제공하는것의-차이">public으로 open한거랑 private으로 닫아놓고 public method를 제공하는것의 차이</h3>
<ul>
<li><p>2가지 차이점이 있다</p>
<ol>
<li><p>getter를 할 수 있게하고, setter를 못하게(안하게) 하는 경우가 있다 (ReadOnly만 된다, 값을 넣을 수 없다, ID라던가 값이 변할 수 없는 고유한 값들)</p>
</li>
<li><p>메소드에서 유효한 데이터를 핸들링 할 수 있다.</p>
<ul>
<li><p>boolean isValid 라는 멤버변수를 선언해주고 이것이 true일 때 올바른 날짜가 출력되게 하므로써 제한사항을 줄 수 있다</p>
</li>
<li><p>멤버변수이기 때문에 클래스 전체에서 사용이 가능하므로 (scope,범위가) 메소드에서 값을 변경하게 되면 멤버변수의 값이 변경되기 때문에</p>
<pre><code class="language-java">public class MyDate {
  private int day;
  private int month;
  private int year;

  private boolean isVaild = true;

  public  void setDay(int day){
      this.day = day;
  }
  public int getDay(){
      return day;
  }

  public int getMonth() {
      return month;
  }

  public void setMonth(int month) {
      if(month &lt;1 || month &gt; 12){
          isVaild = false; // 값이 유효범위에 해당하는지 체크를 해준다.
      }
      this.month = month;
  }

  public int getYear() {
      return year;
  }

  public void setYear(int year) {
      this.year = year;
  }

  public void showDate(){
      if (isVaild){
          System.out.println(this.year + &quot;년&quot; + this.month + &quot;월&quot; +this.day+&quot;일&quot;);
      }else{
          System.out.println(&quot;유효하지 않은 범위 입니다.&quot;);
      }

  }

</code></pre>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<pre><code> }</code></pre><pre><code>
### 그 외의 제어자
  * final 
  * 더 이상 바꿀 수 없음을 의미 상수.
  * 클래스, 메소드, 변수에 사용 가능
    * 클래스 : 더 이상 상속이 불가능해진다.
    * 메소드 : 자식 클래스에서 오버라이드 할 수 없다.
    * 멤버 변수 : 변수의 값이 초기화 이후에 변하지 않는다.
    * 생성자에서 초기화가 이루어지는 것을 blank final 변수라 한다.
   ````java
    public class Foo {
        final int x = 0; // final variable
        final int y; // blank finial variable

        public Foo(int y) {
          this.y = y; // blank final variable initialization
      }
    }</code></pre><ul>
<li><p>static</p>
<ul>
<li>클래스 변수, 클래스 메소드 등을 선언하기 위해 사용</li>
<li><code>클래스의</code> 또는 <code>공통적인</code>의 의미를 가지고 있다.</li>
<li>static이 붙은 멤버변수와 메소드, 초기화 블록은 인스턴스를 생성하지 않아도 사용할 수 있다.<ul>
<li>멤버 변수 : 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다, 클래스가 메모리에 로드될 때 생성된다.</li>
<li>메소드 : 인스턴스를 생성하지 않고도 호출이 가능한 static 메소드가 된다, static 메소드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.</li>
</ul>
</li>
</ul>
</li>
<li><p>abstract</p>
<ul>
<li>추상 클래스, 추상 메소드 앞에 붙여지는 제어자이다.</li>
<li>&#39;추상의&#39; 또는 &#39;미완성의&#39; 의미를 가지고 있다.</li>
<li>메소드의 선언부만 작성하고 실제 수행 내용은 구현하지 않는 추상메소드를 선언하는데 사용<ul>
<li>abstract 클래스 : 클래스 내에 추상메서드가 선언되어 있음을 의미한다.(추상메소드가 없어도 된다.)</li>
<li>abstract 메소드 : 선언부만 작성하고 구현부는 작성하지 않는 메소드 &#39;;&#39;으로 끝낸다.</li>
</ul>
</li>
</ul>
</li>
<li><p>synchronized</p>
<ul>
<li>동시성 프로그래밍에 사용.</li>
</ul>
</li>
</ul>
<h3 id="접근제어자를-이용한-정보은닉information-hiding">접근제어자를 이용한 정보은닉(information hiding)</h3>
<ul>
<li>외부에서 클래스 내부의 정보에 접근하지 못하도록 한다, private 키워드를 활용</li>
<li>private 변수를 외부에서 접근하게 하려면 public 메소드 제공한다.
클래스 내부 데이터를 잘못 사용하는 오류를 방지할 수 있다.</li>
</ul>
<h1 id="싱글톤-패턴singletone">싱글톤 패턴(Singletone)</h1>
<ul>
<li>객체가 단 하나만 존재할 수 있는 클래스</li>
<li>private 생성자를 이용한다.</li>
</ul>
<pre><code class="language-java">class SingletonClass {
  private static SingletoneClass instance = new SingletonClass();
  private SingletonClass() {}

  public static SingletonClass getInstance() {
      return instance;
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[인스턴스와힙메모리]]></title>
            <link>https://velog.io/@im_joonchul/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%ED%9E%99%EB%A9%94%EB%AA%A8%EB%A6%AC</link>
            <guid>https://velog.io/@im_joonchul/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%ED%9E%99%EB%A9%94%EB%AA%A8%EB%A6%AC</guid>
            <pubDate>Sun, 11 Apr 2021 06:51:20 GMT</pubDate>
            <description><![CDATA[<h1 id="인스턴스와힙메모리">인스턴스와힙메모리</h1>
<h2 id="인스턴스란">인스턴스란</h2>
<ul>
<li>클래스로부터 생성된 객체</li>
<li>힙 메모리에 멤버 변수의 크기에 따라 메모리가 생성</li>
<li>클래스를 기반으로 new 키워드를 이용하여 여러 개의 인스턴스를 생성</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/978100e5-6a4a-4198-b7af-d05569113145/MemoryStructure1.png" alt="메모리구조"></p>
<ul>
<li>참조변수와 참조 값<ul>
<li><code>ch05.classPart.Student@1ddc4ec2</code>의 주소값은 실제 물리적인 주소값은 아니고
가상 jvm이 준 해시코드 값이다. student가 가리키는 메모리의 위치가 32비트를 나타내는 메모리를 가리킨다<pre><code class="language-java">Student student  = new Student();
System.out.println(student);</code></pre>
</li>
</ul>
</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/e6398727-2697-4a10-aa7e-734337410f7c/%EC%9A%A9%EC%96%B4%EC%A0%95%EB%A6%AC.png" alt=""></p>
<ul>
<li><p>문자열(String) - 한번 만든 문자열은 변하지 않는다. (Immutable) 그래서 새로운 문자열을 만들어서 값을 넣어 주는 것과 같다.</p>
</li>
<li><p>클래스는 문자열과 달리 mutable 변할 수 있다.</p>
</li>
<li><p>참조형 객체이기 때문에 new일때만 새로운 객체를 생성하고, 이렇게 하면 같은 객체를 가리킨다.</p>
</li>
<li><p>이처럼 carThree 에 carOne을 넣었을 때 Three에서 속성 값을 변경시켰을 때 one의 속성값도 변경됨.</p>
<pre><code class="language-java">Car carThree = carOne;

System.out.println(carThree.speed); //carThree.speed = 5;
System.out.println(carThree.speed);// 5
System.out.println(carOne.speed);// 5</code></pre>
</li>
</ul>
<h2 id="메모리-할당-시점">메모리 할당 시점</h2>
<blockquote>
<p>변수가 메모리에 생성될 때는 초기화가 이루어지는 시점인데, 
초기화가 되는 시점은 클래스나 메소드에서 초기화 값을 준다고 해도 메모리에 생성이 되는게 아니다.
변수를 선언하는 것은 메모리를 자료형의 크기만큼 쓰겠다라고 하는 것이다.(메모리에 공간 확보)
변수 초기화는 메모리에 실제 값을 할당 하는 것이다.
메인 메소드안에 있는 변수들은 실행될 때 메모리에 생성됨.
정적 변수 - 클래스가 생성이 될 때 메모리에 할당이 된다.</p>
</blockquote>
<h2 id="클래스와-객체의-메모리-구조">클래스와 객체의 메모리 구조</h2>
<h3 id="메모리-영역">메모리 영역</h3>
<ul>
<li><p>클래스 영역(class area, method area, code area, static area) 클래스의 공통된 부분이 들어감 어떤 필드가 있는지 어떤 타입을 갖는다던지</p>
</li>
<li><p>어떤 메소드가 있고 어떤동작을 하는 코드라던지. 프로그램이 돌아가면 계속 존재함.</p>
<ul>
<li>field 정보, method 정보, type 정보, constant pool</li>
<li>ex) method의 정보라고 하면 접근 제어자와 자료형, 메소드명이 이러한 메소드가 있다, 어떤동작을 한다 라는 정보만 생성이 된다. </li>
</ul>
</li>
<li><p>스택 영역 메소드콜이 이뤄질때 메소드에 의해 이뤄지는 임시적인 영역</p>
<ul>
<li>method 호출 시 선언된 로컬 변수(호출시 임시로 있는 공간 (사라짐))</li>
</ul>
</li>
<li><p>힙 영역 new키워드로 발생함.</p>
<ul>
<li>new 키워드로 생성된 객체</li>
<li>garbage collection이 동작하는 영역 : 더 이상 사용하지 않는 메모리를 알아서 반환하는  jvm의 기능을 의미한다.(GC)</li>
</ul>
</li>
<li><p>클래스와 객체의 메모리 구조 예제</p>
<pre><code class="language-java">public class MemoryStructure { // 클래스 영역
   int x, y; 
   // 힙 영역 객체에 속하기 때문에 객체를 콜할 때는 힙 영역에 들어감. 객체에 속하는 속성들이므로.
   // 클래스가 아니기 때문에 값 자체가 담긴다.(32비트 값을 잡아서 쓰여져있음)

   String string = &quot;String!!&quot;; 
   // 힙영역, 상수풀에도 생성, 애는 상수풀에 생성됨. 클래스를 만드는 클래스는 힙영역에있고 내용은 상수풀에 들어감.

   public void method(int value){ // 클래스 영역에 만들어 짐 (메소드의 정의)
       // int value = &gt; 스택 영역
       char c = &#39;w&#39;; // 스택 영역
   }
   // 대부분의 주소값은 64비트 운영체제가 대부분 64비트이기때문에 거기에 맞춰지는 것.

}</code></pre>
</li>
</ul>
<h2 id="string-타입의-메모리-구조">String 타입의 메모리 구조</h2>
<ul>
<li><p>class, method 같은 것들은 클래스 영역에 만들어지고, 
method 안에 있는 값들은 스택영역에 만들어졌다가 method의 생명주기가 끝나면 사라짐.</p>
</li>
<li><p>class 안에 변수들은 힙영역에 생성이 되는데, 정수, 실수형 변수는 constant pool 안에 정의 되어있는 값들을 가져와서 사용하는 것이고, 
String은 정의할 때 힙 영역에 값이 생성됨.</p>
</li>
<li><p>처음에 young메모리(nursery)에 생성되었다가 오랫동안 사용하면 올드메모리로 옮겨짐.</p>
</li>
<li><p>new로 생성했을 때 기본적으로 young 메모리에 들어간다.</p>
<pre><code class="language-java">@org.junit.Test
public void testStringEquality (){
  final String literal = &quot;Hello&quot;;
  final String object = new String(&quot;Hello&quot;);

  Assert.assertTrue(literal.equals(object));
  Assert.assertFalse(literal == object);
}</code></pre>
</li>
<li><p>위에서 String의 equals은 true, ==는 false가 나오는 경우를 볼 수 있는데,</p>
</li>
<li><p>equals는 <code>문자열</code>을 비교하고, ==는 객체의 <code>주소값</code>을 비교하기 때문이다.</p>
<pre><code class="language-java">@org.junit.Test
public void testStringIntern(){
  final String literal = &quot;Hello&quot;;
  final String object = new String(&quot;Hello&quot;);
  final String intern = literal.intern();

  Assert.assertTrue(literal.equals(object));
  Assert.assertFalse(literal == object);
  Assert.assertTrue(literal.equals(intern));
  Assert.assertTrue(literal == intern);
}</code></pre>
</li>
</ul>
<blockquote>
<p>위의 코드를 보면 intern()메서드를 호출한 결과값을 intern 변수에 할당되는 것을 볼 수 있다. 
 그 후 literal과 object의 동일성(==)과 동등성(equals)를 비교해보면 둘다 true값이 나와 테스트에 성공하게 된다.
 리터럴로 &quot;Hello&quot;라는 문자열이 string constant pool에 저장되었고, 
 inter() 메서드를 호출하면서 string constant pool에서 Hello라는 문자열을 검색하고 
 이미 존재하기 때문에 &quot;Hello&quot; 의 동일한 주소값을 반환하게 되어 true가 나오게 된다.</p>
</blockquote>
<ul>
<li>String을 리터럴로 선언할 경우 내부적으로 String의 intern()메서드가 호출되게 된다. </li>
<li>intern() 메서드는 주어진 문자열이 string constant pool에 존재하는지 검색하고 있다면 그 주소값을 반환 하고, 없다면 string constant pool에 넣고 새로운 주소값을 반환한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[상속(Inheritance)]]></title>
            <link>https://velog.io/@im_joonchul/%EC%83%81%EC%86%8D-Inheritance</link>
            <guid>https://velog.io/@im_joonchul/%EC%83%81%EC%86%8D-Inheritance</guid>
            <pubDate>Sun, 11 Apr 2021 06:35:01 GMT</pubDate>
            <description><![CDATA[<h1 id="상속inheritence">상속(Inheritence)</h1>
<ul>
<li>상속과 다형성을 이해를 잘하면 유지보수하기 쉽고 확장성있는 시스템을 설계할 수 있다.
객체지향의 큰 특징 중 하나이다.</li>
</ul>
<h2 id="상속이란">상속이란</h2>
<ul>
<li>어떤 클래스의 모든 멤버 변수 및 메소드를 계승하여, 새로운 클래스를 생성하는 것</li>
<li>부모 클래스로부터 상속을 받은 자식 클래스는 부모의 것을 다 가지고 자기의 것을 추가로 더 가지고 만들어진다.</li>
<li>상속 관계를 흔히 &#39;IS-A&#39;관계라고 한다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/039d67cf-49c4-47cc-8c54-e81a6c100040/%EC%83%81%EC%86%8D.jpg" alt="상속"></p>
<ul>
<li>상속대상은 조상클래스, 부모클래스, 상위클래스, 슈퍼클래스 라고 한다.</li>
<li>상속결과는 자손클래스, 자식클래스, 하위클래스, 서브클래스 라고 한다.</li>
</ul>
<h3 id="상속을-사용하는-경우">상속을 사용하는 경우</h3>
<ul>
<li><p>상속은 좀 더 일반적인 클래스가 있고 이것보다 좀 더 기능이 구체적인 클래스를 설계 한다.
유사한 클래스를 만드는데 기존의 클래스를 가져다가 좀 더 확장된 클래스를 만들 때 상속을 사용 한다.</p>
<p><img src="https://images.velog.io/images/im_joonchul/post/7bfd4855-10cf-433b-ab57-cd24d66b084c/%EC%83%81%EC%86%8D3.jpg" alt="상속2"></p>
</li>
</ul>
<h3 id="상속에서-접근-제한">상속에서 접근 제한</h3>
<ul>
<li><a href="https://stellan.tistory.com/entry/%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-%EC%A0%91%EA%B7%BC-%EC%A0%9C%ED%95%9C%EC%9E%90">이미지 출처</a></li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/1c920f92-200c-4997-bc96-ba4c03beb46b/%EC%A0%91%EA%B7%BC%EC%A0%9C%ED%95%9C%EC%9E%90%EC%A0%91%EA%B7%BC%EB%B2%94%EC%9C%84.jpg" alt="접근제한자"></p>
<ul>
<li>protected 예약어<ul>
<li>클래스에서 멤버변수나 메소드를 private 예약어로 지정해 놨을 때 외부 클래스에서 접근을 하지 못한다. 
그래서 상속 관계에서도 접근을 못하게 되는데 protected 예약어를 사용하면 상위클래스에 protected로 선언된 변수나 메소드를 
다른 외부 클래스에서는 사용할 수 없게 하고 하위클래스에서 사용이 가능하다. </li>
</ul>
</li>
</ul>
<h3 id="상속에서-클래스-생성-과정과-형변환">상속에서 클래스 생성 과정과 형변환</h3>
<ul>
<li><p>Customer 상위클래스, VIPCustomer 하위클래스  </p>
<p><img src="https://images.velog.io/images/im_joonchul/post/8f50b152-a31e-44f7-b2fd-334399341478/%EC%83%81%EC%86%8D%EB%A9%94%EB%AA%A8%EB%A6%AC.jpg" alt="상속메모리"></p>
</li>
<li><p>하위클래스가 생성되는 과정</p>
<ul>
<li>상위 클래스의 생성자가 호출되고 하위 클래스의 생성자가 호출 된다.</li>
<li>하위 클래스의 생성자에서는 무조건 상위 클래스의 생성자가 먼저 호출되어야 한다.</li>
<li>하위 클래스에서 상위 클래스의 생성자를 호출하는 코드가 없는 경우 
컴파일러는 상위 클래스 기본 생성자를 호출하기 위한 super()를 추가한다.<ul>
<li>super()로 호출되는 생성자는 상위 클래스의 기본 생성자이다.</li>
</ul>
</li>
<li>만약 상위 클래스의 기본 생성자가 없는 경우(매개변수가 있는 생성자만 존재하는 경우) 하위 클래스는 명시적으로 상위 클래스의 생성자를 호출해야 한다.</li>
</ul>
</li>
</ul>
<h3 id="상위-클래스의-묵시적-형-변환업-캐스팅">상위 클래스의 묵시적 형 변환(업 캐스팅)</h3>
<ul>
<li>상위 클래스 형으로 변수를 선언하고 하위 클래스 인스턴스를 생성 할 수 있다.
하위 클래스는 상위 클래스의 타입을 내포하고 있으므로 상위 클래스로 묵시적 형 변환이 가능하다.
상속 관계에서 모든 하위 클래스는 상위 클래스로 묵시적 형 변환이 된다.
그 반대는 성립하지 않는다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/7cb73e76-d407-49d2-8a03-c8d9b19968ca/%ED%98%95%EB%B3%80%ED%99%98.png" alt="형변환"></p>
<ul>
<li>VIPCustomer() 생성자의 호출로 인스턴스는 모두 생성 되었지만,
타입이 Customer이므로 접근 할 수 있는 변수나 메소드는 Customer의 변수와 메소드이다.</li>
</ul>
<h3 id="하위-클래스로-명시적-형-변환다운-캐스팅">하위 클래스로 명시적 형 변환(다운 캐스팅)</h3>
<ul>
<li>묵시적으로 상위 클래스로 형 변환된 인스턴스가 원래 자료형(하위 클래스)으로 반환되어야 할 때
다운 캐스팅이라고 한다.</li>
<li>하위 클래스로의 형 변환은 명시적으로 되어야 한다.</li>
<li>Customer vc = new VIPCustomer() // 묵시적</li>
<li>VIPCustomer vCustomer = (VIPCustomer)vc; //명시적</li>
</ul>
<h2 id="클래스의-관계">클래스의 관계</h2>
<h3 id="클래스의-상속">클래스의 상속</h3>
<ul>
<li><p>부모 클래스</p>
<pre><code class="language-java">class Person{
  String name;
  public void work(){
      System.out.println(&quot;일하기&quot;);
  }
  public void sleep(){
      System.out.println(&quot;잠자기&quot;);
  }
}</code></pre>
</li>
<li><p>자식 클래스</p>
<pre><code class="language-java">// person을 상속하는 자식 클래스 extends 키워드를 이용하여 상속
class Developer extends Person{
  String mainLang;
  public  void  writeCode(){
      System.out.println(&quot;돈 받은 만큼 코딩하기&quot;);
  }
}</code></pre>
<pre><code class="language-java">class Student extends Person{
  String major;

  public void writeCode(){
      System.out.println(&quot;밤새 코딩하기&quot;);
  }
}</code></pre>
<h2 id="클래스의-포함">클래스의 포함</h2>
</li>
<li><p>관계 클래스를 조합해서 클래스를 만든다.</p>
</li>
<li><p>상속하고 유사하지만, 한 클래스가 다른 클래스의 객체를 포함하는 관계</p>
</li>
<li><p>내부에 포함하고 &#39;HAS-A&#39; 관계로 표현된다.</p>
</li>
<li><p>특별히 자바에선 &#39;HAS-A&#39; 관계가 포함된 경우는 많이 없다.</p>
</li>
<li><p>클래스 컴포지션 (Composition)이라 부른다.</p>
<pre><code class="language-java">// 메인머신 &#39;HAS-A&#39; String 이미 스트링을 컴포지션하고 있었다.
class MainMachine{
  String model;
  boolean isBroken = false;

  public MainMachine(String model){
      this.model = model;
  }
}</code></pre>
<pre><code class="language-java">// developer &#39;HAS-A; MainMachine 개발자클래스가 메인머신의 객체 하나를 보유한다.
// 보유하고 있어서 메인머신의 속성을 건드릴 수 있다.
class Developer{
  String name;
  MainMachine mainMachine;

  public Developer(String name,MainMachine machine){
      this.name = name;
      this. mainMachine = machine;
  }

  public void writeCode(){
      if(mainMachine.isBroken) {
          System.out.println(&quot;코딩할 수 없습니다.&quot;);
      }else{
          System.out.println(mainMachine.model+ &quot;으로 코딩하기&quot;);
      }

      if(Math.random() &gt; 0.9){
          breakMachine();
      }
  }

  public void breakMachine(){
      mainMachine.isBroken = true;
  }
}
</code></pre>
</li>
</ul>
<p>MainMachine mac = new MainMachine(&quot;MacBook Pro&quot;);</p>
<pre><code>Developer dev = new Developer(&quot;나개발&quot;,mac); // 메인머신을</code></pre><p>//  dev.mainMachine.model 가능
//  dev.model 불가능.
//  일치하냐 보유하냐의 차이 (상속과 컴포지션의 차이)<br>    for (int i =0; i&lt;10; i++){
       dev.writeCode();
    }</p>
<pre><code>
## 메소드 재정의
### 메소드 재정의(Method Overriding)란?
* Override -&gt; 덮어씌운다, 해킹해서 뭔가 달라지게 한다.
* 기존의 있던걸 덮어씌워서 다른걸로 변형시키는 것
* 다형성 (polymorphism)의 근간이 됩니다.
````java
class Person{
    public void writeCode(){
        System.out.println(&quot;아무 코드나 일단 적어 보았다.&quot;);
    }
}
class Student extends Person{
    @Override // 이렇게 적어주는 것이 관례 필수는 아님(문법 오류는 아님)   @ - 에노테이션
    public void writeCode(){
        System.out.println(&quot;능숙하게 코드를 작성해 보았다.&quot;);
        System.out.println(&quot;답은 틀렸다.&quot;);
        System.out.println(&quot;하지만 무언가 또 배웠다.&quot;);
    }
}

class Developer extends Person{
    @Override // 다양하게 오버라이드 될 수 있음.
    public void writeCode(){
        System.out.println(&quot;코드 작성이 하기 싫어서 하지 않았다.&quot;);
    }
}</code></pre><h3 id="-애노테이션annotation">@ 애노테이션(Annotation)</h3>
<ul>
<li>재정의된 메소드라는 의미로 선언부가 기존의 메소드와 다른 경우 에러가 발생한다.(같게 해줘야 함)</li>
<li>애노테이션은 컴파일러에게 특정한 정보를 제공해주는 역할을 한다<ul>
<li>(컴파일 오류를 막아주고, 컴파일러에게 정보를 전달해줌.)</li>
</ul>
</li>
<li>주로 사용되는 자바에서 제공되는 애노테이션</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/732463a6-b245-4b23-a8b3-1fdc38883e2b/%EC%95%A0%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98.jpg" alt=""></p>
<h3 id="형변환과-오버라이딩-메소드-호출">형변환과 오버라이딩 메소드 호출</h3>
<pre><code class="language-java">Customer vc = new VIPCustomer();
vc.calcPrice(10000);</code></pre>
<p>위 코드에서 <code>calcPrice()</code> 메소드는 어느 메소드에서 호출 될까?
자바에서 항상 인스턴스의 메소드가 호출이 된다. (메모리의 자료형을 따라서 메소드가 호출이된다.)
그 이유는 <code>Virtual method Call</code>이 이루어지기 때문이다.</p>
<h4 id="가상-메소드virtual-method">가상 메소드(Virtual method)</h4>
<ul>
<li>메소드의 이름과 메소드 주소를 가진 메소드 테이블에서 호출될 메소드의 주소를 참조한다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/08b6fbbe-884a-4a45-b4c7-f5437d187f20/%EA%B0%80%EC%83%81%EB%A9%94%EC%86%8C%EB%93%9C.jpg" alt="가상메소드"></p>
<ul>
<li>재정의된 메소드 호출 과정</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/25217105-7925-473e-bd87-b7fb24460b6f/%EC%9E%AC%EC%A0%95%EC%9D%98%EB%90%9C%EB%A9%94%EC%86%8C%EB%93%9C%ED%98%B8%EC%B6%9C.jpg" alt="재정의된메소드호출"></p>
<pre><code class="language-java">public class Customer {
    protected int customerID;
    protected String customerName;
    protected String customerGrade;
    int bonusPoint; // 보너스 포인트
    double bonusRatio; //보너스 포인트 적립 비율

    public Customer(){ //생성자를 기본 초기값으로 설정해주듯이 사용하면 될 것 같다.
        customerGrade = &quot;Silver&quot;;
        bonusRatio = 0.01; //1%로 적립

        System.out.println(&quot;customer 생성자 호출&quot;);
    }

    public Customer(int customerID,String customerName){
        this.customerID = customerID;
        this.customerName = customerName;
        customerGrade = &quot;Silver&quot;;
        bonusRatio = 0.01; //1%로 적립
        System.out.println(&quot;customer 파라미터 생성자 호출&quot;);

    }

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

    public int calcPrice(int price){ //지불할 가격 반환.
        bonusPoint += price * bonusRatio;
        return price;
    }
}</code></pre>
<pre><code class="language-java">Customer customerLee = new Customer(10010,&quot;이순신&quot;);
customerLee.bonusPoint=1000;

VIPCustomer customerKim = new VIPCustomer(10020,&quot;김유신&quot;);
customerKim.bonusPoint = 10000;

int priceLee = customerLee.calcPrice(10000);
int priceKim = customerKim.calcPrice(10000);
System.out.println(customerLee.showCustomerInfo() +&quot;지불금액은 &quot;+priceLee);
//이순신님의 등급은 Silver이며, 적립된 보너스 포인트는 1100점 입니다. 지불금액은 10000

System.out.println(customerKim.showCustomerInfo()+&quot;지불금액은 &quot;+priceKim);
//김유신님의 등급은 VIP이며, 적립된 보너스 포인트는 10500점 입니다. 지불금액은 9000

Customer customerNo = new VIPCustomer(10030,&quot;나몰라&quot;);
customerNo.bonusPoint=10000;
System.out.println(customerNo.showCustomerInfo()+&quot;지불금액은 &quot;+customerNo.calcPrice(10000));
// 나몰라님의 등급은 VIP이며, 적립된 보너스 포인트는 10000점 입니다. 지불금액은 9000
// 지불금액이 예상하기로 10000이 나와야하지만 결과는 9000이나옴 
// 이유는 vipcustomer의 calcPrice()메소드가 호출되었기 때문에 
// 이것을 가상메소드호출이라 한다.</code></pre>
<h3 id="super-키워드">super 키워드</h3>
<ul>
<li>this 가 자신의 객체를 참조하듯, super 는 부모 객체를 참조한다.</li>
<li>다만 super.super 라는 식으로 부모의 부모는 참조할 수 없다. 바로 윗 부모만 가능하다.</li>
<li>자식 객체를 생성을 하면, 부모 객체를 먼저 생성하고, 그 다음에 자식 객체를 생성하게 된다.</li>
<li>자식 객체를 생성할 때마다 부모 객체를 따로따로 만들어서 가지고 있다.</li>
<li>호출할 때 this와 마찬가지로 첫줄에 써야한다.</li>
<li>멤버 변수명이 부모와 겹치면 재정의 하지만, 부모가 사라지는 것은 아니다.</li>
<li>부모클래스에 기본 생성자를 사용하는 경우에는 호출 안해줘도 된다. 파라미터 생성자일 때만
호출해주면 된다.</li>
<li>부모클래스 생성자와 다르게 파라미터 변수명을 해줘야 한다.</li>
<li>자식클래스 생성자를 만들 때 부모 클래스 생성자도 같이 호출해줘야한다.</li>
</ul>
<pre><code class="language-java">class Foo {
    String x = &quot;Foo&quot;;

    public Foo(String x) {
        this.x = x;
    }
}
class Bar extends Foo {
    String x = &quot;Bar&quot;; 
    // 멤버 변수명이 부모와 겹치면 재정의 하지만 부모가 사라지는 것은 아님.

    // 부모클래스에 기본 생성자를 사용하는 경우에는 호출 안해주어도 된다.
    // 부모클래스에 파라미터 생성자가 있으면 호출해 줘야 한다. super 사용.
    public Bar(String x, String x1) { 
    // 부모클래스 생성자와 다르게 파라미터 변수명을 다르게 해줘야 한다. x,x1
        super(x); //this와 마찬가지로 첫줄에 써야한다. 부모클래스 생성자 호출.
        //부모 객체를 먼저 생성하고, 그 다음에 자식 객체를 생성.
        this.x = x1; //자식클래스 생성자를 만들때 부모클래스 생성자도 같이 호출해줘야한다.
    }

    public void method(){
        //로컬변수명과 멤버변수명은 같을 수 있다.
    // String x = &quot;method&quot;; 로컬변수가 없어지면 멤버변수를 참조, 
    // 멤버변수도 없어지면 super클래스의 변수사용.
        System.out.println(x);
        // 로컬변수 -&gt; 멤버변수 -&gt; 부모의 멤버변수 순으로 접근
        System.out.println(this.x); 
        // 자기 자신의 객체에 접근가능 멤버변수 - &gt; 부모의 멤버변수
        System.out.println(super.x); // 부모 객체에 접근 가능 부모의 멤버변수
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[클래스와 객체]]></title>
            <link>https://velog.io/@im_joonchul/%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@im_joonchul/%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Sun, 11 Apr 2021 05:58:48 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스classes와-객체object">클래스(Classes)와 객체(Object)</h1>
<h2 id="클래스-와-객체-개념">클래스 와 객체 개념</h2>
<h3 id="클래스">클래스</h3>
<ul>
<li><p>객체를 만들어내기 위한 설계 혹은 틀 또는 객체를 정의해 놓은 것, 코드로 구현한 것을 말한다.</p>
</li>
<li><p>문자열(String)도 클래스 형태로 클래스는 한 번 만든 문자열은 변하지 않는데(Immutable), 클래스는 변할 수 있다.(mutable)</p>
</li>
<li><p>클래스 이름은 PascalCase로 적는다.</p>
</li>
<li><p>변수(attribute, filed, 멤버변수) 와 메소드(method,함수)로 구성된다.</p>
</li>
<li><p>클래스의 로딩되는 시점 </p>
<ol>
<li><p>객체가 생성이 될 때 - 클래스가 먼저 클래스 영역에 생성이 되고 그 정보를 가지고 객체가 생성이 되는 것이다. 
초기화 블록을 사용해서 확인해보면 확실히 이해가 간다.</p>
</li>
<li><p>import 할 때 - 클래스가 로딩이 되서 클래스 영역에 생성이 된다.</p>
</li>
<li><p>정적 변수를 사용할 때 - 클래스명.정적 변수 형태로 사용이 가능하기 때문에 클래스의 정보가 먼저 있어야 한다. </p>
<pre><code class="language-java">class Car{ 
  int speed = 0; // 속성, 멤버 변수

  void move(){ //  메소드 (method), 멤버 함수
      speed = 10; //행위를 구현, 속성을 변경
  }
}</code></pre>
</li>
</ol>
</li>
</ul>
<h3 id="객체">객체</h3>
<ul>
<li><p>클래스가 구체화하여 값으로 생성된 것(실체화 된 것) 클래스의 인스턴스라고도 부른다.</p>
</li>
<li><p>하나의 클래스로 여러 개의 객체들을 생성할 수 있다. 같은 타입의 <code>독립적인</code> 객체가 된다.</p>
</li>
<li><p>new 키워드로 생성된 객체는 힙 영역에 생성이 된다.</p>
</li>
<li><p>new 키워드로 생성된 객체는 객체의 주소를 리턴하도록 되어있다.</p>
<pre><code class="language-java"> Car carOne = new Car(); // new 키워드로 클래스에서 객체 생성
 System.out.println(carOne.speed); // 객체명.으로 속성 접근 가능
 carOne.move(); // 메소드 호출(method call) 이라고 부름.
 System.out.println(carOne.speed);

 Car carTwo = new Car();
 System.out.println(carTwo.speed); // speed=0 독립적인 객체를 의미.

 // STRING은 Immutable이기 때문에 값이 변하지 않지만,
 // 클래스는 대부분 muttable이기 때문에 객체 참조에 대한 문제가 발생한다. 중요**

 Car carThree = carOne; 
 // 참조형 객체이기 때문에 new일때만 새로운 객체를 생성하고,
 // 이렇게하면 같은 객체를 가리킨다.
 System.out.println(carThree.speed);
 carThree.speed = 5;
 System.out.println(carThree.speed);// 5
 System.out.println(carOne.speed); // 5</code></pre>
</li>
</ul>
<h2 id="클래스의-구성요소">클래스의 구성요소</h2>
<h3 id="필드속성-멤버-변수">필드(속성, 멤버 변수)</h3>
<ul>
<li>필드는 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳이다.</li>
<li>필드는 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 객체와 함께 존재한다.</li>
</ul>
<h3 id="메소드">메소드</h3>
<ul>
<li>메소드는 객체의 동작을 담당한다. 메소드를 호출하면 중괄호 내의 코드들이 일괄적으로 실행된다.</li>
<li>메소드는 객체 간의 데이터 전달의 수단으로 사용되며, 외부로부터 매개 값을 받을 수도 있고, 실행 후 어떤 값을 리턴할 수도 있다.</li>
</ul>
<h3 id="생성자">생성자</h3>
<ul>
<li>객체 생성시에 초기화를 담당하는 역할을 하고, 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 한다.</li>
<li>생성자는 메소드와 비슷하게 생겼지만, 클래스 이름으로 되어 있고 리턴 타입이 없다.</li>
</ul>
<h2 id="애노테이션annotation">애노테이션(Annotation)</h2>
<ul>
<li>재정의된 메소드라는 의미로 선언부가 기존의 메소드와 다른 경우 에러가 발생한다.(같게 해줘야 함)</li>
<li>애노테이션은 컴파일러에게 특정한 정보를 제공해주는 역할을 한다.</li>
<li>컴파일 오류를 막아 주고, 컴파일러에게 정보를 전달해 준다.</li>
<li>주로 사용되는 자바에서 제공되는 애노테이션</li>
</ul>
<table>
<thead>
<tr>
<th>애노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>@Override</td>
<td>재정의된 메소드라는 정보 제공</td>
</tr>
<tr>
<td>@FuctionalInterface</td>
<td>함수형 인터페이스라는 정보 제공</td>
</tr>
<tr>
<td>@Deprecated</td>
<td>이후 버전에서 사용되지 않을 수 있는 변수, 메서드에 사용됨</td>
</tr>
<tr>
<td>@SupperessWarnings</td>
<td>특정 경고가 나타나지 않도록 함 ex) @SupperessWarnings(&quot;deprecations&quot;)는 @Depreacted가 나타나지 않도록 함.</td>
</tr>
</tbody></table>
<h2 id="getter와-setter">Getter와 Setter</h2>
<ul>
<li><p>클래스의 멤버 변수를 간접적으로 다룰 수 있게 하는 메소드</p>
</li>
<li><p>멤버 변수의 캡슐화를 구현하기 위해 사용. -&gt; 정보은닉 / 보호</p>
</li>
<li><p>멤버 변수의 값을 제한해야 할 때 유용.</p>
<pre><code class="language-java">public class Main {
   int x,y;

   // 멤버변수를 만들어야 생성가능.
   public int getX() { 
   // 경우에 따라 구현되지 않을 수 있다. 출력하지 않으면 사용 안하는 것.
       return x;
   }

   // 들어오는 값에 대해 조건을 걸 수 있다.
   public void setX(int x) {
       if(x &gt; 0 &amp;&amp; x &lt;= 1000){
           this.x = x;
       }else{
           System.out.println(&quot;x should be 1 &lt; x &lt;= 1000!&quot;);
           System.out.println(&quot;however, you put in x = &quot;+x);
       }
       this.x = x;
   }

   public int getY() {
       return y;
   }

   public void setY(int y) {
       this.y = y;
   }
}

class MainTest{
   public static void main(String[] args) {
       Main m = new Main();
       m.x=10; // x에 private를 넣으면 직접 값을 변경할 수 없음.
       System.out.println(m.x);

       m.setX(20);
       System.out.println(m.getX()); //권장된 처리 방식.

       m.x = 20; // 권장하지 않는 멤버 변수 처리 방식

       m.setX(11111);
       System.out.println(m.getX());
   }
}</code></pre>
</li>
</ul>
<h2 id="초기화-블록initializer">초기화 블록(Initializer)</h2>
<ul>
<li><p>클래스 또는 인스턴스를 생성할 때 단 한번 실행되는 코드 블록</p>
<pre><code class="language-java">public class Main {
 static int classVar;
 static  int instanceCount;
 int instanceVar;

 // static initializer
 static { // 객체가 생성되지 않은 상태 객체에서 접근 불가
     System.out.println(&quot;static block1&quot;);
     classVar = 20;
 }
 // object initialzer 객체를 만들어서 접근.
 {
   System.out.println(&quot;block1&quot;);
   instanceVar = 30;
   classVar = 50; 
   // 추천되지 않는다. 
   // 객체를 생성하는데 클래스에 대해 변하는것은 권장하지 않음.
   instanceCount++; // 이러한 패턴은 사용된다.
 }
// 여러개 사용 가능. 스태틱은 스태틱끼리 출력되고, 값은 나중에 선언된 값이 삽입됨.
 static {
     System.out.println(&quot;static block2&quot;);
     classVar = 5;
 }
 {
     System.out.println(&quot;block2&quot;);
     instanceVar = 5;
 }
}

class MainTest{
 public static void main(String[] args) {
     System.out.println(Main.classVar);
     Main m = new Main();
     System.out.println(Main.instanceCount
     System.out.println(m.instanceVar);
     System.out.println(Main.classVar);

     Main m2 = new Main();
     System.out.println(Main.instanceCount);

     Main m3 = new Main();
     System.out.println(Main.instanceCount
  }
}  </code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Wrapper Class]]></title>
            <link>https://velog.io/@im_joonchul/Wrapper-Class-3lwmg5m8</link>
            <guid>https://velog.io/@im_joonchul/Wrapper-Class-3lwmg5m8</guid>
            <pubDate>Sun, 14 Mar 2021 07:16:29 GMT</pubDate>
            <description><![CDATA[<h1 id="wrapper-클래스wrapper-class">Wrapper 클래스(Wrapper Class)</h1>
<h2 id="wrapper-class란">Wrapper Class란</h2>
<ul>
<li>기본형 타입을 객체로 쓰기 위해 있은 클래스</li>
<li>기본형 타입이 허용되지 않는 문법에 기본형 타입을 쓰기 위해서 제공 하는 클래스</li>
</ul>
<h2 id="wrapper-class의-종류">Wrapper Class의 종류</h2>
<table>
<thead>
<tr>
<th align="center">기본형</th>
<th align="center">WrapperClass</th>
</tr>
</thead>
<tbody><tr>
<td align="center">byte</td>
<td align="center">Byte</td>
</tr>
<tr>
<td align="center">char</td>
<td align="center">Character</td>
</tr>
<tr>
<td align="center">short</td>
<td align="center">Short</td>
</tr>
<tr>
<td align="center">int</td>
<td align="center">Integer</td>
</tr>
<tr>
<td align="center">flaot</td>
<td align="center">Float</td>
</tr>
<tr>
<td align="center">double</td>
<td align="center">Double</td>
</tr>
<tr>
<td align="center">boolean</td>
<td align="center">Boolean</td>
</tr>
</tbody></table>
<h2 id="wrapper-객체-생성">Wrapper 객체 생성</h2>
<ul>
<li>생성자를 이용한 객체 생성<pre><code class="language-java">Integer integer = new Integer(10);
Character character = new Character(&#39;v&#39;);</code></pre>
</li>
<li>valueOf를 이용한 객체 생성<pre><code class="language-java">Integer integer1 = Integer.valueOf(10);
Character character1 = Character.valueOf(&#39;v&#39;);</code></pre>
<h2 id="autoboxing--unboxing">Autoboxing &amp; Unboxing</h2>
</li>
<li>기본형을 객체로 사용할 수 있게 하는 것을 - &gt; Autoboxing</li>
<li>객체를 기본형으로 바꾸는 것을 -&gt; Unboxing</li>
</ul>
<h3 id="autoboxing">Autoboxing</h3>
<ul>
<li><p>Java1.5부터 추가된 기능으로, 객체로 다루어야 할 때 자동으로 Wrapper 클래스로 변경하는 기능</p>
<pre><code class="language-java">public static &lt;T&gt; T bypass (T x){
  return x;
}

Integer integer2 = 4;
System.out.println(add(4,2));
bypass(5); // 원래는 프리미티브 타입을t에 넣을 수 없는데 autoboxing이 이뤄져서 가능.
// T: wrapper class인 integer로 결정됨
// 5 -&gt; new Integer(5) autoboxing 1.5버전 이후로 가능해짐.</code></pre>
<h3 id="unboxing">Unboxing</h3>
</li>
<li><p>Wrapper 객체를 기본형으로 자동으로 변경하는 기능</p>
<pre><code class="language-java">int m = new Integer(10); 

int i = 10;
Integer wrapped = i;
int b = 20 + wrapped;</code></pre>
</li>
</ul>
<h2 id="wrapper-타입의-값-비교">Wrapper 타입의 값 비교</h2>
<ul>
<li>Wrapper 타입은 객체이므로, ==를 이용하여 값을 비교할 수 없다.<pre><code class="language-java">Integer intOne = new Integer(100);
Integer intTwo = new Integer(100);
</code></pre>
</li>
</ul>
<p>System.out.println(intOne == intTwo); // false
System.out.println(intOne.equals(intTwo)) // true
System.out.println(intOne == 100) // true (Unboxing)</p>
<pre><code>
## 문자열의 기본 자료형 반환
* Parsing 정적 메소드를 이용한 반환
````java
int x = Integer.parseInt(&quot;100&quot;);
long y = Long.parseLong(&quot;512345124&quot;);</code></pre><ul>
<li>Wrapper 객체로의 반환<pre><code class="language-java">Integer intObj = Integer.valueOf(&quot;1000&quot;);
Integer intObjTwo = new Integer(&quot;1234&quot;);</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Variable]]></title>
            <link>https://velog.io/@im_joonchul/Variable</link>
            <guid>https://velog.io/@im_joonchul/Variable</guid>
            <pubDate>Sun, 14 Mar 2021 07:15:14 GMT</pubDate>
            <description><![CDATA[<h1 id="변수-variable필드-속성-멤버-변수">변수 (Variable,필드, 속성, 멤버 변수)</h1>
<ul>
<li>변수의 자료형은 기본 자료형, 참조 자료형으로 나눠진다.<ul>
<li>변수에 대한 생성은 생성자에서 주로하는데 사용하기 전에만 하면 된다.<br>생성하기 전 상태에서 값을 넣으면 NullPointException이 발생할 수 밖에 없다.<br>메모리가 없는데 값을 넣으면 에러가 날 수 밖에 없다.</li>
</ul>
</li>
</ul>
<p>선언된 위치에 따라 구분되는 변수는 생성 및 소멸 시기, 저장되는 메모리 공간과 사용 방법까지 서로 다르다.</p>
<table>
<thead>
<tr>
<th>변수</th>
<th>생성 시기</th>
<th>소멸 시기</th>
<th>저장 메모리</th>
<th>사용 방법</th>
</tr>
</thead>
<tbody><tr>
<td>클래스 변수</td>
<td>클래스가 메모리에 올라갈 때(클래스가 사용이 될 때)</td>
<td>프로그램이 종료될 때</td>
<td>메소드 영역</td>
<td>클래스 이름, 변수 이름</td>
</tr>
<tr>
<td>인스턴스 변수</td>
<td>인스턴스가 생성될 때</td>
<td>인스턴스가 소멸할 때</td>
<td>힙 영역</td>
<td>인스턴스 이름, 변수 이름</td>
</tr>
<tr>
<td>지역 변수</td>
<td>블록 내에서 변수의 선언문이 실행될 때</td>
<td>블록을 벗어날 때</td>
<td>스택 영역</td>
<td>변수 이름</td>
</tr>
</tbody></table>
<pre><code class="language-java">public class Variables{
   int instanceVar; // 인스턴스 멤버 변수
   static int classVar; // 클래스 멤버 변수

   public void method(int parameterVar){ //파라미터 변수
         int localVar = 0; //로컬 변수
   }
}</code></pre>
<h2 id="클래스-멤버-변수static-variable-class-variable">클래스 멤버 변수(static variable, class variable)</h2>
<ul>
<li>처음 프로그래밍에 로드될 때 클래스 영역에 생긴다, 메모리에 할당된다.</li>
<li>static을 이용하여 정의하는 변수, 클래스에서 바로 접근이 가능한 변수를 의미한다.</li>
<li>인스턴스(객체)들이 공통으로 사용하는 변수, 외부에서 접근하지 못하게 접근제어자를 private을 사용하는 것이 좋다.</li>
<li>초기화를 해주지 않았을 경우, 자동으로 자료형의 기본값으로 초기화가 된다.(static int num; 이라 했을 때 static int num = 0;과 같음)   </li>
<li>객체명으로도 접근이 가능하지만 권장하지 않는다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/0af58fa5-2100-41f0-b73d-01c3515d6aef/static%20%EB%B3%80%EC%88%98.png" alt="static변수"></p>
<ul>
<li><p>모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다, 클래스가 메모리에 로드될 때 생성된다.</p>
</li>
<li><p>처음 프로그램이 로드될 때 데이터 영역(static 영역, 클래스 영역)에 생성이 된다.</p>
</li>
<li><p>인스턴스의 생성과 상관 없이 사용할 수 있으므로 클래스 이름으로 참조한다.(ex- 클래스명.static변수명,Student.name = &quot;홍길동&quot;)</p>
<pre><code class="language-java">       static int classVar; 

       System.out.println(&quot;클래스 변수&quot;);
       System.out.println(Variable.classVar); // 0으로 초기화가 된다. </code></pre>
<h2 id="인스턴스-멤버-변수">인스턴스 멤버 변수</h2>
</li>
<li><p>객체를 생성해서 사용하는 변수로 클래스명으로 접근이 불가능하다.   </p>
</li>
<li><p>초기화를 해주지 않았을 경우, 자동으로 자료형의 기본값으로 초기화가 된다.</p>
<pre><code class="language-java">      int instanceVar; // 인스턴스 멤버 변수, 필드, 속성
      System.out.println(&quot;인스턴스 멤버 변수&quot;);
      Variable var = new Variable();
      // 인스턴스를 만들어야 실체가 있기 때문에
      System.out.println(var.instanceVar);  
      //0으로 초기화가 됨.외워야됨.</code></pre>
</li>
<li><p>각 자료형의 초기화값</p>
<table>
<thead>
<tr>
<th>변수의 타입</th>
<th>초기값</th>
</tr>
</thead>
<tbody><tr>
<td>char</td>
<td>&#39;\u0000&#39;</td>
</tr>
<tr>
<td>byte,short,int</td>
<td>0</td>
</tr>
<tr>
<td>long</td>
<td>0L</td>
</tr>
<tr>
<td>float</td>
<td>0.0f</td>
</tr>
<tr>
<td>double</td>
<td>0.0</td>
</tr>
<tr>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>배열,인스턴스 등</td>
<td>null</td>
</tr>
<tr>
<td>### 클래스 변수와 인스턴스 변수</td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/d2c568a3-b458-4bc7-b04b-78d87a6e0b67/static%EB%B3%80%EC%88%98%EC%99%80%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4%EB%B3%80%EC%88%98.png" alt="static변수와인스턴스변수"></p>
<ul>
<li>각각의 객체들은 데이터 영역에 위치한 동일한 메모리를 참조한다.</li>
</ul>
<h2 id="로컬-변수">로컬 변수</h2>
<ul>
<li>메소드 또는 중괄호 블록 내부에서 생성되는 변수</li>
<li>스택 영역에 생성되며, 초기화가 자동으로 이루어지지 않는다.</li>
<li>생명 주기(Life cycle)은 생성된 중괄호 블록이 종료될 때 까지이다.</li>
</ul>
<h2 id="파라미터-변수">파라미터 변수</h2>
<ul>
<li>메소드에서 값을 호출할 때 넣어 주는 변수. 메소드 내부에서만 사용 가능.</li>
</ul>
<pre><code class="language-java">    public void method(int paramVar){ //로컬 파라미터 변수
    System.out.println(paramVar);
    int localVar; //로컬 변수
    System.out.println(localVar); //error 로컬변수는 초기화가 자동으로 안됨. 
    localVar = 10;
    System.out.println(localVar); //이렇게 값을 대입해서 사용해야 한다.
    {
      localVar = 30;
    }
    int localVar2 = 20;
    }
    System.out.println(localVar); //블록 내에서 수정한 것도 반영됨.     
    localVar2 = 40; // 접근 불가. 생명주기가 끝났다. Life-Cycle이 끝났다.</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[UnitTest And TDD]]></title>
            <link>https://velog.io/@im_joonchul/UnitTest-And-TDD</link>
            <guid>https://velog.io/@im_joonchul/UnitTest-And-TDD</guid>
            <pubDate>Sun, 14 Mar 2021 06:57:00 GMT</pubDate>
            <description><![CDATA[<h1 id="unittest">UnitTest</h1>
<h2 id="유닛-테스트unit-test">유닛 테스트(Unit Test)</h2>
<ul>
<li>단위 테스트라고도 불리며, 최소 단위의 테스트를 말한다.</li>
<li>최소 단위는 메소드 단위를 말하는데 어느 정도의 객체 단위라는 것을 포함하고 있다.<ul>
<li>객체 단위를 포함하고 있다는 의미는 메소드는 객체의 속성을 변화시키는 side-effect를 가지고 있기 때문이다.</li>
</ul>
</li>
<li>환경 셋업과 환경 정리를 반드시 같이 해줘야 한다.</li>
</ul>
<h3 id="통합-테스트integration-test">통합 테스트(Integration Test)</h3>
<ul>
<li>유닛 테스트는 가장 작은 단위로 테스트를 하고 통합 테스트는 시스템 전체적인 테스트를 진행한다.</li>
<li>전체 시스템의 동작을 확인하는 테스트 <ul>
<li>내가 작업한 것을 git에 merge해서 전체 시스템이 잘 동작하는지 체크한다.</li>
</ul>
</li>
</ul>
<h3 id="기존-임시적인-테스트-방식">기존 임시적인 테스트 방식</h3>
<ul>
<li><p>임시적인 테스트의 문제점!</p>
<ul>
<li><p>여러 개의 테스트를 작성하기 어렵고, 여러 개의 테스트를 넣어야 하는데 테스트 내용의 구분이 안간다.</p>
</li>
<li><p>여러가지 테스트를 할 때 &#39;부작용(side-effect)&#39;이 발생하기 쉽다.</p>
<ul>
<li>밑의 Test2 처럼 Test1의 결과에 영향을 받아서 기대했던 값이 아닌 다른 값이 출력되는 등의 부작용이 발생한다.</li>
</ul>
</li>
<li><p>테스트 결과가 성공적인지 여부를 파악하기 어렵다</p>
<ul>
<li>일일이 예상 값을 두고 눈으로 파악해야 하는데, 실제로 테스트를 할 때는 수천 개가 넘는 테스트를 눈으로 파악하기 어렵다.</li>
</ul>
</li>
<li><p>Production 코드와 Test 코드가 섞이게 된다.</p>
<pre><code class="language-java">public class ScoreCollection {
private final List&lt;Scorable&gt; scoreList = new ArrayList&lt;&gt;();

public void add(Scorable item){
   scoreList.add(item);

}
public int arithmeticMean(){
   int total = scoreList.stream().mapToInt(Scorable::getScore).sum();
   return total / scoreList.size();
}
}
</code></pre>
</li>
</ul>
</li>
</ul>
<p>class Main{
    public static void main(String[] args) {
        ScoreCollection collection = new ScoreCollection();
        // Test1. 5와 7의 평균 6
        collection.add(() -&gt; 5);
        collection.add(() -&gt; 7);
        System.out.println(collection.arithmeticMean());
        // Test2. 10 20 의 평균 15
        // 그런데 Test1의 영향을 받아서 원하는 테스트 출력을 얻지 못했다.
        // Test1과 Test2의 순서가 달라지면, 또 결과가 달라진다.
        collection = new ScoreCollection(); // 초기화해서 원하는 값을 얻을 수 있다.
        collection.add(() -&gt; 10);
        collection.add(() -&gt; 20);
        System.out.println(collection.arithmeticMean());</p>
<pre><code>}</code></pre><p>}</p>
<pre><code>
## JUnit
* 위의 임시적인 테스트 방법의 문제점을 해결하기 위한 테스트 프레임워크가 있다.
* 인텔리제이, 이클립스에도 다 포함되어 있는 프레임워크로, Production 코드와 Test 코드를 분리하여 테스트 할 수 있다.

* JUnit 설정방법!
  * 왼쪽 상단에 file -&gt; Project Structure -&gt; moudles에 간다.
  * 테스트를 만들 디렉토리 선택하면 그 디렉토리의 하위 디렉토리들이 나오는데 Test할 디렉토리를 선택하고
  Mark as 부분에 Test를 클릭 해주면 테스트 폴더로 변화한다.
  * 원래 Production 코드의 화면에서 마우스 우클릭을 해서 Generate -&gt; Test를 누르고 확인을 누르면 테스트 클래스로 자동으로 만들어준다.

### JUnit을 사용한 테스트 1번
* Test라는 Annotation을 달아줘서 테스트라는걸 인식하게 하고 assert에 값을 넣어줘서 기대값에 맞는지 테스트한다.
* assert 반드시 이렇다 단언하는 것, 결과가 같다고 해주는 것
```java
package com.company.p01;

import org.junit.Test;

import static org.junit.Assert.*;

public class ScoreCollectionTest {
    @Test
    public void arithmeticMeanOfFiveAndSevenResultsInSIx(){
        ScoreCollection collection = new ScoreCollection();
        collection.add(() -&gt; 5);
        collection.add(() -&gt; 7);
        int actualResult = collection.arithmeticMean();
        assertEquals(6,actualResult);

    }
    @Test
    public void arithmeticMeanOfTenAndTwentyResultsInFifteen(){
        ScoreCollection collection = new ScoreCollection();
        collection.add(() -&gt; 10);
        collection.add(() -&gt; 20);
        int actualResult = collection.arithmeticMean();
        assertEquals(15,actualResult);
    }
}</code></pre><h3 id="pojo">POJO</h3>
<ul>
<li>POJO : Plain Old Java Object 자바 클래스를 의미하는 것인데 클래스 파일 하나가 이런 자바만으로 이루어진 파일이 있을 수 있고 스프링이 묻어 있는 애들이 있을 수 있어서 순수 자바만 이용된걸 포조라고 부른다.<ul>
<li>이렇게 불러야 사람들이 그럴듯해 보여서 자바 클래스를 쓰는 것이다.</li>
<li>프로그래밍 언어들은 사람들의 인지적인 관점을 적용하려 애쓴다. 그래서 이러한 용어들을 만들어내고 하는 것이다. 어이없지만 생각보다 중요한 것들이다.</li>
<li>실무에서 사용하는 언어이다 어떤 것인지 알고 있으면 될 것 같다!</li>
</ul>
</li>
</ul>
<h3 id="junit을-사용한-테스트-2번">JUnit을 사용한 테스트 2번</h3>
<h4 id="aaa-triple-a">AAA (Triple-A)</h4>
<ul>
<li>Arrange(준비) - 테스트를 하기 위해서 시스템이 적절한 상태에 있는지 확인,<ul>
<li>객체 생성, 객체와의 소통, API 호출</li>
</ul>
</li>
<li>Act (실행) - 실제로 테스트 코드를 실행하는 과정</li>
<li>Assert (단언) - 실행한 코드의 결과를 기대하는 값과 비교</li>
<li><code>+@</code> After (사후) - 중간 과정에서 자원을 할당한 경우에는 이를 해제 특수한 경우에만 사용.</li>
</ul>
<pre><code class="language-java">package com.company.p02;

public class Account {
    private  int balance;

    public Account(int balance) {
        this.balance = balance;
    }

    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    public void withdraw(int value){
        balance -= value;
    }

    public void deposit(int value){
        balance += value;
    }

    public boolean isMinus(){
        return balance &lt; 0;
    }

    public void throwExcept(){
        throw new ArithmeticException();
    }
}</code></pre>
<ul>
<li>실행 순서<ul>
<li>before -&gt; test1 -&gt; before -&gt; test2</li>
<li>beforeClass -&gt; before -&gt; Test1 -&gt;(After) -&gt; before -&gt; test2 -&gt; (After) -&gt; (AfterClass)</li>
</ul>
</li>
<li><code>import static org.hamcrest.CoreMatchers.*</code> - EqualTo 이런 메소드들을 사용할 수 있게 import 해줘야한다.</li>
<li><code>@Ignore(&quot;This will be tested later&quot;)</code> - 테스트를 무시한 채 다른 테스트를 하는것 테스트를 안할 것을 따로 빼놀 때 사용.</li>
<li><code>fail()</code> - 익셉션이 발생하지 않아도 통과되서 익셉션이 발생하지 않은 경우에 강제로 fail 시켜버리는 것이다</li>
<li><code>assertThat(actualResult,equalTo(true));</code><ul>
<li>기대값과 출력하려고 하는 값에 대한 정보를 표현할 수 있다. (확인할 수 있음)</li>
<li>단, 실패했을 때 정보를 잘 표현하기 위해서는</li>
<li>hamcrest의 CoreMatchers에 구현된 Matcher를 쓰는 것이 좋다.<pre><code class="language-java">package com.company.p02;
</code></pre>
</li>
</ul>
</li>
</ul>
<p>import org.junit.*;
import org.junit.rules.ExpectedException;</p>
<p>import static org.hamcrest.CoreMatchers.*;</p>
<p>import static org.junit.Assert.*;</p>
<p>public class AccountTest {
    private Account account;</p>
<pre><code>@BeforeClass
public static void classSetUp(){ 
// static으로 만들어야한다 맨 처음 한번 실행 오래되고 
// 딱 한번만 하면 되는 것들 여기다 작성

}

@Before
public void setUpBySetBalanceOneHundred(){ 
//setUp()메소드라고 부른다.
    account = new Account(100); // 1. Arrange
// 각 테스트를 실행할 때마다 매번 다시 실행된다. 초기화가 된다는 의미인듯
}
@Test
public void answerIsMinusWithNegativeBalance(){
// 어렌지와 액트를 구분해줄 필요가 있다 구분하지 않을 때 
// 테스트에 어렌지를 다 구현해줘야하는 문제가 생긴다 그래서 따로 만들어 줄 수있다.
// setUp() 메소드를 만든다.</code></pre><p>//        Account account = new Account(100); // 1. Arrange</p>
<pre><code>    account.withdraw(150); // 2. Act
    boolean actualResult = account.isMinus();
    // boolean에 대한 assertion은 assertTure, assertFalse를 쓰면 좋다.</code></pre><p>//        assertFalse(actualResult);
        // 이건 실패 성공에 대한 것만 나오고 내용이 나오지 않는데 
        // assertThat()은 틀렸을 때 정보를 볼 수 있음
        // assertTure, False가 있다.</p>
<pre><code>    assertThat(actualResult,is(equalTo(true))); // 3. Assert
    // 인지적으로 일기 좋게 actualResult is equalTo false로 문장처럼 읽히게 해준다.

    assertThat(actualResult,not(equalTo(false))); // is &lt;-&gt; not
    // not에 경우엔 not일 때 동작을 하게 된다. 이때 테스트가 통과됨.
}
@Test
public void answerIsNotMinusWithPositiveBalance(){
    account.withdraw(50);
    boolean actualResult = account.isMinus();

    assertThat(actualResult,is(not(equalTo(true))));
}

// 가능하면 모든 메소드르 테스트하되 우선순위를 정해서 하는 것이 좋다.

@Test
public void checkPositiveBalanceAfterWithdrawal(){
    account.withdraw(80);
    int actualResult = account.getBalance();
    assertThat(actualResult,is(equalTo(20)));
}

@Test
@Ignore(&quot;This will be tested later&quot;) 
// 테스트를 무시한 채 다른 테스트를 하는것 테스트를 안할 것을 따로 빼놀 때 사용, 
// 이것을 남겨두고 커밋하지마세요
// 임시로만 사용해야 한다.
public void checkNegativeBalanceAfterWithdrawal(){
    account.withdraw(130);
    int actualResult = account.getBalance();
    assertThat(actualResult,is(equalTo(20)));
}

// ArithmeticException이 발생하는지 assert하는 테스트

// 간단하다는 장점이 있지만, 인지적으로는 별로 좋지 않음 
// 테스트 메소드 내부에 assert가 드러나지 않는다.
@Test(expected = ArithmeticException.class) 
// ArithmeticException을 넣어줘서 ArithmeticException인지 확인
public void checkExceptionByAnnotation(){
    account.throwExcept();
}

// 인지적으로 더 개선되나, 코드가 매우 복잡해진다.
@Test
public void checkExceptionByTryCatch(){
    try{</code></pre><p>//            account.throwExcept();
            fail(); 
            // 익셉션이 발생하지 않아도 통과되서 익셉션이 발생하지 않은 경우에 강제로 fail시켜버리는 것이다
        } catch (ArithmeticException e){
            assertThat(e.getClass(), equalTo(ArithmeticException.class));
//  아리스메틱 클래스의 클래스 클래스(클래스의 정보를 가지고 있는)를 가져온다. 
//  그래서 그것이 맞는지 비교.
//            e.getClass() == ArithmeticException.class
        }
    }</p>
<pre><code>// Rule을 이용하면 메소드 코드에 excepted exception이 드러나서
// 인지적으로 개선 가장 추천함.
@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void checkExceptionByRule(){
    thrown.expect(ArithmeticException.class); 
    // ArithmeticException을 기대한다고 써놔서 인지적으로 더 잘 이해가능
    // 이렇게 해줬을 때 프레임워크에 가서 이 익셉션이 
    // 프레임워크에 올라가서 메소드가 동작할 때 익셉션이 발생했을 때 캐치해준다.
    account.throwExcept();
}</code></pre><p>}</p>
<pre><code>
### 좋은 테스트의 조건(FIRST)
#### Fast
* 전형적인 자바 시스템의 테스트 케이스는 수천 단위 (유닛테스트 기준)
* 평균 200ms가 걸린다 했을 때 (느린 경우를 예로), 5000개를 수행한다 했을 때  16분이 소요된다.
   * 우리가 코드를 1번 수행할 때 마다 매번 16분의 테스트를 수행해야 한다.(굉장히 안좋음)
   * 메소드에 테스트용 우회 코드를 넣거나, stub 객체를 활용

#### Isolated : 고립된
* 테스트는 순서와 시간에 영향을 받지 않아야 한다.
* 고립되지 않은 테스트는 실패했을 때 원인을 찾기 어렵다.(고립되지 않은 경우를 다봐야하므로 어렵다 후폭풍이 엄청난다 외부환경과 격리를 시켜야한다)
* 테스트를 하면서 다른 테스트에 영향을 받지 않아야 한다.

#### Repeatable : 반복 가능한
* 테스트를 반복하면 결과가 같아야 한다.
* 테스트 코드 자체만으로 그 내용을 설명할 수 있어야 한다.
   * 외부 환경에 영향을 받지 않아야 한다.
* 코드 내에서 코드가 작동한 시간, 이런 것에 따라 동작이 달라지는 것에 영향을 받지 않아야 한다.
#### Self-vlidating : 스스로 검증 가능한(굉장히 중요함)
* 테스트는 반드시 기대하는 바를 단언해야 한다.
   * ex) main 메소드에서 이것 저것 프린트해보고 동작시켜보기
* 테스트는 스스로 검증하며, 테스트를 준비하는 것도 스스로 한다. arranged와 assert를 스스로한다
* Continuous Integration(CI) 도구를 활용하기 위해 이것이 꼭 이루어져야 한다
   * 코드가 통합될 때마다 자동으로 모든 테스트를 수행하고, 상태를 점검하는 프레임워크를 CI도구라고 한다.
#### Timely : 적시의, 제때
* 변화하는 코드는 테스트 코드를 항상, 꾸준히 작성해야 한다.(변화하는 코드이니깐 테스트를 작성해야 한다.)
* 리뷰 시스템을 통해서 , 혹은 CI도구를 이용해서 테스트 코드 작성을 강제하기도 한다.
   -&gt; peer Pressure 동료에게 드러내야 하기 때문에 압박감을 받음 테스트가 없으면 커밋이 안됨
* 큰 결함 없이 기존의 잘 동작하는(변경 예정이 없는) 코드 보다는
  말썽을 일으키는, 계속해서 변하고 있는 동적인 코드에 대한 테스트를 먼저 작성해야한다.
  (현실적으로 힘들어서 이렇게 명시를 하는 것이다.)

### JUnit을 사용한 테스트 3번 - Stub 이용
* Stub : 실제 코드나 아직 준비되지 못한 코드를 미리 정해진 답변으로 가장하는 것
   * dummy 객체가 마치 실제로 동작하는 것처럼 보이도록 만들어 놓은 것
````java
package com.company.p04;

import java.io.IOException;
import java.net.MalformedURLException;

public interface Http {
    String get(String targetUrl) throws IOException;
}</code></pre><pre><code class="language-java">package com.company.p04;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class HttpImpl implements Http{
    @Override
    public String get(String targetUrl) throws IOException {
        URL url = new URL(targetUrl);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod(&quot;GET&quot;);

        int responseCode = con.getResponseCode();
        BufferedReader in = 
             new BufferedReader(new InputStreamReader(con.getInputStream()));

        String inputLine;
        StringBuilder response = new StringBuilder();

        while ((inputLine = in.readLine()) != null){
            response.append(inputLine);
        }
        in.close();
        System.out.println(&quot;Response code : &quot; + responseCode);

        return response.toString();
    }
}</code></pre>
<ul>
<li>dependency injection<ul>
<li>테스트 케이스로 인해서 더 테스트하기 좋은 코드로 리팩토링했다. 이부분이 중요함!!!!<pre><code class="language-java">package com.company.p04;
</code></pre>
</li>
</ul>
</li>
</ul>
<p>import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;</p>
<p>public class WebParser {
    private Http http;</p>
<pre><code>// dependency injection di를하기위해 리팩토링을함
// 테스트 케이스로 인해서 더 테스트하기  좋은 코드로 수정하였다. 이부분이 중요함!!!!
public WebParser(Http http) {
    this.http = http;
}

public int countImageFromWebPage(String url) throws IOException {
    String text = http.get(url); // DI 적용</code></pre><p>//        String text = new HttpImpl.get(url); 원래 코드</p>
<pre><code>    Pattern pattern = Pattern.compile(&quot;(\\w+.(png|jpg|gif))&quot;);
    Matcher matcher = pattern.matcher(text);

    int count = 0;
    while (matcher.find()){
        count++;
    }

    System.out.println(text);
    return count;
}</code></pre><p>}</p>
<pre><code>```java
package com.company.p04;

import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

public class WebParserTest {
    // 이렇게 테스트하면 문제점
    // 1. Fast에 맞지 않는다 느리다. 구글에 요청을 보내서 받아오는데 
    // http 반응 속도가 느려서 그런 것이다. 인터넷 연결이 순간 안될 수도 있다.
    // 2. 웹페이지 내용이 변할 수 있다. (기대값이 변할 수 있다.)

//    @Test
//    public void countImageFromGoogleDotCom() throws IOException {
//        WebParser parser = new WebParser();
//        int actualResult =parser.countImageFromWebPage(&quot;http://google.com&quot;);
//
//        assertThat(actualResult, equalTo(5));
//    }

    private WebParser parser;
    @Before
    public void setUpUsingPageWithThreeImages(){
        // DI를 이용해 Http 객체의 stub을 구현하여 넣어준다. 
        // 실제로 웹파서를 이용할 때 HttpImpl을 만들어서 넣어주면 된다.
        parser = new WebParser((targetUrl) -&gt; {
            return &quot;&lt;html&gt;&lt;meta content=a.png&gt; 
             &lt;meta content=b.png&gt; &lt;meta content=c.png&gt; &lt;/html&gt;&quot;; 
            // 테스트 하고자하는 상황을 더 넣으면 더 의미가 있어짐
        }); 
        // 이미지가 3개 나온다는걸 설정을 해줬다. 테스트가 많아질수록 의미가 있어진다.

    }
    @Test
    public void countImageFromThreeImagePageStub() throws IOException {
        int actualResult = parser.countImageFromWebPage(&quot;http://google.com&quot;);
        assertThat(actualResult, is(equalTo(3)));
    }

}</code></pre><h1 id="tddtest-driven-development---테스트-주도-개발">TDD(Test-Driven-Development) - 테스트 주도 개발</h1>
<ul>
<li>&#39;실패하는&#39; 테스트 케이스를 먼저 작성하고, 이것을 통과시키는 방식으로 코드를 구현하는 방식</li>
<li>테스트 케이스 작성 -&gt; 코드 구현 -&gt; (커밋) -&gt; (리팩토링) -&gt; 테스트 케이스 작성 .. 을 빠르게 반복<ul>
<li>1~2분 간격으로 매우 빠른 호흡으로 진행</li>
<li>매번 커밋을 해줘서 돌아갈 수 있는 때를 확보를 하는 것이다.</li>
</ul>
</li>
<li>도메인 지식이 없어도 테스트 케이스를 작성할 수 있다는 관점에서 시작.<ul>
<li>도메인 지식이란 : 프로그래밍하고 상관없이 서비스할 분야에 대한 전반적인 지식을 의미한다.<pre><code class="language-java">package com.company.p05;
</code></pre>
</li>
</ul>
</li>
</ul>
<p>/**</p>
<ul>
<li>I-&gt; 1</li>
<li>II -&gt; 2</li>
<li>III -&gt; 3</li>
<li>IV -&gt; 4...</li>
<li>/</li>
</ul>
<p>public class RomanConverter {
    private String roman = &quot;&quot;;</p>
<pre><code>public void setRoman(String roman) {
    this.roman = roman;
}

// 들여쓰기가 2번넘게 들어가면 리팩토링을 하는게 맞다.
public int transform() {
    if (roman.equals(&quot;&quot;)){
        throw new ArithmeticException();
    }
    if (roman.contains(&quot;X&quot;)){
        return 10;
    }
    int count = 0;
    boolean beforeV = roman.contains(&quot;V&quot;) ? true : false;
    for (char c: roman.toCharArray()){
        if (c == &#39;I&#39;){
            count += beforeV ? -1 : 1;
        }
        // 4
        if (c == &#39;V&#39;){
            beforeV = false;
            count += 5;

        }
        // 6을 했을때 I가 앞에나오는지 뒤에나오는지 구별을해야하는 상황이 됐다.
    }
    return count;
}</code></pre><p>}</p>
<pre><code>```java
package com.company.p05;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

public class RomanConverterTest {
    RomanConverter converter;

    @Before
    public void setUp() throws Exception {
        converter = new RomanConverter();
    }

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void exceptionWhenRomanNotSet(){
        thrown.expect(ArithmeticException.class);
        int actualResult =  converter.transform();
    }

    @Test
    public void convertI(){
        converter.setRoman(&quot;I&quot;);
        int actualResult = converter.transform();
        assertThat(actualResult, is(equalTo(1)));
    }

    @Test
    public void convertX(){
        converter.setRoman(&quot;X&quot;);
        int actualResult = converter.transform();
        assertThat(actualResult, is(equalTo(10)));

    }

    @Test
    public void convertIII(){
        converter.setRoman(&quot;III&quot;);
        int actualResult = converter.transform();
        assertThat(actualResult, is(equalTo(3)));
    }

    @Test
    public void convertIV(){
        converter.setRoman(&quot;IV&quot;);
        int actualResult = converter.transform();
        assertThat(actualResult, is(equalTo(4)));
    }

    @Test
    public void convertVI(){
        converter.setRoman(&quot;VI&quot;);
        int actualResult = converter.transform();
        assertThat(actualResult, is(equalTo(6)));
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[This]]></title>
            <link>https://velog.io/@im_joonchul/This</link>
            <guid>https://velog.io/@im_joonchul/This</guid>
            <pubDate>Sun, 14 Mar 2021 06:35:20 GMT</pubDate>
            <description><![CDATA[<h1 id="this-키워드">This 키워드</h1>
<ul>
<li>객체가 스스로를 가르키는 참조, 자신의 메모리를 가리킨다.</li>
<li>인스턴스 자신의 주소를 반환한다.</li>
<li>멤버 변수와 로컬 변수의 이름이 같을 때, 멤버 변수임을 명시</li>
</ul>
<h2 id="생성자에서-다른-생성자를-호출하는-예제">생성자에서 다른 생성자를 호출하는 예제</h2>
<ul>
<li><p>생성자를 호출하는 데에도 사용할 수 있다.</p>
<ul>
<li>생성자 오버로딩에서 한 클래스 안에 생성자가 여러개 있을 수 있는데
한 생성자에서 다른 생성자를 호출하는 경우가 종종있다.</li>
</ul>
</li>
<li><p>this() 호출시에 반드시 생성자의 첫 줄에서만 사용해야 한다.</p>
<ul>
<li>생성자는 인스턴스의 값들을 초기화하는 인스턴스 생성을 초기화하는 역할을 한다.</li>
<li>this()로 다른 생성자를 호출할 때, 호출한 생성자가 무슨일을 할 줄 모르는 상태인데 this() 호출 보다 먼저 값들을 초기화한다고 하면,
다른 생성자를 호출할 때 다른 스테이트가 올라가는 것을 허용하지 않는다. 그래서 호출은 가장 첫줄에 써야 한다.</li>
</ul>
<pre><code class="language-java">public class Constructor {
    int x;
    int y;
    String z;

    public Constructor(){ // 기본 생성자, 구현하지 않아도 알아서 생긴다.
        this(0,0);
//        x = 1;
//        y = 2;
//        z = &quot;자동 초기화 값이 들어간다.&quot;;
    }


</code></pre>
</li>
</ul>
<pre><code>  // 파라미터 생성자
   public Constructor(int x, int y, String z){ //오버로딩
       this.x = x; // this는 멤버 변수를 표기하기 위해 사용될 수 있다.
       this.y = y;
       this.z = z;
   }

   public Constructor(int a, int b){
       this(a,b,&quot;&quot;); 
    // 자기 자신을 가르키는 애 위에 함수가 호출됨.
    // this는 무조건 첫줄에만 쓰일 수 있다.(단한번) 규칙입니다.</code></pre><p>   //        x = a;
   //        y = b;
   //        z = &quot;&quot;;
       }
   }</p>
<p> ````</p>
<h2 id="자기-자신의-메모리를-가리키는-this-예제">자기 자신의 메모리를 가리키는 this 예제</h2>
<p><img src="https://images.velog.io/images/im_joonchul/post/9b581952-cfb5-4f35-8391-3024500be2cd/this.png" alt="this"></p>
<pre><code class="language-java">public class MyDate {
    private int day;
    private int month;
    private int year;

    private boolean isVaild = true;

    public  void setDay(int day){
        this.day = day;
    }
    public int getDay(){
        return day;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        if(month &lt;1 || month &gt; 12){
            isVaild = false;
        }
        this.month = month;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void showDate(){
        if (isVaild){
            System.out.println(this.year + &quot;년&quot; + this.month + &quot;월&quot; +this.day+&quot;일&quot;);
        }else{
            System.out.println(&quot;유효하지 않은 범위 입니다.&quot;);
        }
    }
}

public class MyDateTest {
    public static void main(String[] args) {
        MyDate date = new MyDate();

        date.setYear(2019);
        date.setMonth(13);
        date.setDay(10);

        date.showDate();

    }
}</code></pre>
<ul>
<li><p>인스턴스 자신의 주소를 반환할 일이 있으면 this를 반환 하면 된다.</p>
</li>
<li><p>day로부터 setYear라는 메소드를 호출하게 되면 setYear는 BirthDay에 대한 메소드이니깐</p>
</li>
<li><p>setYear의 세그멘테이션이 stack영역에 만들어지고 만약 setYear 안에서 this를 썼다하면 힙영역의 BirthDay에 대한  메모리를 가리킨다.
인스턴스 내부에서(객체 내부에서) 자기 자신이 생성된 메모리 주소를 가리킨다.
인스턴스가 여러 개 생성 됬다 하면 각각의 this는 다 다름 코드상에서 this하나만 쓰지만 각각은 다 다르다</p>
</li>
<li><p>여기서 stack 영역에 this가 들어가게 되는데 왜 this가 들어가는지 이해가 안 갔는데</p>
</li>
<li><p>메인에서 this가 date.setYear() 이런식으로 호출이 되어있다면 this는 date변수 대신이라고 생각해도 될까?</p>
</li>
<li><p>로컬변수에 this는 참조변수로 생성된다. 그런의미로 이해하면 될 것 같다.</p>
</li>
</ul>
<h3 id="자기-자신을-반환하는-this">자기 자신을 반환하는 this</h3>
<pre><code class="language-groovy">public Person getPerson(){
     return this;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Stream API]]></title>
            <link>https://velog.io/@im_joonchul/Stream-API</link>
            <guid>https://velog.io/@im_joonchul/Stream-API</guid>
            <pubDate>Sun, 14 Mar 2021 06:19:34 GMT</pubDate>
            <description><![CDATA[<h1 id="스트림-apistream-api">스트림 API(Stream API)</h1>
<ul>
<li>여기서 말하는 스트림과 나중에 자바 io에서 말하는 스트림은 다른 것이다.<ul>
<li>여기서의 스트림은 자료의 연산을 위해서 사용하는 객체를 말한다.</li>
<li>자바 io에서의 스트림은 입출력을 위한 스트림이다.<h2 id="스트림-api">스트림 API</h2>
</li>
</ul>
</li>
<li>Java 8에서 추가된 Java.util.stream 패키지</li>
<li>컬렉션의 요소를 람다식으로 처리할 수 있도록 하는 함수형 프로그래밍 도구</li>
<li>스트림 API는 데이터를 추상화하여 다루므로, 다양한 방식으로 저장된 데이터를 읽고 쓰기 위한 공통된 방법을 제공한다.</li>
<li>따라서 스트림 API를 이용하면 배열이나 컬렉션뿐만 아니라 파일에 저장된 데이터도 모두 같은 방법으로 다룰 수 있게 된다.</li>
<li>중간 연산과 최종 연산으로 구분 된다,최종 연산이 수행되어야 모든 연산이 적용되는 지연 연산이다.</li>
</ul>
<h3 id="스트림의-특징">스트림의 특징</h3>
<h4 id="1-스트림은-한-번-밖에-사용-못한다">1. 스트림은 한 번 밖에 사용 못한다.</h4>
<ul>
<li>내부적으로 몇번째 동작을 하고 있는지 체크하는 것이 들어가 있다. 그래서 사용할 때마다 다시 정의해주고 사용해야 한다.<h4 id="2-간결한-코드로-작성할-수-있다">2. 간결한 코드로 작성할 수 있다.</h4>
<pre><code class="language-java">// 기존의 Java 7방식의 작성 방법
List&lt;String&gt; list = Arrays.asList(&quot;fast&quot;,&quot;campus&quot;,&quot;rocks&quot;);
List&lt;String&gt; newList = new ArrayList&lt;&gt;();
</code></pre>
</li>
</ul>
<p>for (String s : list){
    newList.add(s.toUpperCase());
}
for (String s : newList){
    System.out.println(s);
}</p>
<pre><code>```java
// java 8 - Stream API -&gt; 훨씬 더 간결한 코드로 작성할 수 있다.
List&lt;String&gt; list1 = Arrays.asList(&quot;fast&quot;,&quot;campus&quot;,&quot;rocks&quot;);
Stream&lt;String&gt; stream = list1.stream(); //스트림으로 변환해준다.

// 스트링에서 스트림으로 매핑해준다.
//uppercase를 string에 매핑, 각각의 요소에 적용해라
stream.map(String::toUpperCase).forEach(System.out::println); // foreach는 Consumer를 받는다,각각의 요소를 하나씩 출력한다.</code></pre><h4 id="3-데이터-소스에-대한-공통된-접근-방식-제공">3. 데이터 소스에 대한 공통된 접근 방식 제공.</h4>
<ul>
<li>Stream으로 변경해주고 나면, List, Set, Map 모두 동일한(표준화된) 방식으로 데이터를 접근 가능.</li>
<li>컬렉션 프레임워크는 각각을 다른 방식으로 데이터를 처리 해줘야 한다.</li>
<li>특히 Stream::sorted() 메소드는 공통된 정렬 방식을 제공한다.</li>
</ul>
<h4 id="4중간-처리와-최종-처리를-지원한다">4.중간 처리와 최종 처리를 지원한다.</h4>
<ul>
<li>Mapping, Filtering, Sorting 등 중간 처리 지원(여러 개 사용이 가능하다.)</li>
<li>Iteration, Count, Average, Summation, Reduce 등 최종 처리 지원(마지막에 하나 사용 가능하다.)</li>
</ul>
<h4 id="5데이터-소스와-처리-결과를-분리">5.데이터 소스와 처리 결과를 분리</h4>
<ul>
<li>원본 데이터를 유지하여 처리하는 것에 의한 부작용을 방지한다.</li>
<li>처리 결과를 새로운 컬렉션으로 저장이 가능하다.</li>
</ul>
<h4 id="6-람다식으로-요소-처리-코드를-제공한다">6. 람다식으로 요소 처리 코드를 제공한다.</h4>
<ul>
<li>스트림이 제공하는 대부분의 요소처리 메소드는 함수적 인터페이스 매개타입을 가진다.   </li>
<li>매개값으로 람다식 또는 메소드 참조를 대입할 수 있다.
(함수적 인터페이스 매개타입을 가지기 때문에 람다식,메소드 참조로 매개값을 제공할 수 있음)</li>
</ul>
<h4 id="7-내부-반복자를-사용하므로-병렬-처리가-쉽다">7. 내부 반복자를 사용하므로 병렬 처리가 쉽다.</h4>
<ul>
<li><p>외부 반복자 - 개발자가 코드로 직접 컬렉션 요소를 반복해서 요청하고 가져오는 코드패턴
(Iterator를 생각하면 될 것 같다. Iterator을 사용해서 반복문을 구현해서 하나씩 값을 출력하게
코드를 구현해야 하는 것을 말하는 것 같다.)</p>
</li>
<li><p>내부 반복자 - 컬렉션 내부에서 요소들을 반복시키고 개발자는 요소당 처리해야할 코드만 제공하는 코드 패턴
 (forEach메소드 처럼 내부가 어떻게 구현되어있는지 모르지만 이것을 사용하면 요소들 하나씩 가져오라는 코드가 없지만 
 알아서 반복해서  반환시켜 처리해준다. 이런 것을 의미하는 것 같다)</p>
</li>
<li><p>내부 반복자의 이점 - 개발자는 요소 처리 코드에만 집중, 멀티 코어 cpu를 활용하기 위해 요소들을 분배시켜 병렬 처리 작업을 수 있다.</p>
<ul>
<li>컬렉션의 요소가 많을 경우에 요소를 나눠서 별도의 스트림으로 만들어서 각각의 코어에서 병렬적으로 처리할 수 있다.</li>
</ul>
</li>
</ul>
<h2 id="스트림-api를-이용한-자료-처리">스트림 API를 이용한 자료 처리</h2>
<h3 id="스트림-api의-종류">스트림 API의 종류</h3>
<table>
<thead>
<tr>
<th>종류</th>
<th>처리 대상</th>
</tr>
</thead>
<tbody><tr>
<td><code>Stream&lt;T&gt;</code></td>
<td>일반적인 객체를 처리</td>
</tr>
<tr>
<td><code>IntStream</code></td>
<td>기본 자료형 <code>int</code>를 처리</td>
</tr>
<tr>
<td><code>LongStream</code></td>
<td>기본 자료형 <code>long</code>을 처리</td>
</tr>
<tr>
<td><code>DoubleStream</code></td>
<td>기본 자료형 <code>double</code>을 처리</td>
</tr>
</tbody></table>
<h3 id="스트림-객체-생성-메소드">스트림 객체 생성 메소드</h3>
<ul>
<li>데이터 소스(인터페이스, 클래스)로부터 스트림 생성</li>
</ul>
<table>
<thead>
<tr>
<th>데이터 소스</th>
<th>메소드</th>
</tr>
</thead>
<tbody><tr>
<td>Collection</td>
<td>default Stream<E> stream()</td>
</tr>
<tr>
<td>Collection</td>
<td>default Stream<E> parallelStream()</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static <T> Stream<T> stream(T[] array)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static <T> Stream<T> of(T ... values)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static IntStream stream(int[] array)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static IntStream of(int ... values)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static LongStream stream(long[] array)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static LongStream of(long ... values)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static DoubleStream stream(double[] array)</td>
</tr>
<tr>
<td>Arrays</td>
<td>public static DoubleStream of(double ... values)</td>
</tr>
</tbody></table>
<ul>
<li>정수 범위와 java.util.Random으로부터 생성</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>메소드</th>
</tr>
</thead>
<tbody><tr>
<td>int형 범위</td>
<td>public static IntStream range(int startInclusive, int endExclusive)</td>
</tr>
<tr>
<td>int형 범위</td>
<td>public static IntStream rangeClosed(int startInclusive, int endInclusive)</td>
</tr>
<tr>
<td>long형 범위</td>
<td>public static LongStream range(long startInclusive, long endExclusive)</td>
</tr>
<tr>
<td>long형 범위</td>
<td>public static LongStream rangeClosed(long startInclusive, long endInclusive)</td>
</tr>
<tr>
<td>Random p형 값</td>
<td>public PStream ps()</td>
</tr>
<tr>
<td>Random p형 값</td>
<td>public PStream ps(long streamSize)</td>
</tr>
<tr>
<td>Random p형 값</td>
<td>public PStream ps(long streamSize, p origin, p bound)</td>
</tr>
</tbody></table>
<h4 id="스트림-생성-방식-예제">스트림 생성 방식 예제</h4>
<ul>
<li><p>컬렉션의 인스턴스 메소드 stream()</p>
<pre><code class="language-java">Stream&lt;String&gt; stream1 = list1.stream();</code></pre>
</li>
<li><p>Arrays 클래스의 클래스 메소드 stream() 을 이용</p>
<pre><code class="language-java">// 함수형 인터페이스랑 비슷함 P Type
// LongStream, DoubleStream 도 있다.
int[] ints = {4, 6, 2, 19, 2, 58, 4, 6, 5};
IntStream intStream = Arrays.stream(ints);
intStream.forEach(System.out::println);</code></pre>
</li>
<li><p>위의 두 개의 다른점</p>
<ul>
<li><code>Stream&lt;Integer&gt;</code>로 할 경우, <code>Primitive Type</code>이 들어올 때 오토박싱으로 변경되고 다시 출력할 때 언방식이 되는데 이럴 때 오버헤드가 발생한다.</li>
<li><code>IntStream</code>을 사용 할 경우, 오버헤드 필요 없이, <code>WrapperClass</code>없이 사용 가능하다. 그래서 효율적이다.</li>
</ul>
</li>
<li><p>Stream 클래스의 클래스 메소드 <code>of()</code>를 이용해서 <code>Collection</code>을 걸치지 않고도 스트림을 생성 가능</p>
<pre><code class="language-java">DoubleStream doubleStream = DoubleStream.of(0.4, 0.6, 0.2, 1.2, 0.94);
doubleStream.forEach(System.out::println);</code></pre>
</li>
<li><p>range()를 이용한 스트림 -&gt; for i문 (for(int i=0...))을 대체하는 스트림</p>
</li>
<li><p>rangeClosed() : 0~10까지 10을 포함한다.</p>
</li>
<li><p>순서대로 값을 출력한다.</p>
<pre><code class="language-java">IntStream intStream1 = IntStream.range(0,10); // 0~9까지 10은 포함되지 않는다.
intStream1.forEach(System.out::println);
</code></pre>
</li>
</ul>
<p>IntStream intStream2 = IntStream.rangeClosed(0,10); // 0~10까지 10포함된다.
intStream2.forEach(System.out::println);
// LongStream도 range, rangeClosed 가 있다.</p>
<pre><code>
* Random 객체를 이용한 스트림이 있다. Java.util 패키지 안에 있다.
```java
Random random = new Random();
// LongStream longStream =  random.longs();
// longStream.forEach(System.out::println); // 개수 제한 없이 무한히 출력

// 개수 제한 가능
LongStream longStream1 =  random.longs(100);
longStream1.forEach(System.out::println); // 개수를 정해질 수있다 100개

// 개수제한 + 범위 제한 가능 젤 많이 사용함
LongStream longStream2 =  random.longs(100,0,1000);
longStream2.forEach(System.out::println); // 개수를 정해질 수있다 0~1000까지 100개를 출력</code></pre><h3 id="중간-처리-메소드">중간 처리 메소드</h3>
<ul>
<li><a href="https://velog.io/@im_joonchul/Java-Stream%EC%A4%91%EA%B0%84%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C">https://velog.io/@im_joonchul/Java-Stream%EC%A4%91%EA%B0%84%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C</a><h3 id="최종-처리-메소드">최종 처리 메소드</h3>
</li>
<li><a href="https://velog.io/@im_joonchul/Java-Stream%EC%B5%9C%EC%A2%85%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C">https://velog.io/@im_joonchul/Java-Stream%EC%B5%9C%EC%A2%85%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C</a></li>
</ul>
<h3 id="병렬-스트림">병렬 스트림</h3>
<h4 id="병렬-처리">병렬 처리</h4>
<ul>
<li>한가지 작업을 서브 작업으로 나누고, 서브 작업들을 분리된 스레드에서 병렬 적으로 처리한 후,
서브 작업들의 결과들을 최종 결합하는 방법, 자바는 ForkJoinPool 프레임워크를 이용해서 병렬 처리를 한다.</li>
</ul>
<h4 id="병렬-스트림의-생성">병렬 스트림의 생성</h4>
<ul>
<li><p>stream() 대신 parallelStream()으로 변경</p>
</li>
<li><p>stream 생성 후 parallel()으로 병렬화</p>
<ul>
<li>combiner를 이용해 병렬 스트림으로 생성된 컬렉션을 결합</li>
</ul>
</li>
<li><p>BiConsumer&lt;T, K&gt; combiner : T 객체에 K 객체를 결합 </p>
<table>
<thead>
<tr>
<th>인터페이스</th>
<th>리턴타입</th>
<th>메소드(매개변수)</th>
</tr>
</thead>
<tbody><tr>
<td>java.util.Collection</td>
<td>Stream</td>
<td>parallelStream()</td>
</tr>
<tr>
<td>java.util.Stream</td>
<td>Stream</td>
<td>parallel()</td>
</tr>
<tr>
<td>java.util.Intstream</td>
<td>IntStream</td>
<td></td>
</tr>
<tr>
<td>java.util.Longstream</td>
<td>Longstream</td>
<td></td>
</tr>
<tr>
<td>java.util.Doublestream</td>
<td>Doublestream</td>
<td></td>
</tr>
</tbody></table>
<ul>
<li>parallelStream()<ul>
<li>컬렉션으로부터 병렬 스트림을 바로 리턴</li>
</ul>
</li>
<li>parallel()<ul>
<li>순차 처리 스트림을 병렬 스트림으로 변환해서 리턴</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="병렬성-구분">병렬성 구분</h4>
<ul>
<li><p>데이터 병렬성</p>
<ul>
<li>데이터 병렬성은 한 작업 내에 있는 전체 데이터를 쪼개어 서브 데이터들로 만들고
 이 서브 데이터들을 병럴 처리해서 작업을 빨리 끝내는 것을 말한다.</li>
</ul>
<ul>
<li>작업 병렬성<ul>
<li>작업 병렬성은 서로 다른 작업을 병렬 처리하는 것을 말한다.</li>
<li>작업 병렬성은 대표적인 예는 웹서버이다.
웹 서버는 각각의 브라우저에서 요청한 내용을 개별 스레드에서 병렬로 처리한다.</li>
</ul>
</li>
</ul>
</li>
<li><p>병렬 스트림은 데이터 병렬성을 구현한 것이다.</p>
<ul>
<li>멀티 코어의 수만큼 대용량 요소를 서브 요소들로 나누고,
 각각의 서브 요소들을 분리된 스레드에서 병렬 처리시킨다.</li>
<li>예를 들어 쿼드 코어cpu일 경우 4개의 서브 요소들로 나누고,
4개의 스레드가 각가의 서브 요소들을 병렬처리한다.</li>
<li>병렬 스트림은 포크조인 프레임워크를 이용한다.</li>
</ul>
</li>
</ul>
<pre><code class="language-java">Stream&lt;String&gt; parStream = Arrays.stream(arr).parallel(); //  스트림을 parallel로 바꿔줌
System.out.println(parStream.map(String::length).count());
// parallelStream을 사용하면 연산 순서가 달라질 수 있다.

List&lt;String&gt; list4 = List.of(&quot;atwe&quot;,&quot;bff&quot;,&quot;cqqqw&quot;,&quot;dtwer&quot;);
Stream&lt;String&gt; stream6 = list4.parallelStream(); // 어떤 요소가 먼저 수행되는지 알 수 없음
// Stream&lt;String&gt; stream6 = list4.stream();

stream6.map(String::length).peek(s-&gt;System.out.println(&quot;A: &quot;+ s))
              .filter(value-&gt;value &gt;=3)
              .peek(s-&gt; System.out.println(&quot;B :&quot;+ s))
              .forEach(System.out::println);</code></pre>
<h3 id="포크조인-프레임워크forkjoin-framework">포크조인 프레임워크(ForkJoin Framework)</h3>
<ul>
<li><p>포크조인 프레임워크 동작 방식</p>
<ul>
<li><p>포크 단계</p>
<ul>
<li>데이터를 서브 데이터로 반복적으로 분리한다.</li>
<li>서브 데이터를 멀티 코어에서 병렬로 처리한다.</li>
</ul>
</li>
<li><p>조인 단계</p>
<ul>
<li>서브 결과를 결합해서 최종 결과를 만들어 낸다.</li>
</ul>
</li>
<li><p>실제로 병렬 처리 스트림은 포크 단게에서 <code>차례대로 요소를 4등분 하지 않는다.</code>내부적으로 서브 요소를 나누는 알고리즘이 있기 때문에 개발자는 신경 쓸 필요가 없다.</p>
</li>
</ul>
<ul>
<li>포크조인풀(포크조인프레임워크는 내부적으로 스레드를 포크조인풀에서 관리한다.)<ul>
<li>각각의 코어에서 서브요소를 처리하는 것은 개별 스레드가 해야하므로 스레드 관리가 필요<ul>
<li>코어에서 작업을 할려면 코어별로 각각의 스레드가 존재해야한다.</li>
</ul>
</li>
<li>포크조인 프레임워크는 ExcutorService의 구현 객체인 ForkJoinPool을 사용</li>
<li>4개의 코어를 가진 cpu일 경우</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="병렬-처리-성능">병렬 처리 성능</h3>
<ul>
<li><p>병렬 처리는 항상 빠르다?</p>
<ul>
<li>스트림 병렬 처리가 스트림 순차 처리보다 항상 실행 성능이 좋다고 판단해서는 안된다.</li>
</ul>
</li>
<li><p>병렬 처리에 영향을 미치는 3가지 요인</p>
<ul>
<li><p>요소의 수와 요소당 처리 시간 - 요소우의 수가 적고 요소당 처리시간이 짧으면 순차 처리가 오히려 병렬처리보다
빠를 수 있다 병렬처리는 스레드풀 생성, 스레드 생성이라는 추가적인 비용이 발생하기 때문이다.</p>
</li>
<li><p>스트림 소스의 종류</p>
<ul>
<li>ArrayList, 배열은 램덤 액세스를 지원(인덱스로 접근)하기 때문에 포크 단계에서 쉽게 요소를
분리할 수 있어 병렬 처리 시간이 절약된다, 반면 HashSet, TreeSet은 요소를 분리하기가 쉽지않고,
LinkedList는 램덤 액세스를 지원하지 않아서 요소를 분리하기가 쉽지 않다.
또한, BufferedReader.lines()은 전체 요소의 수를 알기 어렵기 때문에 포크 단계에서 부분 요소로
나누기 어렵다. 따라서 이들 소스들은 ArrayList, 배열 보다는 상대적으로 병럴처리가 늦다.</li>
</ul>
</li>
<li><p>코어의 수 
 *싱글코어 cpu일 경우 순차처리가 빠르다. 코어의 수가 많으면 병렬처리 속도가 빨라진다.</p>
</li>
</ul>
</li>
</ul>
<h4 id="패럴레-스트림을-사용한다는-것이-어떤-의미인가">패럴레 스트림을 사용한다는 것이 어떤 의미인가</h4>
<ul>
<li>원래 스트림(페럴레아닌 상태)은 [0,0,0,0,0,0] 이런게 있다로 시작, 스트림을 정하고 맵이 있으면 맵을 한 결과가 나와야함[0,0,0,0,0,0]</li>
<li>그런다음 맵을 한 번 더 실행하고 [0,0,0,0,0,0] foreach가 실행이 된다. 하나하나가 함수로 소비가 되는 상태가 된다</li>
<li>하나씩 처리가 된다 각 요소 가 모든 연산이 쭉되고 다음 요소가 모든 연산이 실행이 됨</li>
<li>그 중간에 peek(),peek(),foreach()의 결과가 출력이 된다 이것이 우리가 생각하는 기본적인 스트림</li>
</ul>
<h4 id="병렬-스트림-동작">병렬 스트림 동작</h4>
<ul>
<li><p>자바에서 스레드가 기본적인건 모르겠으나 여기서 7개의 스레드가 각각있다고 가정하고 동시에 동작을한다</p>
</li>
<li><p>스레드는 프로그램을 동작할 때 한줄씩 실행되는데 이 한 줄씩 실행되는 것이 여러개 있는 것이다.각각 독립적으로 한줄을 실행한다.</p>
</li>
<li><p>한줄 한줄 계산하는게 동시에 계산해도 된다 각각을 순수함수로 되어있어야 하니깐</p>
<ul>
<li>여기서 한줄이란 세로로 한줄이 시작되고 그옆에 세로가 시작되는건데 병렬처리면 스레드의 개수에 따라
이 세로줄의 실행이 스레드 개수에 따라서 한번에 실행된다는 의미이다 4개스레드이면 4개의 세로줄이 동시에 실행됨.</li>
<li>한줄 계산되는 동안 다른 한줄이 같이 계산되고 몇개가 같이 연산이 진행되는진 모르지만 스레드의 개수에 따라 한줄이 같이 진행됨</li>
</ul>
</li>
<li><p>[0,0,0,0,0,0]</p>
</li>
<li><p>[0,0,0,0,0,0]</p>
</li>
<li><p>[0,0,0,0,0,0]</p>
</li>
<li><p>[0,0,0,0,0,0]</p>
<ul>
<li>명령형/ 순차처리 &lt;-&gt; 함수형/병렬처리 큰 간극을 보인다</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java Stream_최종처리메소드]]></title>
            <link>https://velog.io/@im_joonchul/Java-Stream%EC%B5%9C%EC%A2%85%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C</link>
            <guid>https://velog.io/@im_joonchul/Java-Stream%EC%B5%9C%EC%A2%85%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C</guid>
            <pubDate>Sun, 14 Mar 2021 06:05:06 GMT</pubDate>
            <description><![CDATA[<h1 id="최종-처리-메소드">최종 처리 메소드</h1>
<table>
<thead>
<tr>
<th>동작</th>
<th>메소드</th>
</tr>
</thead>
<tbody><tr>
<td>루핑</td>
<td>forEach()</td>
</tr>
<tr>
<td>매칭</td>
<td>allMatch(), anyMatch(), noneMatch()</td>
</tr>
<tr>
<td>집계</td>
<td>count(), max(), min(), average(), sum(), reduce()</td>
</tr>
<tr>
<td>조사</td>
<td>findFirst(), findAny()</td>
</tr>
<tr>
<td>수집</td>
<td>collect()</td>
</tr>
</tbody></table>
<h2 id="루핑">루핑</h2>
<h3 id="foreach-메소드로-스트림-요소를-순차적으로-consumert를-이용해-소비">forEach() 메소드로 스트림 요소를 순차적으로 Consumer<T>를 이용해 소비</h3>
<ul>
<li>forEach() - 요소들을 계속해서 반복해서 가져와라라는 의미이다.<ul>
<li><code>stream.forEach(name -&gt; System.out.println(name))</code>으로 되어있을 때
스트림에 가져온 요소를 name에 넣어서 하나씩 출력되게 하는 것이다.</li>
<li>매개값의 형태는 Consumer 함수형 인터페이스 타입을 갖는다.</li>
</ul>
</li>
<li><code>void forEach(Comsumer&lt;? super T&gt; action)</code> : 스트림의 각 요소를 action으로 소비  </li>
</ul>
<h2 id="매칭">매칭</h2>
<h3 id="predicate-계열을-이용해-스트림-요소들이-특정-조건에-만족하는지-조사하는-메소드">Predicate 계열을 이용해 스트림 요소들이 특정 조건에 만족하는지 조사하는 메소드</h3>
<ul>
<li><p>boolean allMatch(Predicate&lt;? super T&gt; predicate) : 스트림의 모든 요소가 Predicate를 만족하면 true를 반환</p>
</li>
<li><p>boolean anyMatch(Predicate&lt;? super T&gt; predicate) : 스트림의 요소 중 하나라도 Predicate를 만족하면 true를 반환</p>
</li>
<li><p>boolean noneMatch(Predicate&lt;? super T&gt; predicate) : 스트림의 요소 중 하나라도 Predicate를 만족하지 않으면 true를 반환</p>
<pre><code class="language-java">Stream&lt;String&gt; st0 = Stream.of(&quot;abc&quot;,&quot;cde&quot;,&quot;efg&quot;);
System.out.println(st0.allMatch(s -&gt; s.equals(&quot;abc&quot;))); //false
st0 = Stream.of(&quot;abc&quot;,&quot;cde&quot;,&quot;efg&quot;);
System.out.println(st0.anyMatch(s -&gt; s.equals(&quot;cde&quot;))); //true
st0 = Stream.of(&quot;abc&quot;,&quot;cde&quot;,&quot;efg&quot;);
System.out.println(st0.noneMatch(s -&gt; s.equals(&quot;abcde&quot;)));//true</code></pre>
<h2 id="조사">조사</h2>
<h3 id="첫번째-요소-또는-아무-요소를-조사하는-최종-처리-메소드-필터링-등으로-인해-스트림에-요소가-남아있는지-확인할-수-있다">첫번째 요소 또는 아무 요소를 조사하는 최종 처리 메소드. 필터링 등으로 인해 스트림에 요소가 남아있는지 확인할 수 있다.</h3>
</li>
<li><p><code>Optional&lt;T&gt; findFirst()</code> : 스트림의 첫 요소 또는 empty Optional 객체를 반환</p>
</li>
<li><p><code>Optional&lt;T&gt; findAny()</code> : 스트림의 아무 요소나 가지는 Optional 객체를 반환 (병렬 스트림일 때 사용한다.)</p>
<pre><code class="language-groovy">int firstValue = Arrays.stream(new int[]{1,2,3,4,5})
                .filter(n -&gt; n%3 ==0)
                .findFirst()
                .getAsInt();</code></pre>
</li>
</ul>
<h2 id="집계-통계">집계 (통계)</h2>
<ul>
<li><p>최종 처리 기능</p>
<ul>
<li>카운팅, 합계, 평균값, 최대값, 최소값 등과 같이 하나의 값으로 산출한다.</li>
<li>대량의 데이터를 가공해서 축소하는 리덕션이라고 볼 수 있다.</li>
</ul>
</li>
<li><p>기본 집계 메소드</p>
<ul>
<li>기본형 스트림의 통계 : count(), sum(), average(), min(), max()</li>
<li>T 타입 스트림의 통계 : count(), min(), max() (min, max의 경우 Comparator 필요)</li>
</ul>
</li>
</ul>
<h3 id="reduce-메소드--사용자-정의-집계-메소드">reduce() 메소드 : 사용자 정의 집계 메소드</h3>
<ul>
<li>모든 자료형에서 사용할 수 있는 집계 메소드이다!</li>
<li>개발자가 프로그램화해서 다양한 집계(리덕션) 결과물을 만들 수 있다.</li>
<li>특정한 값을 집계 할 수 있게 하기 위해서 reduce를 제공한다.</li>
</ul>
<h4 id="세가지-인자를-받아서-처리">세가지 인자를 받아서 처리</h4>
<ul>
<li>accmulator : 각 요소를 처리하는 계산 로직이다. 각 요소가 올 때마다 중간 결과를 생성한다.<pre><code class="language-java"> Optional&lt;T&gt; reduce(BinaryOperator&lt;T&gt; accumulator) 
 //accumulator를 수행하고 Optional&lt;T&gt; 타입 반환</code></pre>
</li>
<li>identity : 계산을 위한 초기값이다. stream이 비어서 계산할 값이 없더라도 이 값은 반한된다.<pre><code class="language-java"> T reduce(T identity, BinaryOperator&lt;T&gt; accumulator) 
 // identity를 초기값으로 하여, accumulator를 이용해 집계 연산</code></pre>
</li>
<li>combiner : 병럴 stream에서 나눠 계산한 결과를 하나로 합쳐 반환한다.<pre><code class="language-java"> &lt;U&gt; U reduce(U identity, BiFunction&lt;U, ? super T, U&gt; accumulator, BinaryOperator&lt;U&gt; combiner) 
 // combiner를 이용해 병렬 스트림 결합</code></pre>
</li>
</ul>
<h4 id="메소드-형태-및-사용코드">메소드 형태 및 사용코드</h4>
<table>
<thead>
<tr>
<th>인터페이스</th>
<th>리턴 타입</th>
<th>메소드</th>
</tr>
</thead>
<tbody><tr>
<td>Stream</td>
<td>Optional<T></td>
<td>reduce(BinaryOperator<T> accumulator</td>
</tr>
<tr>
<td></td>
<td>T</td>
<td>reduce(T identitiy, BianryOperator<T> accmulator)</td>
</tr>
<tr>
<td>IntStream</td>
<td>OptionalInt</td>
<td>reduce(IntBinaryOperator  op)</td>
</tr>
<tr>
<td></td>
<td>int</td>
<td>reduce(int indentity, IntBinaryOperator  op)</td>
</tr>
<tr>
<td>LongStream</td>
<td>OptionalLong</td>
<td>reduce(LongBinaryOperator  op)</td>
</tr>
<tr>
<td></td>
<td>long</td>
<td>reduce(long indentity, LongBinaryOperator  op)</td>
</tr>
<tr>
<td>DoubleStream</td>
<td>OptionalDouble</td>
<td>reduce(DoubleBinaryOperator  op)</td>
</tr>
<tr>
<td></td>
<td>double</td>
<td>reduce(double indentitiy, DoubleBinaryOperator  op)</td>
</tr>
</tbody></table>
<ul>
<li><p>reduce(BinaryOperator<T> accumulator)</p>
<ul>
<li>이건 연산의 결과가 없으면 예외가 발생한다. NotSuchElementException 요소가 있어야 동작한다.</li>
</ul>
</li>
<li><p>reduce(T identitiy, BianryOperator<T> accmulator) </p>
<ul>
<li>연산의 결과가 없다면, 디폴트로 identity 사용  요소가 없어도 동작한다.</li>
<li>연산의 결과가 없는 것은 요소가 없는 것이다. 그래서 연산의 결과로 디폴트 값으로 identity를 하는 것이다.</li>
</ul>
</li>
<li><p>매개변수</p>
<ul>
<li>XXXBinaryOperator : 두 개의 매개 값을 받아 연산 후 리턴하는 함수적 인터페이스</li>
<li>identity : 스트림에 요소가 전혀 없을 경우 리턴될 디폴트 값   </li>
</ul>
<pre><code class="language-java">System.out.println(IntStream.range(0,10).reduce(0,(value1,value2)-&gt;value1+value2)); //sum()
// 1,2와 더한걸 3이랑 더하고 12 와 3을 더한걸 4 와 더함 .. 누적해서 더하는 것이다.
// identity가 사용이 되는 이유는 처음 identitiy와 1을 더한값과 2를계산하기위해서
// 0 [0,1,2,3,4,5,6,7,8,9] 0+0 =0 -&gt; 0+1-&gt;1 1+2-&gt; 3 과같은 연산 0~9까지 더한 연산
// sum()으로도 나타낼 수 있다 sum,min,max등등 도 reduce로 구현되어 있다

System.out.println(IntStream.range(0,10).reduce(Integer.MAX_VALUE,(value1,value2)-&gt;value1&lt;value2? value1:value2));// min()</code></pre>
</li>
</ul>
<h3 id="optionalt-클래스">Optional<T> 클래스</h3>
<ul>
<li><p>T 타입 객체의 null 여부에 따라 다르게 동작하는 Wrapper 클래스</p>
</li>
<li><p>자바 8부터 추가된 값을 저장하는 값 기반 클래스</p>
</li>
<li><p>java.util 패키지의 Optional, OptionalDouble, OptionalInt, OptionLong 클래스를 말한다.</p>
</li>
<li><p>집계 메소드의 리턴 타입으로 사용되어 집계 값을 가지고 있다. 이게 핵심이다!!</p>
</li>
<li><p>저장된 값을 얻으려면 get(), getAsDouble(), getAsInt(), getAsLong()를 호출한다. </p>
</li>
<li><p>Optional 클래스의 정적 메소드를 이용해 Optional 객체 생성</p>
<ul>
<li><code>public static &lt;T&gt; Optional&lt;T&gt; of(T value)</code> : value가 null인 경우 NullPointerException을 발생시키는 Wrapping 메소드</li>
<li><code>public static &lt;T&gt; Optional&lt;T&gt; ofNullable(T value)</code> : value가 null인 경우 empty()의 결과를 리턴하는 Wrapping 메소드</li>
<li><code>public static &lt;T&gt; Optional&lt;T&gt; empty()</code> : 값이 비어있는 Optional 객체를 리턴</li>
</ul>
</li>
<li><p>Optional 객체를 처리하는 메소드</p>
<ul>
<li><code>public T get()</code> : Optional의 값을 리턴하며, null일 경우 NullPointerException 발생</li>
<li><code>public void ifPresent(Consumer&lt;? super T&gt; consumer)</code> : Optional 값이 null이 아닐 경우 consumer를 이용해 소비한다, 값이 저장되어 있지 않을 경우 디폴트 값(매개변수가 디폴트 값이 된다)<ul>
<li>consumer로 집계 값을 받아서 처리하는 코드를 람다식으로 작성한다</li>
</ul>
</li>
<li><code>public T orElse(T other)</code> : Optional의 값이 null일 경우 other를 반환한다, 값이 저장되어 있을 경우 Consumer 에서 처리</li>
<li><code>public T orElseGet(Supplier&lt;? extends T&gt; other)</code> : Optional의 값이 null일 경우 Supplier를 통해 공급받은 값을 반환한다.</li>
<li><code>public &lt;X extends Throwable&gt; T orElseThrow(Supplier&lt;? extends X&gt; exceptionSupplier) throws X</code> : Optional의 값이 null일 경우 exceptionSupplier에서 공급받은 예외를 throw</li>
</ul>
</li>
</ul>
<pre><code class="language-java">    double avg = list.stream()
            .mapToInt(Integer::intValue)
            .average()
            .getAsDouble();
    System.out.println(avg); //NotSuchElementException

    // isPresent()
    OptionalDouble optionalDouble = list.stream()
            .mapToInt(Integer::intValue)
            .average()

    if (optionalDouble.isPresent()){
        System.out.println(&quot;값이 있는 경우 : &quot; + optionalDouble.getAsDouble());
    }else{
        System.out.println(&quot;방법 1-값이 없는 경우 : &quot; + 0.0);

    // orElse()
    double avg = list.stream()
            .mapToInt(Integer::intValue)
            .average()
            .orElse(0.0;
    System.out.println(&quot;방법 2 : &quot; + avg);

    // ifPresent()
    list.add(2);
    list.add(4);
    list.stream()
            .mapToInt(Integer::intValue)
            .average()
            .ifPresent(i-&gt; System.out.println(&quot;방법 3 : &quot;+ i));
    // 값이 없을 경우 false가 되서 종료가 된다. consumer로 했기 때문에 바로 값 출력</code></pre>
<h2 id="수집">수집</h2>
<h3 id="필요한-요소를-수집하여-새로운-collection으로-구성하여-반환하는-메소드">필요한 요소를 수집하여 새로운 Collection으로 구성하여 반환하는 메소드</h3>
<ul>
<li>최종 처리 기능으로 요소들을 수집 또는 그룹핑한다.<ul>
<li>필터링 또는 매핑된 요소들로 최종적으로 얻은요소들로 새로운 컬렉션 생성하는 것.</li>
<li>요소들을 그룹핑하고, 집계를 할 수 있다. </li>
</ul>
</li>
<li>Stream API는  JCF-&gt; STREAM -&gt; 처리 -&gt; 결과</li>
<li>결과가 출력일 수도 있고 값일 수도 있고, 다시 컬렉션으로 만들고 싶을 수 있다.</li>
<li>요소가 여러개 있는 프레임워크 혹은 Arrays에서 스트림을 생성한 다음에 스트림에서 중간 처리를 쭉쭉한 다음에 마지막에 출력이나 값을 낼 수 있지만
다음 중 3가지중 하나의 조건은 꼭 선택해야 한다.<ul>
<li>조건1. foreach()를 사용하거나</li>
<li>조건2. 특정한 값을 리턴을 받거나(reduce())</li>
<li>조건3. count,min,max 스트림을 간추려서 통계를 낼 수 있는 값들을 가져오던지 다시 컬렉션으로 만들어 주던지 해야한다.</li>
</ul>
</li>
</ul>
<h3 id="보통-수집을-하기-위해서-필터링을-한다">보통 수집을 하기 위해서 필터링을 한다.</h3>
<ul>
<li><p>스트림에서 필요한 요소만 필터링해서 별도의 컬렉션으로 만든다</p>
</li>
<li><p>collect라는 메소드 사용 collect(Collector &lt;T,A,R&gt; collector)</p>
</li>
<li><p>collect가  요소를 어떤 컬렉션에 수집할 것인지를 결정한다.</p>
</li>
<li><p>collect()메소드</p>
<ul>
<li><p><code>&lt;R,A&gt; R collect(Collector&lt;? super T,A,R) collector)</code> : collector를 이용해 새로운 Collection R에 담아 반환</p>
<ul>
<li>Collectors의 <code>정적 메소드</code> : toList(), toSet(), toCollection(), toMap(), toConcurrentMap()</li>
</ul>
</li>
<li><p><code>&lt;R, A&gt; R collect(Supplier&lt;R&gt; supplier, BiConsumer&lt;R, ? super T&gt; accumulator, BiConsumer&lt;R, R&gt; combiner)</code> 
: supplier를 통해 공급된 컨테이너 R에 accumulator를 이용해 T값을 저장. 병렬처리 스트림에 사용될 경우 combiner를 이용해 스레드별 컨테이너 R을 통합</p>
</li>
</ul>
</li>
<li><p>Collector의 타입 파라미터</p>
<ul>
<li>T : 요소                                </li>
<li>A : 누적기(accumulator) 요소를 컬렉션에 수집하는 역할을한다.</li>
<li>R : 요소가 저장될 새로운 컬렉션 <ul>
<li>T 요소를 A 누적기가 R에 저장한다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>리턴 타입</th>
<th>메소드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Collector&lt;T,?,Collection<T>&gt;</td>
<td>Collectors.toCollection{Supplier<T>}</td>
<td>Supplier가 제공한 Collection에 저장</td>
</tr>
<tr>
<td>Collector&lt;T,?,ConcurrentMap&lt;K,U&gt;&gt;</td>
<td>Collectors.toConcurrentMap(...)</td>
<td>ConcurrentMap에 저장한다.</td>
</tr>
<tr>
<td>Collector&lt;T,?,List<T>&gt;</td>
<td>Collectors.toList()</td>
<td>List에 저장</td>
</tr>
<tr>
<td>Collector&lt;T,?,Map&lt;K,U&gt;&gt;</td>
<td>Collectors.toMap()</td>
<td>Map에 저장</td>
</tr>
<tr>
<td>Collecotr&lt;T,?,Set<T>&gt;</td>
<td>Collectors.toSet()</td>
<td>Set에 저장</td>
</tr>
</tbody></table>
<ul>
<li><p>Collectors.toConcurrentMap(...) - 멀티쓰레드 환경에서 쓰레드의 안전한 concurrentmap을 만들어서 거기에 요소를 수집하는 Collector를 얻는다. </p>
</li>
<li><p>A가 ? 인 이유</p>
<ul>
<li>List, Set, Map 컬렉션에 누적할 경우 별도의 누적기가 필요 없다. </li>
<li>컬렉터내부에서 이들 컬렉션에 저장하는 방법을 알고 있기 때문에 별도의 누적기가 필요 없음.</li>
</ul>
<pre><code class="language-java">  String[] array = {&quot;Java&quot;, &quot;Is&quot;, &quot;Fun&quot;, &quot;Isn&#39;t&quot;, &quot;It&quot;, &quot;?&quot;};
  List&lt;String&gt; list = Arrays.stream(array)
          .filter(s -&gt; s.length() &gt;= 3)
          .collect(Collectors.toList()); // ArrayList
          // .collect(Collectors.toCollection(LinkedList::new))
  System.out.println(list.getClass().getName() + &quot;:&quot; + list);

  Set&lt;String&gt; set = Arrays.stream(array)
          .filter(s -&gt; s.length() &gt;= 3)
          .collect(Collectors.toSet()); // HashSet
          // .collect(Collectors.toCollection(HashSet::new))
  System.out.println(set.getClass().getName() + &quot;:&quot; + set);

  Map&lt;String, Integer&gt; map = Arrays.stream(array)
          .filter(s -&gt; s.length() &gt;= 3)
          .collect(Collectors.toMap(s -&gt; s, String::length)); // HashMap
          // .collect(Collectors.toCollection(s -&gt; s, String::length, (oldVal, newVal) -&gt; newVal, TreeMap::new))
  System.out.println(map.getClass().getName() + map);</code></pre>
</li>
<li><p>Collectors의 정적 메소드를 이용한 그룹화와 분리</p>
</li>
<li><p>partitioningBy는 어떤 기준으로 무더기로 나누는 것 (2가지 true or false)</p>
</li>
<li><p>groupingBy는 어떤 기준으로 여러개 묶어 내는 것  (여러개)</p>
<ul>
<li><p><code>public static &lt;T, K&gt; Collector&lt;T, ?, Map&lt;K, List&lt;T&gt;&gt;&gt; groupingBy(Function&lt;? super T, ? extends K&gt; classifier)</code>
: classifier를 key값으로, 해당하는 값의 목록을 List인 value로 가지는 Map으로 스트림을 수집하는 Collector를 반환</p>
<ul>
<li><code>public static &lt;T, K, A, D&gt; Collector&lt;T, ?, Map&lt;K, D&gt;&gt; groupingBy(Function&lt;? super T, ? extends K&gt; classifier, Collector&lt;? super T, A, D&gt; downstream)</code> : List 대신 downstream collector로 수집</li>
<li>groupingBy(R Function<T>) - Map&lt;R, List<T>&gt;입력받은게 function으로 출력됨 R타입에 따라 그룹이 됨 그래서 R이 키가 된다.</li>
<li>T를 String..length 로 해주면 R은 Integer</li>
<li>결과 - 1: [...........], 2: [...........], 3: [...........]</li>
<li>키를 기준으로 그룹화 하는 것이다 다 대 다 형태 n:m이면 m이 조금 작을 것이다</li>
</ul>
</li>
<li><p><code>public static &lt;T&gt; Collector&lt;T, ?, Map&lt;Boolean, List&lt;T&gt;&gt;&gt; partitioningBy(Predicate&lt;? super T&gt; predicate)</code> : predicate 결과를 key로, 해당하는 값의 목록을 List value로 가지는 Map으로 스트림을 수집하는 Collector를 반환</p>
<ul>
<li><code>public static &lt;T, A, D&gt; Collector&lt;T, ?, Map&lt;Boolean, D&gt;&gt; partitioningBy(Predicate&lt;? super T&gt; predicate, Collector&lt;? super T, A, D&gt; downstream))</code> : List 대신 downstream collector로 수집</li>
<li>partitionBy(predciate)- Map&lt;Boolean, List<T>&gt; 왜냐하면 이건 두가지로 나누는 것이기 때문에 predicate 계열을 가지고 참인지 거짓인지 판단을 해야 해서</li>
<li>결과 - true :[......] , false: [......]  <pre><code class="language-java">String[] array = {&quot;Java&quot;, &quot;Is&quot;, &quot;Fun&quot;, &quot;Isn&#39;t&quot;, &quot;It&quot;, &quot;?&quot;};
</code></pre>
</li>
</ul>
<p>Map&lt;Character, List<String>&gt; map1 = Arrays.stream(array)</p>
<pre><code>   .collect(Collectors.groupingBy(s -&gt; s.charAt(0)));</code></pre><p>System.out.println(map1);</p>
<p>Map&lt;Boolean, List<String>&gt; map2 = Arrays.stream(array)</p>
<pre><code>   .collect(Collectors.partitioningBy(s -&gt; s.length() &gt;= 3));</code></pre><p>System.out.println(map2);</p>
<pre><code></code></pre></li>
</ul>
</li>
<li><p>집계를 위한 Collector</p>
<ul>
<li>Downstream collector로 집계를 위한 Collector를 사용할 경우 유용하다.</li>
<li>counting(), summingP(), averagingP(), maxBy(), minBy(), reducing()</li>
</ul>
<pre><code class="language-java">String[] array = {&quot;Java&quot;, &quot;Is&quot;, &quot;Fun&quot;, &quot;Isn&#39;t&quot;, &quot;It&quot;, &quot;?&quot;};

  Map&lt;Character, Long&gt; map = Arrays.stream(array)
          .collect(Collectors.groupingBy(s -&gt; s.charAt(0),
                                         Collectors.counting()));
  System.out.println(map);</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java Stream_중간처리메소드]]></title>
            <link>https://velog.io/@im_joonchul/Java-Stream%EC%A4%91%EA%B0%84%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C</link>
            <guid>https://velog.io/@im_joonchul/Java-Stream%EC%A4%91%EA%B0%84%EC%B2%98%EB%A6%AC%EB%A9%94%EC%86%8C%EB%93%9C</guid>
            <pubDate>Sun, 14 Mar 2021 05:55:25 GMT</pubDate>
            <description><![CDATA[<h1 id="중간-처리-메소드중간-연산자">중간 처리 메소드(중간 연산자)</h1>
<ul>
<li>중간 처리 메소드 이후에 최종 처리 메소드를 붙여서 사용한다.</li>
<li>값을 원하는 형태로 처리하기 위한 연산자이다. 중간 연산자들은 lazy하게 실행되고 결과로 stream을 반환한다.<ul>
<li>lazy한 처리는 최종처리메소드가 실행되기전까지 연산이 실행되지 않음,결과가 필요하기 전까지 실행되지 않는다, 연산의 시점을 최대한 늦춘다는 의미이다.</li>
</ul>
</li>
<li>그렇기 때문에 중간연산자는 연쇄적으로 연결하여 연산을 처리할 수 있다. (Ex - list.stream().filter(...).map(...))</li>
</ul>
<table>
<thead>
<tr>
<th>동작</th>
<th>메소드</th>
</tr>
</thead>
<tbody><tr>
<td>필터링</td>
<td>dinstict(), filter()</td>
</tr>
<tr>
<td>자르기</td>
<td>skip(), limit()</td>
</tr>
<tr>
<td>정렬</td>
<td>sorted()</td>
</tr>
<tr>
<td>매핑</td>
<td>flatMap(), flatMapToP(), map(), mapToP(), asDoubleStream(), asLongStream()</td>
</tr>
<tr>
<td>조회</td>
<td>peek()</td>
</tr>
</tbody></table>
<h2 id="필터링">필터링</h2>
<h3 id="필터링은-스트림의-일부-요소를-제거하는-역할을-한다">필터링은 스트림의 일부 요소를 제거하는 역할을 한다.</h3>
<pre><code class="language-java">Stream&lt;String&gt; stringStream = Stream.of(&quot;Java&quot;,&quot;Is&quot;,&quot;Fun&quot;,&quot;Isn&#39;t&quot;,&quot;It&quot;,&quot;?&quot;,&quot;Java&quot;);
stringStream.forEach(System.out::println); // 기본형 중복이 포함되서 출력됨.</code></pre>
<ul>
<li>distinct() : 스트림에 같은 요소가 있을 경우 하나만 남기고 삭제하는 메소드(중복 제거)<pre><code class="language-java">stringStream.distinct().forEach(System.out::println);
// stringStream.distinct() 여기까지 중간처리메소드, foreach는 최종처리 메소드</code></pre>
</li>
<li>filter() : Predicate 계열을 입력을 받아, true인 요소만 남긴다.<pre><code class="language-java">stringStream = Stream.of(&quot;Java&quot;,&quot;Is&quot;,&quot;Fun&quot;,&quot;Isn&#39;t&quot;,&quot;It&quot;,&quot;?&quot;);
stringStream.filter(s- &gt;s.length()&gt;=3).forEach(System.out::println);</code></pre>
</li>
</ul>
<h2 id="자르기">자르기</h2>
<h3 id="자르기는-스트림의-일부-요소를-한번에-생략한다">자르기는 스트림의 일부 요소를 한번에 생략한다.</h3>
<ul>
<li><p>skip(long n) : 스트림의 처음부터 n개의 요소를 생략하는 메소드, n개 자른다. n+1부터 끝까지 반환</p>
<pre><code class="language-java">List&lt;Integer&gt; list = Arrays.asList(1,2,3,4,5,6,7,8,9);
Stream&lt;Integer&gt; stream = list.stream().skip(5).forEach(n-&gt; System.out.println(s));</code></pre>
</li>
<li><p>limit(long maxsize) : 스트림의 최대 요소 개수를 maxsize를 제한한다, maxsize의 요소보다 뒤에 있는 값들은 짤린다. 0부터 n개까지 반환</p>
</li>
</ul>
<pre><code class="language-java">List&lt;Integer&gt; list = Arrays.asList(1,2,3,4,5,6,7,8,9);
Stream&lt;Integer&gt; stream = list.stream().limit(5).forEach(n-&gt; System.out.println(s));
</code></pre>
<h2 id="정렬">정렬</h2>
<h3 id="스트림-요소의-compareto-또는-입력받은-comparator를-이용해-정렬한다">스트림 요소의 <code>compareTo()</code> 또는 입력받은 <code>Comparator</code>를 이용해 정렬한다.</h3>
<pre><code class="language-java">// Comparable 객체를 정렬한 스트림 반환
stringStream = Stream.of(&quot;abc&quot;,&quot;fwf&quot;,&quot;twtie&quot;,&quot;dnmov&quot;,&quot;work&quot;);
stringStream.sorted().forEach(System.out::println); // 사전순으로 정렬됨</code></pre>
<pre><code class="language-java">// Comparator 인터페이스를 람다식으로 구현하여 정렬한다.
// Comparator를 이용하여 정렬된 스트림 반환
stringStream = Stream.of(&quot;abc&quot;,&quot;fwf&quot;,&quot;twtie&quot;,&quot;dnmov&quot;,&quot;work&quot;);
stringStream.sorted((o1, o2) -&gt; o1.length() - o2.length())
                                        .forEach(System.out::println); 
//compreator를 람다식으로 작성해줄 수 있다, 길이가 짧은 것부터 나온다.</code></pre>
<h2 id="매핑">매핑</h2>
<h3 id="function-인터페이스를-이용해-요소의-값을-변환한다">Function 인터페이스를 이용해 요소의 값을 변환한다.</h3>
<ul>
<li><p>map 계열 - 입력 1 : 1 출력</p>
<ul>
<li><p><code>&lt;R&gt; Stream&lt;R&gt; map(Function&lt;? super T, ? extends R&gt; mapper)</code> : 기존 스트림의 T 타입 요소를 R 타입으로 변환하여 새로운 스트림 반환</p>
<pre><code class="language-java">// Function 계열의 인터페이스를 사용하여 스트림의 각 요소를 매핑(Operator 계열도 사용)
stringStream = Stream.of(&quot;abc&quot;,&quot;fwf&quot;,&quot;twtie&quot;,&quot;dnmov&quot;,&quot;work&quot;);
// Function 계열로 string -&gt; integer 로 변환하는 매핑 
// Function&lt;String,Intger&gt;와 같은 형식을 람다식에 넣어준 것이다.
Stream&lt;Integer&gt; stream2 = stringStream.map(s-&gt;s.length()) ;
//입력은 string 출력은 원하는대로 할수 있다
stream2.forEach(System.out::println);</code></pre>
</li>
<li><p><code>PStream mapToP(ToPFunction&lt;? super T&gt; mapper)</code> : R(return)이 기본형 타입으로 제한된 map()</p>
<pre><code class="language-java">// PStream (기본형 타입의 스트림)은 Operator 계열로 처리(자료형 반환x)
// 입출력 값이 똑같기 때문에
IntStream intStream3 = IntStream.of(5,2,30,8,0,2,-34);
IntStream intStream4 = intStream3.map(value -&gt; value * 10); 
// 형 변환이 되지 않고 입력이 출력이 된다.
intStream4.forEach(System.out::println);</code></pre>
</li>
</ul>
</li>
<li><p>flatMap 계열 - 입력 1 : n 출력(스트림 형태로 출력한다.)(Function 계열만 사용)</p>
<ul>
<li><code>&lt;R&gt; Stream&lt;R&gt; flatMap(Function&lt;? super T, ? extends Stream&lt;? extends R&gt;&gt; mapper)</code> : 스트림의 T 타입 요소가 n개의 R 타입 요소로 매핑된 새로운 스트림을 반환</li>
<li><code>PStream flatMapToP(Function&lt;? super T, ? extends PStream&gt; mapper)</code> : R이 기본형 타입으로 제한된 flatMap()<pre><code class="language-java"> // s.split(&quot;&quot;) : &quot;java&quot; -&gt; {&quot;j&quot;,&quot;a&quot;,&quot;v&quot;,&quot;a&quot;}
 List&lt;String&gt; list2 = Arrays.asList(&quot;java&quot;,&quot;backend&quot;,&quot;best&quot;,&quot;course&quot;);
 list2.stream().flatMap(s -&gt; {
     return Arrays.stream(s.split(&quot;&quot;));
 }).forEach(System.out::println); 
 //foreach를 사용하면 스트림이 끝나게 된다.</code></pre>
</li>
</ul>
</li>
</ul>
<h2 id="조회">조회</h2>
<h3 id="스트림-처리-과정에-영향을-미치지-않으며-중간-결과를-확인할-수-있으며-입력받은-스트림과-동일한-스트림을-반환한다">스트림 처리 과정에 영향을 미치지 않으며, 중간 결과를 확인할 수 있으며 입력받은 스트림과 동일한 스트림을 반환한다.</h3>
<ul>
<li>Stream<T> peek(Consumer&lt;? super T&gt; action)<ul>
<li>peek() -&gt; Consumer 계열의 람다식 입력을 받아 입력 요소를 소비</li>
<li>peek()는 입력받아 스트림과 동일한 스트림을 다시 출력<pre><code class="language-java">System.out.println(list2.stream().flatMap(s -&gt; {
 return Arrays.stream(s.split(&quot;&quot;));
}).peek(s-&gt; System.out.println(&quot;flatMap():&quot;+s))
       .distinct().peek(s-&gt; System.out.println(&quot;distinct():&quot;+s))
       .count()); // 함수형 프로그래밍은 선언형이어서 어떻게 해라라고 말해야한다.
// flatmap은 모든 요소를 다 나타내고 distinct는 중복된것을 없애고 하나만 출력됨.</code></pre>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[정규표현식]]></title>
            <link>https://velog.io/@im_joonchul/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D</link>
            <guid>https://velog.io/@im_joonchul/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D</guid>
            <pubDate>Sun, 14 Mar 2021 05:43:55 GMT</pubDate>
            <description><![CDATA[<h1 id="정규표현식regular-expression">정규표현식(Regular Expression)</h1>
<h2 id="정규표현식이란">정규표현식이란?</h2>
<ul>
<li>문자열을 다루는 패턴화된 작업을 정의하는 수식</li>
<li>문자열 매칭, 템플릿 일치 여부 확인, 템플릿 매칭 검색(문서가 있을 때 이메일만 뽑는 작업을 할 때 등등)</li>
<li>정규표현식은 느리기 때문에 남용하면 안된다. 많은 동작을 돌리면 안된다. 알고리즘 문제를 정규표현식을 푸는건 적합하지 않음</li>
<li>특정 조건에 맞는 문자열을 검색(search) / 치환(Replace)를 하는 패턴 기반의 식( 패턴: 전화번호 같은 것, 이메일)</li>
<li>이메일, 전화 번호 등 특정한 형식에 맞게 적혀 있는지 Validation 하는데 사용 가능</li>
<li>Crawling(자료를 긁어 모으는 것) 등 날 것의 자료를 긁어 모았을 때 정리 하는데 유용</li>
<li>튜브 댓글이 있으면 형식에 따라 분석을 하고 구분을 할 수 있다.</li>
</ul>
<h2 id="정규표현식-표현-방법">정규표현식 표현 방법</h2>
<ul>
<li><p>정규 표현식의 기본 작성 방식</p>
<pre><code class="language-text">&quot;/패턴/[플래그(Opt.)]&quot;</code></pre>
</li>
<li><p>기본 메타 문자</p>
<table>
<thead>
<tr>
<th>메타 문자</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td><code>^x</code></td>
<td>x로 시작</td>
</tr>
<tr>
<td><code>x$</code></td>
<td>x로 끝</td>
</tr>
<tr>
<td><code>.x</code></td>
<td>x앞에 하나의 문자가 있다.</td>
</tr>
<tr>
<td><code>x+</code></td>
<td>x가 1번 이상 반복</td>
</tr>
<tr>
<td><code>x?</code></td>
<td>x가 있거나 없다.</td>
</tr>
<tr>
<td><code>x*</code></td>
<td>x가 0번 이상 반복</td>
</tr>
<tr>
<td><code>.</code></td>
<td>아무 문자 하나를 의미</td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><p>괄호의 활용</p>
<table>
<thead>
<tr>
<th>regexp</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td><code>(xy)</code></td>
<td>괄호 안의 내용을 그룹화</td>
</tr>
<tr>
<td><code>x{n}</code></td>
<td>n번 반복됨</td>
</tr>
<tr>
<td><code>x{n,}</code></td>
<td>n번 이상 반복됨</td>
</tr>
<tr>
<td><code>x{n, m}</code></td>
<td>n번 이상, m번 이하 반복됨</td>
</tr>
<tr>
<td><code>[xy]</code></td>
<td>x 또는 y</td>
</tr>
<tr>
<td><code>[a-z]</code></td>
<td>알파벳 소문자 (a~z)</td>
</tr>
<tr>
<td><code>[0-9]</code></td>
<td>숫자</td>
</tr>
<tr>
<td><code>[가-힣]</code></td>
<td>한글</td>
</tr>
<tr>
<td><code>[^x]</code></td>
<td>x가 아닌 것</td>
</tr>
<tr>
<td><code>[^0-9]</code></td>
<td>숫자가 아닌 것</td>
</tr>
</tbody></table>
</li>
<li><p><code>\...</code> 축약 문자</p>
<table>
<thead>
<tr>
<th>regexp</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td><code>\^</code>,<code>\.</code>...</td>
<td><code>\</code> 뒤에 나오는 문자를 문자로 처리</td>
</tr>
<tr>
<td><code>\b</code></td>
<td>단어의 경계를 찾는다.</td>
</tr>
<tr>
<td><code>\B</code></td>
<td>단어의 경계가 아닌 것을 찾는다.</td>
</tr>
<tr>
<td><code>\d</code></td>
<td>숫자를 찾는다.</td>
</tr>
<tr>
<td><code>\D</code></td>
<td>숫자가 아닌 것을 찾는다.</td>
</tr>
<tr>
<td><code>\s</code></td>
<td>공백 문자를 찾는다.</td>
</tr>
<tr>
<td><code>\S</code></td>
<td>공백 문자가 아닌 것을 찾는다.</td>
</tr>
<tr>
<td><code>\w</code></td>
<td>[a-zA-Z0-9_]</td>
</tr>
<tr>
<td><code>\W</code></td>
<td>[^a-zA-Z0-9_]</td>
</tr>
</tbody></table>
</li>
<li><p>유용한 정규식 예</p>
<ul>
<li>한글 이름 : <code>^[가-힣]{2,5}$</code></li>
<li>핸드폰 번호: <code>^01(0|1|2|6|9)[-\s]?\d{3,4}[-\s]?\d{4}$</code></li>
<li>이메일 주소: <code>^[\w\.-]{1,64}@[\w\.-]{1,252}\.\w{2,4}$</code></li>
</ul>
</li>
</ul>
<h2 id="flag">Flag</h2>
<table>
<thead>
<tr>
<th>Flag</th>
<th>기능</th>
</tr>
</thead>
<tbody><tr>
<td><code>g</code></td>
<td>문자열 내 모든 패턴을 찾음</td>
</tr>
<tr>
<td><code>i</code></td>
<td>대소문자를 구분하지 않음</td>
</tr>
<tr>
<td><code>m</code></td>
<td>문자열의 모든 줄에서 찾음</td>
</tr>
</tbody></table>
<h2 id="정규표현식을-사용하는-클래스">정규표현식을 사용하는 클래스</h2>
<h3 id="pattern-클래스">Pattern 클래스</h3>
<table>
<thead>
<tr>
<th>메소드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>public</td>
<td>static Pattern compile(String regex)    Pattern 객체를 생성</td>
</tr>
<tr>
<td>public</td>
<td>Matcher matcher(CharSequence input)    입력을 분석하는 Matcher 객체 생성</td>
</tr>
<tr>
<td>public</td>
<td>static boolean matches(String regex, CharSequence input)    입력이 regexp에 해당하는지 판단</td>
</tr>
</tbody></table>
<h3 id="matcher-클래스">Matcher 클래스</h3>
<table>
<thead>
<tr>
<th>메소드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>find()</td>
<td>정규표현식에 부합되는 내용이 문자열에 포함되어 있는지 반환. 이전 검색 위치부터 이어서 검색.</td>
</tr>
<tr>
<td>start()</td>
<td>패턴에 부합되는 요소의 시작 인덱스 반환</td>
</tr>
<tr>
<td>end()</td>
<td>패턴에 부합되는 요소가 끝나는 위치 + 1을 반환</td>
</tr>
<tr>
<td>matches()</td>
<td>문자열 전체가 정규표현식에 일치하는지 반환</td>
</tr>
<tr>
<td>lookingAt()</td>
<td>비교하려는 문자열이 정규표현식으로 시작하는지 반환. 0번 인덱스부터 검색.</td>
</tr>
<tr>
<td>replaceFirst()</td>
<td>일치하는 첫 패턴을 문자열로 대체</td>
</tr>
<tr>
<td>replaceAll()</td>
<td>일치하는 모든 패턴을 문자열로 대체</td>
</tr>
<tr>
<td>reset()</td>
<td>Matcher의 정보를 리셋하여 0번 인덱스부터 다시 검색</td>
</tr>
</tbody></table>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://regexper.com/">정규표현식을 이미지로 보여주 사이트</a></li>
<li><a href="https://regexone.com/lesson/introduction_abcs">정규표현식 연습문제 사이트</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[참조 자료형]]></title>
            <link>https://velog.io/@im_joonchul/%EC%B0%B8%EC%A1%B0-%EC%9E%90%EB%A3%8C%ED%98%95</link>
            <guid>https://velog.io/@im_joonchul/%EC%B0%B8%EC%A1%B0-%EC%9E%90%EB%A3%8C%ED%98%95</guid>
            <pubDate>Sun, 14 Mar 2021 05:40:52 GMT</pubDate>
            <description><![CDATA[<h1 id="참조-자료형referencedatatype">참조 자료형(ReferenceDataType)</h1>
<h2 id="변수의-자료형">변수의 자료형</h2>
<p><img src="https://images.velog.io/images/im_joonchul/post/22730326-16b7-4d93-88fb-ea14203e0a22/%EC%B0%B8%EC%A1%B0%20%EC%9E%90%EB%A3%8C%ED%98%95.png" alt="참조자료형"></p>
<ul>
<li>기본 자료형은 사용하는 메모리가 정해져 있지만, 참조 자료형은 클래스에 따라 다르다.</li>
</ul>
<h2 id="참조-자료형-직접-만들어-사용하기">참조 자료형 직접 만들어 사용하기</h2>
<ul>
<li>학생 클래스에 있는 과목 이름, 과목 성적 속성을 학생클래스와 과목 클래스로 분리하고,
과목 참조 자료형 멤버 변수를 학생에 정의하여 사용한다.</li>
</ul>
<p><img src="https://images.velog.io/images/im_joonchul/post/51f6b693-a86a-4372-8fb7-506631f6bf77/%EC%B0%B8%EC%A1%B0%EC%9E%90%EB%A3%8C%ED%98%952.png" alt="참조자료형"></p>
<ul>
<li>예제<pre><code class="language-java"></code></pre>
</li>
</ul>
<p>// Subject 클래스
public class Student {
    int stuID;
    String stuName;
    Subject korSub;
    Subject matSub;</p>
<pre><code>public Student(int stuID,String stuName){
    this.stuID = stuID;
    this.stuName = stuName;

    korSub = new Subject();
    matSub = new Subject();
}

public void setKoreaSubject(String subName, int subScore) {
    korSub.subName = subName;
    korSub.subScore = subScore;
}

public void setMathSubject(String subName, int subScore) {
    matSub.subName = subName;
    matSub.subScore = subScore;
}

public void getKoreaSubject(String subName,int subScore){
    korSub.setSubject(subName,subScore);
}

public void getMathSubject(String subName,int subScore){
    matSub.setSubject(subName,subScore);
}

public void showStudentScore() {
    int total = korSub.subScore + matSub.subScore;
    System.out.println(stuName+&quot;학생의 총점은 &quot;+total+&quot;입니다.&quot;);
}</code></pre><p>}</p>
<p>// Subject 클래스
public class Subject {
    String subName;
    int subScore;</p>
<pre><code>public void setSubject(String subName,int subScore){
    this.subName = subName;
    this.subScore = subScore;
}</code></pre><p>}</p>
<p>// Test클래스
public class StudentTest {
    public static void main(String[] args) {
        Student studentLee = new Student(123,&quot;lee&quot;);
        Student studentKim = new Student(456,&quot;kim&quot;);</p>
<p>//        studentLee.setKoreaSubject(&quot;국어&quot;,100);
//        studentLee.setMathSubject(&quot;수학&quot;,95);
//        studentKim.setKoreaSubject(&quot;국어&quot;,99);
//        studentKim.setMathSubject(&quot;수학&quot;,80);</p>
<pre><code>    studentLee.getKoreaSubject(&quot;국어&quot;,95);
    studentLee.getMathSubject(&quot;수학&quot;,100);
    studentKim.getKoreaSubject(&quot;국어&quot;,99);
    studentKim.getMathSubject(&quot;수학&quot;,80);

    studentLee.showStudentScore();
    studentKim.showStudentScore();

}</code></pre><p>}
```</p>
]]></description>
        </item>
    </channel>
</rss>