<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>0ne-hsj.log</title>
        <link>https://velog.io/</link>
        <description>@Hanyang univ(seoul). CSE</description>
        <lastBuildDate>Sun, 22 Sep 2024 14:29:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. 0ne-hsj.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/0ne-hsj" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[BE development plan]]></title>
            <link>https://velog.io/@0ne-hsj/BE-development-plan</link>
            <guid>https://velog.io/@0ne-hsj/BE-development-plan</guid>
            <pubDate>Sun, 22 Sep 2024 14:29:19 GMT</pubDate>
            <description><![CDATA[<h3 id="협업-방식">협업 방식</h3>
<h4 id="2명이서-각자-db-server와-application-server를-맡는게-좋을까">2명이서 각자 DB server와 Application server를 맡는게 좋을까?</h4>
<ul>
<li>BE developer database operation(queries, schema design) and the business logic layer (services, controllers) 모두를 다룰 줄 알아야 한다.</li>
<li>병목현상 : debugging, testing, evolving application을 위해 database에 변경이 생길 때마다 기다려야 함</li>
</ul>
<h4 id="그럼-end-to-end-ownership-of-features">그럼? end-to-end ownership of features</h4>
<p>modules, functionalities에 따라 분류해, 각각의 features마다 DBdesign + businessLogic + API development을 모두 다루도록 하기</p>
<h4 id="db-server와-application-server로-분리">DB server와 Application server로 분리</h4>
<h1 id="1st-requirement-gathering-and-planning">1st. Requirement Gathering and Planning</h1>
<p>(both)</p>
<h3 id="output">Output</h3>
<blockquote>
<p>Detailed requirement document and task assignment.</p>
</blockquote>
<h3 id="detail-task">Detail task</h3>
<p>•    Clearly define the requirements for each feature.
•    Break down the service into manageable modules (e.g., “Publisher Management,” “Book Management,” “Stock Management,” etc.).</p>
<p>•    Assign features to each person. For example:</p>
<pre><code>    •    Person 1: Handles Publisher Management and Book Inventory.
    •    Person 2: Handles Orders and Stock Management.</code></pre><hr>
<h1 id="2nd-high-level-system-architecture-design">2nd. High-Level System Architecture Design</h1>
<p>(both)</p>
<h3 id="output-1">Output</h3>
<blockquote>
<p>Architecture diagram (data flow, service-to-service communication, etc.)</p>
</blockquote>
<h3 id="detailed-task">detailed task</h3>
<p>•    Design the overall architecture of the system, including the application server (Spring Boot) and database server (MySQL, PostgreSQL, etc.).</p>
<p>•    Agree on a shared structure for your REST API design (e.g., /publishers, /books, /orders).</p>
<hr>
<h1 id="3rd-database-design-and-schema-definition">3rd. Database Design and Schema Definition</h1>
<p>(Each Person for Their Feature)</p>
<h3 id="output-2">Output</h3>
<p>•    ER Diagrams for your features.
•    JPA entities with relationships and proper annotations (@OneToMany, @ManyToOne, etc.).</p>
<h3 id="detailed-task-1">detailed task</h3>
<p>•    Each person will design the database schema for their feature(s). For example:</p>
<pre><code>•    Person 1: Designs tables for Publisher, Book, and BookInventory.
•    Person 2: Designs tables for Order, Stock, and Return.</code></pre><p>•    Define the relationships (one-to-many, many-to-many) using JPA annotations in Spring Boot.
•    Use tools like Flyway or Liquibase to manage migrations and keep the database schema consistent.</p>
<h3 id="migration-tool의-사용">migration Tool의 사용</h3>
<hr>
<h1 id="4th-jpa-entity-modeling">4th. JPA Entity Modeling</h1>
<p>(Each Person for Their Feature)</p>
<h3 id="output-3">Output</h3>
<p>JPA entity classes for each feature.</p>
<h3 id="detailed-task-2">Detailed task</h3>
<p>•    Create JPA entity classes that represent your database tables.</p>
<p>•    Example for Person 1 (Publisher Management):</p>
<pre><code>•    Publisher, Book, BookInventory entities.</code></pre><p>•    Example for Person 2 (Order Management):</p>
<pre><code>•    Order, Stock, Return entities.</code></pre><p>•    Define relationships, constraints, and cascading operations where needed.</p>
<hr>
<h1 id="5th-repository-layer">5th. Repository Layer</h1>
<p>(Each Person for Their Feature)</p>
<h3 id="output-4">Output</h3>
<p>Repository classes to interact with the database.</p>
<h3 id="detailed-task-3">Detailed task</h3>
<p>•    Create Spring Data JPA repositories for each entity.
•    Use repositories to handle CRUD operations for the database.
•    Example for Person 1</p>
<pre><code>        •    PublisherRepository, BookRepository.</code></pre><p>•    Example for Person 2:</p>
<pre><code>•    OrderRepository, StockRepository.</code></pre><p>•    Implement custom queries for complex retrievals using @Query annotations or JPA method conventions.</p>
<hr>
<h1 id="6th-service-layer-implemetation">6th. Service Layer Implemetation</h1>
<p>(Each Person for Their Feature)</p>
<h3 id="output-5">output</h3>
<p>Service classes that contain all the business logic.</p>
<h3 id="detailed-task-4">detailed task</h3>
<p>•    Implement the service classes that contain the business logic for your assigned features.
•    Example for Person 1:</p>
<pre><code>•    PublisherService: Logic for adding, editing, and retrieving publishers.
•    BookInventoryService: Logic for managing book stock and availability.</code></pre><p>•    Example for Person 2:</p>
<pre><code>•    OrderService: Logic for processing orders, handling returns, and updating stock.
•    StockService: Logic for adjusting stock levels and validating transactions.</code></pre><p>•    Use @Transactional to manage transactions where multiple database operations need to happen atomically.</p>
<hr>
<h1 id="7th-rest-api-development">7th. REST API Development</h1>
<p>(Each Person for Their Feature)  </p>
<h3 id="output-6">output</h3>
<p>REST API endpoints for each feature.</p>
<h3 id="detailed-task-5">detailed task</h3>
<p>• Implement controllers to expose the business logic via RESTful APIs.<br>• Example for Person 1:  </p>
<ul>
<li>Create endpoints like <code>/publishers</code>, <code>/books</code>, <code>/inventory</code>.  </li>
<li>Example:  <ul>
<li><code>GET /publishers</code> to list all publishers.  </li>
<li><code>POST /books</code> to add a new book.<br>• Example for Person 2:  </li>
</ul>
</li>
<li>Create endpoints like <code>/orders</code>, <code>/stock</code>, <code>/returns</code>.  </li>
<li>Example:  <ul>
<li><code>POST /orders</code> to place a new order.  </li>
<li><code>GET /orders/{id}</code> to get order details.<br>• Ensure you handle validation, error handling, and responses in a standardized way (e.g., returning HTTP status codes and proper error messages).</li>
</ul>
</li>
</ul>
<hr>
<h1 id="8th-security-and-authentication">8th. Security and Authentication</h1>
<p>(Both)  </p>
<h3 id="output-7">output</h3>
<p>Secured APIs with user authentication and role-based access.</p>
<h3 id="detailed-task-6">detailed task</h3>
<p>• Implement security using <strong>Spring Security</strong> to protect sensitive endpoints.<br>• Define roles and permissions (e.g., admin vs regular users).<br>• Use JWT tokens or OAuth for user authentication.<br>• Secure routes like <code>/inventory</code>, <code>/orders</code> with proper role-based access control.</p>
<hr>
<h1 id="9th-testing">9th. Testing</h1>
<p>(Each Person for Their Feature)  </p>
<h3 id="output-8">output</h3>
<p>A suite of tests to ensure both database interactions and APIs work as expected.</p>
<h3 id="detailed-task-7">detailed task</h3>
<p>• Write <strong>unit tests</strong> for your service layer to ensure business logic is working correctly.<br>• Write <strong>integration tests</strong> for your REST APIs to ensure they respond correctly to requests.<br>• Use <strong>JUnit</strong>, <strong>Mockito</strong>, and Spring Boot&#39;s testing features for this.</p>
<hr>
<h1 id="10th-database-and-application-server-setup">10th. Database and Application Server Setup</h1>
<p>(Both)  </p>
<h3 id="output-9">output</h3>
<p>Fully functional database and application servers, ready for use.</p>
<h3 id="detailed-task-8">detailed task</h3>
<p>• Set up the <strong>database server</strong> (MySQL, PostgreSQL) on a cloud platform or local environment.<br>• Set up the <strong>Spring Boot application server</strong>.  
• Configure database connections in <code>application.properties</code> or <code>application.yml</code>.</p>
<hr>
<h1 id="11th-cicd-and-deployment">11th. CI/CD and Deployment</h1>
<p>(Both)  </p>
<h3 id="output-10">output</h3>
<p>Deployed application with automated testing and deployment processes.</p>
<h3 id="detailed-task-9">detailed task</h3>
<p>• Use Docker to containerize both the application and database servers for consistent deployment.<br>• Set up a <strong>CI/CD pipeline</strong> (e.g., GitHub Actions, Jenkins, GitLab CI) to automate testing and deployment.<br>• Deploy the application to a cloud platform (AWS, Azure, GCP) or use a container orchestration tool like <strong>Kubernetes</strong>.</p>
<hr>
<h1 id="12th-final-integration-and-optimization">12th. Final Integration and Optimization</h1>
<p>(Both)  </p>
<h3 id="output-11">output</h3>
<p>Finalized and optimized backend ready for production.</p>
<h3 id="detailed-task-10">detailed task</h3>
<p>• Integrate all features and ensure that they work together smoothly.<br>• Perform load testing to ensure that the application can handle the expected number of users.<br>• Optimize performance for any database queries that are slow or APIs that are inefficient.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Proxy and Associations]]></title>
            <link>https://velog.io/@0ne-hsj/Proxy-and-Associations</link>
            <guid>https://velog.io/@0ne-hsj/Proxy-and-Associations</guid>
            <pubDate>Thu, 04 Jul 2024 12:53:51 GMT</pubDate>
            <description><![CDATA[<h2 id="when-and-why">When and Why?</h2>
<h5 id="연관관계에-걸린-두-엔티티의-모든-정보를-조회해야하는-경우가-있는가-하면-두-엔티티-중-하나의-정보만-조회해도-되는-경우도-있다">연관관계에 걸린 두 엔티티의 모든 정보를 조회해야하는 경우가 있는가 하면, 두 엔티티 중 하나의 정보만 조회해도 되는 경우도 있다.</h5>
<h3 id="프록시란">프록시란?</h3>
<h4 id="emgetreference--db-쿼리가-안나가는데-객체가-조회가-되는-것"><code>em.getReference()</code> : DB 쿼리가 안나가는데 객체가 조회가 되는 것.</h4>
<ul>
<li><code>em.find()</code>는 DB를 조회해서 실제 entity 객체를 조회하는 반면, hibernate가 내부의 라이브러리를 이용해 가짜 엔티티객체 (프록시)를 줌</li>
<li>proxy : 1) 실제 클래스를 상속받아 만들어 겉 모양이 같음 2) 실제 객체의 reference(=target)을 보관함 <h4 id="프록시-특징">프록시 특징</h4>
</li>
</ul>
<ol>
<li>proxy object는 처음 사용할 때 한 번만 초기화</li>
<li>프록시 객체를 초기화 할 때 <strong>프록시 객체가 실제 엔티티로 바뀌는 게 아님.</strong> 접근 가능해지는 것이지 내부의 참조만 target으로 가지게 될 뿐</li>
<li>원본 entity를 상속받기에 타입 체크시 주의 : <code>==</code>대신 <code>instanceof</code>사용</li>
<li>Persistence Context에 찾는 entity가 이미 있으면 <strong>em.getReference를 호출해도 실제 entity를 반환</strong>
1) 이미 1차캐시에 있는데 proxy로 반환해봐야 얻을 수 있는 이점이 없음
2) 한 PersistenceContext에 존재하고 PK가 동일하면 동일성을 보장하기 위해서</li>
<li>PersistenceContext의 도움을 받을 수 없는 준영속상태일 때 proxy를 초기화하면 문제 발생</li>
</ol>
<h3 id="즉시로딩과-지연로딩">즉시로딩과 지연로딩</h3>
<pre><code class="language-java">    @Entity
    public class Member {
        @Id @GeneratedValue
        private Long id;

        @Column(name = &quot;username&quot;)
        private String name;

        @ManyToOne(fetch = FetchType.Lazy)
        @JoinColumn(name = &quot;team_id&quot;)
        private Team team;
    }</code></pre>
<pre><code class="language-java">    Member member = em.find(Member.class, 1L);
    //member.team은 프록시임
    Team team = member.getTeam();
    team.getName(); //실제 team을 사용하는 시점에 초기화; DB조회</code></pre>
<h4 id="실무에선-모든-연관관계에-지연로딩만-사용해야-함">실무에선, 모든 연관관계에 지연로딩만 사용해야 함</h4>
<ul>
<li>JPQL fetch조인이나 entity 그래프기능을 사용해야 함.</li>
<li>즉시로딩을 사용하면 예상치 못한 SQL이 발생</li>
<li>또한 JPQL에서 N+1 문제를 일으킴<ul>
<li>처음 query를 하나 날렸는데 그것 때문에 추가 query가 n개 나간다고 해서 N+1문제라고 한다.<h5 id="→-manytooneonetoone은-기본이-즉시로딩이므로-lazy로-설정해야-함">→ <code>ManyToOne``OneToOne</code>은 기본이 즉시로딩이므로 Lazy로 설정해야 함.</h5>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="persistence-cascade">persistence Cascade</h3>
<blockquote>
<p>WHEN AND WHY? 특정 entity를 persist할 때 연관된 entity도 함께 persist하고 싶을 때 
특히, 어떤 entity가 단일 Entity에 완전히 종속적일 때; 다른 entity와 연관관계가 없을 경우</p>
</blockquote>
<ul>
<li>예를 들어, 부모 Entity를 저장할 때 자식 entity도 함께 저장하는 경우</li>
</ul>
<h4 id="association-mapping과-아무-관련이-없음-그저-함께-persist하는-편리함을-제공할-뿐">association mapping과 아무 관련이 없음. 그저 함께 Persist하는 편리함을 제공할 뿐</h4>
<h4 id="종류">종류</h4>
<ul>
<li>ALL</li>
<li>Persist</li>
<li>Remove<h3 id="orphan-object">orphan Object</h3>
부모 Entity와 association이 끊어진 자식 entity를 자동으로 삭제
<code>orphanRemoval = true</code></li>
</ul>
<h4 id="참조하는-곳이-하나일-때만-사용해야-함-특정-entity가-개인-소유할-때-사용해야-함">참조하는 곳이 하나일 때만 사용해야 함. 특정 Entity가 개인 소유할 때 사용해야 함.</h4>
<h3 id="cascadetypeall-orphanremovaltrue"><code>CascadeType.ALL, orphanRemoval=true</code></h3>
<ul>
<li>두 옵션을 모두 활성화할 때, 부모entity를 통해 자식의 생명 주기를 관리할 수 있음</li>
<li>스스로 생명주기를 관리하는 entity는 <code>em.persist()</code> 후 <code>em.remove()</code>로 제거한다.</li>
</ul>
<h4 id="ddd도메인-주도-설계의-aggregate-root개념을-구현할-때-유용">DDD(도메인 주도 설계)의 Aggregate Root개념을 구현할 때 유용.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[ORM - entity, association]]></title>
            <link>https://velog.io/@0ne-hsj/ORM-entity-relationships</link>
            <guid>https://velog.io/@0ne-hsj/ORM-entity-relationships</guid>
            <pubDate>Thu, 04 Jul 2024 05:38:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Object-RDB Mapping</p>
</blockquote>
<h1 id="entity-mapping">entity mapping</h1>
<p>DDL(DataDefinitionLanguage)을 application 실행 시점에 자동 생성 → database schema(Tables, Field/columns, relationships ...)가 자동 생성됨</p>
<ul>
<li>이때 database dialect를 사용하여 적절한 DDL생성</li>
<li>테이블 중심에서 객체 중심으로</li>
<li>개발 서버에서만 사용해야 함! (운영 서버에서는 사용 ㄴㄴ or 다듬어서 사용)<h4 id="개요">개요</h4>
</li>
</ul>
<table>
<thead>
<tr>
<th><strong>Category</strong></th>
<th><strong>Annotations</strong></th>
</tr>
</thead>
<tbody><tr>
<td>객체와 테이블 매핑</td>
<td>@Entity, @Table</td>
</tr>
<tr>
<td>필드와 컬럼 매핑</td>
<td>@Column</td>
</tr>
<tr>
<td>기본 키 매핑</td>
<td>@Id</td>
</tr>
<tr>
<td>연관관계 매핑</td>
<td>@ManyToOne, @JoinColumn</td>
</tr>
</tbody></table>
<h4 id="hibernatehbm2ddlauto"><code>hibernate.hbm2ddl.auto</code></h4>
<ul>
<li>운영 장비에는 절대 create, create-drop, update 사용하면 안됨</li>
<li>local서버에서만 update, create사용하자</li>
</ul>
<h2 id="object---table-mapping">Object - table mapping</h2>
<h3 id="entity"><code>@Entity</code></h3>
<p><code>@Entity</code>가 붙은 클래스를 entity라 하고, JPA가 관리한다. 
 실제 DB 테이블과 매핑되는 핵심 클래스로, 데이터베이스의 테이블에 존재하는 컬럼들을 필드로 가지는 객체</p>
<h4 id="속성-name">속성 name</h4>
<p>JPA에서 사용할 entity의 이름.
기본값 = 클래스 명</p>
<hr>
<h2 id="field와-column-mapping">field와 Column mapping</h2>
<h4 id="column-매핑-사용"><code>@Column</code> 매핑 사용</h4>
<p>속성은 다음과 같다
<img src="https://velog.velcdn.com/images/0ne-hsj/post/c77ba852-8d37-4d8d-9440-a45663736b97/image.png" alt=""></p>
<h4 id="enum타입의-경우-enumeratedenumtypestring">enum타입의 경우 <code>@Enumerated(EnumType.STRING)</code></h4>
<h4 id="매핑하지-않으려면-transient">매핑하지 않으려면 <code>@Transient</code></h4>
<h4 id="긴-것은-lob이용">긴 것은 <code>@Lob</code>이용</h4>
<hr>
<h2 id="primarykey-mapping">PrimaryKey mapping</h2>
<ul>
<li><p>기본 키 제약 조건: null 아님, 유일, 변하면 안된다.</p>
</li>
<li><p>but, 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
  예를 들어 주민등록번호도 기본 키로 적절하기 않다. </p>
<blockquote>
<p>⟹ 권장: Long형 + 대체키 + 키 생성전략(AUTO_INCREMENT, SEQUENCE_OBJECT 사용 등)</p>
</blockquote>
<ul>
<li>직접 할당: @Id만 사용</li>
<li>자동 생성 : @GeneratedValue 사용</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th><strong>Generation Strategy</strong></th>
<th><strong>Description</strong></th>
<th><strong>Database</strong></th>
<th><strong>Additional Annotation</strong></th>
</tr>
</thead>
<tbody><tr>
<td>IDENTITY</td>
<td>데이터베이스에 위임</td>
<td>MYSQL</td>
<td>None</td>
</tr>
<tr>
<td>SEQUENCE</td>
<td>데이터베이스 시퀀스 오브젝트 사용</td>
<td>ORACLE</td>
<td>@SequenceGenerator</td>
</tr>
<tr>
<td>TABLE</td>
<td>키 생성용 테이블 사용, 모든 DB에서 사용</td>
<td>All Databases</td>
<td>@TableGenerator</td>
</tr>
<tr>
<td>AUTO</td>
<td>방언에 따라 자동 지정, 기본값</td>
<td>Default</td>
<td>None</td>
</tr>
</tbody></table>
<h3 id="1-identity-전략--기본-키-생성을-데이터베이스에-위임">1) IDENTITY 전략 : 기본 키 생성을 데이터베이스에 위임</h3>
<ul>
<li>MySQL, PostgresQL,, </li>
<li>JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행한다 그러나 AUTO_ INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 PK값이 나오기 때문에</li>
<li>따라서 IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회</li>
</ul>
<pre><code class="language-java">    @Entity
    public class Member {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;</code></pre>
<h3 id="2-sequence-전략">2) SEQUENCE 전략</h3>
<p>database sequence = 유일한 값을 순서대로 생성하는 DB Object</p>
<ul>
<li>oracle, PostgresQL, H2</li>
</ul>
<pre><code class="language-java">    @Entity
    @SequenceGenerator(
        name = &quot;MEMBER_SEQ_GENERATOR&quot;,
        sequenceName = &quot;MEMBER_SEQ&quot;,
        initialValue = 1, allocationSize = 50)
    public class Member {
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE)
        private Long id;</code></pre>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/327ca1bb-a529-4e4f-bc46-bfe4f87941c9/image.png" alt=""></p>
<h3 id="table-전략">TABLE 전략</h3>
<p>키 생성 전용 테이블을 하나 만들어서 database sequence를 흉내내는 전략</p>
<ul>
<li>모든 DB에 적용가능</li>
<li>성능이 안좋음</li>
</ul>
<hr>
<h2 id="association-mapping">association mapping</h2>
<ul>
<li>객체의 reference와 table의 foreign Key를 mapping</li>
<li>table은 FK로 join해서 연관 Table을 찾음</li>
<li>객체는 참조를 사용해서 연관된 객체를 찾음</li>
</ul>
<h3 id="1-단방향-mapping만으로-일단-설계를-완료해야-함">1. 단방향 mapping만으로 일단 설계를 완료해야 함</h3>
<p>테이블 설계를 같이 그리면서 객체 설계가 일어나야 함
이때 단방향으로 설계를 끝내야 함</p>
<h4 id="단방향으로-이미-설계가-완료된-것">단방향으로 이미 설계가 완료된 것</h4>
<h4 id="단지-역방향으로-조회하기-위해-단방향을-필요할-때만-또-추가해서-양방향을-만드는-것이다">단지 역방향으로 조회하기 위해 단방향을 필요할 때만 또 추가해서 양방향을 만드는 것이다.</h4>
<ul>
<li>JPQL에서 역방향으로 탐색해야할 일이 많음</li>
<li>어플리케이션 개발 때 추가<h4 id="양방향-association">양방향 association</h4>
</li>
<li>table의 경우, FK가 다른 테이블에서 PK이므로 FK하나로 양쪽을 다 알 수 있다(양쪽으로 join가능)</li>
<li>객체의 양방향 관계는 사실상 서로 다른 2개의 단방향 관계이다.<h5 id="따라서-객체의-두-관계-중-하나를-연관관계의-주인으로-지정해-이것-만이-외래키를-관리등록-수정할-수-있어야-한다">따라서 객체의 두 관계 중 하나를 연관관계의 주인으로 지정해 이것 만이 외래키를 관리(등록, 수정)할 수 있어야 한다.</h5>
<h5 id="fk가-있는-쪽을-주인으로-정하자-비즈니스적으로-중요한-쪽이-주인이-되는-것이-아니다"><strong>FK가 있는 쪽을 주인으로 정하자</strong>. 비즈니스적으로 중요한 쪽이 주인이 되는 것이 아니다.</h5>
</li>
<li>1 : N이면 N이 주인</li>
<li>주인이 아닌쪽은 읽기만 가능</li>
<li>주인은 <code>mappedBy</code>속성을 사용하면 ㄴㄴ, 주인이 아닌 쪽이 <code>mappedBy</code>로 주인을 지정해야 함
<img src="https://velog.velcdn.com/images/0ne-hsj/post/d42c28fa-77a3-4a99-b12d-1316cd757e8f/image.png" alt=""></li>
</ul>
<h4 id="주의점">주의점</h4>
<h5 id="1-연관관계-owner에-값을-입력해야-한다-또한-순수한-객체-관계를-고려해-항상-양쪽에-값을-입력해야-한다">1. 연관관계 Owner에 값을 입력해야 한다. 또한 순수한 객체 관계를 고려해 항상 양쪽에 값을 입력해야 한다.</h5>
<h5 id="2-양쪽에-값을-입력할-수-있도록-association-helper-method를-작성하자">2. 양쪽에 값을 입력할 수 있도록 association helper method를 작성하자.</h5>
<h5 id="3-무한-loop">3. 무한 loop</h5>
<h6 id="lombok에서-tostring만드는-것은-웬만하면-쓰지-마라">lombok에서 toString()만드는 것은 웬만하면 쓰지 마라</h6>
<h6 id="json생성-라이브러리--controller에는-entity를-반환하면-안된다">JSON생성 라이브러리 : controller에는 Entity를 반환하면 안된다.</h6>
<h3 id="3-연관관계-mapping시-고려사항">3. 연관관계 mapping시 고려사항</h3>
<h6 id="1-다중성-2-단방향-양방향-3-연관관계의-주인">1) 다중성 2) 단방향, 양방향 3) 연관관계의 주인</h6>
<p><code>@JoinColumn(name = &quot;매핑할 외래키 이름&quot;)</code></p>
<h4 id="다대일-가장-많이-쓰는">다대일 (가장 많이 쓰는.)</h4>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/85894828-b185-4782-a1a2-0a1000e08208/image.png" alt="">
<img src="https://velog.velcdn.com/images/0ne-hsj/post/3f1c307b-8c7f-47a2-a107-f28519073d76/image.png" alt=""></p>
<h4 id="일대다">일대다</h4>
<ul>
<li>다대일의 반대</li>
<li>entity가 관리하는 FK가 다른 테이블에 존재</li>
<li>연관관계 관리를 위해 추가로 UPDATE sql 실행<blockquote>
<p>⟹ 다대일 양방향으로 사용하자. (객체에서 참조를 하나 더 넣는 한이 있더라도)</p>
</blockquote>
<h4 id="일대일">일대일</h4>
</li>
<li>DB입장에선 외래 키의 DB 유니크 제약조건이 추가된 것</li>
<li>한마디로 정리하면, 객체는 상응하는 table만 관리할 수 있다
<img src="https://velog.velcdn.com/images/0ne-hsj/post/654db1eb-6a0e-42e5-978a-ca51196b458b/image.png" alt="">
<img src="https://velog.velcdn.com/images/0ne-hsj/post/1e4e1a9e-555b-4830-ad99-5c5a7bb29405/image.png" alt="">
(주 테이블에 FK가 있는 경우만 제시한 것임)
(대상 테이블에 FK가 있는 경우도 가능)</li>
</ul>
<h4 id="다대다--쓰면-안됨">다대다 : 쓰면 안됨</h4>
<ul>
<li>RDB는 정규화된 Table2개로 다대다 관계를 표현할 수 없음</li>
<li>연결테이블을 추가해서 일대다 + 다대일 관계로 풀어내야 함</li>
</ul>
<h3 id="4-상속관계--association-mapping">4. 상속관계  association mapping</h3>
<ul>
<li>RDB는 상속관계가 없음</li>
<li>조인전략을 기본으로 하되, 너무 단순하고 확장성이 없는 경우 단일테이블 전략으로 전환하자.</li>
</ul>
<h4 id="전략1-inheritancestrategy--inheritancetypejoined">전략1. <code>@Inheritance(strategy = InheritanceType.JOINED)</code></h4>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/b4dd7c86-e02a-44e9-be3c-88a80b614215/image.png" alt=""></p>
<h5 id="장점--1-data가-정규화-설계가-깔끔-2-제약조건을-아이템에-걸어서-맞출-수-있음-3-저장공간-효율화">장점 : 1) Data가 정규화, 설계가 깔끔 2) 제약조건을 아이템에 걸어서 맞출 수 있음 3) 저장공간 효율화</h5>
<h5 id="단점--1-조회시-join을-많이-사용-성능-저하-2-조회-쿼리가-복잡-3-데이터-저장시-insert-sql-2번-호출">단점 : 1) 조회시 join을 많이 사용, 성능 저하 2) 조회 쿼리가 복잡 3) 데이터 저장시 Insert sql 2번 호출</h5>
<h4 id="전략2-inheritancestrategy--inheritancetypesingle_table">전략2. <code>@Inheritance(strategy = InheritanceType.SINGLE_TABLE)</code></h4>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/8c9b3919-5021-406e-8fab-8b2040696bf2/image.png" alt=""></p>
<h6 id="dtype을-자동으로-추가해-줌">dtype을 자동으로 추가해 줌</h6>
<h5 id="장점-1-join이-필요가-없으므로-조회가-빠름-2-조회-쿼리가-단순">장점 1) join이 필요가 없으므로 조회가 빠름 2) 조회 쿼리가 단순</h5>
<h5 id="단점-1-치명적-자식-엔티티가-매핑한-칼럼은-모두-null허용-2-단일-테이블에-모든-것을-저장하므로-테이블이-커질-수-있어-상황에-따라-성능저하-가능">단점 1) ((치명적)) 자식 엔티티가 매핑한 칼럼은 모두 null허용 2) 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있어 상황에 따라 성능저하 가능</h5>
<h4 id="전략3-아무도-추천하지-않는-전략-inheritancestrategy--inheritancetypetable_per_class">전략3. (아무도 추천하지 않는 전략) <code>@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)</code></h4>
<h4 id="mappedsuperclass"><code>@MappedSuperclass</code></h4>
<blockquote>
<p>상속관계 매핑이 전혀 아니라, 단순히 entity가 공유하는 속성을 같이 쓰고 싶을 때
주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통 으로 적용하는 정보를 모을 때 사용</p>
</blockquote>
<h5 id="주로-registerdate-lastmodifieddate-registorname-modifiername과-같은-전체-entity에서-공통으로-적용하는-정보를-모을-때-사용">주로 registerDate, lastModifiedDate, registorName, modifierName과 같은 전체 entity에서 공통으로 적용하는 정보를 모을 때 사용</h5>
<h6 id="부모-클래스를-상속-받는-자식-클래스에-매핑-정보만-제공-조회">부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공 조회</h6>
<h6 id="검색-불가emfindbaseentity-불가">검색 불가(em.find(BaseEntity) 불가)</h6>
<h6 id="직접-생성해서-사용할-일이-없으므로-추상-클래스-권장">직접 생성해서 사용할 일이 없으므로 추상 클래스 권장</h6>
<h5 id="참고로-엔티티-객체에서-extend할-수-있는-것은-mappedsuperclass이거나-----entity인-엔티티만-가능하다">참고로, 엔티티 객체에서 extend할 수 있는 것은 <code>@MappedSuperclass</code>이거나     <code>@Entity</code>인 엔티티만 가능하다.</h5>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA에 대한 개론]]></title>
            <link>https://velog.io/@0ne-hsj/JPA%EB%9E%80</link>
            <guid>https://velog.io/@0ne-hsj/JPA%EB%9E%80</guid>
            <pubDate>Tue, 02 Jul 2024 12:48:57 GMT</pubDate>
            <description><![CDATA[<h2 id="p-문제점">P. 문제점</h2>
<blockquote>
<p>객체 지향 프로그래밍 vs relational DB</p>
</blockquote>
<p>패러다임 불일치</p>
<h4 id="객체답게-모델링-할수록-매핑작업만-늘어날뿐">객체답게 모델링 할수록 매핑작업만 늘어날뿐.</h4>
<p>상속
연관관계
데이터 타입
데이터 식별 방법</p>
<h4 id="객체를-java-collection에-저장하듯이-db에-저장할-수-없을까">객체를 java Collection에 저장하듯이 DB에 저장할 수 없을까?</h4>
<h2 id="s-이-고민에서-나온게-jpa">S. 이 고민에서 나온게 JPA</h2>
<h4 id="orm--object-relational-mapping">ORM : Object-Relational Mapping</h4>
<ul>
<li>객체는 객체대로</li>
<li>RDB는 RDB대로</li>
<li>프레임워크를 이용해 중간에서 mapping<h3 id="장점">장점</h3>
<h4 id="sql중심-→-객체-중심의-개발-가능">SQL중심 → 객체 중심의 개발 가능</h4>
</li>
<li>생산성</li>
<li>유지보수<h4 id="패러다임-불일치-해결">패러다임 불일치 해결</h4>
</li>
</ul>
<h2 id="jpql">JPQL</h2>
<h4 id="한마디로-객체-지향-sql">한마디로 객체 지향 SQL</h4>
<ul>
<li>SQL을 추상화해서 여러 DB에 맞는 dialect사용하게끔해서 의존성 없앰</li>
<li>테이블이 아닌 객체를 대상으로 검색하는 객체지향 query</li>
</ul>
<h1 id="jpa">JPA</h1>
<ol>
<li>항상 Entity Manager Factory를 만들어야 한다; 데이터베이스 하나씩 묶여서 돌아가는 것</li>
<li>작업을 해야하면 꼭 Entity Manager를 통해서 작업을 해야한다.</li>
<li>JPA의 모든 작업은 transaction 안에서 일어나야 한다.<ul>
<li>transaction 시작</li>
<li>필요한 로직 실행</li>
<li>commit</li>
</ul>
</li>
</ol>
<h2 id="핵심1-orm">핵심1. <a href="https://velog.io/@0ne-hsj/ORM-entity-relationships">[ORM]</a></h2>
<p>객체랑 RDB랑 어떻게 매핑을 해서 쓸 것인가?</p>
<h2 id="핵심2-persistence-context">핵심2. persistence context</h2>
<blockquote>
<p>&quot;Entity를 영구 저장하는 환경.&quot; </p>
</blockquote>
<p>내부 구현이 어떻게 되는가?</p>
<p>application과 database사이의 중간 매개체</p>
<h4 id="entity-manager를-통해-persistence-context에-접근">Entity Manager를 통해 Persistence Context에 접근</h4>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/cd296604-1e80-460f-b228-9c7f57694964/image.png" alt=""></p>
<p>하지만 EntityManger 도 자신의 인스턴스를 관리해줄 곳이 필요한데 그런 공간을 만들어 주는 곳이 EntityManagerFactory 이다. (Factory같은 경우는 한번 생성하는데 비용이 많이 들기 때문에 한번 생성 후 애플리케이션 전체에 공유)</p>
<p>EntityMangerFactory 생성 시 커넥션 풀도 만들어 준다</p>
<h4 id="entity의-4가지-상태">Entity의 4가지 상태</h4>
<ol>
<li>new/transient : JPA와 전혀 관련 없는 상태</li>
<li>managed : Persistence Context에 &#39;관리&#39;</li>
<li>detached : Entity를 PersistencContext에서 &#39;분리&#39;</li>
<li>removed : 객체를 삭제한 상태<h3 id="특징과-이점">특징과 이점</h3>
<img src="https://velog.velcdn.com/images/0ne-hsj/post/92c4f59c-b143-465a-8e3a-51c7531dc8f1/image.png" alt=""></li>
</ol>
<h4 id="1-entity-등록--transaction단위로-등록하므로-쓰기-지연이-됨">1. Entity 등록 : transaction단위로 등록하므로 쓰기 지연이 됨</h4>
<pre><code class="language-java">    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    //EntityManager는 데이터 변경시 transaction을 시작해야 한다
    transaction.begin(); //transaction시작

    em.persist(memberA); //쓰기지연 SQ저장소에 INSERT 저장하고 1차 캐시에 memberA를 저장함.
    em.persist(memberB); //쓰기지연 SQ저장소에 INSERT 저장하고 1차 캐시에 memberA를 저장함.
    //여기까지 INSERT SQL을 DB에 보내지 않음

    transaction.commit(); //커밋하는 순간 flush()호출 : DB에 SQL저장소에 있던 쿼리를 보냄 </code></pre>
<h4 id="2-entity-수정--persistenccontext의-쓰기-지연-→-변경-감지dirty-checking로-인해-db-데이터의-수정을-java의-컬렉션에-데이터를-수정하듯이-할-수-있다">2. Entity 수정 : PersistencContext의 &quot;쓰기 지연 → 변경 감지(dirty checking)&quot;로 인해 DB 데이터의 수정을 Java의 컬렉션에 데이터를 수정하듯이 할 수 있다.</h4>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/b9af79d8-5cc2-4a33-b343-9d57d81fe11e/image.png" alt=""></p>
<p>⟹ 수정 후 다시 <code>em.persist(member)</code>할 필요가 없다
쓰기 지연 SQL 저장소 : JPA는 transaction이 commit되는 시점에 변경을 반영함.</p>
<pre><code class="language-java">Member member1 = em.find(Member.class, 1L); // 조회
member1.setName(&quot;ha&quot;);

em.persist(member1) // ???

transaction.commit();</code></pre>
<p>1차 캐시 내부 공간에서 만약 사용자가 em.persist를 하면 snapshot으로 해당 객체를 저장
<code>member.setName(&#39;ha&#39;)</code> 와 같은 코드로 setter를 호출해서 데이터를 바꿀 때 기존에 있던 스냅 샷과 바꾼 Member 객체 간 데이터를 비교해서 다르다면 Update 쿼리문을 자동으로 날려준다</p>
<h4 id="3-entity삭제">3. Entity삭제</h4>
<pre><code class="language-java">    Member memberA = em.find(member.class, &quot;memberA&quot;);
    em.remove(memberA); //entity삭제</code></pre>
<h4 id="4-동일성보장--entitymanager에서-같은-객체를-불렀을-때-동일성을-보장">4. 동일성보장 : EntityManager에서 같은 객체를 불렀을 때 동일성을 보장</h4>
<pre><code class="language-java">Member a = em.find(Member.class, &quot;memberA&quot;); 
member b = em.find(Member.class, &quot;memberB&quot;);  
a == b ?? // true
</code></pre>
<h3 id="flush-≡-persistencecontext의-변경-내용을-db에-반영하는-것">*flush ≡ persistenceContext의 변경 내용을 DB에 반영하는 것</h3>
<h4 id="과정">과정</h4>
<p>flush 자동 호출 : i) transaction이 commit될 때 ii) JPQL 쿼리 실행할때 자동으로</p>
<p>or <code>em.flush()</code> (직접 호출하는 방법, 자동으로 ㄴㄴ)</p>
<p>ㄱ. dirty checking 변경 감지
ㄴ. 수정된 entity를 쓰기 지연 SQL 저장소에 등록
ㄷ. 쓰기 지연 SQL저장소의 쿼리를 DB에 전송</p>
<h4 id="주의점">주의점</h4>
<ul>
<li>1차 cache를 지우는 게 아님 </li>
<li>persistence context를 지우는 것도 아님</li>
<li>transaction이라는 작업 단위. commit직전에만 동기화하면 됨</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Design Pattern : Decorator]]></title>
            <link>https://velog.io/@0ne-hsj/Design-Pattern-Decorator-mq0qjlmn</link>
            <guid>https://velog.io/@0ne-hsj/Design-Pattern-Decorator-mq0qjlmn</guid>
            <pubDate>Thu, 20 Jun 2024 04:46:29 GMT</pubDate>
            <description><![CDATA[<h4 id="component-interface">component interface</h4>
<pre><code class="language-java">public interface Beverage {
    String getDescription();
    double cost();
}</code></pre>
<h4 id="concrete-component-class">concrete component class</h4>
<ul>
<li>Component 인터페이스를 구현하며, 기본적인 동작을 정의합니다. </li>
<li>이 클래스는 실제 객체를 나타냄</li>
</ul>
<pre><code class="language-java">public class Espresso implements Beverage {
    @Override
    public String getDescription() {
        return &quot;Espresso&quot;;
    }

    @Override
    public double cost() {
        return 1.99;
    }
}</code></pre>
<h4 id="decorator-abstract-class">decorator abstract class</h4>
<ul>
<li>Component 인터페이스를 구현</li>
<li>내부적으로 Component 타입의 객체를 포함</li>
</ul>
<pre><code class="language-java">public abstract class BeverageDecorator implements Beverage {
    protected Beverage beverage;

    public BeverageDecorator(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription();
    }
}</code></pre>
<h4 id="concrete-decorator-class">concrete decorator class</h4>
<p>Decorator 클래스를 확장하여 추가적인 기능을 제공; 이 클래스는 동적으로 기능을 추가할 때 사용</p>
<pre><code class="language-java">public class Milk extends BeverageDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + &quot;, Milk&quot;;
    }

    @Override
    public double cost() {
        return beverage.cost() + 0.50;
    }
}</code></pre>
<h4 id="client에서-활용">client에서 활용</h4>
<ol>
<li><p>기본 객체 생성: ConcreteComponent 객체를 생성합니다. 이 객체는 기본적인 기능을 가지고 있습니다.</p>
</li>
<li><p>데코레이터 적용: ConcreteDecoratorA와 ConcreteDecoratorB를 순차적으로 적용하여 기능을 확장합니다. 각 데코레이터는 Component 객체를 인수로 받아 기능을 확장</p>
</li>
<li><p>재할당(다형적 참조)을 통한 확장된 객체 사용: 확장된 객체를 사용하여 결과를 출력합니다. 각 데코레이터는 이전의 상태를 기반으로 추가 기능을 제공하므로, 결과적으로 객체의 기능이 단계적으로 확장</p>
<pre><code class="language-java">public class CoffeeShop {
 public static void main(String[] args) {
     Beverage beverage = new Espresso();
     System.out.println(beverage.getDescription() + &quot; $&quot; + beverage.cost());

     beverage = new Milk(beverage);
     System.out.println(beverage.getDescription() + &quot; $&quot; + beverage.cost());

     beverage = new Mocha(beverage);
     System.out.println(beverage.getDescription() + &quot; $&quot; + beverage.cost());
 }
}</code></pre>
</li>
</ol>
<h2 id="io에서의-decorator-pattern">[I/O에서의 decorator pattern]</h2>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/8e96403a-394e-4f04-b28a-2be4d9589231/image.png" alt=""></p>
<pre><code class="language-java">import java.io.*;

public class InputStreamDecoratorExample {
    public static void main(String[] args) {
        String filePath = &quot;example.txt&quot;;

        try {
            // FileInputStream을 생성합니다.
            InputStream fileInputStream = new FileInputStream(filePath);

            // FileInputStream을 BufferedInputStream으로 데코레이팅합니다.
            InputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

            // BufferedInputStream을 LineNumberInputStream으로 데코레이팅합니다.
            LineNumberInputStream lineNumberInputStream = new LineNumberInputStream(bufferedInputStream);

            // 파일을 읽고 출력합니다.
            int data;
            while ((data = lineNumberInputStream.read()) != -1) {
                System.out.print((char) data);

                // 줄바꿈 문자일 때 줄 번호를 출력합니다.
                if (data == &#39;\n&#39;) {
                    System.out.println(&quot;Line number: &quot; + lineNumberInputStream.getLineNumber());
                }
            }

            // 스트림을 닫습니다.
            lineNumberInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_디테일]]></title>
            <link>https://velog.io/@0ne-hsj/JAVA%EB%94%94%ED%85%8C%EC%9D%BC</link>
            <guid>https://velog.io/@0ne-hsj/JAVA%EB%94%94%ED%85%8C%EC%9D%BC</guid>
            <pubDate>Tue, 18 Jun 2024 12:52:12 GMT</pubDate>
            <description><![CDATA[<h3 id="메서드-정의-시-키워드-순서-규칙">메서드 정의 시 키워드 순서 규칙</h3>
<p>ㄱ. 접근 제어자 : public, protected, private
ㄴ. 기타 제어자 : static, abstract, final, synchronized, (관례상 이 순서)
ㄷ. 리턴 타입
ㄹ. 메서드 이름
ㅁ. parameter list
ㅂ. Exception List</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_Polymorphism]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAPolymorphism</link>
            <guid>https://velog.io/@0ne-hsj/JAVAPolymorphism</guid>
            <pubDate>Sun, 16 Jun 2024 13:09:40 GMT</pubDate>
            <description><![CDATA[<h2 id="binding">binding</h2>
<h3 id="정의--method-invocation과-method-definition을-연결하는-과정">정의 : method invocation과 method definition을 연결하는 과정</h3>
<h3 id="early-binding-static-binding">early binding; static binding</h3>
<p>컴파일 시점에 메서드 정의와 메서드 호출을 연결하는 방식</p>
<ul>
<li>정적 메서드 호출; 클래스명이 아닌 심지어 객체를 통해 호출할 때도
* method hiding이 일어나는 경우 : 참조된 타입에 의해 결정(late binding이랑 반대)</li>
</ul>
<ul>
<li>오버로딩
* 컴파일러는 각 메서드 호출에 대해 올바른 메서드 정의를 찾고, 이를 컴파일 시점에 결정하므로</li>
</ul>
<h3 id="late-binding-dynamic-binding">late binding; dynamic binding</h3>
<p>실행 시점에 메서드 정의와 메서드 호출을 연결하는 방식 (동적 바인딩)</p>
<ul>
<li>오버라이딩 (다형성)</li>
<li>java는 기본적으로 late binding을 사용<h2 id="polymorphism">polymorphism</h2>
</li>
</ul>
<h3 id="정의">정의</h3>
<p>(&quot;다양한 형태&quot;) 한 객체가 여러 타입의 객체로 취급될 수 있는 것</p>
<blockquote>
<p>다형적 참조 + 메서드 overriding 으로 구현되는 것</p>
</blockquote>
<h3 id="핵심-2가지">핵심 2가지</h3>
<h4 id="1-부모는-자식을-품을-수-있다">1. 부모는 자식을 품을 수 있다.</h4>
<p><code>Parent poly = new Parent()</code>
<code>Parent poly = new Child()</code>
<code>Parent poly = new GrandChild()</code></p>
<p>상속관계는 부모 방향으로 찾아 올라갈 수는 있으나 자식방향으로 찾아 내려갈 수는 없다.
<code>poly.childMethod()</code> : ㄴㄴ (캐스팅 필요)</p>
<h4 id="2-overriding-된-메서드가-항상-우선권을-가짐">2. overriding 된 메서드가 항상 우선권을 가짐</h4>
<p>객체 자체가 사실상 자식 인스턴스도 포함할 때, 그 자식에서 override된 메서드로 작동한다; 실행 시점에 객체의 실제 타입에 따라 호출되는 메서드가 결정</p>
<pre><code class="language-java">public class OverridingMain {
    public static void main(String[] args) {
//자식 변수가 자식 인스턴스 참조
        Child child = new Child();
        System.out.println(&quot;Child -&gt; Child&quot;); 
        System.out.println(&quot;value = &quot; + child.value);//value = child
        child.method(); //childmethod
//부모 변수가 부모 인스턴스 참조
        Parent parent = new Parent(); 
        System.out.println(&quot;Parent -&gt; Parent&quot;); 
        System.out.println(&quot;value = &quot; + parent.value);//value = 
        parent.method(); //parentmethod
//부모 변수가 자식 인스턴스 참조(다형적 참조)
        Parent poly = new Child();
        System.out.println(&quot;Parent -&gt; Child&quot;); 
        System.out.println(&quot;value = &quot; + poly.value); //변수는 오버라이딩X value = parent
        poly.method(); //메서드 오버라이딩! : childmethod</code></pre>
<h3 id="casting">casting</h3>
<h4 id="1-downcasting--원래-부모-타입인-걸-자식타입으로-변경">1) downcasting : (원래 부모 타입인 걸) 자식타입으로 변경</h4>
<pre><code class="language-java">    Parent poly1 = new Child();
    Parent poly2 = new Parent();
    Child child1 = (Child) poly1; 
    Child child2 = (Child) poly2;  //runtime error
    child1.childMethod(); ((Child) poly1).childMethod();
    child2.childMethod() //execute impossible</code></pre>
<ul>
<li><p>poly의 타입은 그래로! 자바에선 항상 value-copy!!</p>
</li>
<li><p>poly와 child모두 같은 참조값(e.g. x001)을 참조함</p>
</li>
<li><p>재할당외에는 변수의 내용을 바꿀수 있는 게 없음</p>
</li>
<li><p>memory상에 자식이 존재하지 않는 경우, 실패하는 문제가 생성된다. casting 표시를 항상 해줘야 한다. </p>
</li>
</ul>
<h4 id="2-upcasting--자식타입을-부모타입으로-변경">2) upcasting : 자식타입을 부모타입으로 변경</h4>
<pre><code class="language-java">    Child child = new Child();
    Parent parent1 = (Parent) child; //캐스팅 표시
    Parent parent2 = child; //권장</code></pre>
<ul>
<li><p>객체를 생성하면 해당 타입의 부모타입은 항상 생성되는데, </p>
</li>
<li><p>memory상에 부모가 존재하므로 upcasting은 항상 성공하고, casting 생략도 가능</p>
</li>
<li><p>업캐스팅된 객체는 부모 클래스 타입으로만 참조되기 때문에, 자식 클래스에서 정의된 메서드나 필드에는 접근할 수 없다</p>
<h3 id="instanceof의-사용"><code>instanceOf</code>의 사용</h3>
<pre><code class="language-java">public class CastingMain5 {
  public static void main(String[] args) { 
  Parent parent1 = new Parent(); 
  System.out.println(&quot;parent1 호출&quot;); 
  call(parent1); // if false
  Parent parent2 = new Child();
  System.out.println(&quot;parent2 호출&quot;); 
  call(parent2); //if true
}
   private static void call(Parent parent) {
       parent.parentMethod();
       if (parent instanceof Child) {
          System.out.println(&quot;Child 인스턴스 맞음&quot;); 
          Child child = (Child) parent; 
          child.childMethod();
      }
  }
}</code></pre>
</li>
</ul>
<h2 id="주의">주의</h2>
<h3 id="static-method에는-다형성이-적용되지-않는다">static method에는 다형성이 적용되지 않는다</h3>
<pre><code class="language-java">class Parent {
    public static void staticMethod() {
        System.out.println(&quot;Parent static method&quot;);
    }

    public void instanceMethod() {
        System.out.println(&quot;Parent instance method&quot;);
    }
}

class Child extends Parent {
    public static void staticMethod() {
        System.out.println(&quot;Child static method&quot;);
    }

    @Override
    public void instanceMethod() {
        System.out.println(&quot;Child instance method&quot;);
    }
}

public class Main {
    public static void main(String[] args) {
        Parent parent = new Child();

        // 정적 메서드 호출
        parent.staticMethod(); // Parent static method 출력
        Parent.staticMethod(); // Parent static method 출력
        Child.staticMethod();  // Child static method 출력

        // 인스턴스 메서드 호출 (다형성 적용)
        parent.instanceMethod(); // Child instance method 출력
    }
}
</code></pre>
<h3 id="final-메소드는-애초에-override가-안되니까-당연히-다형성을-적용할-수-없다">final 메소드는 애초에 override가 안되니까 당연히 다형성을 적용할 수 없다.</h3>
<h2 id="적용">적용</h2>
<h3 id="tostring과-다형성">[<code>toString()</code>과 다형성]</h3>
<pre><code class="language-java">class Parent {
    @Override
    public String toString() {
        return &quot;This is a Parent object&quot;;
    }
}

class Child extends Parent {
    @Override
    public String toString() {
        return &quot;This is a Child object&quot;;
    }
}

public class Main {
    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child(); // 업캐스팅

        // toString() 메서드 호출
        System.out.println(parent.toString()); // This is a Parent object
        System.out.println(child.toString());  // This is a Child object
    }
}
</code></pre>
<h3 id="clone">[<code>clone()</code>]</h3>
<pre><code class="language-java">class Parent {
    private int value;

    public Parent(int value) {
        this.value = value;
    }

    // 복사 생성자
    public Parent(Parent other) {
        this.value = other.value;
    }

    public Parent clone() {
        return new Parent(this); // 복사 생성자를 사용하여 객체 복사
    }

    @Override
    public String toString() {
        return &quot;Parent{&quot; + &quot;value=&quot; + value + &#39;}&#39;;
    }
}
</code></pre>
<ul>
<li><p>참고로 접근 제어자가 protected에서 public으로 확장되었다.</p>
<pre><code class="language-java">class Child extends Parent {
  private int extraValue;

  public Child(int value, int extraValue) {
      super(value);
      this.extraValue = extraValue;
  }

  // 복사 생성자
  public Child(Child other) {
      super(other); // 부모 클래스의 복사 생성자 호출
      this.extraValue = other.extraValue;
  }

  @Override
  public Child clone() {
      return new Child(this); // 복사 생성자를 사용하여 객체 복사
  }

  @Override
  public String toString() {
      return &quot;Child{&quot; + &quot;value=&quot; + super.toString() + &quot;, extraValue=&quot; + extraValue + &#39;}&#39;;
  }
}
</code></pre>
</li>
</ul>
<pre><code>
원래 clone()의 리턴타입은 `Object`이다. 그런데 리턴타입을 `Child`로 바뀌었다. 이를 오버라이딩이라 할 수 있는가?
- override의 예외라 봐야 한다.
- covariant return type은 자바에서 오버라이딩할 때 리턴 타입을 부모 클래스 메서드의 리턴 타입의 하위 타입으로 변경할 수 있게 해주는 예외적인 규칙


```java
public class Main {
    public static void main(String[] args) {
        Child original = new Child(10, 20);
        Child copy = original.clone(); // 복사 생성자를 사용하여 객체 복사

        System.out.println(&quot;Original: &quot; + original);
        System.out.println(&quot;Copy: &quot; + copy);
    }
}
</code></pre><ul>
<li>기본적으로 얕은 복사만 수행하는 clone()을 깊은 복사를 수행하도록 override할 수 있다.</li>
<li>다형성을 이용하여 실제 타입에 맞는 재정의된 메서드를 사용할 수 있게 되었다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_inheritance]]></title>
            <link>https://velog.io/@0ne-hsj/Javainheritance</link>
            <guid>https://velog.io/@0ne-hsj/Javainheritance</guid>
            <pubDate>Sat, 15 Jun 2024 14:35:59 GMT</pubDate>
            <description><![CDATA[<h4 id="a-is-a-b">A is a B</h4>
<p><code>class A extends B</code></p>
<h2 id="상속되지-않는-것">상속되지 않는 것.</h2>
<p>아래 3가지 빼고는 모두 상속됨 (초기화 블록은 다루지 않음)</p>
<h4 id="1-생성자constructor">1. 생성자(Constructor)</h4>
<ul>
<li><p>자식 클래스는 부모 클래스의 생성자를 상속받지 않음 </p>
</li>
<li><p>생각해보면 당연한 것; 자식 클래스는 자신의 생성자를 명시적으로 정의해야 함</p>
</li>
<li><p>부모 클래스의 생성자를 호출하려면 super() 키워드를 사용 </p>
<h4 id="2-private-멤버-변수-및-메서드">2. private 멤버 변수 및 메서드</h4>
</li>
<li><p>자식 클래스는 부모 클래스의 private 멤버 변수와 메서드를 직접 상속받지 않음</p>
</li>
<li><p>그러나 메서드를 이용한 접근은 가능 : 부모 클래스의 public 또는 protected 메서드를 통해 접근할 수 있다.</p>
<h4 id="3-static-메서드">3. static 메서드</h4>
</li>
<li><p>static 메서드는 클래스 자체에 속하므로 상속의 개념이 아님</p>
</li>
<li><p>따라서 자식 클래스는 부모 클래스의 static 메서드를 상속받지 않지만, 부모 클래스의 static 메서드를 사용할 수 있긴 하다.</p>
<pre><code class="language-java">public class Main {
  public static void main(String[] args) {
      Child child = new Child();
      child.accessMethods();

      Parent.staticMethod(); // 가능: static 메서드는 클래스 이름으로 접근
      Child.staticMethod(); // 가능: 부모 클래스의 static 메서드를 자식 클래스 이름으로도 접근 가능
  }
}</code></pre>
<h2 id="상속시-주의사항">상속시 주의사항</h2>
<h3 id="1-constructor-상속">1. constructor 상속</h3>
</li>
<li><p>base class의 constructor는 상속이 안됨</p>
</li>
<li><p>derived class에서 사용하려면, <code>super</code>를 이용</p>
<ol>
<li>자식클래스의 first statement에서 사용해야 함</li>
<li>자식의 필드를 super의 인자로 전달할 수 없다.(왜냐하면, 부모의 생성자 호출 시점에 필드는 초기화 되지 않기에)</li>
<li>별다른 super를 호출하지 않는다면 부모의 no-argument constructor가 호출된다</li>
<li>따라서 부모 클래스에 매개변수가 있는 생성자만 정의된 경우(기본 생성자를 따로 정의하지 않으면 java에서 만들지 않음), <code>super</code>를 쓰지 않으면 컴파일 에러가 발생한다.</li>
</ol>
</li>
</ul>
<h3 id="2this-constructor-for-constructor-chaining">2.<code>this</code> constructor for constructor chaining</h3>
<ul>
<li>다른 생성자를 활용해 정의하는 것</li>
<li>반드시 생성자의 첫 번째 문장이어야 함</li>
</ul>
<h3 id="this와-super를-동시에-쓸-수-없음">*this와 super를 동시에 쓸 수 없음</h3>
<p>주의 : this로 호출된 다른 constructor에서 super를 호출하는 것은 가능</p>
<h3 id="3-private-멤버는-다른-클래스에서-사용될-수-없다">3. <code>private</code> 멤버는 다른 클래스에서 사용될 수 없다.</h3>
<h4 id="proxy-access-는-가능">proxy access 는 가능</h4>
<pre><code class="language-java">    // 부모 클래스
class SuperClass {
    // 슈퍼클래스의 private 메서드
    private void privateMethod() {
        System.out.println(&quot;Private method in SuperClass&quot;);
    }

    // 슈퍼클래스의 public 메서드
    public void publicMethod() {
        System.out.println(&quot;Public method in SuperClass calling the private method&quot;);
        privateMethod();  // private 메서드를 호출
    }
}

// 자식 클래스
class SubClass extends SuperClass {
    // 자식 클래스에서 슈퍼클래스의 public 메서드를 통해 간접적으로 private 메서드를 호출
    public void accessSuperPrivateMethod() {
        System.out.println(&quot;SubClass calling SuperClass&#39;s publicMethod&quot;);
        publicMethod();  // 슈퍼클래스의 public 메서드를 호출, 이 메서드는 내부적으로 private 메서드를 호출
    }
}

public class Main {
    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        subClass.accessSuperPrivateMethod();  // SubClass를 통해 슈퍼클래스의 private 메서드에 간접적으로 접근
    }
}</code></pre>
<h3 id="4-package-access">4. package access</h3>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/e5a1956f-7751-408c-bf6a-edcf23fc0280/image.png" alt=""></p>
<ul>
<li>protected 멤버에 대해, 다른 패키지에 정의된 자식 클래스는 접근이 가능하다.</li>
<li>public만 package에 자유롭다; protected, default, private은 안된다.</li>
</ul>
<p>* 같은 package의 클래스들은 같은 namespace에 들어가 다른 package내 같은 이름과 구분해 준다.</p>
<h3 id="5final--상속-방지--override-금지">5.<code>final</code> : 상속 방지 // override 금지</h3>
<ul>
<li>final class : 상속 방지</li>
<li>final method : override 금지</li>
<li>final field : constant처리</li>
</ul>
<h3 id="6-access-허용-변화--허용치를-높인다-제한은-불가">6. Access 허용 변화 : 허용치를 높인다; 제한은 불가</h3>
<h2 id="활용">활용</h2>
<h3 id="활용-예시---stringtokenizer를-상속받아-기능-강화">[활용 예시 - <code>StringTokenizer</code>를 상속받아 기능 강화]</h3>
<p>원래 StringTokenizer는 한 번에 한 번씩 문자열의 토큰을 생성하는 기능을 제공하지만, 기본적으로 두 번째 순회 또는 반복을 지원하지 않는다</p>
<p>하지만 상속으로 기능을 강화할 수 있다</p>
<pre><code class="language-java">import java.util.StringTokenizer;

public class CustomStringTokenizer {
    private String originalString;
    private StringTokenizer tokenizer;
    private String delim;
    private boolean returnDelims;

    // Constructor for default delimiters
    public CustomStringTokenizer(String str) {
        this.originalString = str;
        this.delim = &quot; \t\n\r\f&quot;; // default delimiters
        this.returnDelims = false;
        this.tokenizer = new StringTokenizer(str);
    }

    // Constructor with custom delimiters
    public CustomStringTokenizer(String str, String delim) {
        this.originalString = str;
        this.delim = delim;
        this.returnDelims = false;
        this.tokenizer = new StringTokenizer(str, delim);
    }

    // Constructor with custom delimiters and returnDelims flag
    public CustomStringTokenizer(String str, String delim, boolean returnDelims) {
        this.originalString = str;
        this.delim = delim;
        this.returnDelims = returnDelims;
        this.tokenizer = new StringTokenizer(str, delim, returnDelims);
    }

    // Reset method: reinitialize the tokenizer
    public void reset() {
        this.tokenizer = new StringTokenizer(this.originalString, this.delim, this.returnDelims);
    }

    // Delegate methods to the tokenizer
    public boolean hasMoreTokens() {
        return tokenizer.hasMoreTokens();
    }

    public String nextToken() {
        return tokenizer.nextToken();
    }

    // Main method for demonstration
    public static void main(String[] args) {
        CustomStringTokenizer tokenizer = new CustomStringTokenizer(&quot;Hello World&quot;);

        while (tokenizer.hasMoreTokens()) {
            System.out.println(tokenizer.nextToken());
        }

        // Reset the tokenizer
        tokenizer.reset();

        while (tokenizer.hasMoreTokens()) {
            System.out.println(tokenizer.nextToken());
        }
    }
}
</code></pre>
<h3 id="object-class"><code>Object</code> class</h3>
<ul>
<li><code>java.lang</code>에 포함 -&gt; 자동으로 import</li>
<li>모든 클래스의 조상</li>
<li><code>equals</code>, <code>toString</code> method는 모든 클래스가 상속 받음</li>
</ul>
<h4 id="equals-정의법"><code>equals</code> 정의법</h4>
<ol>
<li><p>null 검사 + 같은 타입인지 검사</p>
</li>
<li><p><code>Object o</code>에서 <code>o</code>는 반드시 타입 캐스팅되어야 한다. 그 후에 필드 동일성을 검사한다.</p>
</li>
</ol>
<pre><code class="language-java">public boolean equals(Object otherObject) {
  if(otherObject == null) { 
      return false;
    } else if (getClass( ) != otherObject.getClass( )) { 
        return false;
    } else {
    Employee otherEmployee = (Employee)otherObject; r
    eturn (name.equals(otherEmployee.name) &amp;&amp;
hireDate.equals(otherEmployee.hireDate)); 
    }
}</code></pre>
<h4 id="getclass-vs-instanceof-operator"><code>getClass()</code> VS <code>instanceof</code> operator</h4>
<blockquote>
<p>모두 타입 체크 용</p>
</blockquote>
<p>getClass()는 final 메서드다 =&gt; override불가능</p>
<ol>
<li><code>obj instanceof ClassA</code> </li>
</ol>
<ul>
<li>true : classA 거나 그 자식 클래스 타입</li>
<li>false : 그 외</li>
</ul>
<ol start="2">
<li>차이를 예시로 이해하자<pre><code class="language-java">class Parent {}
</code></pre>
</li>
</ol>
<p>class Child extends Parent {}</p>
<p>public class Main {
    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        Parent parentChild = new Child();</p>
<pre><code>    System.out.println(parent instanceof Parent); // true
    System.out.println(child instanceof Child);   // true
    System.out.println(child instanceof Parent);  // true
    System.out.println(parentChild instanceof Parent); // true
    System.out.println(parentChild instanceof Child);  // true
}</code></pre><p>}</p>
<pre><code>```java
class Parent {}

class Child extends Parent {}

public class Main {
    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        Parent parentChild = new Child();

        System.out.println(parent.getClass() == Parent.class); // true
        System.out.println(child.getClass() == Child.class);   // true
        System.out.println(parentChild.getClass() == Parent.class); // false
        System.out.println(parentChild.getClass() == Child.class);  // true
    }
}
</code></pre><p>getClass() 메서드는 다형성(polymorphism)에서 부모 클래스 타입의 변수로 참조된 자식 클래스 객체의 정확한 타입을 알 수 있게 해준다.</p>
<pre><code class="language-java">class Animal {
    public void makeSound() {
        System.out.println(&quot;Some generic animal sound&quot;);
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println(&quot;Bark&quot;);
    }

    public void fetch() {
        System.out.println(&quot;Dog is fetching&quot;);
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println(&quot;Meow&quot;);
    }

    public void scratch() {
        System.out.println(&quot;Cat is scratching&quot;);
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal1 = new Dog();
        Animal myAnimal2 = new Cat();

        // 다형성을 이용하여 상위 클래스 타입 변수로 메서드 호출
        myAnimal1.makeSound(); // 출력: Bark
        myAnimal2.makeSound(); // 출력: Meow

        // instanceOf를 사용하여 실제 객체 타입에 따라 다른 동작 수행
        if (myAnimal1 instanceof Dog) {
            Dog myDog = (Dog) myAnimal1;
            myDog.fetch(); // 출력: Dog is fetching
        }

        if (myAnimal2 instanceof Cat) {
            Cat myCat = (Cat) myAnimal2;
            myCat.scratch(); // 출력: Cat is scratching
        }
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Design Pattern : Singleton]]></title>
            <link>https://velog.io/@0ne-hsj/Design-Pattern-Singleton</link>
            <guid>https://velog.io/@0ne-hsj/Design-Pattern-Singleton</guid>
            <pubDate>Sat, 15 Jun 2024 06:12:52 GMT</pubDate>
            <description><![CDATA[<h1 id="정의">정의</h1>
<p>클래스가 오직 하나의 객체만 가지도록 함.
객체 하나 생성시 많은 자원을 필요로 하는 경우 이 패턴을 사용.</p>
<h3 id="사용-사례">사용 사례</h3>
<ul>
<li>Logging</li>
<li>Caches</li>
<li>Registry Settings</li>
<li>Access External Resources : Printer, Device Driver, Database</li>
</ul>
<h1 id="구현">구현</h1>
<ul>
<li>생성자를 private으로</li>
<li>생성된 단 하나의 인스턴스를 반환하는 <code>static</code> method구현</li>
</ul>
<table>
<thead>
<tr>
<th>초기화 방식</th>
<th>Lazy Initialization</th>
<th>Thread-Safe</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Eager Initialization</td>
<td>아니요</td>
<td>예</td>
<td>클래스 로드 시점에 인스턴스를 생성합니다.</td>
</tr>
<tr>
<td>Simple Locking</td>
<td>예</td>
<td>예</td>
<td>인스턴스 생성 시 항상 동기화 블록을 사용합니다.</td>
</tr>
<tr>
<td>Double-Checked Locking</td>
<td>예</td>
<td>예</td>
<td>인스턴스가 존재하는 경우 동기화 블록을 건너뛰어 성능을 최적화합니다.</td>
</tr>
</tbody></table>
<p>*Lazy Initialization = 인스턴스가 실제로 필요할 때까지 생성되지 않는 방식</p>
<h2 id="i-simple-locking">i) Simple Locking</h2>
<p>단일 스레드 환경: 단일 스레드 환경에서는 동기화 없이도 안전하게 싱글턴을 생성할 수 있습니다.
간단한 구현: 코드가 비교적 간단하며, 동기화에 따른 성능 저하가 없습니다.</p>
<pre><code class="language-java">public class Singleton
{
   private Singleton() {}
   private static Singleton uniqueInstance;
   public static Singleton getInstance()
   {
        synchronized(Singleton.class) {
            if (uniqueInstance == null)
                   uniqueInstance = new Singleton();
}
         return uniqueInstance;
   }
}</code></pre>
<p>멀티스레드 환경에서 안전하지 않음: 동기화를 하지 않기 때문에, 멀티스레드 환경에서는 여러 스레드가 동시에 인스턴스를 생성하려 할 수 있습니다.</p>
<h2 id="ii-double-checked-locking">ii) Double-checked Locking</h2>
<p>멀티스레드 환경에서 안전함: 두 번의 체크와 동기화를 통해 인스턴스가 동시에 여러 번 생성되는 것을 방지합니다.
성능 최적화: 필요할 때만 동기화를 사용하여 성능 저하를 최소화합니다.</p>
<pre><code class="language-java">public class Singleton2
{
  private Singleton2() {}

  private volatile static Singleton2 uniqueInstance;

  public static Singleton2 getInstance()
     {
          if (uniqueInstance == null) { // single checked 
            synchronized(Singleton2.class) {
                  if (uniqueInstance == null)    // double checked
                     uniqueInstance = new Singleton();
              }
        }    

        return uniqueInstance;
     }
}</code></pre>
<ol>
<li>먼저 instance가 존재하는지 검사한다. 즉 동기화 블록이 먼저 실행되지 않는다.
따라서 오버헤드를 방지</li>
<li><code>volatile</code>키워드 사용</li>
</ol>
<ul>
<li>cashe가 아닌 main memory에 저장됨</li>
<li>따라서 변수의 값을 모든 스레드에 동일하게 보이도록 보장; 변수가 변경될 때 모든 스레드가 그 변경을 볼 수 있게 함</li>
<li>volatile을 사용하지 않으면, 인스턴스의 초기화가 완료되기 전에 다른 스레드가 이 인스턴스를 사용할 가능성이 있습니다. volatile 키워드는 이런 문제를 방지해줍니다.</li>
</ul>
<h2 id="iii-eager-initialization">iii) &quot;Eager&quot; initialization</h2>
<p>멀티스레드 환경에서 안전함: 클래스가 로드될 때 인스턴스가 생성되므로 동기화가 필요 없습니다.
간단하고 직관적: 구현이 매우 간단하며, 성능 문제가 없습니다.</p>
<pre><code class="language-java">public class Singleton
{
   private Singleton() {}
   private static Singleton uniqueInstance = new Singleton();

   public static Singleton getInstance()
   {
         return uniqueInstance;
   }
}</code></pre>
<p>지연 초기화 불가: 클래스 로딩 시점에 인스턴스가 생성되기 때문에, 사용하지 않더라도 메모리를 차지합니다.</p>
<h4 id="특징1-thread-safe">특징1. thread-safe</h4>
<ol>
<li>Eager Initialization을 사용할 경우, Singleton 인스턴스는 클래스가 로드될 때 JVM에 의해 한 번만 생성된다</li>
</ol>
<ul>
<li>클래스 로드 : JVM에 의해 단 한 번만 이루어지며, 이 시점에서 클래스의 모든 정적 멤버들이 초기화 된다</li>
</ul>
<ol start="2">
<li>로드 시점은 스레드 접근 시점 이전에 발생</li>
<li>따라서 무조건 thread-safe; 추가적인 동기화가 필요 없음</li>
</ol>
<h4 id="특징2-클래스가-처음-참조될-때-즉-클래스의-어떤-멤버가-처음으로-접근될-때-인스턴스가-생성됨">특징2. 클래스가 처음 참조될 때, 즉 클래스의 어떤 멤버가 처음으로 접근될 때 인스턴스가 생성됨</h4>
<p>즉 위의 예시에서 <code>Singleton.getInstance()</code>가 실행될 때 인스턴스가 생성된다</p>
<h3 id="when--why">when &amp; why</h3>
<p>i) 인스턴스 생성이 복잡하지 않거나 리소스를 많이 소모하지 않는 경우에 적합
ii) application이 실행될 때 항상 인스턴스가 필요한 경우</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Design Pattern : Observer]]></title>
            <link>https://velog.io/@0ne-hsj/Design-Pattern-Observer</link>
            <guid>https://velog.io/@0ne-hsj/Design-Pattern-Observer</guid>
            <pubDate>Sat, 15 Jun 2024 04:38:17 GMT</pubDate>
            <description><![CDATA[<h1 id="정의">정의</h1>
<p>옵저버 패턴(Observer Pattern)에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고, 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의한다.</p>
<p>예시로 기억하자</p>
<h2 id="eg">e.g.</h2>
<p> WeatherData 객체는 온도, 습도, 기압 정보를 가지고 있으며, 해당 정보가 변경될 때마다 다음의 세 객체에 데이터가 갱신되어야 한다. 1)현재 날씨 2) 날씨 예보 3) 기상 통계</p>
<h3 id="쓰레기-코드">쓰레기 코드</h3>
<pre><code class="language-java">class WeatherData {
    getTemperature()
    getHumidity()
    getPressure()
    measurementsChanged() // 기상 관측값이 갱신되면 해당 메소드가 호출됨

    public void measurementsChanged() {
        float temp = getTemperature();
        float humidity = getHumidity();
        float pressure = getPressure();

        currentWeatherDisplay.update(temp, humidity, pressure);
        forecastWeatherDisplay.update(temp, humidity, pressure);
        staticsticDisplay.update(temp, humidity, pressure);
    }
}</code></pre>
<p>문제점 : 다른 화면을 추가하고자 한다면 measurementsChanged() 메소드를 고쳐야 함
해결책 : 바뀔 수 있는 부분을 encapsulate 해야 함</p>
<h3 id="observer-pattern을-사용한-개선">observer pattern을 사용한 개선</h3>
<h4 id="1-subject--subject-impl">1. subject + subject impl</h4>
<pre><code class="language-java">public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}

class WeatherData implements Subject {
    registerObserver()
    removeObserver()
    notifyObserver()

    getTemperature()
    getHumidity()
    getPressure()
    measurementsChanged()
}</code></pre>
<p>구체적인 code</p>
<pre><code class="language-java">public class WeatherData implements Subject {
    private List&lt;Observer&gt; observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList&lt;Observer&gt;();
    }

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }

}</code></pre>
<h4 id="2-observer-interface-정의">2. observer interface 정의</h4>
<p>새로 갱신된 subject 데이터를 전달하는 interface를 정의해야 함</p>
<pre><code class="language-java">interface Observer {
    update() // 새로 갱신된 주제 데이터를 전달하는 인터페이스
}</code></pre>
<h4 id="3-observer의-공통된-기능을-interface로-정의">3. observer의 공통된 기능을 interface로 정의</h4>
<p>이 예시의 경우, 화면에 표시하는 기능이 공통되므로 이를 interface로 정의한다.</p>
<pre><code class="language-java">interface DisplayElement {
    display() // 화면에 표현시키는 인터페이스
}</code></pre>
<h4 id="4-23의-interface를-구현한-객체-만들기">4. 2,3의 interface를 구현한 객체 만들기</h4>
<pre><code class="language-java">class CurrentWeather implements Observer, DisplayElement{
    update()
    display() { // 현재 측정 값을 화면에 표시 }
}

class ForcastWeather implements Observer, DisplayElement{
    update()
    display() { // 날씨 예보 표시 }
}

class StatisticsDisplay implements Observer, DisplayElement{
    update()
    display() { // 평균 기온, 평균 습도 등 표시 }
}</code></pre>
<p>하나만 구체적인 코드를 보자면,</p>
<pre><code class="language-java">public class StatisticsDisplay implements Observer, DisplayElement {
    private float maxTemp = 0.0f;
    private float minTemp = 200;
    private float tempSum= 0.0f;
    private int numReadings;
    private WeatherData weatherData;

    public StatisticsDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    public void update(float temp, float humidity, float pressure) {
        tempSum += temp;
        numReadings++;

        if (temp &gt; maxTemp) {
            maxTemp = temp;
        }

        if (temp &lt; minTemp) {
            minTemp = temp;
        }

        display();
    }

    public void display() {
        System.out.println(&quot;Avg/Max/Min temperature = &quot; + (tempSum / numReadings)
            + &quot;/&quot; + maxTemp + &quot;/&quot; + minTemp);
    }
}</code></pre>
<h4 id="5-if-새로운-객체-discomfortdisplay를-추가한다면">5. if, 새로운 객체 <code>DiscomfortDisplay</code>를 추가한다면?</h4>
<pre><code class="language-java">class DiscomfortDisplay implements Observer, DisplayElement{
    update()
    display() { // 불쾌지수를 화면에 표시 }
}</code></pre>
<h4 id="main">main</h4>
<pre><code class="language-java">public class WeatherStation {

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

        CurrentConditionsDisplay currentDisplay = 
            new CurrentConditionsDisplay(weatherData);
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);

        weatherData.removeObserver(forecastDisplay);
        weatherData.setMeasurements(62, 90, 28.1f);
    }
}</code></pre>
<h2 id="특징--loose-coupling">특징 : loose coupling</h2>
<ul>
<li>The only thing the subject knows about an observer is that it implements a certain interface.
객체간 결합도가 낮은 이유임.</li>
<li>We can add or remove new observers at any time.
옵저버를 언제든 새로 추가, 제거할 수 있다.</li>
<li>We never need to modify the subject to add new types of
observers.
새로운 형식의 옵저버라 할 지라도 주제를 전혀 변경할 필요가 없다.</li>
<li>We can reuse subjects or observers independently of each other.
주제와 옵저버는 서로 독립적으로 재사용 할 수 있다.</li>
<li>Changes to either the subject or an observer will not affect the other.
주제나 옵저버가 바뀌더라도 서로에게 영향을 미치지 않는다.</li>
</ul>
<h3 id="핵심-구현-포인트">핵심 구현 포인트</h3>
<h4 id="observer_impl">Observer_impl</h4>
<ol>
<li><p>Subject_impl을 필드로 가지고 있어야 함</p>
</li>
<li><p>Observer_impl 생성자 : 해당 필드 초기화 + observer배열에 등록</p>
<pre><code class="language-java"> private Subject_impl s;

 public Observer_impl(Subject_impl ss) {
     this.s = ss;
     s.registerObserver(this)
 }</code></pre>
</li>
<li><p>update구현 : 정보 전달 받는 메서드
*update는 Observer interface에 정의. 이를 구현해야 함</p>
</li>
</ol>
<ul>
<li><p>이때 Subject의 정보를 받아올 수 있도록 한다.</p>
</li>
<li><p>Subject_impl에 정의된 execute() (* notifyObserver와 정보 전달 기능을 하는 메서드)에 쓰인다.</p>
</li>
</ul>
<p>방법1. Subject가 변경된 데이터를 update 메서드의 인자로 직접 전달 (위 예시)</p>
<pre><code class="language-java">public interface Observer {
    void update(int newNumber);
}

public class DigitObserver implements Observer {
    @Override
    public void update(int newNumber) {
        System.out.println(&quot;DigitObserver: &quot; + newNumber);

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}</code></pre>
<p>방법2. Observer_impl이 Subject_impl에 대한 참조를 갖도록 하기</p>
<pre><code class="language-java">public interface Observer {
    void update(NumberGenerator generator);
}

public class DigitObserver implements Observer {
    @Override
    public void update(NumberGenerator generator) {
        System.out.println(&quot;DigitObserver: &quot; + generator.getNumber());

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}</code></pre>
<h4 id="subject_impl">Subject_impl</h4>
<ol>
<li><p>전달할 정보 정의
위 예시의 경우 temperature, humidity, pressure</p>
</li>
<li><p>Observer인터페이스에 정의된 update()메서드를 모든 observer에 대해 실행시키는 <code>notifyObservers()</code></p>
<pre><code class="language-java">public void notifyObservers() {
     for (Observer observer : observers) {
         observer.update();
     }
}</code></pre>
</li>
<li><p>execute기능 메서드 : 정보 업데이트(중요) + <code>notifyObservers</code>를 실행시키는 메소드를 만든다.</p>
</li>
</ol>
<ul>
<li>정보를 새로 업데이트 하는 기능. 1번에 정의된 곳에 할당.</li>
<li>notifyObserver를 꼭 실행시켜 통해 update를 실행시키고, 이는 1번에 정의된 필드를 활용한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Design Pattern : Factory]]></title>
            <link>https://velog.io/@0ne-hsj/Design-Pattern-Factory</link>
            <guid>https://velog.io/@0ne-hsj/Design-Pattern-Factory</guid>
            <pubDate>Sat, 15 Jun 2024 03:48:55 GMT</pubDate>
            <description><![CDATA[<h1 id="simple-factory-idiom">Simple Factory (idiom)</h1>
<p>code로 이해하자.
<img src="https://velog.velcdn.com/images/0ne-hsj/post/b8243e9a-fc87-47cc-b558-d22cab5312c9/image.png" alt=""></p>
<h4 id="restaurant--client">Restaurant : client</h4>
<pre><code class="language-java">public class Restaurant { //client
    SimpleBurgerFactory factory;

    public Restaurant(SimpleBurgerFactory factory) {
        this.factory = factory;
    }

    public Burger orderBurger(String type) {
        Burger burger = factory.createBurger(type);

        burger.prepare();
        burger.cook();

        return burger;
    }

}</code></pre>
<h4 id="simpleburgerfactory--factory">SimpleBurgerFactory : factory</h4>
<pre><code class="language-java">public class SimpleBurgerFactory {

    public Burger createBurger(String type) {
        Burger burger = null;

        if(type.equals(&quot;beef&quot;)) {
            burger = new BeefBurger();
        } else if (type.equals(&quot;veggie&quot;)) {
            burger = new VeggieBurger();
        }

        return burger;
    }
}
</code></pre>
<h4 id="burger--product">Burger : Product</h4>
<pre><code class="language-java">public abstract class Burger {
    public abstract void prepare();

    public abstract void cook();
}
</code></pre>
<h4 id="veggieburger--concrete-product">VeggieBurger : Concrete Product</h4>
<pre><code class="language-java">public class VeggieBurger extends Burger {
    public void prepare() {
        System.out.println(&quot;Veggie preparing&quot;);
    }

    public void cook() {
        System.out.println(&quot;Veggie cooking&quot;);
    }
}</code></pre>
<h4 id="beefburger--concrete-product">BeefBurger : Concrete Product</h4>
<pre><code class="language-java">public class BeefBurger extends Burger {
    public void prepare() {
        System.out.println(&quot;BeefBurger preparing&quot;);
    }

    public void cook() {
        System.out.println(&quot;BeefBurger cooking&quot;);
    }
}
</code></pre>
<h1 id="factory-method-pattern">Factory Method Pattern</h1>
<blockquote>
<p>creation design pattern</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/ef8a49f1-1ed4-4c12-8ecf-3e33c9a15bd0/image.png" alt="">
위 UML로 구현하는게 결론인데 코드 예시로 기억하자.
<img src="https://velog.velcdn.com/images/0ne-hsj/post/84b7f8ae-92ac-4851-807f-953bb7b4c641/image.png" alt=""></p>
<h3 id="restaurant--creator">Restaurant : creator</h3>
<pre><code class="language-java">public abstract class Restaurant {

//    public Restaurant(SimpleBurgerFactory factory) {
//        this.factory = factory;
//    }
    // 더이상 다른 객체에 의존할 필요가 없어짐!

    public Burger orderBurger() {
        Burger burger = createBurger();
        burger.prepare();
        burger.cook();
        return burger;
    }

    public abstract Burger createBurger(); //이게 Factory Method!!!!
}</code></pre>
<h4 id="beefburgerrestaurant--concrete-creator">BeefBurgerRestaurant : Concrete Creator</h4>
<pre><code class="language-java">public class BeefBurgerRestaurant extends Restaurant {

    @Override
    public Burger createBurger() {
        return new BeefBurger();
    }
}
</code></pre>
<h4 id="veggieburgerrestaurant--concrete-creator">VeggieBurgerRestaurant : Concrete Creator</h4>
<pre><code class="language-java">public class VeggieBurgerRestaurant extends Restaurant {

    @Override
    public Burger createBurger() {
        return new VeggieBurger();
    }
}</code></pre>
<h3 id="burger--product-1">Burger : Product</h3>
<pre><code class="language-java">public interface Burger {
    public abstract void prepare();

    public abstract void cook();
}</code></pre>
<h4 id="beefburger--concrete-product-1">BeefBurger : Concrete Product</h4>
<pre><code class="language-java">public class BeefBurger implements Burger {
    public void prepare() {
        System.out.println(&quot;BeefBurger preparing&quot;);
    }

    public void cook() {
        System.out.println(&quot;BeefBurger cooking&quot;);
    }
}
</code></pre>
<h4 id="veggieburger--concrete-product-1">VeggieBurger : concrete product</h4>
<pre><code class="language-java">public class VeggieBurger implements Burger {
    public void prepare() {
        System.out.println(&quot;Veggie preparing&quot;);
    }

    public void cook() {
        System.out.println(&quot;Veggie cooking&quot;);
    }
}
</code></pre>
<h3 id="main">main</h3>
<pre><code class="language-java">import java.util.Scanner;

public class RestaurantMain {
    public static void main(String[] args) {
        Restaurant beefRestaurant = new BeefBurgerRestaurant();
        Restaurant veggieRestaurant = new VeggieBurgerRestaurant();

        Burger burger1 = beefRestaurant.orderBurger();
        Burger burger2= veggieRestaurant.orderBurger();

    }
}
</code></pre>
<h2 id="factory-method는-반드시-concrete-product를-반환해야-한다">Factory Method는 반드시 Concrete Product를 반환해야 한다.</h2>
<h1 id="when-and-why">when and why?</h1>
<h4 id="product-construction-code와-product-application-code를-분리">product construction code와 product application code를 분리</h4>
<p>-&gt; 새 product를 다른 코드의 수정없이 사용가능</p>
<h4 id="특정-객체의-정확한-type과-dependency를-모를-때">특정 객체의 정확한 type과 dependency를 모를 때</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[Design Pattern이란?]]></title>
            <link>https://velog.io/@0ne-hsj/Design-Pattern%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@0ne-hsj/Design-Pattern%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sat, 15 Jun 2024 03:27:37 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<blockquote>
<p>&quot;A proven solution to a commmon problem in a specified context&quot;</p>
</blockquote>
<h2 id="분류">분류</h2>
<h3 id="creational">Creational</h3>
<ul>
<li>Abstract Factory</li>
<li>Builder</li>
<li>Factory Method</li>
<li>Prototype</li>
<li>Singleton<h3 id="structural">Structural</h3>
</li>
<li>Adapter</li>
<li>Bridge </li>
<li>Composite </li>
<li>Decorator </li>
<li>Façade </li>
<li>Flyweight </li>
<li>Proxy<h3 id="behavioral">Behavioral</h3>
</li>
<li>Chain of Responsibility </li>
<li>Command</li>
<li>Interpreter</li>
<li>Iterator</li>
<li>Mediator</li>
<li>Memento</li>
<li>Observer</li>
<li>State</li>
<li>Strategy</li>
<li>Template Method </li>
<li>Visitor<h2 id="law">Law</h2>
</li>
</ul>
<ol>
<li>서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.</li>
</ol>
<ul>
<li>observer pattern에서 잘 드러남</li>
</ul>
<ol start="2">
<li>클래스는 확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다. 이를 Open-Closed Principle (OCP)라 한다.</li>
</ol>
<ul>
<li>decorator pattern에서 잘 드러남</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_Iterator]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAIterator</link>
            <guid>https://velog.io/@0ne-hsj/JAVAIterator</guid>
            <pubDate>Tue, 11 Jun 2024 14:21:51 GMT</pubDate>
            <description><![CDATA[<h3 id="iteratort-인터페이스">Iterator&lt;T&gt; 인터페이스</h3>
<h4 id="iteratort-인터페이스를-만족하는-모든-클래스의-객체는-iteratort타입으로-사용될-수-있다">Iterator&lt;T&gt; 인터페이스를 만족하는 모든 클래스의 객체는 Iterator&lt;T&gt;타입으로 사용될 수 있다.</h4>
<h4 id="iteratort는-독립적으로-존재-ㄴㄴ">Iterator&lt;T&gt;는 독립적으로 존재 ㄴㄴ</h4>
<ul>
<li><p>반드시 컬렉션 객체와 연관되어야 하며, 보통 컬렉션의 내부 클래스(inner class)로서 iterator 메서드를 통해 사용</p>
</li>
<li><p>Iterator는 내부 데이터 구조를 순회함
<code>Object next()</code>
내부 구조에서 다음 항목을 반환합니다.
<code>boolean hasNext()</code>
구조 내에 더 많은 항목이 있는지 여부를 반환합니다.
<code>void remove()</code>
현재 항목을 구조에서 제거합니다.</p>
</li>
</ul>
<h4 id="arraylist에서-iterator사용">ArrayList에서 Iterator사용</h4>
<ul>
<li>ArrayList에서 Iterator를 사용하려면, 먼저 ArrayList로부터 이를 얻어야 합니다.</li>
<li>예를 들어, <code>Iterator&lt;String&gt; iterator = myArrayList.iterator();</code>와 같이 사용<pre><code class="language-java">import java.util.ArrayList;
import java.util.Iterator;
</code></pre>
</li>
</ul>
<p>public class ArrayListIteratorExample {
    public static void main(String[] args) {
        // ArrayList 생성 및 요소 추가
        ArrayList<String> myArrayList = new ArrayList&lt;&gt;();
        myArrayList.add(&quot;A&quot;);
        myArrayList.add(&quot;B&quot;);
        myArrayList.add(&quot;C&quot;);</p>
<pre><code>    // Iterator를 통해 요소 순회
    Iterator&lt;String&gt; iterator = myArrayList.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        System.out.println(item);

        // 요소 &quot;B&quot;를 제거
        if (item.equals(&quot;B&quot;)) {
            iterator.remove();
        }
    }

    // 제거 후 ArrayList 출력
    System.out.println(&quot;After removal:&quot;);
    for (String item : myArrayList) {
        System.out.println(item);
    }

}</code></pre><p>}</p>
<pre><code>```java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ConcurrentModificationException;

public class GenericManager&lt;T&gt; {
    private ArrayList&lt;T&gt; items;

    public GenericManager() {
        this.items = new ArrayList&lt;&gt;();
    }

    // 요소 추가 메서드
    public void addItem(T item) {
        items.add(item);
    }

    // 요소 제거 메서드
    public void removeItem(T item) {
        items.remove(item);
    }

    // 이터레이터를 사용하여 리스트를 순회하는 메서드
    public void iterateItems() {
        try {
            for (Iterator&lt;T&gt; iterator = items.iterator(); iterator.hasNext(); ) {
                T item = iterator.next();
                System.out.println(item);
                // 특정 조건을 만족하면 요소를 제거
                if (/* 조건 */ item.equals(&quot;B&quot;)) {
                    iterator.remove();
                }
            }
        } catch (ConcurrentModificationException e) {
            System.out.println(&quot;ConcurrentModificationException 발생: 이터레이터 사용 시 리스트를 직접 수정할 수 없습니다.&quot;);
        }
    }

    public static void main(String[] args) {
        GenericManager&lt;String&gt; manager = new GenericManager&lt;&gt;();
        manager.addItem(&quot;A&quot;);
        manager.addItem(&quot;B&quot;);
        manager.addItem(&quot;C&quot;);

        System.out.println(&quot;초기 리스트:&quot;);
        manager.iterateItems();

        System.out.println(&quot;요소 제거 후 리스트:&quot;);
        manager.iterateItems();
    }
}
</code></pre><h3 id="사용자-정의-컬렉션과-iterator">사용자 정의 컬렉션과 Iterator</h3>
<pre><code class="language-java">import java.util.Iterator;
import java.util.NoSuchElementException;

public class CustomCollection&lt;T&gt; implements Iterable&lt;T&gt; {
    private T[] items;
    private int size;

    @SuppressWarnings(&quot;unchecked&quot;)
    public CustomCollection(int capacity) {
        items = (T[]) new Object[capacity];
        size = 0;
    }

    // 요소 추가 메서드
    public void add(T item) {
        if (size == items.length) {
            throw new IllegalStateException(&quot;컬렉션이 가득 찼습니다.&quot;);
        }
        items[size++] = item;
    }

    // 요소 제거 메서드
    public void remove(T item) {
        for (int i = 0; i &lt; size; i++) {
            if (items[i].equals(item)) {
                for (int j = i; j &lt; size - 1; j++) {
                    items[j] = items[j + 1];
                }
                items[--size] = null;
                return;
            }
        }
        throw new NoSuchElementException(&quot;요소가 컬렉션에 없습니다.&quot;);
    }

    // 컬렉션의 크기 반환 메서드
    public int size() {
        return size;
    }

    // 이터레이터를 반환하는 메서드
    @Override
    public Iterator&lt;T&gt; iterator() {
        return new CustomIterator();
    }

    // 내부 클래스: CustomIterator
    private class CustomIterator implements Iterator&lt;T&gt; {
        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
            return currentIndex &lt; size;
        }

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            return items[currentIndex++];
        }

        @Override
        public void remove() {
            if (currentIndex &lt;= 0) {
                throw new IllegalStateException(&quot;next()를 먼저 호출해야 합니다.&quot;);
            }
            CustomCollection.this.remove(items[currentIndex - 1]);
            currentIndex--;
        }
    }

    public static void main(String[] args) {
        CustomCollection&lt;String&gt; customCollection = new CustomCollection&lt;&gt;(10);
        customCollection.add(&quot;A&quot;);
        customCollection.add(&quot;B&quot;);
        customCollection.add(&quot;C&quot;);

        System.out.println(&quot;초기 컬렉션:&quot;);
        for (String item : customCollection) {
            System.out.println(item);
        }

        // 이터레이터를 사용하여 &quot;B&quot; 요소 제거
        Iterator&lt;String&gt; iterator = customCollection.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            if (item.equals(&quot;B&quot;)) {
                iterator.remove();
            }
        }

        System.out.println(&quot;요소 제거 후 컬렉션:&quot;);
        for (String item : customCollection) {
            System.out.println(item);
        }
    }
}
</code></pre>
<p>내가 구현한 iterator for 사용자 정의 hashmap</p>
<pre><code class="language-java">    public void printElements() {
        for (int i = 0; i &lt; a.size(); i++) {
            LinkedList&lt;Pair&lt;K, V&gt;&gt; bucket = a.get(i);
            System.out.println(&quot;Bucket &quot; + i + &quot;:&quot;);

            Iterator&lt;Pair&lt;K, V&gt;&gt; iterator = bucket.iterator();
            while (iterator.hasNext()) {
                Pair&lt;K, V&gt; pair = iterator.next();
                System.out.println(&quot;  &quot; + pair.getKey() + &quot; -&gt; &quot; + pair.getValue());
            }
        }
    }


    @Override
    public Iterator&lt;Pair&lt;K, V&gt;&gt; iterator() { 

        return new Iterator&lt;Pair&lt;K, V&gt;&gt;() {
            private int i = 0;
            Iterator&lt;Pair&lt;K, V&gt;&gt; bucketIterator = a.get(i).iterator(); //

            @Override
            public boolean hasNext() {
                while(!bucketIterator.hasNext()) {
                    i++;
                    if (i &gt;= a.size()) {
                        return false;
                    }
                    bucketIterator = a.get(i).iterator();
                }
                return true;
                //returns whether the Linked List has a next element //your code
            }

            @Override
            public Pair&lt;K, V&gt; next() {
                if(!hasNext()) {
                    throw new NoSuchElementException();
                }
                return bucketIterator.next();
                //returns the next element of the linked List // your code
            }
        };
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_generics]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAgenerics</link>
            <guid>https://velog.io/@0ne-hsj/JAVAgenerics</guid>
            <pubDate>Tue, 11 Jun 2024 13:59:02 GMT</pubDate>
            <description><![CDATA[<h3 id="여러개의-type-parameter가능">여러개의 type parameter가능</h3>
<h3 id="primitive-type은-사용-불가-class-type만">primitive type은 사용 불가; class Type만</h3>
<p>당연히 array도 가능하겠죠?</p>
<h2 id="generic-method">generic method</h2>
<pre><code class="language-java"> public class Utility {

    // 제네릭 메서드
    public static &lt;T&gt; void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] stringArray = {&quot;Hello&quot;, &quot;World&quot;};

        // 제네릭 메서드 호출
        Utility.&lt;Integer&gt;printArray(intArray);
        Utility.&lt;String&gt;printArray(stringArray);
    }
}
</code></pre>
<h2 id="generic-class-parameterized-class">generic class; parameterized class</h2>
<pre><code class="language-java">public class Pair&lt;K, V&gt; {
    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue(V value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return &quot;Pair{&quot; +
               &quot;key=&quot; + key +
               &quot;, value=&quot; + value +
               &#39;}&#39;;
    }

    public static void main(String[] args) {
        // String과 Integer 타입을 사용하는 Pair 객체
        Pair&lt;String, Integer&gt; pair1 = new Pair&lt;String, Integer&gt;(&quot;One&quot;, 1);
        System.out.println(pair1);

        // String과 String 타입을 사용하는 Pair 객체
        Pair&lt;String, String&gt; pair2 = new Pair&lt;String, String&gt;(&quot;Hello&quot;, &quot;World&quot;);
        System.out.println(pair2);

        // Integer와 Double 타입을 사용하는 Pair 객체
        Pair&lt;Integer, Double&gt; pair3 = new Pair&lt;Integer, Double&gt;(42, 3.14);
        System.out.println(pair3);
    }
}
</code></pre>
<h2 id="binding-t에-가능한-타입을-제약">binding; T에 가능한 타입을 제약</h2>
<ol>
<li>제네릭을 특정 인터페이스나 부모 클래스에 바인딩하는 경우:</li>
</ol>
<ul>
<li>extends 키워드를 사용합니다.</li>
<li>인터페이스나 부모 클래스에 바인딩되면 제네릭 타입이 특정 인터페이스나 클래스의 서브타입이어야 합니다.</li>
</ul>
<pre><code class="language-java">public class MyClass&lt;T extends Comparable&gt; {
    // 이 코드는 T가 Comparable 타입만 가능하도록 강제합니다.
}
</code></pre>
<ol start="2">
<li>제네릭을 여러 타입에 바인딩하는 경우:</li>
</ol>
<ul>
<li>여러 인터페이스에 바인딩할 수 있습니다.</li>
<li>하나의 클래스에만 바인딩할 수 있으며, 클래스는 항상 첫 번째로 나와야 합니다.<pre><code class="language-java">public class MyClass&lt;T extends Employee &amp; Comparable &amp; Iterable&gt; {
  // 이 코드는 T가 Employee의 서브클래스이면서 동시에 Comparable 및 Iterable 인터페이스를 구현해야 한다는 것을 강제합니다.
  // 확장된 클래스(Employee)는 항상 첫 번째로 나와야 합니다.
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_ArrayList]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAArrayList</link>
            <guid>https://velog.io/@0ne-hsj/JAVAArrayList</guid>
            <pubDate>Tue, 11 Jun 2024 13:40:36 GMT</pubDate>
            <description><![CDATA[<h4 id="import">import</h4>
<p><code>import java.util.ArrayList;</code> </p>
<h1 id="정의">정의</h1>
<h2 id="length가-변할-수-있는-배열">length가 변할 수 있는 배열</h2>
<h4 id="array--만들어지는-순간-길이-고정">array : 만들어지는 순간 길이 고정</h4>
<h4 id="원리">원리</h4>
<p>array를 private 필드로 가지고 있음 + 꽉 찰때마다 더 긴 array가 생성되어 이동</p>
<h3 id="문법">문법</h3>
<pre><code class="language-java">ArrayList&lt;T&gt; aList = new ArrayList&lt;T&gt;(); //초기는 capacity 10
ArrayList&lt;String&gt; bList = new ArrayList&lt;String&gt;(20)</code></pre>
<h2 id="사용">사용</h2>
<h4 id="항상-array를-대체하는-것은-아님">항상 array를 대체하는 것은 아님</h4>
<ul>
<li><code>ArrayList</code> 객체는 array보다 비효율적</li>
<li>&#39;[]&#39; 사용 불가</li>
<li><code>ArrayList</code>의 요소는 class type이어야 함. primitive type은 불가능
; 물론 automatic boxing, unboxing으로 해결</li>
</ul>
<h3 id="method">method</h3>
<p>사용자 정의 클래스 타입</p>
<pre><code class="language-java">class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return &quot;Person{name=&#39;&quot; + name + &quot;&#39;, age=&quot; + age + &quot;}&quot;;
    }
}</code></pre>
<h4 id="adde-e">add(E e)</h4>
<pre><code class="language-java">ArrayList&lt;Person&gt; list = new ArrayList&lt;&gt;();
list.add(new Person(&quot;Alice&quot;, 30));
list.add(new Person(&quot;Bob&quot;, 25));
System.out.println(list);</code></pre>
<h4 id="addint-index-e-element">add(int index, E element)</h4>
<pre><code class="language-java">list.add(1, new Person(&quot;Charlie&quot;, 35));
System.out.println(list);</code></pre>
<h4 id="getint-index">get(int index)</h4>
<pre><code class="language-java">Person p = list.get(1);
System.out.println(p);</code></pre>
<h4 id="setint-index-e-element">set(int index, E element)</h4>
<pre><code class="language-java">list.set(1, new Person(&quot;David&quot;, 40));
System.out.println(list);</code></pre>
<h4 id="removeint-index">remove(int index)</h4>
<pre><code class="language-java">list.remove(2);
System.out.println(list);</code></pre>
<h4 id="removeobject-o">remove(Object o)</h4>
<pre><code class="language-java">list.remove(new Person(&quot;Alice&quot;, 30));
System.out.println(list);
</code></pre>
<h4 id="removerangeint-fromidx-int-toidx">removeRange(int fromIdx, int toIdx)</h4>
<p>ArrayList의 상위 클래스인 AbstractList클래스에서 protected메소드로 정의되어 있음
따라서 ArrayList를 상속받은 커스텀클래스를 통해 removeRange를 사용해야 함</p>
<pre><code class="language-java">import java.util.ArrayList;

class CustomArrayList&lt;E&gt; extends ArrayList&lt;E&gt; {
    @Override
    protected void removeRange(int fromIndex, int toIndex) {
        super.removeRange(fromIndex, toIndex);
    }
}
public class Main {
    public static void main(String[] args) {
        CustomArrayList&lt;Person&gt; list = new CustomArrayList&lt;&gt;();
        list.add(new Person(&quot;Alice&quot;, 30));
        list.add(new Person(&quot;Bob&quot;, 25));
        list.add(new Person(&quot;Charlie&quot;, 35));
        list.add(new Person(&quot;David&quot;, 40));
        list.add(new Person(&quot;Eve&quot;, 22));

        System.out.println(&quot;Before removeRange: &quot; + list);

        list.removeRange(1, 4);

        System.out.println(&quot;After removeRange: &quot; + list);
    }
}
</code></pre>
<h4 id="clear">clear()</h4>
<pre><code class="language-java">list.clear();
System.out.println(list);
</code></pre>
<h4 id="containsobject-o">contains(Object o)</h4>
<pre><code class="language-java">boolean contains = list.contains(new Person(&quot;Alice&quot;, 30));
System.out.println(contains);</code></pre>
<h4 id="indexofobject-o">indexOf(Object o)</h4>
<pre><code class="language-java">int index = list.indexOf(new Person(&quot;Alice&quot;, 30));
System.out.println(index);
</code></pre>
<h4 id="lastindexofobject-o">lastIndexOf(Object o)</h4>
<pre><code>int lastIndex = list.lastIndexOf(new Person(&quot;Alice&quot;, 30));
System.out.println(lastIndex);
</code></pre><h4 id="ensurecapacityint-mincapacity">ensureCapacity(int minCapacity)</h4>
<p>최소 용량 보장</p>
<h4 id="trimtosize">trimToSize()</h4>
<p>리스트의 용량을 현재 크기로 줄임</p>
<h4 id="toarray">toArray()</h4>
<pre><code class="language-java">Object[] array = list.toArray();
for (Object obj : array) {
    System.out.println(obj);
}</code></pre>
<p>지정된 배열에 리스트의 모든 요소를 포함시킴</p>
<pre><code class="language-java">import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList&lt;Person&gt; list = new ArrayList&lt;&gt;();
        list.add(new Person(&quot;Alice&quot;, 30));
        list.add(new Person(&quot;Bob&quot;, 25));
        list.add(new Person(&quot;Charlie&quot;, 35));
        list.add(new Person(&quot;David&quot;, 40));
        list.add(new Person(&quot;Eve&quot;, 22));

        System.out.println(&quot;Original list: &quot; + list);

        // Person 배열로 변환
        Person[] personArray = list.toArray(new Person[0]);

        for (Person p : personArray) {
            System.out.println(p);
        }
    }
}
</code></pre>
<p>인자로 전달된 배열이 list보다 작은경우 새 배열을 만들어 전달.</p>
<h4 id="clone">clone()</h4>
<p>얕은복사!!</p>
<pre><code class="language-java">ArrayList&lt;Person&gt; clonedList = (ArrayList&lt;Person&gt;) list.clone();
System.out.println(clonedList);
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_file I/O]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAfile-IO</link>
            <guid>https://velog.io/@0ne-hsj/JAVAfile-IO</guid>
            <pubDate>Tue, 11 Jun 2024 04:27:24 GMT</pubDate>
            <description><![CDATA[<h4 id="stream">stream</h4>
<ul>
<li>input stream : keyboard or from a file</li>
<li>output stream : screen or to a file<h4 id="file">file</h4>
</li>
<li>file(; ASCII file) : 모든 컴퓨터에서 동일하기에 송수신 가능</li>
<li>binary file : 같은 컴퓨터, 같은 언어에서 읽을 수 있음, textfile보다 효율적, 자바 binary file의 경우 platform에 독립적임</li>
</ul>
<h1 id="writing-to-a-text-file">writing to a text file</h1>
<h2 id="printwriter-객체를-이용해야-함"><code>PrintWriter</code> 객체를 이용해야 함</h2>
<h3 id="import">import</h3>
<pre><code class="language-java">    import java.io.PrintWriter;
    import java.io.FileOutputStream;
    import java.io.FileNotFoundException;</code></pre>
<h3 id="try-catch-block-밖에-printwriter-객체가-선언되어야-함">try-catch block 밖에 PrintWriter 객체가 선언되어야 함</h3>
<p>local객체이면 안되므로</p>
<h3 id="파일명을-사용하려면-fileoutputstream_filename을-이용해야-함">파일명을 사용하려면 <code>FileOutputStream(_filename)</code>을 이용해야 함</h3>
<pre><code class="language-java">    PrintWriter outputStreamName; 
    outputStreamName = new PrintWriter(new FileOutputStream(FileName));</code></pre>
<h4 id="file-존재시--옛날-자료-사라짐">file 존재시 : 옛날 자료 사라짐</h4>
<p>따라서 <code>outputStreamName = new PrintWriter(new FileOutputStream(FileName, true));</code> 를 이용해야 함  ; 덧붙이기 모드</p>
<h4 id="file-존재x시--새로운-파일-생성">file 존재x시 : 새로운 파일 생성</h4>
<h3 id="printprintln를-사용하여-file에-쓸-수-있음"><code>print</code>,<code>println</code>를 사용하여 file에 쓸 수 있음</h3>
<h3 id="outputstreamnameclose"><code>outputStreamName.close()</code></h3>
<ul>
<li>file에 연결했던 stream을 자원을 해제함<h3 id="buffer">buffer</h3>
physical writing to a file이 느림이에, 즉시 쓰지 않고 temporary location에 저장하는데 이곳이 buffer.<h4 id="close할-때나-buffer에-data가-쌓였을-때flush가-호출되어-buffer의-데이터가-file에-한-번에-쓰임"><code>close()</code>할 때나 buffer에 data가 쌓였을 때,<code>flush()</code>가 호출되어 buffer의 데이터가 file에 한 번에 쓰임</h4>
<h2 id="주의점">주의점</h2>
<h4 id="program-terminates-abnormally">program terminates abnormally</h4>
bufferd data날라감<h4 id="close-전에-reopen하려-할-때">close 전에 reopen하려 할 때</h4>
파일이 제대로 읽히지 않거나 파일에 손상을 가져옴<h4 id="가능한한-빨리-닫아야-함">가능한한 빨리 닫아야 함</h4>
</li>
</ul>
<h1 id="reading-from-a-text-file">reading from a text file</h1>
<h2 id="scanner-객체를-이용"><code>Scanner</code> 객체를 이용</h2>
<h3 id="import-1">import</h3>
<pre><code class="language-java">    import java.util.Scanner;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;</code></pre>
<h3 id="파일명을-이용하려면-fileinputstream_filename을-이용해야-함">파일명을 이용하려면 <code>FileInputStream(_filename)</code>을 이용해야 함</h3>
<p>* keyboard input을 이용하려면 단순히 <code>Scanner(System.in)</code>이용</p>
<pre><code class="language-java">    Scanner inputStream = null;

    try {
        inputStream = new Scanner(new FileInputStream(FileName));
    } catch (FileNotFoundException e){
        System.exit(0);
    }

    int n1 = inputStream.nextInt();
    int n2 = inputStream.nextInt();
    int n3 = inputStream.nextInt();

    inputStream.nextLine(); //다음 줄로

    inputStream.close();</code></pre>
<h3 id="text-file-끝-처리">text file 끝 처리</h3>
<ul>
<li>끝을 넘어서 read하려고 하면 예외가 던져짐</li>
<li>이를 해결하기 위해 <code>hasNextLine()</code>,<code>hasNextInt()</code>메서드를 활용<pre><code class="language-java">String line = null;
int count = 0;
while (inputStream.hasNextLine()) {
  line = inputStream.nextLine();
  count++;
  outputStream.println(count + &quot; &quot; + line);
}</code></pre>
</li>
</ul>
<h2 id="bufferedreader객체를-이용한-읽기"><code>BufferedReader</code>객체를 이용한 읽기</h2>
<h3 id="import-2">import</h3>
<pre><code>import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;</code></pre><h3 id="파일명을-이용하려면-filereader_filename을-이용해야-함">파일명을 이용하려면 <code>FileReader(_filename)</code>을 이용해야 함</h3>
<pre><code class="language-java">BufferedReader inputStream = null
try {
    inputStream = new BufferedReader(new FileReader(_filename));
    String line = inputStream.readLine();
    System.out.println(line);
} catch (FileNotFoundException e) {
    e.getMessage();
} catch (IOException e) {
    e.getMessage();
}</code></pre>
<h3 id="method">method</h3>
<h4 id="readline"><code>readLine()</code></h4>
<ul>
<li>line을 읽어 String 반환</li>
<li>end of file일 때 null 리턴; IOException 예외 throw 안함<h4 id="read"><code>read()</code></h4>
</li>
<li>각 char를 읽어 해당하는 int값 반환</li>
<li>end of file일 때 -1 리턴<h4 id="skiplong-n"><code>skip(Long n)</code></h4>
n개의 char 생략 </li>
</ul>
<h3 id="reading-number">Reading number</h3>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) {
        String fileName = &quot;numbers.txt&quot;;
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader(fileName));
            String line;

            // Read and convert single numbers on separate lines
            line = reader.readLine();
            if (line != null) {
                int intValue = Integer.parseInt(line);
                System.out.println(&quot;Integer value: &quot; + intValue);
            }

            line = reader.readLine();
            if (line != null) {
                double doubleValue = Double.parseDouble(line);
                System.out.println(&quot;Double value: &quot; + doubleValue);
            }

            // Read and convert multiple numbers on a single line
            line = reader.readLine();
            if (line != null) {
                StringTokenizer tokenizer = new StringTokenizer(line);
                while (tokenizer.hasMoreTokens()) {
                    String token = tokenizer.nextToken();
                    int number = Integer.parseInt(token);
                    System.out.println(&quot;Tokenized integer value: &quot; + number);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}</code></pre>
<h1 id="ioexception">IOException</h1>
<p>checked exception임 exception을 상속받음;;</p>
<h4 id="filenotfoundexception">FileNotFoundException</h4>
<p>I/O상황에서 예외일 때 대부분 이 예외가 던져짐</p>
<h4 id="nosuchelementexception">NoSuchElementException</h4>
<p>파일 끝에서 read를 시도할 때</p>
<h1 id="관련-주제">관련 주제</h1>
<h2 id="path-names">[Path Names]</h2>
<h4 id="file-name이-인자로-들어갈때의-전제--같은-디렉토리에-있다">file name이 인자로 들어갈때의 전제 : 같은 디렉토리에 있다.</h4>
<p>따라서 같은 디렉토리에 없다면, the full or relative path name을 제시해야 한다.</p>
<h3 id="정의">정의</h3>
<h4 id="full-path-name">full path name</h4>
<pre><code>•    Unix/Linux: /home/user/documents/file.txt
•    Windows: C:\Users\User\Documents\file.txt</code></pre><h4 id="relative-path-name">relative path name</h4>
<pre><code>•    . (현재 디렉터리)와 .. (상위 디렉터리) 등을 사용할 수 있습니다.
•    예시:
•    현재 디렉터리가 /home/user인 경우:
•    documents/file.txt (현재 디렉터리에서 documents 디렉터리 안의 file.txt 파일)
•    ../other_user/file.txt (현재 디렉터리의 상위 디렉터리인 /home 디렉터리 안의 other_user 디렉터리의 file.txt 파일)</code></pre><h3 id="사용">사용</h3>
<p>윈도우 </p>
<pre><code class="language-java">BufferedReader inputStream = new BufferedReader(new FileReader (&quot;C:\\dataFiles\\goodData\\data.txt&quot;));</code></pre>
<p>UNIX</p>
<pre><code class="language-java">BufferedReader inputStream =
        new BufferedReader(new
        FileReader(&quot;/user/sallyz/data/data.txt&quot;));</code></pre>
<h2 id="stream-redirection">[stream redirection]</h2>
<ul>
<li>System.in: 표준 입력 스트림으로, 일반적으로 키보드 입력을 처리합니다.</li>
<li>System.out: 표준 출력 스트림으로, 일반적으로 화면에 정상 출력을 나타냅니다.</li>
<li>System.err: 표준 오류 스트림으로, 일반적으로 화면에 오류 메시지를 나타냅니다.</li>
</ul>
<h3 id="다른-스트림으로-redirection하기">다른 스트림으로 redirection하기</h3>
<p>예를 들어, 에러 메시지를 화면이 아닌 파일에 기록하기</p>
<pre><code class="language-java">import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class Main {
    public static void main(String[] args) {
        // 원래 System.err는 콘솔을 가리킵니다.
        System.err.println(&quot;This error message will go to the console.&quot;);

        PrintStream errStream = null;
        try {
            // 새로운 PrintStream 객체를 생성하여 &quot;errMessages.txt&quot; 파일에 출력
            errStream = new PrintStream(new FileOutputStream(&quot;errMessages.txt&quot;));

            // System.err을 errStream으로 리다이렉션
            System.setErr(errStream);

            // 이제 System.err로 출력되는 메시지는 파일에 기록됩니다.
            System.err.println(&quot;This error message will go to the file.&quot;);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 리다이렉션한 스트림을 닫음
            if (errStream != null) {
                errStream.close();
            }
        }

        // 리다이렉션 후, 다시 콘솔로 출력되는지 확인 (일반적으로는 프로그램 종료 전까지 유지됨)
        System.err.println(&quot;This error message will also go to the file.&quot;);
    }
}</code></pre>
<h2 id="file-객체">[File 객체]</h2>
<p>wrapper class 같은 거</p>
<pre><code class="language-java">import java.util.Scanner;
import java.io.File;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

public class FileclassDemo {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        String line = null;
        String filename = null;
        line = keyboard.nextLine();
        filename = Keyboard.nextLine();
        File fileobj = new File(filename);

        while(fileobj.exists()) {
            System.out.println(&quot;해당 파일 이름이 이미 존재\n 다른 거&quot;);
               filename = keyboard.nextLine();
            fileobj = new File(filename);
        }

    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/12f01526-01ae-432d-aacd-465214435781/image.png" alt="">
<img src="https://velog.velcdn.com/images/0ne-hsj/post/96adbb71-58cd-4a7d-8ffc-1692da502910/image.png" alt="">
<img src="https://velog.velcdn.com/images/0ne-hsj/post/0a307dcd-639a-41eb-81c3-d3a3da422143/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_exception handling]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAexception-handling</link>
            <guid>https://velog.io/@0ne-hsj/JAVAexception-handling</guid>
            <pubDate>Mon, 10 Jun 2024 11:29:49 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<h4 id="throwing-an-exception">throwing an exception</h4>
<p>unusual한 무언가가 일어났을 때 신호를 보내는 기작</p>
<h4 id="handling-the-exception">handling the exception</h4>
<p>exceptional case를 다루는 코드</p>
<h2 id="1-throws-메서드를-이용하기">1. throws 메서드를 이용하기</h2>
<blockquote>
<p>pass the buck </p>
</blockquote>
<p>예외만 던지는 메서드</p>
<ul>
<li>해당 메서드는 try, catch블록을 가지고 있으면 안됨; 따라서 throws clause를 사용해 catch를 안함을 나타냄</li>
<li>이 메서드는 try블록 안에서 invoke됨; 해당 try블록을 가진 다른 메서드가 exception handling을 책임짐 즉, throws메서드는 throw만 함</li>
<li>여러개의 exception를 throw할 수 있도록 throws뒤에 여러 exception 타입을 명시할 수 있음<h2 id="2-trythrow-catch-finally">2. try(throw)-catch-finally</h2>
<h3 id="try--정상-흐름">try : 정상 흐름!!</h3>
<h4 id="i-exception-ㄴㄴ">i) exception ㄴㄴ</h4>
</li>
<li>try블록 끝까지 실행</li>
<li>catch블록 skip</li>
<li>catch블록 다음에 있는 코드까지 실행<h4 id="ii-exception-ㅇㅇ">ii) exception ㅇㅇ</h4>
중간에 <code>throw</code> 예외 객체</li>
<li>오류가 발생하면 예외 객체를 만들고 이를 throw함</li>
<li>try block 멈춤; 남은 try블록 skip</li>
<li>catch block을 call함</li>
</ul>
<h3 id="catch--예외-흐름">catch : 예외 흐름!!</h3>
<h4 id="던져진-예외-객체를-인자로-받음">던져진 예외 객체를 인자로 받음</h4>
<p>* 메서드 정의는 아님</p>
<ul>
<li>catch블록에서 잡을 수 있는 객체의 타입을 명시함</li>
<li>던져진 exception의 identifier를 정의<h4 id="multiple-catch-block">multiple catch block</h4>
</li>
<li>특정 exception 타입만 catch할 수 있으므로 여러 개의 catch 블록은 타당</li>
<li>하지만 순서가 중요하다; Specific이 먼저 오도록!!</li>
</ul>
<h3 id="finally--마무리-흐름">finally : 마무리 흐름!!</h3>
<p>i) ㄱ. 정상 흐름 ㄴ. finally
ii) ㄱ. 예외 catch ㄴ. finally
iii) ㄱ. 예외 catch 실패 ㄴ. finally ㄷ. method 종료, 밖으로 exception object 던져짐</p>
<h4 id="try를-시작만-해도-finally는-반드시-호출됨">try를 시작만 해도 finally는 반드시 호출됨</h4>
<h4 id="try-catch안에서-잡을-수-없는-예외가-발생해도-finally는-반드시-호출">try, catch안에서 잡을 수 없는 예외가 발생해도 finally는 반드시 호출</h4>
<h4 id="주로-try에서-사용한-자원을-해제할-때-주로-사용">주로 try에서 사용한 자원을 해제할 때 주로 사용</h4>
<h1 id="exception-class">exception class</h1>
<h2 id="predefined-exception-class">predefined exception class</h2>
<p><img src="https://velog.velcdn.com/images/0ne-hsj/post/50778df9-1052-48b8-95b3-9ccf091941f5/image.png" alt=""></p>
<h3 id="check-exception">check exception</h3>
<p>1) catch 블록에서 포착하거나 2) throws 키워드로 예외 선언을 해야 함</p>
<h3 id="uncheck-exception">uncheck exception</h3>
<p>예외를 잡아서 처리하지 않아도 throws키워드를 생략할 수 있다</p>
<pre><code class="language-java">package exception.basic.unchecked;
/**
* RuntimeException을 상속받은 예외는 언체크 예외가 된다. */
 public class MyUncheckedException extends RuntimeException {
     public MyUncheckedException(String message) {
         super(message);
     }
}</code></pre>
<pre><code class="language-java"> package exception.basic.unchecked;
 public class Client {
     public void call() {
         throw new MyUncheckedException(&quot;ex&quot;);
     }
}</code></pre>
<pre><code class="language-java">package exception.basic.unchecked;
/**
* UnChecked 예외는
* 예외를 잡거나, 던지지 않아도 된다.
* 예외를 잡지 않으면 자동으로 밖으로 던진다. */
 public class Service {
     Client client = new Client();
/**
* 필요한 경우 예외를 잡아서 처리하면 된다. */
     public void callCatch() {
         try {
             client.call();
         } catch (MyUncheckedException e) {
//예외 처리 로직
System.out.println(&quot;예외 처리, message=&quot; + e.getMessage()); }
System.out.println(&quot;정상 로직&quot;); }
/**
* 예외를 잡지 않아도 된다. 자연스럽게 상위로 넘어간다.
* 체크 예외와 다르게 throws 예외 선언을 하지 않아도 된다. */
     public void callThrow() {
         client.call();
} }</code></pre>
<p>check exception과 다르게 (예외를 처리할 수 없을 때 밖으로 던지는) <code>throws</code>예외 선언을 컴파일러가 체크하지 않기 때문에 &#39;언체크&#39; 예외이다.</p>
<h2 id="특징">특징</h2>
<p>모든 predefined exception class는</p>
<h4 id="string타입을-인자로-받는-생성자를-가짐">String타입을 인자로 받는 생성자를 가짐</h4>
<h4 id="해당-인자를-리턴하는-getmessage-accessor가-있음">해당 인자를 리턴하는 <code>getMessage</code> accessor가 있음</h4>
<h4 id="주의점-2가지를-일관되게-사용해야-함">주의점 2가지를 일관되게 사용해야 함</h4>
<p>동일한 예외에 대해서는 일관된 방식으로 처리 즉, 특정 예외를 catch 블록에서 처리하지 않으면 throws 키워드로 선언해야 하고, 반대로 catch 블록에서 처리하면 throws 키워드로 선언할 필요가 없어</p>
<h3 id="사용자-정의-exception-class">사용자 정의 exception class</h3>
<h4 id="predefined-exception-class를-상속받아야-함">predefined exception class를 상속받아야 함</h4>
<h4 id="최소-2개이상의-생성자를-정의해야-함">최소 2개이상의 생성자를 정의해야 함</h4>
<pre><code class="language-java">Public class MyException extends Exception{
    // variables
    public MyException() {
        super(&quot;default message&quot;);
        //perform other tasks
        }
    public MyException(VariableType var){
        super(var+ &quot;rest of message&quot;);
        //perform other tasks
    }
    //other methods if needed
}</code></pre>
<ol>
<li>문자열 매개변수를 갖는 생성자: 이 생성자는 super를 호출하여 매개변수를 인자로 사용해야 함</li>
<li>기본 생성자: 이 생성자는 super를 호출하여 기본 문자열을 인자로 사용해야 함</li>
</ol>
<h2 id="exception-controlled-loops">Exception controlled loops</h2>
<pre><code class="language-java">import java.util.Scanner;
import java.util.InputMismatchException; //unchecked

public class InputMismatchExceptionDemo {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        int number = 0;
        boolean done = false;

        while (!done) {
            try {
                System.out.println(&quot;Enter a whole num&quot;);
                number = keyboard.nextInt();
                done = true;
            }
            catch (InputMismatchException e) {
                keyboard.nextline(); //예외가 발생한 후에는 여전히 잘못된 입력이 남아있으므로 이를 소비.
                System.out.println(&quot;Not a correclty written whole number&quot;);
            }
        }
        System.out.println(&quot;You entered &quot; + number);
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_Thread]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAThread</link>
            <guid>https://velog.io/@0ne-hsj/JAVAThread</guid>
            <pubDate>Mon, 10 Jun 2024 00:46:57 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<h4 id="separate-computation-process">Separate Computation Process</h4>
<ul>
<li><p>multiple operation을 concurrently하게 할 수 있게 함</p>
<h4 id="parallel-execution">Parallel execution</h4>
</li>
<li><p>multiple threads를 동시에</p>
<h4 id="single-sequential-flow">Single Sequential Flow</h4>
</li>
<li><p>each thread는 코드를 선형적으로 처리함</p>
<h4 id="shared-resource">Shared Resource</h4>
</li>
<li><p>Thread는 고유의 메모리 공간을 가지지 않음</p>
</li>
<li><p>대신 프로세스의 메모리와 자원을 공유함 
* 각 프로세스는 다른 프로세스와 메모리 공간을 공유하지 않음
* 프로세스의 메모리 공간 : 코 데 힙 스
* 스레드는 독립적인 스택을 가짐, 같은 코드, 데이터, 힙 영역을 공유함</p>
</li>
</ul>
<h2 id="특성">특성</h2>
<h4 id="lightweight">Lightweight</h4>
<ul>
<li>Thread간 전환 비용 &lt;&lt; process간 전환 비용<h4 id="easy-to-spawn">easy to spawn</h4>
</li>
<li><code>Thread</code>class or<code>Runnable</code>interface로 쉽게 생성가능
* Runnable 선호; 다른 클래스 상속 가능하므로 <h4 id="priority-존재">priority 존재</h4>
</li>
<li>1~10까지</li>
<li>5가 디폴트</li>
</ul>
<h1 id="사용">사용</h1>
<h2 id="multithreading">multithreading</h2>
<h4 id="언제">언제</h4>
<ul>
<li>parallel processing(프로세스 내) 향상</li>
<li>user반응성 증가</li>
<li>cpu의 idle 시간 활용</li>
<li>priority에 다른 작업 처리 가능<h3 id="run구현---start로-스레드-생성-후-run실행">run()구현 -&gt; start()로 스레드 생성 후 run실행</h3>
<pre><code>class MyRunnable implements Runnable {
  @Override
  public void run() {
      for (int i = 0; i &lt; 5; i++) {
          System.out.println(Thread.currentThread().getName() + &quot; is running: &quot; + i);
          try {
              Thread.sleep(1000); // 1초 대기
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  }
}
</code></pre></li>
</ul>
<p>public class RunnableExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new MyRunnable());
        Thread thread2 = new Thread(new MyRunnable());</p>
<pre><code>    // 스레드를 시작
    thread1.start();
    thread2.start();
}</code></pre><p>}</p>
<pre><code>## synchronization
#### 왜
- multithreading은 asynchronous처리를 하게 하는데 필요할 때 synchronicity하게 처리 할 수 있어야 한다.
- `synchronized`를 이용
#### 언제
- thread interference 방지
- consistency 문제 방지
- data corruption 방지
### 작동 방식
#### `synchronized`
e.g. `public synchronized void produce()`
ㄱ. thread가 synchronized method실행시 해당 객체를 lock함
ㄴ. 하나의 thread만 lock을 할 수 있음 ⟹ 따라서 해당 메서드는 그 스레드만 작동 가능
ㄷ. method가 끝나면 lock은 해제됨
#### `wait()`

스레드는 `notify()`or`notifyAll()`메서드가 호출될 때까지 기다린다.
#### `notify()`or`notifyAll()`
- `notify()` 대기 중인 스레드 중 하나를 활성상태로 전환
- `notifyAll()` 대기 중인 모든 스레드를 활성 상태로 전환

\*메서드

| Method                    | Meaning                                                                                   |
|---------------------------|-------------------------------------------------------------------------------------------|
| Thread currentThread()    | returns a reference to the current thread                                                 |
| Void sleep(long msec)     | causes the current thread to wait for msec milliseconds                                   |
| String getName()          | returns the name of the thread.                                                           |
| Int getPriority()         | returns the priority of the thread                                                        |
| Boolean isAlive()         | returns true if this thread has been started and has not yet died. Otherwise, returns false. |
| Void join()               | causes the caller to wait until this thread dies.                                         |
| Void run()                | comprises the body of the thread. This method is overridden by subclasses.                |
| Void setName(String s)    | sets the name of this thread to s.                                                        |
| Void setPriority(int p)   | sets the priority of this thread to p.                                                    |
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_nested class]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAnested-class</link>
            <guid>https://velog.io/@0ne-hsj/JAVAnested-class</guid>
            <pubDate>Sun, 09 Jun 2024 11:55:53 GMT</pubDate>
            <description><![CDATA[<h2 id="분류">분류</h2>
<h4 id="static--바깥-클래스와-관련-없음-인스턴스에-소속되지-않음">[static] : 바깥 클래스와 관련 없음, 인스턴스에 소속되지 않음</h4>
<ul>
<li>static nested class<h4 id="non-static--바깥-클래스의-인스턴스에-소속-구성요소">[non-static] : 바깥 클래스의 인스턴스에 소속, 구성요소</h4>
</li>
<li>inner class</li>
<li>local class (inner + localVar에 접근)</li>
<li>anonymous class (local + class에 이름이 없음)</li>
</ul>
<h2 id="주의점">주의점</h2>
<h4 id="같은-시그니처인-method">같은 시그니처인 method</h4>
<ul>
<li>inner class의 method가 불림</li>
<li>outer class의 method를 사용할 수 없고, 새로 정의해야 함</li>
</ul>
<pre><code class="language-java">public class OuterClass {
    private int outerValue = 10;

    // 외부 클래스의 메서드
    public void display() {
        System.out.println(&quot;Outer class display method. outerValue: &quot; + outerValue);
    }

    public class InnerClass {
        private int innerValue = 5;

        // 내부 클래스의 메서드
        public void display() {
            System.out.println(&quot;Inner class display method. innerValue: &quot; + innerValue);

            // 외부 클래스의 메서드를 호출
            OuterClass.this.display();
        }

        public void invokeOuterDisplay() {
            // 외부 클래스의 display 메서드를 호출하는 방법
            OuterClass.this.display();
        }
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();

        // 내부 클래스의 display 메서드 호출
        inner.display();

        // 내부 클래스에서 외부 클래스의 display 메서드 호출
        inner.invokeOuterDisplay();
    }
}
</code></pre>
<h4 id="outer-class-어디에-정의해도-무관">Outer class 어디에 정의해도 무관</h4>
<h4 id="주로-helping-class로-사용-private으로-해야함">주로 helping class로 사용 (private으로 해야함)</h4>
<h3 id="inner-outer-private-멤버는-서로-접근-가능">inner, outer private 멤버는 서로 접근 가능</h3>
<pre><code class="language-java">public class OuterClass {
    private int outerValue = 10;

    // 외부 클래스의 private 메서드
    private void outerPrivateMethod() {
        System.out.println(&quot;Outer class private method.&quot;);
    }

    public class InnerClass {
        private int innerValue = 5;

        // 내부 클래스의 private 메서드
        private void innerPrivateMethod() {
            System.out.println(&quot;Inner class private method.&quot;);
        }

        // 내부 클래스의 메서드
        public void innerMethod() {
            // 외부 클래스의 private 인스턴스 변수 참조
            System.out.println(&quot;Accessing outer class private variable: &quot; + outerValue);

            // 외부 클래스의 private 메서드 호출
            outerPrivateMethod();
        }
    }

    // 외부 클래스의 메서드
    public void outerMethod() {
        InnerClass inner = new InnerClass();

        // 내부 클래스의 private 인스턴스 변수 참조
        System.out.println(&quot;Accessing inner class private variable: &quot; + inner.innerValue);

        // 내부 클래스의 private 메서드 호출
        inner.innerPrivateMethod();
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();

        // 내부 클래스의 메서드 호출
        inner.innerMethod();

        // 외부 클래스의 메서드 호출
        outer.outerMethod();
    }
}
</code></pre>
<h4 id="compile시-두개가-별도의-class파일로-생성됨">compile시 두개가 별도의 .class파일로 생성됨</h4>
<ul>
<li><code>ClassName.class</code></li>
<li><code>ClassName$InnerClassName.class</code></li>
</ul>
<h2 id="상속과-nested-class">상속과 nested class</h2>
<h4 id="outer-class를-상속받은-class">outer class를 상속받은 class</h4>
<ul>
<li>nested class를 가지게 됨</li>
<li>outer class의 해당 nested class를 override할 수는 없음<h4 id="inner-class-outer-class-모두-다른-클래스를-상속받을-수-있음">inner class, outer class 모두 다른 클래스를 상속받을 수 있음</h4>
</li>
</ul>
<hr>
<h1 id="static-nested-class">static nested class</h1>
<h4 id="static">static</h4>
<p>outer class의 instance member 접근 불가
outer class의 class member 접근 가능</p>
<h3 id="사용하는-상황">사용하는 상황</h3>
<h4 id="outer-class의-static-method에-static-nested-class의-객체를-이용할-때">outer class의 static method에 static nested class의 객체를 이용할 때</h4>
<h4 id="static-nested-class가-static-멤버를-가져야-할-때">static nested class가 static 멤버를 가져야 할 때</h4>
<pre><code class="language-java">public class NestedOuter {  

    private static int outClassValue = 3;  
    private int outInstanceValue = 2;  

    static class Nested {  
        private int nestedInstanceValue = 1;  

        public void print() {  
            // 자신의 멤버에 접근  
            System.out.println(nestedInstanceValue);  

            // 바깥 클래스의 인스턴스 멤버에 접근에는 접근할 수 없다.  
            //System.out.println(outInstanceValue);  
            // 바깥 클래스의 클래스 멤버에는 접근할 수 있다. private도 접근 가능  
            System.out.println(NestedOuter.outClassValue); 
        }  
    }  
}
-----------------------------------------------------------
package nested.nested;  

public class NestedOuterMain {  

    public static void main(String[] args) {  
        Nested.StaticNestedClass nested = new Nested.StaticNestedClass();
        nested.print();  

        System.out.println(&quot;nestedClass = &quot; + nested.getClass());  
    }  
}</code></pre>
<h1 id="public-inner-class">(public) Inner class</h1>
<h2 id="정의">정의</h2>
<h4 id="outer-class의-instance-멤버에-직접-접근-가능">outer class의 instance 멤버에 직접 접근 가능</h4>
<h4 id="⟹-inner-class-내부에서만-사용할-멤버를-public으로-만들-필요가-없음">⟹ inner class 내부에서만 사용할 멤버를 public으로 만들 필요가 없음</h4>
<h4 id="inner-class는-outer-class를-reference함">inner class는 outer class를 reference함.</h4>
<pre><code class="language-java">public class OuterClass {
    private int outerValue = 10;

    // Public method를 통해 내부 클래스의 메서드를 호출
    public void doSomething() {
        InnerClass inner = new InnerClass();
        inner.innerMethod();
    }

    // 내부 클래스
    private class InnerClass {
        // 외부 클래스의 메서드를 호출하여 특정 작업을 수행
        private void innerMethod() {
            System.out.println(&quot;Inner method is accessing outerValue: &quot; + outerValue);
            helperMethod(); // 외부 클래스의 private 메서드 호출
        }
    }

    // 외부 클래스의 private 메서드; 이걸 public으로 안해도 됨
    private void helperMethod() {
        System.out.println(&quot;Helper method is doing some work.&quot;);
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.doSomething();
    }
}
</code></pre>
<h1 id="anonymous-class">anonymous class</h1>
<h2 id="사용">사용</h2>
<h4 id="보통-인터페이스나-추상-클래스를-구현하거나-확장하기-위해-사용됨">보통 인터페이스나 추상 클래스를 구현하거나 확장하기 위해 사용됨</h4>
<pre><code class="language-java">interface Greet {
    void sayHello();
}</code></pre>
<pre><code class="language-java">public class AnonymousClassExample {
    public static void main(String[] args) {
        // Greet 인터페이스를 구현하는 익명 클래스
        Greet greeter = new Greet() {
            @Override
            public void sayHello() {
                System.out.println(&quot;Hello from anonymous class!&quot;);
            }
        };

        // 익명 클래스 메서드 호출
        greeter.sayHello();

        // 또 다른 예제: 여러 메서드를 가진 사용자 정의 클래스를 확장한 익명 클래스
        GreeterClass greeterClass = new GreeterClass() {
            @Override
            public void greet() {
                System.out.println(&quot;Greetings from extended anonymous class!&quot;);
            }
        };

        greeterClass.greet();
        greeterClass.sayGoodbye();
    }
}

// 또 다른 사용자 정의 클래스
class GreeterClass {
    public void greet() {
        System.out.println(&quot;Hello from GreeterClass!&quot;);
    }

    public void sayGoodbye() {
        System.out.println(&quot;Goodbye from GreeterClass!&quot;);
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA_interface]]></title>
            <link>https://velog.io/@0ne-hsj/JAVAinterface</link>
            <guid>https://velog.io/@0ne-hsj/JAVAinterface</guid>
            <pubDate>Sun, 09 Jun 2024 09:38:23 GMT</pubDate>
            <description><![CDATA[<h2 id="abstract-class">abstract class</h2>
<h3 id="규칙">규칙</h3>
<ol>
<li>Abstract method가 있으면 무조건 그 class는 abstact class이다.</li>
<li>abstract method는 <code>private</code>이 될 수 없음</li>
<li>abstract class는 인스턴스를 만들 수 없음</li>
</ol>
<ul>
<li>abstract class의 생성자는 객체를 생성할 수 없다. 대신 상속받은 자식 클래스에서 super로 사용가능하다.</li>
</ul>
<ol start="4">
<li>그럼에도 타입으로서 인정되기에 파라미터로 사용가능.</li>
</ol>
<h4 id="pure-abstract-class-≡-모든-메서드가-abstract-method인-클래스">pure abstract class ≡ 모든 메서드가 abstract method인 클래스</h4>
<ul>
<li><p>실행 로직을 전혀가지고 있지 않은, 그저 다형성을 위한 부모 타입으로써의 껍데기.</p>
</li>
<li><p><a href="https://velog.io/@0ne-hsj/JAVAinterface">JAVA_interface</a></p>
</li>
</ul>
<h3 id="사용하는-이유">사용하는 이유</h3>
<ul>
<li>의미없는 기능 just 상속용 base class의 인스턴스가 생성되면?<ul>
<li>abstract class!로 해결</li>
<li>abstact class는 인스턴스를 만들 수 없음</li>
</ul>
</li>
<li>새로운 자식 class를 만들 때 까먹고 override하지 않을 문제<ul>
<li>abstract method는 직접 정의하도록 자바에서 제약을 줌</li>
<li>abstact method는 자식 클래스가 반드시 오버라이딩해서 사용해야 함</li>
<li>그렇지 않으면 자식도 추상 클래스가 되어야 함</li>
</ul>
</li>
</ul>
<ol>
<li>코드를 공유하는 경우; 공통된 메서드, 필드가 많은 경우</li>
<li>protected와 private 접근 제어자는 서브클래스와 클래스 내부에서의 접근을 제어하여, 적절한 캡슐화를 제공함</li>
<li>non-static member 사용</li>
</ol>
<h1 id="정의">정의</h1>
<h3 id="method-heading--constant로만-구성">method heading + constant로만 구성</h3>
<ul>
<li>method definition ㄴㄴ</li>
<li>field ㄴㄴ</li>
<li>&quot;abstract&quot; method의 모음; 그렇다고 <code>abstract</code>를 정의에 쓰면 안됨<h4 id="interface도-type임">interface도 type임</h4>
parameter로 쓰일 수 있음<h3 id="constants">constants</h3>
<h4 id="public-static-final-굳이-안적어도-됨"><code>public static final</code> (굳이 안적어도 됨)</h4>
<h4 id=""></h4>
</li>
</ul>
<h3 id="implements">implements</h3>
<h4 id="여러개의-interface를-implement할-수-있음">여러개의 interface를 implement할 수 있음</h4>
<h4 id="i-abstract-class가-구현하는-경우">i) abstract class가 구현하는 경우</h4>
<p>모든 method define 할 필요 없음
define하지 않은 method는 abstract로 표시</p>
<h4 id="ii-non-abstract-class가-구현하는-경우">ii) non-abstract class가 구현하는 경우</h4>
<p>모든 method define 필요</p>
<h2 id="주의점">주의점</h2>
<h3 id="public">public!!</h3>
<p>모든 method가 public으로 declare되어야 함
implement하는 class도 interface에 있는 method를 define할 때 public으로 해야함.</p>
<h3 id="inconsistent-interfaces">inconsistent interfaces</h3>
<h4 id="같은-constant-define-but-value-상이">같은 constant define but value 상이</h4>
<h4 id="같은-method-signatureheader-메소드-이름-파라미터-리스트-다른-return-type">같은 method signature(header; 메소드 이름, 파라미터 리스트) 다른 return type</h4>
<h2 id="class-vs-interface">class VS interface</h2>
<h3 id="공통점">공통점</h3>
<p>1) (파일명 = Interface명).java 로 쓰임
2) 컴파일시 .class로 byte code가 나타남</p>
<h3 id="차이점">차이점</h3>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Class</th>
<th>Interface</th>
</tr>
</thead>
<tbody><tr>
<td>Instantiation</td>
<td>ㅇㅇ</td>
<td>ㄴㄴ</td>
</tr>
<tr>
<td>Constructors</td>
<td>Contains constructors</td>
<td>Does not contain constructors</td>
</tr>
<tr>
<td>Methods</td>
<td>Can have both abstract and concrete methods</td>
<td>All methods are abstract</td>
</tr>
<tr>
<td>Instance variables</td>
<td>ㅇㅇ</td>
<td>ㄴㄴ (only static and final fields)</td>
</tr>
<tr>
<td>Inheritance</td>
<td>Extended by a class</td>
<td>Implemented by a class</td>
</tr>
<tr>
<td>Multiple inheritance</td>
<td>Cannot extend multiple classes</td>
<td>Can extend multiple interfaces</td>
</tr>
</tbody></table>
<h2 id="interface의-inheritance">interface의 inheritance</h2>
<h4 id="다중-상속-가능">다중 상속 가능</h4>
<pre><code>interface A {
    void methodA();
}

interface B {
    void methodB();
}

interface C extends A, B {
    void methodC();
}</code></pre><h4 id="상속관계에-있는-interface를-구현한-class">상속관계에 있는 interface를 구현한 class</h4>
<p>base interface, derived interface의 모든 method를 구현해야 함</p>
<hr>
<h1 id="comparable-interface"><code>Comparable</code> interface</h1>
<h3 id="single-sorting-method에-이용">single sorting method에 이용</h3>
<h4 id="arrayssort를-사용하려면-comparable을-implement한-objects만-가능"><code>Arrays.sort()</code>를 사용하려면 Comparable을 implement한 objects만 가능</h4>
<h3 id="public-int-comparetoobject-other만-구현하면-됨"><code>public int compareTo(Object other)</code>만 구현하면 됨</h3>
<h4 id="같은-type일-때-정의한-기준에-따라-비교-가능">같은 type일 때, 정의한 기준에 따라 비교 가능</h4>
<p>아니라면 <code>ClassCastException</code> throw</p>
<h4 id="return-값">return 값</h4>
<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>음수</td>
<td>this &lt; other</td>
</tr>
<tr>
<td>0</td>
<td>this = other</td>
</tr>
<tr>
<td>양수</td>
<td>this &lt; other</td>
</tr>
</tbody></table>
<h4 id="javalang--import-필요-ㄴㄴ"><code>java.lang</code> =&gt; import 필요 ㄴㄴ</h4>
<pre><code class="language-java">public class Person implements Comparable&lt;Person&gt; {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int compareTo(Person other) {
        return this.name.compareTo(other.name);
    }

    @Override
    public String toString() {
        return &quot;Person{name=&#39;&quot; + name + &quot;&#39;, age=&quot; + age + &quot;}&quot;;
    }

    public static void main(String[] args) {
        Person[] people = {
            new Person(&quot;Alice&quot;, 30),
            new Person(&quot;Bob&quot;, 25),
            new Person(&quot;Charlie&quot;, 35)
        };

        Arrays.sort(people);

        for (Person person : people) {
            System.out.println(person);
        }
    }
}
</code></pre>
]]></description>
        </item>
    </channel>
</rss>