<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kama_code.log</title>
        <link>https://velog.io/</link>
        <description>[Java SQL HTML CSS JS Studying] 발전을 꿈꾸며 이상을 실현합니다</description>
        <lastBuildDate>Sun, 13 Aug 2023 15:41:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kama_code.log</title>
            <url>https://velog.velcdn.com/images/kama_code/profile/efa803ec-2626-496f-a463-c828ccc19ad5/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kama_code.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kama_code" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[SQL.00] 오라클(Oracle) DB 완전히 삭제하기🕊]]></title>
            <link>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-DB-%EC%99%84%EC%A0%84%ED%9E%88-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-DB-%EC%99%84%EC%A0%84%ED%9E%88-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 13 Aug 2023 15:41:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>오라클(Oracle) DB를 삭제하는 것은 쉽지 않다. 
제어판에서 그냥 삭제하다가는 삭제불가로 짜증을 겪는 사람들이 많다.
오라클을 완전히 삭제하는 방법을 다뤄보겠다.</p>
</blockquote>
<h2 id="step-1-서비스에서-오라클-중지하기">&lt;STEP 1&gt; 서비스에서 오라클 중지하기</h2>
<p>  1) <span style='background-color: yellow'>시작 - 서비스 실행</span></p>
<pre><code>- 내컴퓨터에서 오른쪽마우스 클릭 -&gt; 관리 -&gt; 서비스 선택

- 제어판 -&gt; 관리도구 -&gt; 서비스 선택</code></pre><p>  2) 서비스에서 Oracle로 시작하는 서비스를 모두 중지한다.</p>
<h2 id="step-2-레지스트리-삭제">&lt;STEP 2&gt; 레지스트리 삭제</h2>
<p>  1) <span style='background-color: yellow'>시작 -&gt; 실행 -&gt; regedit</span>
  POINT: Oracle로 되어있는 것은 모두 전체 삭제한다.</p>
<p>2) HKEY_LOCAL_MACHINE -&gt; SOFTWARE -&gt; ORACLE 삭제</p>
<p>  3) HKEY_LOCAL_MACHINE - SYSTEM - CurrentControlSet - Services - 
  EventLog - Application 에서 Oracle로 시작되는 것을 삭제</p>
<p>  4) HKEY_LOCAL_MACHINE - SYSTEM - CurrentControlSet - Services 에서 
  Ora로 시작되는 것을 삭제</p>
<p>  5) HKEY_LOCAL_MACHINE - SYSTEM - ControlSet001 - Services - EventLog - Application 에서 Oracle로 시작되는 것을 삭제</p>
<p>  6) HKEY_LOCAL_MACHINE - SYSTEM - ControlSet001 - Services  에서 
  Ora로 시작되는 것을 삭제</p>
<p>  7) HKEY_LOCAL_MACHINE - SYSTEM - ControlSet002 - Services - EventLog - Application 에서 Oracle로 시작되는 것을 삭제</p>
<p>  8) HKEY_LOCAL_MACHINE - SYSTEM - ControlSet002 - Services  에서 
  Ora로 시작되는 것을 삭제</p>
<p>  9) HKEY_CLASSES_ROOT 에서 Ora로 시작되는 것을 삭제</p>
<h2 id="step-3-환경변수-삭제">&lt;STEP 3&gt; 환경변수 삭제</h2>
<p>  1) 내컴퓨터에서 오른쪽 마우스 클릭 -&gt; 속성 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N) 클릭</p>
<p>  2) 시스템 변수(S)에서 변수명이 path를 찾아 더블클릭 -&gt; 값 중에 오라클에 관련된 것 삭제</p>
<p>  3) 시스템 변수(S)에서 변수명이 ORACLE_HOME인 것 삭제</p>
<h2 id="step-4-오라클-설치-폴더-삭제">&lt;STEP 4&gt; 오라클 설치 폴더 삭제</h2>
<p> 1) C:\Program Files\Oracle 삭제</p>
<p> 2) C:\Users\사용자명\Oracle 삭제</p>
<p> 3) 또는 Oracle 관련된 설치 경로가 있다면 폴더째 삭제</p>
<p> 4) 제어판 - 프로그램 기능/추가 - oracle 삭제</p>
<h2 id="step-5-재부팅">&lt;STEP 5&gt; 재부팅</h2>
<blockquote>
<p>중요한 점은 STEP1과 STEP2를 깔끔하게 삭제하는 것이다.
그리고 나머지는 STEP4를 통해 지우는 마무리를 하는 것이다.
이를 통해 삭제까지 포스팅으로 다루어보았다.
다음 포스팅부터는 정식적으로 SQL문을 다뤄보도록 하겠다.
앞으로 계속..</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL.00] 오라클(Oracle) 데이터베이스(DB)의 오류 해결하기👀]]></title>
            <link>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4DB%EC%9D%98-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4DB%EC%9D%98-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 12 Aug 2023 17:50:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>오라클(Oracle) DB를 사용하면서 참으로 오류가 많았다.
필자도 정말 환장할 듯한 많은 오류를 겪었으며, 이 경험을 토대로
포스팅을 작성해보려고 한다.</p>
</blockquote>
<h2 id="▣-오라클-실행시-패스워드-만료-경고가-뜨는-경우">▣ 오라클 실행시 패스워드 만료 경고가 뜨는 경우</h2>
<img src = "https://velog.velcdn.com/images/kama_code/post/b3e28e3d-924b-4736-a2a7-a0ec0885751f/image.PNG" width = "60%" height = "60%">

<p>SQL Developer 를 실행했을때 위와 같이 패스워드 관련 경고창이 뜬다면 
만료기간이 다 되었다는 뜻입이다.
이런 경고 메시지가 뜨는 이유는 사용자 계정이 180일 지나면 비밀번호가 
만료되도록 변경 되었기 때문이다.</p>
<p>해결방법은 비밀번호를 변경해하는 것!
먼저 system 계정으로 접속한 후 다음 쿼리문을 실행하면 된다.</p>
<pre><code>alter user 계정명 identified by 새비밀번호;</code></pre><ul>
<li>컨트롤 + 엔터를 누르면 더이상 경고창이 뜨지 않는다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/0456a99e-de99-4926-87fa-d82305810bac/image.PNG" width = "60%" height = "60%">

<p>그런데 매번 패스워드를 변경하는것이 번거로울 수도 있다.
이런 경우 만료되지 않도록 설정할 수 있다.</p>
<pre><code>ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;</code></pre><img src = "https://velog.velcdn.com/images/kama_code/post/9dc28ca2-f665-487e-a41c-5afbd628ff05/image.PNG" width = "60%" height = "60%">

<hr>
<h2 id="▣-tns-오류--가장-심각하면서-많은-오류-">▣ TNS 오류 ( 가장 심각하면서 많은 오류 )</h2>
<p>Oracle] &#39;상태: 실패 -테스트 실패:IO 오류: 
The Network Adapter could not establish the connection&#39; </p>
<blockquote>
<p>여기서 서비스 - Oracle TNS Listener를 찾아 실행하면 해결된다는 포스팅이 많다.
하지만 실행이 되면 좋은데.. 아래 사진처럼 서비스 실행이 안될 수도 있다.</p>
</blockquote>
<p>OracleOraHomeTNSListener 서비스가 로컬 컴퓨터에서 시작했다가 중지되었습니다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/80936c4b-1a00-49df-9bf6-b724954db762/image.jpg" width = "60%" height = "60%">

<blockquote>
<p>필자 역시 가장 환장하는 오류였다.. 오라클 데이터베이스를 삭제하고 
다시 설치하면 역시 되는데 시간이 지나면 또 이런 오류가 발생한다. </p>
</blockquote>
<h2 id="▶-해결방법">▶ 해결방법</h2>
<p>계정 연결 전 확인 할 사항
먼저 명령 프롬프트 창 실행 후 netstat 친 후 localhost와 오라클 포트번호 확인한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/c8bff073-c7ea-43bd-99cb-1700c0cc0d67/image.PNG" width = "70%" height = "70%">

<p>아래처럼 이렇게 나올 수도 있다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/3ebdff59-6bad-4ccd-b96f-1821c579e59b/image.PNG" width = "70%" height = "70%">

<p>다음 tnsping localhost 치면 아래와 같이 되면 정상적으로 연결된 것이다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/e50d1ff2-d2cb-44eb-9a8f-682b23af8fb7/image.PNG" width = "70%" height = "70%">

<p>하지만, 리스너가 없다는 말이 뜨거나 위 사진처럼 뜨지 않을시 아래를 실행한다.</p>
<p><span style='background-color: yellow'>WINDOW + CMD (명령 프롬포트) 실행</span></p>
<pre><code class="language-c">lsnrctl services </code></pre>
<p>해당 명령어를 입력해준다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/6ec88507-f1e2-4c2c-8d06-f86a39efe70c/image.png" width = "80%" height = "80%">

<p>참으로 특이한 점이 뭘 건들고 바꾼 적도 없는데 필자의 ip가 아닌 
다른 ip로 연결된다고 쓰여져 있었다.</p>
<p>이것이 왜냐면 인터넷마다 고정ip가 아닌 유동ip로 돌아가는 집이 있다.
그렇다고 해서 고정ip로 바꿔버리면 인터넷이 안켜질 수도 있다. 
그래서 <strong>ip가 아닌 컴퓨터 이름</strong>으로 바꾸는 것이 필요하다!</p>
<p><a href="https://www.findip.kr/">▶ 내 아이피 확인하기</a></p>
<p>자신의 오라클 설치한 경로\OracleXE21c\homes\OraDB21Home1\network\admin 들어가서 listener.ora와 tnsnames.ora 2가지를 수정한다.</p>
<blockquote>
<p>간혹 sample 폴더에 들어가서 listener.ora와 tnsnames.ora 2가지를 수정하는 사람이 있는데 sample 폴더는 예비용 파일이므로 전혀 관련이 없다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/4715b040-c64d-4243-8cbe-7aa590b58320/image.PNG" width = "80%" height = "80%">

<p>먼저 listener.ora 파일 노트 패드나 메모창으로 열어서
네모 부분을 localhost (안되면 본인 컴퓨터 이름으로)로 수정한다.</p>
<p>컴퓨터 이름 확인법
<span style='background-color: yellow'>cmd - hostname </span></p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ca835dd3-f6fc-4648-8620-ac9daf415ec8/image.PNG" width = "80%" height = "80%">

<img src = "https://velog.velcdn.com/images/kama_code/post/b0c580a6-fd4b-4675-94ab-9666f3a968c0/image.PNG" width = "80%" height = "80%">

<p>다음 tnsnames.ora 파일을 열어서 리스너 파일과 마찬가지로 수정한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/9cb6315a-d06e-42a1-997c-39de1614197d/image.PNG" width = "80%" height = "80%">

<p>그리고 cmd - SQLPlus에 접속해서 
select value from v$parameter where name like &#39;%service_name%&#39;; 을 치면
XE이 나오는지 확인 한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/f061c2c1-ccf8-4337-8c16-5412c9dce3a9/image.PNG" width = "70%" height = "70%">

<p>그리고 다시 아래를 실행하여 확인한다. </p>
<p><span style='background-color: yellow'>WINDOW + CMD (명령 프롬포트) 실행</span></p>
<pre><code class="language-c">lsnrctl services </code></pre>
<p>정상적으로 listener.ora와 tnsnames.ora 파일을 수정한 내용이 적용되었는지
확인한다. 정상적으로 바뀌었다면 잘한 것이고 적용이 안되었다면
sample 폴더에 있는 잘못된 경로의 파일을 수정한 것이니 확인한다.</p>
<ul>
<li>서비스를 실행해준다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/1ea2e02a-c427-446d-a11a-72c6bb7e6f2b/image.PNG" width = "60%" height = "60%">

<ul>
<li>빨간색 박스의 OracleOraDB21Home1TNSListener를 중지 후 시작을 하고
컴퓨터를 재부팅 후 sql을 실행하면 정상적으로 작동된다. </li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/42f5696c-26df-4752-9bbc-e790175cfa60/image.PNG" width = "60%" height = "60%">

<hr>
<h2 id="▣-오라클oracle-11g-xe-설치하기">▣ 오라클(Oracle) 11g xe 설치하기</h2>
<blockquote>
<p>하지만 세상에 완벽한 것은 없듯이 위 방법으로도 해결이 안될 수도 있다.
그럴때는 21c를 포기하고 11g xe버전을 사용하는 것을 추천하는 바이다.
21c보다 11g는 번거롭게 hr과 scott 계정을 따로 추가할 필요도 없고 
c##을 매번 붙이지 않아도 가능하기에 훨씬 편리하다.
설치만 하면 간단하기에 사실 필자도 11g를 사용하고 있다.</p>
</blockquote>
<ul>
<li><p>11g xe 를 다운받아서 사용하는 이유
● 10g 이후에 처음으로 나온 무료 버전
● 기존 회사에 가장 많이 설치되어 있다.(11 버전)
● 이 버전의 책 및 참고자료가 가장 많다.</p>
</li>
<li><p>많은 사람들이 착각하는 점
● 11g 가 무료다 (X) → xe 가 무료이다. (O)
Oracle Database Express Edition (XE) Release 11.2.0.2.0 (11gR2)
<a href="https://www.oracle.com/database/technologies/xe-prior-release-downloads.htm">https://www.oracle.com/database/technologies/xe-prior-release-downloads.htm</a></p>
</li>
</ul>
<p><a href="https://www.oracle.com/database/technologies/xe-prior-release-downloads.html">▶ 오라클 XE 11g 다운로드</a></p>
<img src = "https://velog.velcdn.com/images/kama_code/post/029a5ad5-9c0c-409d-8d3a-83d3b6a59a07/image.PNG" width = "70%" height = "70%">

<ul>
<li>설치 파일 다운로드 후 setup.exe 실행한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/e157aaa2-389b-4551-82f8-d1537f25aa10/image.PNG" width = "60%" height = "60%">

<ul>
<li>다음을 계속 누르면 아래 사진이 뜬다.
ㄴ절대 잊어버리면 안되는 관리자 비밀번호를 설정한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/2c27ab50-601c-4669-b094-9d3692fef13e/image.PNG" width = "60%" height = "60%">

<p>그리고 쭉 Next를 눌러주면 설치가 완료된다.</p>
<p><span style='background-color: yellow'>WINDOW + CMD(명령 프롬프트) 실행</span>
SQLPLUS를 입력해주고 초기에 설정해준 비밀번호를 입력해준다. </p>
<img src = "https://velog.velcdn.com/images/kama_code/post/37bde782-2da3-490f-b4e3-5642fc438972/image.PNG" width = "80%" height = "80%">

<hr>
<h2 id="▣-오라클-11g-checking-for-oracle-xe-service-instance-failed-오류-해결하기">▣ 오라클 11g Checking for Oracle XE service instance failed 오류 해결하기</h2>
<p>Oracle 11g Express Edition 을 설치하다 다음과 같은 오류가 뜨는 경우가 있다.
이 오류는 대부분의 경우 설치도중 문제가 생겨 다시 설치하는 경우에 발생한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/25acfe1d-2fb7-46fb-be6c-c0d388d251ec/image.PNG" width = "70%" height = "70%">

<p>오류메세지를 보면 Oracle XE service instance가 설치되어 있으므로 실패했다는 내용이다.</p>
<p><span style='background-color: yellow'>해결방법 1.</span>
프로그램 추가/제거에서 Oracle XE 를 삭제한 후 다시 설치를 시도한다.</p>
<p><span style='background-color: yellow'>해결방법 2.</span>
만약 첫번째 방법으로 안된다면 cmd창에서 다음과 같이 입력하여 
서비스를 제거한 후 다시 설치를 시도한다.</p>
<pre><code class="language-c">C:\nakja&gt; sc delete OracleServiceXE</code></pre>
<p>단 cmd는 관리자로 실행해야 한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/42a13166-f2a3-4a7c-9ece-21ac495970b0/image.PNG" width = "70%" height = "70%">

<p>관리자 권한으로 실행하지 않으면 다음과 같이 오류가 발생한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/8f1c8a04-31a8-4c7e-95d3-2c0c7ae59390/image.PNG" width = "60%" height = "60%">

<p>다시 한번 실행하면 정상적으로 삭제된다.
[SC] DeleteService 성공 이라고 출력되면, 
오라클 11g Express Edition 설치 작업을 다시 진행하면 된다!</p>
<hr>
<h2 id="▣-일부-모듈을-설치하지-못했습니다">▣ 일부 모듈을 설치하지 못했습니다</h2>
<p><span style='background-color: yellow'>오류내용</span></p>
<blockquote>
<p>경고 - 일부 모듈을 설치하지 못했습니다: oracle.ide.searchbar - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\ide\extensions\oracle.ide.searchbar.jar: Not found
bundle:oracle.ide.searchbar oracle.java_annotations - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\ide\lib\annotations.jar: Not found bundle:oracle.java_annotations
oracle.external.jdbc - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\external\oracle.external.jdbc.jar: Not found bundle:oracle.external.jdbc
oracle.javatools - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\ide\lib\javatools.jar: Not found bundle:oracle.javatools
oracle.javatools_nodeps - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\external\oracle.javatools-nodeps.jar: Not found
bundle:oracle.javatools_nodeps oracle.idert - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\ide\lib\idert.jar: Not found bundle:oracle.idert oracle.ide.indexing -
org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\ide\extensions\oracle.ide.indexing.jar: Not found
bundle:oracle.ide.indexing oracle.ide.webbrowser - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\ide\extensions\oracle.ide.webbrowser.jar: Not found
bundle:oracle.ide.webbrowser oracle.external.timing - org.netbeans.InvalidException: Netigso:
C:\01Developkits\sqldeveloper\external\oracle.external.timing.jar: Not found bundle:oracle.external</p>
</blockquote>
<p><span style='background-color: yellow'>문제해결</span>
출처: <a href="https://thingsthis.tistory.com/40">https://thingsthis.tistory.com/40</a></p>
<p>SQL Developer 실행 시 모듈을 못 찾는다고 모듈 비활성 화 및 계속하기, 
종료 버튼이 있는 화면이 뜨면</p>
<p>C:\Users\사용자명\AppData\Roaming\SQL Developer 폴더에 가서 
system4.0.2.15.21 폴더를 지우고 다시 해본다.</p>
<p>SQL Developer 처음 실행 후 javaw.exe Path 를 잘못 잡아줘서 발생한 것</p>
<blockquote>
</blockquote>
<ol>
<li>SQLDEVELOPER_HOME/sqldeveloper/bin/sqldeveloper.conf 파일 열기</li>
<li>SetJavaHome 변경
ex) SetJavaHome C:\Program Files\Java\jdk1.7.0_75</li>
<li>C:\Users\사용자명\AppData\Roaming\SQL Developer\system4.0.2.15.21 폴더 삭제</li>
<li>다시 실행</li>
</ol>
<hr>
<blockquote>
<p>이렇게 오라클 SQL에 대한 오류 및 해결방안을 알아보았다.
필자도 오라클 DB를 사용하면서 수많은 오류를 마주하여 환장하는 적이 
정말 많았다. 지금은 모두 해결한 상태이다.
만일 오라클에 문제가 생겼다면 반드시 이 포스팅을 읽고 모두 해결되었으면 하는 
바람이다. 다음 포스팅에서 계속...</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL.00] 오라클(Oracle) 데이터베이스(DB)의 명령어 미리보기]]></title>
            <link>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4DB%EC%9D%98-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AF%B8%EB%A6%AC%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4DB%EC%9D%98-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AF%B8%EB%A6%AC%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sat, 12 Aug 2023 17:07:13 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이번 포스팅은 급한 사람들을 위해 작성해본다.
바로 시작
!</p>
</blockquote>
<h2 id="step1-sql-db-접속하기">&lt;STEP.1&gt; SQL DB 접속하기</h2>
<p><span style='background-color: yellow'>WINDOW + CMD (명령 프롬포트) 실행</span></p>
<ul>
<li><p>방법1
SQLPLUS &gt; SYSTEM &gt; 비밀번호 입력(보이지 않음) 으로 접속완료
( &gt; 는 엔터를 의미 )</p>
</li>
<li><p>방법2
sql developer 실행 &gt; 계정 접속 ( 자세한 방법은 이전 포스팅 참고 )</p>
</li>
</ul>
<hr>
<h2 id="step2-계정-생성-및-권한">&lt;STEP.2&gt; 계정 생성 및 권한</h2>
<p>12c 이후부터는 이 명령어부터 쳐야 아래 명령어 실행 가능하다.</p>
<pre><code class="language-c"> alter session set &quot;_ORACLE_SCRIPT&quot;=true;</code></pre>
<p>◈ <span style='background-color: yellow'>계정 만들기</span></p>
<pre><code class="language-c">create user [id] identified by [pw];</code></pre>
<p>◈ <span style='background-color: yellow'>계정 삭제</span></p>
<pre><code>drop user [id] cascade;</code></pre><p>◈ <span style='background-color: yellow'>권한 주기</span></p>
<pre><code class="language-c">grant connect, resource, dba to [id];</code></pre>
<blockquote>
<ul>
<li>grant [권한] to [id]; 로 설정할 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>connect(접속 권한), resource(객체 및 데이터 조작 권한), 
dba(데이터베이스에 관련된 모든 관리)를 의미한다.</li>
</ul>
<p>◈ <span style='background-color: yellow'>권한 뺏기</span></p>
<pre><code>revoke connect, resource, dba from sampleid;</code></pre><blockquote>
<ul>
<li>revoke [권한] from [id]; 로 설정할 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>connect(접속 권한), resource(객체 및 데이터 조작 권한), 
dba(데이터베이스에 관련된 모든 관리)를 의미한다.</li>
</ul>
<h2 id="step3-조회하기">&lt;STEP.3&gt; 조회하기</h2>
<p>◈ <span style='background-color: yellow'>모든 계정 조회</span></p>
<pre><code class="language-c">select * from all_users;</code></pre>
<p>◈ <span style='background-color: yellow'>테이블 목록 조회</span></p>
<pre><code class="language-c">select * from tab; -- 계정에 테이블이 몇개인지</code></pre>
<p>◈ <span style='background-color: yellow'>테이블 데이터 조회</span></p>
<pre><code>select * from [테이블명];  -- 테이블의 모든 데이터를 보여줘</code></pre><p>◈ <span style='background-color: yellow'>테이블 구조 조회</span></p>
<pre><code>desc [테이블명]; -- 테이블의 구조를 보여줘</code></pre><h2 id="step4-입력하기">&lt;STEP.4&gt; 입력하기</h2>
<p>◈ <span style='background-color: yellow'>데이터 입력하기</span></p>
<pre><code class="language-c">INSERT INTO &lt;테이블명&gt; (&lt;컬럼1&gt;, &lt;컬럼2&gt;....)
VALUES (&lt;값1&gt;, &lt;값2&gt;...);</code></pre>
<h2 id="step5-삭제하기">&lt;STEP.5&gt; 삭제하기</h2>
<p>◈ <span style='background-color: yellow'>테이블 삭제</span></p>
<pre><code class="language-c">drop table [테이블명];</code></pre>
<p>◈ <span style='background-color: yellow'>테이블 행 삭제</span></p>
<pre><code>DELETE FROM [테이블명]  WHERE field1=&#39;data2&#39;;</code></pre><blockquote>
<p>테이블명의 ield1의 값이 &#39;data2&#39; 인 행을 삭제하라!</p>
</blockquote>
<h2 id="step6-만들기">&lt;STEP.6&gt; 만들기</h2>
<p>◈ <span style='background-color: yellow'>테이블 만들기</span></p>
<pre><code>-- 회원 테이블 만들기: id는 30~40 줘야 한다.
create table member(
    id varchar2(10) not null, 
    pass varchar2(10) not null,
    name varchar2(30) not null,
    regidate date default sysdate not null,
    primary key (id)
);</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL.00] 오라클(Oracle) 데이터베이스(DB)의 기본지식]]></title>
            <link>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4DB%EC%9D%98-%EA%B8%B0%EB%B3%B8%EC%A7%80%EC%8B%9D</link>
            <guid>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4DB%EC%9D%98-%EA%B8%B0%EB%B3%B8%EC%A7%80%EC%8B%9D</guid>
            <pubDate>Sat, 12 Aug 2023 16:36:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>21C 설치와 설정에 대해 배워보았다. 
사실 오라클 설치는 어려운 편에 속한다. 
독자는 성공적으로 되었으니 이 포스팅을 보는 거라고 추측한다.
설치에 성공했다면 깊은 축하를 보낸다.</p>
</blockquote>
<p>데이터베이스는 엄청 중요하다. 
SQL에 관심이 있는 사람은 추천하는 것이 있는데
<a href="https://www.dataq.or.kr/www/sub/a_04.do">▶  SQL 국가 자격증 바로가기</a></p>
<p>이것이 있다. 
국가 DB를 다룰 때 필수인 자격증이라 따두면 굉장히 유용하다.</p>
<h2 id="기본-개념과-용어">기본 개념과 용어</h2>
<p>❖ 데이터베이스</p>
<blockquote>
<ul>
<li>여러 사람에 의해 공유되어 사용될 목적으로 
통합하여 관리되는 데이터의 집합</li>
</ul>
</blockquote>
<ul>
<li>몇 개의 자료 파일을 조직적으로 통합하여 자료 항목의 중복을
없애고 구조화하여 기억시켜 놓은 자료의 집합체</li>
</ul>
<p>❖ 관계형 데이터베이스 관리시스템</p>
<blockquote>
<ul>
<li>RDBMS(Relational DataBase Management System)</li>
</ul>
</blockquote>
<ul>
<li>IBM 산호세 연구소의 에드거 F. 커드가 도입한 관계형 모델을
기반으로 하는 데이터베이스 관리 시스템</li>
<li>다수의 사용자들이 데이터베이스 내의 데이터를 접근할 수 있도록
해주는 소프트웨어 도구의 집합</li>
<li>DBMS은 사용자 또는 다른 프로그램의 요구를 처리하고 적절히
응답하여 데이터를 사용할 수 있도록 해준다</li>
</ul>
<p>❖ DBMS의 종류</p>
<blockquote>
<p>ORACLE, DB2, INFORMIX, SYBASE, MS-SQL, Postgres,
Tibero, MySQL, MS-access</p>
</blockquote>
<hr>
<p>❖ SQL(Structured Query Language)</p>
<blockquote>
<ul>
<li>RDBMS(관계형 데이터베이스 관리 시스템)의 데이터를 관리하기
위해 설계된 특수 목적의 프로그래밍 언어이다.</li>
</ul>
</blockquote>
<ul>
<li>관계형 데이터베이스 관리 시스템에서 자료의 검색과 관리,
데이터베이스 스키마 생성과 수정, 데이터베이스 객체 접근 조정
관리를 위해 고안되었다.</li>
<li>대부분의 데이터베이스 관련 프로그램들이 SQL을 표준으로
채택하고 있다</li>
</ul>
<p>❖ SQL의 종류</p>
<blockquote>
<ol>
<li><span style='background-color: yellow'>DQL : Data Query Language(질의어)</span>
ㄴ SQL에서 테이블에 저장된 데이터를 조회하는데 사용
ㄴ SELECT문 : 데이터 조회</li>
<li><span style='background-color: yellow'>DML : Data Manipulation Language(데이터 조작어) // 데이터</span>
ㄴ데이터베이스에 저장된 데이터를 조작하기 위해 사용하는 언어
(1) Insert문 : 데이터 삽입
(2) Update문 : 데이터 수정
(3) Delete문 : 데이터 삭제</li>
<li><span style='background-color: yellow'>DDL : Data Definition Language(데이터 정의어) // 테이블</span>
ㄴ데이터베이스 관리자나 응용 프로그래머가 데이터베이스의
ㄴ논리적 구조를 정의하기 위한 언어로서 데이터 사전(Data
ㄴDictionary)에 저장된다.
(1) Create문 : 테이블, 뷰, 프로시저 생성
(2) Alter문 : 테이블, 뷰, 프로시저 수정
(3) Drop문 : 테이블, 뷰, 프로시저 삭제</li>
<li><span style='background-color: yellow'>DCL : Data Control Language(데이터 제어어)</span>
ㄴ 데이터에 대한 접근 권한 부여 등의 데이터베이스 시스템의
트랜잭션을 관리하기 위한 목적으로 사용되는 언어
(1) GRANT문 : 사용자에게 특정 권한을 부여
(2) REVOKE문 : 사용자에게 부여했던 특정 권한을 제거</li>
</ol>
</blockquote>
<p>❖ 용어 몇가지</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/badd9bc3-d451-497d-9e09-350fa1d2b3b6/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/f522f664-d9d2-4b46-a7e0-f229b0a9a591/image.PNG" width = "70%" height = "70%">

<hr>
<p>❖ 스키마</p>
<blockquote>
<p>데이터베이스의 구조를 전반적으로 기술한 것
구체적으로 데이터베이스를 구성하는 데이터 레코드의 크기, 키의 정의,
레코드 간의 관계 등을 정의</p>
</blockquote>
<p>● 외부 스키마</p>
<blockquote>
<p>○ 사용자의 입장에서 정의한 데이터베이스의 논리적 구조
○ 데이터들을 어떤 형식, 구조, 화면을 통해 사용자에게 보여줄 것인가에 대한 명세
○ 하나의 데이터베이스에는 여러개의 외부 스키마가 존재
○ 일반 사용자에게는 Query를 이용해 DB를 사용할 수 있도록 하고 
응용 프로그래머는 언어를 사용해서 DB에 접근하도록 한다.</p>
</blockquote>
<p>● 개념 스키마</p>
<blockquote>
<p>○ 조직체 전체를 관장하는 입장에서 DB를 정의한 스키마.
○ DB에 대한 모든 논리적 구조를 기술하기 때문에 하나만 존재
○ 통상 스키마 라고 하면 개념 스키마를 일컫는다.</p>
</blockquote>
<p>● 내부 스키마</p>
<blockquote>
<p>○ 데이터베이스가 어떻게 저장장치에 저장될 지에 대한
명세(어떤 일에 관련된 자세한 내용이나 구체적인 항목.).
○ 물리적인 저장장치와 데이터베이스 간의 관계를 정의하므로
시스템 관점의 스키마이다.</p>
</blockquote>
<hr>
<p>❖ CRUD</p>
<blockquote>
<p>Create(생성), Read(읽기), Update(갱신), Delete(삭제)를 묶어서
일컫는 말.
데이터베이스의 가장 기본적인 데이터 처리 기능을 가리키는 말</p>
</blockquote>
<p>❖ 오라클의 자료형</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/b6ae99d6-06bf-4add-9313-879a36f56e3e/image.PNG" width = "70%" height = "70%">

<p>● 문자형 데이터 타입</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/3b8bb476-adad-413b-b0ed-3bc79e717298/image.PNG" width = "70%" height = "70%">

<p>● 숫자형 데이터 타입</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/c32e557a-3bed-461e-965e-dc6033a841d7/image.PNG" width = "70%" height = "70%">

<p>● 날짜형 데이터 타입</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/47d9e74b-dc3a-4575-9513-ce5a504bac33/image.PNG" width = "70%" height = "70%">

<hr>
<p>❖ 파일 시스템이란?</p>
<blockquote>
<p>컴퓨터에서 파일이나 자료를 쉽게 발견 및 접근할 수 있도록 보관 또는 
조직하는 체제를 가리키는 말</p>
</blockquote>
<p>❖ 파일 시스템 대신 데이터베이스를 사용하는 이유?</p>
<blockquote>
<ul>
<li>데이터 중복과 불일치 (Data redundancy and inconsistency)
ㄴ같은 정보가 서로 다른 파일에 저장될 수 있으며, 이를 확인하기 어렵다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>자료 접근이 어렵다(Difficulty in accessing data)
ㄴ파일 시스템의 경우, 파일에 접근하는 방식이 응용 프로그램마다 정의되기 때문에, 특정 기능을 위해 자료 접근을 하기 위해서는 그 접근하는 방식을 직접 구현해야 한다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>생산성이 낮다
ㄴ각 응용 프로그램마다 새로운 파일 형식과 설명을 설계하는 과정부터 시작해서 새로운 파일에 접근하는 방식을 일일이 구현해야 하기 때문에 생산성이 낮다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>데이터 모델링 개념이 부족하다
ㄴ단순히 순차적인 레코드만으로 나타내기 때문에 데이터의 의미와 데이터 간의 상호관계를 나타내기 힘들다.</li>
</ul>
</blockquote>
<blockquote>
<p>★ <span style='background-color: yellow'>데이터 모델링</span> : 현실세계를 데이터로 표현하기 위해 추상화한다.
★★ 특징 : 추상화, 단순화, 명확화</p>
</blockquote>
<blockquote>
<ul>
<li>보안 기능이 미흡하다
ㄴ파일 시스템에서는 파일 단위로만 접근을 할 수 있기 때문에, 사용자 권한에 따른 세밀한 접근 제어(레코드 단위)를 실행하기 어렵다.
(Hard to provide user access to some, but not all, data)</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>쉬운 질의어가 제공되지 않는다
ㄴSQL과 같은 쉬운 질의어가 제공되지 않는다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>다수의 사용자를 위한 동시성 제어가 제공되지 않는다(Concurrent access by multiple users)
ㄴ파일 시스템의 경우, 다수의 사용자가 동시에 접근을 할 때에, 데이터의 불일치 등의 문제를 일으킬 수 있다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>데이터 무결성을 유지하기 어렵다 (Integrity problem)
ㄴ파일 내의 데이터가 만족시켜야 하는 무결성 제약조건(constraint)들을 명시하려면 프로그래머가 직접 프로그래밍 언어를 사용하여 일일이 프로그램에 표현해야 하므로 데이터 무결성을 유지하기가 어렵다. 또한, 새로운 제약조건들을 추가하거나 기존의 제약조건을 수정하는 것도 어렵다.</li>
</ul>
</blockquote>
<hr>
<h2 id="sql과-nosql의-차이">SQL과 NOSQL의 차이</h2>
<blockquote>
<p>SQL (관계형 DB)</p>
</blockquote>
<p>SQL을 사용하면 RDBMS에서 데이터를 저장, 수정, 삭제 및 검색 할 수 있다
관계형 데이터베이스에는 핵심적인 두 가지 특징이 있다.</p>
<p>데이터는 정해진 데이터 스키마에 따라 테이블에 저장된다.
데이터는 관계를 통해 여러 테이블에 분산된다.</p>
<p><span style='background-color: yellow'>SQL 장점</span>
ㄴ명확하게 정의된 스키마, 데이터 무결성 보장
ㄴ관계를 중요시하며 각 데이터를 중복없이 한번만 저장</p>
<p><span style='background-color: RED'>SQL 단점</span>
ㄴ덜 유연함. 데이터 스키마를 사전에 계획하고 알려야 함. (나중에 수정하기 힘듬)
ㄴ관계를 맺고 있어서 조인문이 많은 복잡한 쿼리가 만들어질 수 있음
ㄴ대체로 수직적 확장만 가능함</p>
<blockquote>
<p>NoSQL (비관계형 DB)</p>
</blockquote>
<p>말그대로 관계형 DB의 반대다.</p>
<p>스키마도 없고, 관계도 없다!</p>
<p><span style='background-color: yellow'>NoSQL 장점</span>
ㄴ스키마가 없어서 유연함. 언제든지 저장된 데이터를 조정하고 새로운 필드 추가 가능
ㄴ데이터는 애플리케이션이 필요로 하는 형식으로 저장됨. 데이터 읽어오는 속도 빨라짐
ㄴ수직 및 수평 확장이 가능해서 애플리케이션이 발생시키는 모든 읽기/쓰기 요청 처리 가능</p>
<p><span style='background-color: RED'>NoSQL 단점</span>
ㄴ유연성으로 인해 데이터 구조 결정을 미루게 될 수 있음
ㄴ데이터 중복을 계속 업데이트 해야 함
ㄴ데이터가 여러 컬렉션에 중복되어 있기 때문에 수정 시 모든 컬렉션에서 수행해야 함 (SQL에서는 중복 데이터가 없으므로 한번만 수행이 가능)</p>
<blockquote>
<p>즉, 관계를 맺고 있는 데이터가 자주 변경될 때는 SQL이 수월하며, 
읽기를 자주 하지만, 데이터 변경은 자주 없는 경우 NOSQL이 수월하다.
관계의 형태로 데이터의 정확성을 따지기 위해선 SQL이 좋으며, 
유동적이며 속도가 중요할 땐 NOSQL이 좋다. 
배달의 민족이나 일부 대기업들의 DB는 NOSQL을 사용하긴 한다.</p>
</blockquote>
<hr>
<blockquote>
<p>이렇게 기본 개념과 용어까지 알아보았다.
다음 포스팅은 급한 사람들을 위해 sql db 명령어 미리보기를 작성해보도록 하겠다.
다음 포스팅에서 계속..</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL.00] 오라클(Oracle) 21c SQL 최초 실행 및 설정 + SQL Developer 설치⚡]]></title>
            <link>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-21c-SQL-%EC%B5%9C%EC%B4%88-%EC%8B%A4%ED%96%89-%EB%B0%8F-%EC%84%A4%EC%A0%95-SQL-Developer-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-21c-SQL-%EC%B5%9C%EC%B4%88-%EC%8B%A4%ED%96%89-%EB%B0%8F-%EC%84%A4%EC%A0%95-SQL-Developer-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Sat, 12 Aug 2023 16:04:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>전 포스팅에서 간단하게 오라클 SQL을 설치해보았다.
이번 포스팅에서는 복잡하지만 설정해줄 것들과 SQL을 좀 더 쉽게 다루기 위한
도구를 설치해줄 것이다. 
(시작이 반! 하나도 놓치지 말고 차근차근 따라가보자! ) </li>
</ul>
</blockquote>
<h2 id="step01-오라클oracle-연결-및-기본-명령어">&lt;STEP.01&gt; 오라클(Oracle) 연결 및 기본 명령어</h2>
<ul>
<li><span style='background-color: yellow'>WINDOW + CMD ( 명령 프롬포트 )</span>를 실행해보자</li>
</ul>
<p>● <span style='background-color: GREEN'>오라클에 접속하는 방법 1</span>
C:\User&gt; sqlplus
사용자명 : system
비밀번호 : [비밀번호 입력은 보안상 화면에 보이지 않는다]</p>
<p>● <span style='background-color: GREEN'>오라클에 접속하는 방법 2</span>
C:\User&gt; sqlplus system/123456
이 경우에는 비밀번호가 보인다.</p>
<hr>
<h2 id="▣-sys-와-system-의-차이">▣ sys 와 system 의 차이</h2>
<blockquote>
<p>오라클을 설치하면 기본적으로 관리자 권한을 가진 sys와 system계정이 생성되어있다.
사용자계정을 생성하거나 권한 등을 부여할때는 항상 관리자 계정으로 접속한 후 
진행해야 한다. 이 둘은 비슷해 보이지만 약간의 차이를 가지고 있어 차이점을 알아본다.</p>
</blockquote>
<p>● sys
Oracle 시스템의 총 관리자로 SYSDBA 권한을 갖는다.
DB 생성 및 삭제 가능
접속방법
● <span style='background-color: YELLOW'>C:\User&gt; sqlplus sys as sysdba</span></p>
<p>비밀번호 입력: ⇐ 입력한 비밀번호는 보이지 않는다.</p>
<p>● system
sys와 유사한 권한을 가지고 있지만 DB생성과 삭제는 불가능
운영을 위한 SYSOPER 권한을 갖는다.
접속방법
● <span style='background-color: YELLOW'>C:\User&gt; sqlplus system</span></p>
<p>비밀번호 입력: ⇐ 입력한 비밀번호는 보이지 않는다.</p>
<hr>
<h2 id="▣-간단한-몇-가지-기본-명령어">▣ 간단한 몇 가지 기본 명령어</h2>
<p>▶ <span style='background-color: YELLOW'>연결끊기</span>
SQL&gt; exit; 혹은 quit;</p>
<p>▶ <span style='background-color: YELLOW'>현재 사용자 보기</span>
SQL&gt; show user;</p>
<p>▶ <span style='background-color: YELLOW'>해당 사용자의 테이블 목록 보기</span>
SQL&gt; select * from tab;</p>
<p>▶ <span style='background-color: YELLOW'>테이블 구조 보기</span>
SQL&gt; desc 테이블명;</p>
<p>▶ <span style='background-color: YELLOW'>로그인 계정 바꾸기</span>
SQL&gt; conn 사용자아이디/암호
혹은
SQL&gt; conn
사용자명 입력:nakja
비밀번호 입력:****</p>
<p>▶ <span style='background-color: YELLOW'>계정 비밀번호 변경</span>
SQL&gt; alter user 계정명 identified by 변경할비밀번호;</p>
<p>▶ <span style='background-color: YELLOW'>계정 활성화(11g에만 있음 21c는 없음)</span>
SQL&gt; alter user hr account unlock;
SQL&gt; alter user hr identified by 1234;</p>
<p>▶ <span style='background-color: YELLOW'>▶생성된 사용자 조회</span>
SQL&gt; select * from dba_users;
SQL&gt; select * from all_users;</p>
<p>▶ <span style='background-color: YELLOW'>▶사용자가 소유한 테이블 조회</span>
SQL&gt; select * from user_tables;</p>
<hr>
<h2 id="step02-sql-계정-생성-및-관리하기">&lt;STEP.02&gt; SQL 계정 생성 및 관리하기</h2>
<blockquote>
<ul>
<li>이제 SQL DB에 계정을 생성하고 관리해보자!
공부용 샘플 계정인 hr 및 scott를 추가할 것이다</li>
</ul>
</blockquote>
<p>여기서 필자가 도저히 이해가 안가는 점이 있다. 21C는 11g에 비해 
훨씬 최신 버전임에도 사용하기가 굉장히 번거로운 부분이 있다.
그 이유를 아래에서 알아보자</p>
<p>● Oracle 11g 에서는 기본적으로 hr, scott 계정을 제공한다.
● 하지만 Oracle 21c 에서는 제공되고 있지 않아 번거롭게 추가해줘야 한다.</p>
<h2 id="▣-span-stylebackground-color-yellow사용자-계정-추가하기span">▣ <span style='background-color: yellow'>사용자 계정 추가하기</span></h2>
<pre><code class="language-c">SQL&gt; create user 계정아이디 identified by 비밀번호;</code></pre>
<p> Oracle 11g에서는 계정 생성하기 명령어 한번으로 정상적으로 실행된다
 하지만 12c 이상에서는 다음과 같은 에러가 발생한다.</p>
 <img src = "https://velog.velcdn.com/images/kama_code/post/869dda02-5d16-464d-b5a5-776d905d3306/image.PNG" width = "70%" height = "70%">

<p>12c 이후로는 계정 생성시 계정명 앞에 “C##” 을 추가해야 공통 유저를 생성할 수 있다.
너무나 번거로우므로 아래 명령을 통해 기존과 같은 방법으로 계정을 생성할 수
있다. 가장 먼저 입력해야 할 명령어이다. 
단, <span style='background-color: yellow'>명령 실행시 sys 혹은 system으로 접속해야 한다.</span></p>
<pre><code class="language-c">SQL&gt; alter session set &quot;_ORACLE_SCRIPT&quot;=true</code></pre>
 <img src = "https://velog.velcdn.com/images/kama_code/post/a70b9d35-f1b2-4729-a3ab-845ef2f718f1/image.PNG" width = "60%" height = "60%">

<hr>
<p>● 공부용 샘플 계정 hr 추가</p>
<p>먼저 스키마를 다운로드 한다.</p>
<p><a href="https://github.com/oracle-samples/db-sample-schemas/releases">▶ 스키마 다운로드</a></p>
 <img src = "https://velog.velcdn.com/images/kama_code/post/10df4f70-a97a-46fd-8425-6352c7e7d158/image.PNG" width = "70%" height = "70%">

<p>압축을 해제한 후 다음 경로로 이동한다.</p>
<p>오라클이 설치된 위치에 따라 다를 수 있으니 본인의 경로를 확인한 후 진행한다.</p>
<p>OracleXE21c\dbhomeXE\demo\schema\human_resources</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/37dfee98-cb2e-41b7-af12-cd0323df946c/image.PNG" width = "60%" height = "60%">

<p>위 파일중 hr_main.sql 파일을 에디터로 오픈한다. 
메모장이나 Notepad++ 정도면 된다.
스크립트에서 몇가지 수정할 부분이 있다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/d091942d-63ac-4c4c-aed4-759247593e9a/image.PNG" width = "80%" height = "80%">

<ul>
<li>사진상에서 보이지 않은 맨 아래 끝까지 수정해주어야 한다.<img src = "https://velog.velcdn.com/images/kama_code/post/eecd8a13-49a8-4359-86f5-0df920d61f79/image.PNG" width = "80%" height = "80%">

</li>
</ul>
<p>수정이 끝나면 저장한 후 CMD를 실행한 후 다음 명령을 실행한다.</p>
<pre><code class="language-c">SQL&gt; alter session set &quot;_ORACLE_SCRIPT&quot;=true;
SQL&gt; @?/demo/schema/human_resources/hr_main.sq</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/6220a877-bb29-4f05-9bbb-dfc1d66ad6a1/image.PNG" width = "70%" height = "70%">

<blockquote>
<p>specify password for HR as parameter 1:
1의 값을 입력하십시오: 1234 ⇐ hr계정의 비밀번호
specify default tablespeace for HR as parameter 2:
2의 값을 입력하십시오: users ⇐ 기본 테이블 스페이스
specify temporary tablespace for HR as parameter 3:
3의 값을 입력하십시오: temp ⇐ 임시 테이블 스페이스
specify password for SYS as parameter 4:
4의 값을 입력하십시오: 123456 ⇐ system 계정의 비밀번호
specify log path as parameter 5:
5의 값을 입력하십시오: ⇐ 로그 저장 디렉토리. 입력하지 않고 Skip해도 됨(엔터)
SP2-0137: DEFINE의 등호 뒤에 값이 필요합니다.
specify connect string as parameter 6:
6의 값을 입력하십시오: ⇐ 접속 문자열을 입력. 입력하지 않고 Skip해도 됨(엔터)</p>
</blockquote>
<ul>
<li>스크립트 실행후 다음과 같이 PL/SQL procedure successfully completed. 
이 문구가 나온다면 정상적으로 완료된 것이다</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/0bf5fdf9-285c-404f-a4a3-470b6f3be3f2/image.PNG" width = "80%" height = "80%">

<hr>
<h2 id="step03-sql-developer-설치하기">&lt;STEP.03&gt; SQL Developer 설치하기</h2>
<p>오라클 사용을 위한 관리툴이다.</p>
<ol>
<li><a href="https://www.oracle.com/index.html">https://www.oracle.com/index.html</a> 접속</li>
<li>Resources ⇒ Downloads ⇒ Popular Developer Downloads ⇒ SQL Developer</li>
</ol>
<p><a href="https://www.oracle.com/database/sqldeveloper/technologies/download/">SQL Developer 설치 바로가기</a></p>
<ul>
<li>Windows 32-bit/64-bit 을 다운로드 한다.
압축을 해제한 후 폴더를 정리하여 exe 파일을 실행한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/3bf955be-ad14-48e3-bb98-5e6257fbd89b/image.PNG" width = "80%" height = "80%">

<p>실행한 후 system 계정을 등록한다. + 버튼을 누른다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/91e386af-0430-473e-a3b8-deeade6c5f34/image.PNG" width = "50%" height = "50%">

<p>새로만들기 창이 뜨면 표시한 부분에 다음과 같이 입력한다.
Name : System 계정
사용자이름 : system
비밀번호 : 123456 입력 후 비밀번호저장 박스 체크 (체크하지 않으면 계속 물어본다)
테스트 ⇒ 저장 ⇒ 접속</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ed59c609-204e-400c-923c-613f651215db/image.PNG" width = "70%" height = "70%">

<p>입력을 마친 후 테스트를 눌렀을때 상태 부분에 ‘성공’ 뜨는걸 확인하고 저장, 
접속을 순서대로 누른다.
접속이 완료되면 좌측 접속창에서 다른 사용자를 열어본다.</p>
<blockquote>
<p>앞에서 생성한 HR 계정이 있는지 확인해본다.
확인되었다면 정상적으로 추가된 것이니 계정을 등록한다</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/1c6fd780-e558-4251-a367-86f95021aaba/image.PNG" width = "25%" height = "25%">

<ul>
<li>아래 사진과 같이 테스트 - 성공이라고 떠야만 정상이다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/6923b511-059c-4c12-8e78-9808f194fb1b/image.PNG" width = "70%" height = "70%">

<p>등록이 완료되면 좌측 접속창에서 확인할 수 있다.
( 심지어 샘플로 생성되어 있는 테이블 및 데이터도 확인할 수 있다 )</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ed125b01-22f0-4250-90bf-2f81f6cdc800/image.PNG" width = "70%" height = "70%">

<hr>
<p>● scott 계정 추가</p>
<blockquote>
<p>SQL Developer 에서 system으로 접속한다.
새로운 워크시트가 생성되면 다음과 같이 scott 계정을 생성한다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/fdee259b-c7bf-4d42-89a3-56c5e6f16404/image.PNG" width = "70%" height = "70%">

<ul>
<li>열기를 눌러 오라클이 설치된 경로를 찾아서 아래와 같이 찾아준다.
\OracleXE21c\dbhomeXE\rdbms\admin</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/c8be3c2f-bc71-4df7-8258-5b57649cdffb/image.PNG" width = "70%" height = "70%">

<ul>
<li>scott.sql 파일을 찾아서 연다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/d253e5f4-553f-4f3d-8b0f-cf6eeb9d716b/image.PNG" width = "50%" height = "50%">

<p>BUT] 24번 라인의 명령은 다음과 같은데 실행하면 에러가 발생한다</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/d176ac75-a6c1-43c6-a3af-baf955a9f5ce/image.PNG" width = "80%" height = "80%">

<ul>
<li>수정 되었다면 ‘스크립트 실행’ 버튼을 누른다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/bd781d8e-b7eb-4031-85c1-3ef11157afbd/image.PNG" width = "80%" height = "80%">

<p>그대로 SCOTT 계정을 등록해주면 끝이다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/78131c73-47b7-45fe-88be-28c37998341e/image.PNG" width = "80%" height = "80%">

<blockquote>
<p>이렇게 설치까지 끝이 났다. 다음 시간은 데이터베이스(DB)의 기본지식을 알아볼 것이다.
다음 포스팅에서 계속..</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL.00] 오라클(Oracle) SQL 정책 및 종류 + 21C 설치하기➕]]></title>
            <link>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-SQL-%EC%A0%95%EC%B1%85-%EB%B0%8F-%EC%A2%85%EB%A5%98-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kama_code/SQL.00-%EC%98%A4%EB%9D%BC%ED%81%B4Oracle-SQL-%EC%A0%95%EC%B1%85-%EB%B0%8F-%EC%A2%85%EB%A5%98-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 12 Aug 2023 15:02:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>프로그램을 사용하다보면 무궁무진한 데이터가 만들어지게 되는데
이 데이터는 어디에 보관하고 저장하는 걸까? 
바로 데이터베이스(database)이다.
이번 포스팅에서는 SQL 데이터베이스 오라클을 설치해볼 것이다.</li>
</ul>
</blockquote>
<h2 id="step01-오라클oracle-라이선스-정책">&lt;STEP.01&gt; 오라클(Oracle) 라이선스 정책</h2>
<p><span style="color:red">● 사용자 수를 기반으로 하는 라이선스와 CPU 수를 기반으로 하는 라이선스 정책이 있다.</span></p>
<ol>
<li>Named User 라이선스 방식</li>
<li>DB를 사용하는 인원이 명확하게 정해졌을 때 산정됨.</li>
<li>각 오라클 버전마다 최소 구매 라이선스가 다름.
a. Standard One : 장착 CPU 당 최소 5 Users.(한국 내 사용은 10 Users)
b. Standard : 장착 CPU 당 최소 10 Users.
c. EnterPrise : 장착 CPU 당 최소 25 Users.</li>
<li>프로세서 라이선스 방식
● 무작위 다수가 접속할 때 산정되는 방식.
● CPU 확장 가능한 소켓 수와 실제 장착 CPU 수를 기준으로 한다.
● OS와 오라클 버전 별로 라이선스 금액은 동일하다.
● 구매 후 1년간만 업데이트와 패치에 대한 권한을 가지며 1년 후 업데이트와 패치를 위해서는 최초 구매 가격의 22% 비용이 발생한다.</li>
</ol>
<hr>
<h2 id="step02-오라클oracle-데이터베이스-종류">&lt;STEP.02&gt; 오라클(Oracle) 데이터베이스 종류</h2>
<ol>
<li><p>Oracle Personal Edition(PE)
● CPU 개수와 상관 없으나, 단일 사용자만 사용 가능.
● 모든 Oracle Database 제품군과 호환이 가능.
● 모든 제품의 특징이 포함된 개인 사용자용.
● SE1, SE, EE와의 완벽한 호환성을 요구하는 단일 사용자 개발 환경 지원. 개발자용 버전.</p>
</li>
<li><p>Oracle Standard Edition One(SE1)
● 2 CPU까지 확장 가능한 서버에 설치 가능.
● 최소 사용자 수는 5이며 RAC는 지원되지 않음.
● 400명 미만의 사용자가 있는 회사나 조직에 적합.
● Named User 라이선스 방식에서 주로 사용되는 Edition.</p>
</li>
<li><p>Oracle Standard Edition(SE)
● 4 CPU까지 확장 가능한 서버에 설치 가능.
● 최소 사용자 수는 5, RAC 포함.
● 클러스터를 구성하는 경우 클러스터의 모든 서버 소켓의 합이 4를 넘지 않아야 함.
● 1,000명 미만의 사업장에 적당.
● GB 데이터베이스 크기에 적당.</p>
</li>
<li><p>Oracle Enterprise Edition(EE)
● 4 CPU 이상 확장 가능한 서버에 설치 가능.
● 최고의 성능과 확장성, OTLP 상의 안정성, 의사 결정 지원 기능.
● 최소 사용자 수는 25, RAC는 옵션.
● 운용하는 규모에는 제한이 없음.
● 오라클 데이터베이스의 모든 컴포넌트를 지니고 있음.
● 옵션과 확장팩을 도입해 기능을 더욱 향상 시킬 수 있음.</p>
</li>
<li><p>Oracle eXpress Edition(XE)
● 무료 버전. 개발, 배포, 보급까지 무료.
● 사용자 데이터 4GB, 메모리 1GB, 호스트머신에 1CPU로 제약이 되어 있다.
● 10g 이후에 나온 Edition.
● 필요하다면 추가 비용 없이 간편하게 SE나 EE로 업그레이드 가능.
● 다운로드 받는 곳 - 오라클 홈페이지</p>
</li>
</ol>
<p><a href="https://www.oracle.com/database/technologies/xe-prior-release-downloads.html">https://www.oracle.com/database/technologies/xe-prior-release-downloads.html</a></p>
<p>Oracle database Express Edtion(XE)는
데이터베이스 응용 프로그램을 개발하는 개발자나 비싼가격 때문에 
데이터베이스를 활용하지 못했던 중소기업의 전산 관리자, 
IT 전문가에게 효과적인 데이터베이스 도구이다.</p>
<hr>
<h2 id="step03-오라클oracle-21c-설치하기">&lt;STEP.03&gt; 오라클(Oracle) 21C 설치하기</h2>
<blockquote>
<ul>
<li>드디어 데이터베이스(DB)를 설치할 포스팅을 작성한다. </li>
</ul>
</blockquote>
<p><span style="color:red"><a href="https://www.oracle.com/database/technologies/xe-downloads.htm">○ 오라클 21C 설치 바로가기</a></span></p>
<ul>
<li>위의 링크를 클릭하여 설치를 한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/0fe34c5d-fc71-4817-b8ad-896137b3bc8e/image.PNG" width = "70%" height = "70%">

<ul>
<li>압축을 풀어 다음 또 다음을 눌러 설치하다보면 비밀번호를 입력하라는 창이 나온다.
바로 Oracle Database 정보에서 오라클 관리자 계정인 SYS, SYSTEM 의 비밀번호이다.
<span style='background-color: yellow'>절대 잃어버리면 안되는 비밀번호</span>라서 필자는 123456 으로 외우기 쉽게 설정했다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/692ca16b-7f6b-4f3c-ba8a-0caf865106d3/image.PNG" width = "70%" height = "70%">

<ul>
<li>설치도중 보안경고가 뜨면 허용을 눌러준다.
다음 다음 계속 누르면 설치 진행중.. (시간이 꽤 많이 걸린다.)</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/326ed5c2-f2d4-4378-bdff-a4adeea77b96/image.PNG" width = "80%" height = "80%">

<ul>
<li>이렇게 뜬다면 설치가 완료된 것이다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/358b7060-c2e2-494c-bae2-7603b31c52fc/image.PNG" width = "60%" height = "60%">

<blockquote>
<p>다음 포스팅은 Oracle 최초 실행과 몇가지 준비할 것들이 있다.
그리고 오라클 sql 데이터베이스를 보다 손쉽게 쓰기 위해 만든 도구가 있다.
그것도 함께 설치를 해볼 것이다. 
그럼 다음 포스팅에서...</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.15] 쓰레드(Thread)와 채팅 프로그래밍 (Chatting Programming)]]></title>
            <link>https://velog.io/@kama_code/JAVA.15-%EC%93%B0%EB%A0%88%EB%93%9CThread%EC%99%80-%EC%B1%84%ED%8C%85-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-Chatting-Programming</link>
            <guid>https://velog.io/@kama_code/JAVA.15-%EC%93%B0%EB%A0%88%EB%93%9CThread%EC%99%80-%EC%B1%84%ED%8C%85-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-Chatting-Programming</guid>
            <pubDate>Sat, 29 Jul 2023 11:54:44 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>드디어 자바(JAVA) 정식 교육의 마지막 단원 쓰레드이다.
쓰레드가 정식적인 자바 공부는 마무리되지만 포스팅은 끝나지 않는다.
이후는 심화 내용이 있을 경우 게속 추가해서 작성될 예정이다.</li>
</ul>
</blockquote>
<h2 id="step-1-쓰레드-thread">&lt; Step 1. 쓰레드 (Thread) &gt;</h2>
<blockquote>
<ul>
<li>쓰레드? 
<span style='background-color: yellow'>프로세스</span>는 실행중인 프로그램을 의미한다.
<span style='background-color: yellow'>쓰레드</span>는 프로세스 내에서 별도의 실행흐름을 갖는 대상이다.
프로세스 내에서 둘 이상의 쓰레드를 생성하는 것이 가능하다.
= 여러 개의 작업을 동시에 할 수 있게 된다.
두 가지 이상의 작업을 동시에 처리하는 것을 <span style='background-color: yellow'>멀티태스킹 Multi-tasking</span> 이라고 한다.]
java.lang패키지에 포함되어 있어서 따로 import할 필요가 없다</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/9e9b84df-d150-406c-9b11-a6f0d559e157/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/d7e761a6-e347-43c5-97bc-838db5138b2e/image.PNG" width = "50%" height = "50%">

<h2 id="step-2-쓰레드-thread의-생성과-실행">&lt; Step 2. 쓰레드 (Thread)의 생성과 실행 &gt;</h2>
<ol>
<li>쓰레드를 생성하는 첫번째 방법<blockquote>
<ul>
<li>Thread 클래스를 상속 받아 run() 메서드를 오버라이딩한다.
start() 메소드를 통해 쓰레드가 생성된다.
생성된 쓰레드는 run() 메소드를 호출하여 동장한다.</li>
</ul>
</blockquote>
</li>
</ol>
<p>run() 메소드는 쓰레드의 main() 메소드에 해당한다
run() 메소드는 오버라이딩 한 것으로 해당 메소드는 직접 호출하면 안된다.
start() 메소드를 통해 간접적으로 호출해야 한다</p>
<pre><code class="language-java">class ShowThread extends Thread{
    String threadName;
    public ShowThread(String name) {
        threadName = name;
    }
    @Override
    public void run() {         
        메소드의 실행부...
    }
}</code></pre>
<p>▣ 둘 이상의 스레드를 생성</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/334f7322-14fe-48a6-986f-64029ec375a8/image.PNG" width = "60%" height = "60%">

<p>▣ 쓰레드의 우선순위</p>
<ul>
<li>쓰레드는 생성시 기본적으로 동일한 우선순위를 부여받는다.</li>
<li>높은 우선순위가 필요한 쓰레드가 있다면 setPriority()메소드를 사용하여 설정한다. </li>
<li>단, 우선순위는 절대적이지 않다.  CPU의 유휴상태가 생기면 
우선순위가 낮은 쓰레드도 실행될 수 있다.</li>
</ul>
<pre><code class="language-java">new MessageThread(&quot;첫번째&quot;, Thread.MAX_PRIORITY);//10
new MessageThread(&quot;두번째&quot;, Thread.NORM_PRIORITY);//5
new MessageThread(&quot;세번째&quot;, Thread.MIN_PRIORITY);//1</code></pre>
<p>▣ 쓰레드의 생명주기(Life cycle)</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ba179edd-20eb-4446-8549-b20dd6da243e/image.PNG" width = "50%" height = "50%">

<ul>
<li>Runnable 상태의 쓰레드만이 스케쥴러에 의해 스케쥴링 가능하다.</li>
<li>sleep(), join() 메소드를 호출로 인해 쓰레드는 Blocked 상태가된다.</li>
<li>Blocked 상태의 쓰레드는 조건에 따라 Runnable 상태로 변경될 수 있다. </li>
<li>Dead상태가 된 쓰레드는 Runnable 상태가 될 수 없다.</li>
</ul>
<p>▣ 독립쓰레드와 데몬쓰레드</p>
<ul>
<li><p>◈ 독립 스레드(Non Daemon Thread)
일반적으로 main() 메소드의 종료는 프로그램의 종료로 이어진다.
단, 독립쓰레드는 main() 메소드가 종료되어도 계속 실행되며 Dead 상태가 되어야 종료된다.</p>
</li>
<li><p>◈ 데몬 스레드(Daemon Thread)
모든 독립쓰레드가 종료될때 자동으로 종료되는 쓰레드
프로그램이 종료될때 자동으로 종료되므로 주로 무한루프로 쓰레드를 구성한다.
일반적으로 main()메소드가 종료될때 프로그램도 종료되지만,
독립쓰레드가 남아있다면 종료된 것이 아니라서 유의해야한다.
ㄴ배경음악재생, 로그 자동저장 등의 업무에 많이 쓰인다</p>
</li>
</ul>
<pre><code class="language-java">DaemonThread dThread = new DaemonThread();
dThread.setDaemon(true);
dThread.start();</code></pre>
<ol start="2">
<li>쓰레드를 생성하는 두번째 방법</li>
</ol>
<ul>
<li>Runnable 인터페이스의 구현 (java.lang 패키지에 포함)</li>
<li>일반적인 인터페이스의 구현</li>
<li>람다식으로 구현</li>
</ul>
<pre><code class="language-java">class AdderThread extends Sum implements Runnable {
    public void run() {
        함수의 실행부...
    }
}</code></pre>
<p>▣ 쓰레드의 메모리 구성</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/d2a48cb4-4ac3-4528-a88d-2219951319d8/image.PNG" width = "50%" height = "50%">

<ul>
<li>쓰레드1과 쓰레드2는 스택을 제외한 메소드 영역과 힙영역을 공유한다.
ㄴ스태틱 역시 서로 한 구역을 공유한다.</li>
<li>이 두 영역을 통해서 데이터를 공유할 수 있다. </li>
<li>쓰레드의 실행이 메소드의 호출을 통해서 이뤄지고, </li>
<li>메소드 호출을 위해 사용되는 공간이 스택이므로 공유할 수 없다. </li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/c45aa58f-d3b6-4977-87d6-9696c168999f/image.PNG" width = "70%" height = "70%">

<p>▣ 쓰레드의 동기화 ( ★★★ 매우 중요 )
쓰레드는 하나의 메모리 공간에 동시에 접근하면 따로 논다.
ㄴ그러므로 동기화를 해줘야 한다.
ㄴ메소드 전체를 호출하면 시간은 길어지나 정확한 값을 가지게 된다.</p>
<blockquote>
<p>동기화 방법: 메소드에 synchronized 키워드를 지정하거나 
코드의 일부에 동기화 블럭을  지정한다</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/432c6b8f-9128-440f-a9d0-98fc21335a8c/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/03bdf8dc-517a-4511-a0df-963273ae970d/image.PNG" width = "50%" height = "50%">

<ul>
<li>synchronized에 의해 쓰레드1이 메소드를 호출하게 되면 
쓰레드2는 접근이 불가능하다. 호출시 자물쇠로 잠그게 되고, 
실행종료시 열쇠를 통해 열게되는 개념이다. 이를 ‘동기화’라고 한다.</li>
</ul>
<p>▣ 동기화 메소드</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/5a131dcf-60bc-4dff-8180-97483a7f4559/image.PNG" width = "45%" height = "45%">

<h2 id="step-3-쓰레드-풀--thread-pool-">&lt; Step 3. 쓰레드 풀 ( Thread pool ) &gt;</h2>
<ul>
<li>쓰레드 풀이란?
쓰레드를 미리 생성하고, 작업 요청이 발생할 때 마다 미리 생성된 쓰레드로 
해당 작업을 처리하는 방식 = 쓰레드 재활용하기 위한 모델
(쓰레드의 생성과 소멸은 리소스 소모가 많은 작업이므로)</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/2c8bd8db-978b-4b8f-981e-5e3571330b3e/image.PNG" width = "70%" height = "70%">

<p>▣ 쓰레드 풀 유형
<span style='background-color: blue'><span style="color:white">newSingleThreadExecutor</span></p>
<ul>
<li>풀 안에 하나의 스레드만 생성하고 유지한다.
스레드의 숫자가 하나이고 하나의 태스크가 완료된 이후에 다음 태스크가 실행한다.</li>
</ul>
<p><span style='background-color: blue'><span style="color:white">newFixedThreadPool</span></p>
<ul>
<li>풀 안에 인자로 전달된 수의 스레드를 생성하고 유지한다.
초기 스레드 개수는 0개, 코어 스레드 수와 
최대 스레드 수는 매개변수 nThreads 값으로  지정한다.
만약 생성된 스레드가 놀고 있어도 스레드를 제거하지 않고 내버려 둔다.</li>
</ul>
<p><span style='background-color: blue'><span style="color:white">newCachedThreadPool</span> </p>
<ul>
<li>풀 안의 쓰레드의 수를 작업의 수에 맞게 유동적으로 관리한다.
초기 스레드와 코어 스레드 개수는 0개, 
최대 스레드 수는 integer 데이터형이 가질 수 있는 최대  값이다.
만약 스레드가 60초동안 아무일도 하지 않으면 스레드를 종료시키고 스레드풀에서 제거한다.</li>
</ul>
<h2 id="step-4-callable--future--reentrantlock">&lt; Step 4. Callable &amp; Future,  ReentrantLock &gt;</h2>
<ul>
<li>스레드는 실행만 시켜 줄 수 있고, 스레드로부터 결과를 반환 받을 수 없다.  </li>
<li>스레드가 실행될 때 각 스레드마다 스택영역, 힙 영역이 따로 가지기 때문이다.  </li>
<li>스레드끼리 데이터를 공유하기 위해서는 스태틱 영역의 변수를 사용했다.</li>
</ul>
<blockquote>
<ul>
<li>Callable: Runnalble과 유사하지만 return을 통해 작업의 결과를 받아볼 수 있다.</li>
</ul>
</blockquote>
<ul>
<li><p>Future: 비동기적인 작업의 현재 상태를 조회하거나 결과를 가져올 수 있다. get()</p>
<p>Executor 프레임워크를 사용하면 태스크 처리가 끝난 다음 
결과를 반환 받아 태스크들을 병렬로(concurrent) 실행할 수 있다.</p>
</li>
</ul>
<p>▣ <span style='background-color: yellow'>ReentrantLock</span>(명시적 동기화) : 눈으로 볼 수 있는 동기화
    synchronized는 메소드 전체나 구간을 묶어서 동기화를 시켰다.<br>  그런데 ReentrantLock 클래스를 사용하면 시작점과 끝점을 명백히 명시할 수  있다.</p>
<blockquote>
<p>사용법 : lock, unlock 메소드를 통해 시작과 종료를 명시적으로 작성해줄 수 있다. </p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/b63ebd0e-12e8-4374-9f0b-3e544695a498/image.PNG" width = "40%" height = "40%">


<h2 id="step-5-컬렉션-객체-동기화">&lt; Step 5. 컬렉션 객체 동기화&gt;</h2>
<p>비동기화된 메소드를 동기화된 메소드로 래핑하는 
  Collections의 synchronizedXXX() 메서드를 제공한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/372b0859-f653-4d1c-bbae-d0b43c44c7fd/image.PNG" width = "70%" height = "70%">

<p>하지만 컬렉션 객체의 동기화를 이렇게 했다고 하더라도 
이 컬렉션 객체를 기반으로 생성하는 반복자는 별도로 동기화를 다시 해 주어야 한다.</p>
<p>▣ ConcurrentHashMap
스레드가 컬렉션 객체의 요소를 처리할 때 전체 잠금이 발생하여 
컬렉션 객체에 접근하는 다른 스레드는 대기 상태가 된다. 
이는 객체의 요소를 다루는 것은 안전해졌지만, 처리 속도는 느려졌다는 이야기가 된다.</p>
<p>멀티스레드가 컬렉션의 요소를 병렬적으로 처리할 수 있도록
java.util.concurrent 패키지에서 
ConcurrentHashMap, ConcurrentLinkedQueue를 제공한다.</p>
<p>이 클래스는 부분적으로 잠금을 사용하기 때문에 객체의 요소를 처리할 때 
스레드에 안전하면서 빠르게 처리가 가능해진다.</p>
<h2 id="step-6-채팅-프로그래밍--chatting-programming-">&lt; Step 6. 채팅 프로그래밍 ( Chatting Programming )</h2>
<blockquote>
<p>먼저 이것을 읽어보자!
  <a href="https://drive.google.com/file/d/1Zr1iLoiTOJ84u42meQe411uMKo9Z3Gyw/view?usp=sharing">네트워크 기초 다운로드</a></p>
</blockquote>
<p>▣ 안드로이드 폰에서 IP 주소 찾기</p>
<p>홈 화면에서 &quot;설정&quot; 아이콘을 찾고 누르세요. 
일반적으로 기어 모양의 아이콘입니다.
설정 메뉴에서 &quot;Wi-Fi 및 인터넷&quot; 또는 &quot;Wi-Fi&quot;를 선택하세요.
현재 연결된 Wi-Fi 네트워크를 찾아 탭하세요.
네트워크 세부 정보가 표시됩니다. 여기에서 &quot;IP 주소&quot; 또는 &quot;IPv4 주소&quot;를 
확인할 수 있습니다.</p>
<p>▣ 아이폰에서 IP 주소 찾기</p>
<p>홈 화면에서 &quot;설정&quot; 앱을 찾고 누르세요. 
일반적으로 기어 모양의 아이콘이 있습니다.
설정 메뉴에서 &quot;Wi-Fi&quot;를 선택하세요.
현재 연결된 Wi-Fi 네트워크를 찾아 탭하세요.
네트워크 세부 정보가 표시됩니다. 여기에서 &quot;IP 주소&quot; 또는 &quot;IPv4 주소&quot;를 
확인할 수 있습니다.</p>
<p><a href="https://dora-guide.com/putty-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C/">채팅서버 한글이 깨진다면 Putty</a></p>
<img src = "https://velog.velcdn.com/images/kama_code/post/a39b9a48-9e03-4c30-b2c3-cef9af14ef5c/image.PNG" width = "50%" height = "50%">

<ul>
<li>서버 코드<pre><code class="language-java">import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
</code></pre>
</li>
</ul>
<p>public class MultiServer7
{
    ServerSocket serverSocket = null;
    Socket socket = null;
    Map&lt;String, PrintWriter&gt; clientMap;</p>
<pre><code>// 생성자
public MultiServer7()
{
    //클라이언트의 출력스트림을 저장할 해쉬맵 생성.
    clientMap = new HashMap&lt;String, PrintWriter&gt;();
    //해쉬맵 동기화 설정.
    Collections.synchronizedMap(clientMap);
}

public void init()
{
    try
    {
        serverSocket = new ServerSocket(9999);
        System.out.println(&quot;서버가 시작되었습니다.&quot;);
        while(true)
        {
            socket = serverSocket.accept();
            // 연결된 원격 어드레스의 정보를 보여준다.
            System.out.println(socket.getInetAddress() + &quot;:&quot; + socket.getPort());

            Thread mst = new MultiServerT(socket); //쓰레드 생성
            mst.start(); //쓰레드 시동
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        try
        {
            serverSocket.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

// 접속자 리스트 보내기
public void list(PrintWriter out)
{
    //출력스트림을 순차적으로 얻어와서 해당 메세지를 출력
    Iterator&lt;String&gt; it = clientMap.keySet().iterator();
    String msg = &quot;사용자 리스트[&quot;;
    while (it.hasNext())
    {
        msg += (String)it.next() + &quot;,&quot;;
    }
    msg = msg.substring(0, msg.length()-1) + &quot;]&quot;;
    try
    {
        out.println(msg);
    }
    catch (Exception e)
    {

    }
}
// 접속된 모든 클라이언트들에게 메세지를 전달
public void sendAllMsg(String msg, String name)
{
    //출력 스트림을 순차적으로 얻어와서 해당 메세지를 출력한다.
    Iterator&lt;String&gt; it = clientMap.keySet().iterator();

    while (it.hasNext())
        try
        {
            PrintWriter it_out = (PrintWriter) clientMap.get(it.next());
            if(name.equals(&quot;&quot;))
            {
                it_out.println(msg);
            }
            else
            {
                it_out.println(name + &quot; &gt; &quot; + msg);
            }
        }
        catch (Exception e)
        {
            System.out.println(&quot;예외:&quot;+e);
        }

    }
    public static void main(String[] args)
    {
        // 서버객체 생성
        MultiServer7 ms = new MultiServer7();
        ms.init();
    }

// 내부 클래스
// 클라이언트로부터 읽어온 메세지를 다른 클라이언트에 보내는
// 역할을 하는 메소드

class MultiServerT extends Thread
{
    Socket socket;
    PrintWriter out = null;
    BufferedReader in = null;
    String name = &quot;&quot;;

    //생성자
    public MultiServerT(Socket socket)
    {
        this.socket = socket;
        try
        {
            out = new PrintWriter(this.socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
        }
        catch(Exception e)
        {
            System.out.println(&quot;예외:&quot;+e);
        }
    }
        @Override
        public void run()
        {
            String s = &quot;&quot;;

            try
            {
                name = in.readLine();
                System.out.println(&quot;[&quot; + name + &quot;]님이 대화방에 입장하셨습니다.&quot;);

                // 현재 객체가 가지고 있는 소켓을 제외하고 다른 소켓(클라이언트)들에게
                // 접속을 알림

                sendAllMsg(name + &quot;님이 입장하셨습니다.&quot;, &quot;&quot;);

                // 해쉬맵에 키를 name으로 출력스트림 객체를 저장.
                clientMap.put(name, out);

                System.out.println(&quot;현재 접속자 수는 &quot;+clientMap.size()+&quot;명 입니다.&quot;);

                // 입력스트림이 null이 아니면 반복
                while (in!=null)
                {
                    s = in.readLine();

                    if (s.equals(&quot;q&quot;) || s.equals(&quot;Q&quot;))
                        break;

                    System.out.println(name + &quot; &gt; &quot;+ s);
                    if (s.equals(&quot;/list&quot;))
                        list(out);
                    else
                        sendAllMsg(s,name);
                }
                System.out.println(&quot;쓰레드 종료&quot;);
            }
            catch (Exception e)
            {
                System.out.println(&quot;예외:&quot;+e);
            }
            finally
            {
                // 예외가 발생할때 퇴장. 해쉬맵에서 해당 데이터 제거.
                // 보통 종료하거나 나가면 java.net.SocketException: 예외발생
                clientMap.remove(name);
                sendAllMsg(name + &quot;님이 퇴장하셨습니다.&quot;, &quot;&quot;);
                System.out.println(&quot;현재 접속자 수는&quot;+clientMap.size()+&quot;명 입니다.&quot;);
                try
                {
                    in.close();
                    out.close();

                    socket.close();
                } 
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }</code></pre><p>}</p>
<pre><code>
+클라이언트 코드

```java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
//서버와 클라이언트 연결
public class MultiClient5
{
    public static void main(String[] args) throws UnknownHostException, IOException
    {
        System.out.println(&quot;이름을 입력해 주세요.&quot;);
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();

        try
        {
            String ServerIP = &quot;localhost&quot;;
            if(args.length &gt; 0)
                ServerIP = args[0];
            Socket socket = new Socket(ServerIP, 9999); //소켓 객체 생성
            System.out.println(&quot;서버와 연결이 되었습니다.....&quot;);

            //서버에서 보내는 메세지를 사용자의 콘솔에 출력하는 쓰레드
            Thread receiver = new Receiver5(socket);
            receiver.start();            

            //사용자로부터 얻은 문자열을 서버로 전송해주는 역할을 하는 쓰레드
            Thread sender = new Sender5(socket, name);
            sender.start();
        }    
        catch(Exception e)
        {
            System.out.println(&quot;예외[MultiClient class]:&quot;+e);
        }
    }

}</code></pre><ul>
<li>Receiver 코드</li>
</ul>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

public class Receiver5 extends Thread
{
    Socket socket;
    BufferedReader in = null;

    //Socket을 매개변수로 받는 생성자
    public Receiver5(Socket socket)
    {
        this.socket = socket;

        try
        {
            in = new BufferedReader(new InputStreamReader(this.socket.getInputStream() ));
        }
        catch(Exception e)
        {
            System.out.println(&quot;예외1:&quot; +e);
        }
    }
    //run()메소드 재정의
    @Override
    public void run()
    {
        while (in!=null)
        {
            try
            {
                System.out.println(&quot;Thread Receive : &quot; + in.readLine());                
            }
            catch (java.net.SocketException ne)
            {
                break;
            }
            catch (Exception e)
            {
                System.out.println(&quot;예외:&quot;+e);
            }
        }
        try
        {
            in.close();
        }
        catch (Exception e)
        {
            System.out.println(&quot;예외3:&quot;+e);
        }
    }

}</code></pre>
<ul>
<li>sender 코드</li>
</ul>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Sender5 extends Thread
{
    Socket socket;
    PrintWriter out = null;
    String name;

    // 생성자
    public Sender5(Socket socket, String name)
    {
        this.socket = socket;        
        try
        {
            out = new PrintWriter(this.socket.getOutputStream(), true);
            this.name = name;
        }
        catch(Exception e)
        {
            System.out.println(&quot;예외S3:&quot; +e);
        }
    }
    //run()메소드 재정의
    @Override
    public void run()
    {
        Scanner sc = new Scanner(System.in);
        try
        { // 입력한 사용자의 이름을 서버에 보내준다
            out.println(name);

            while(out!=null)
            {
                try
                {
                    String s = sc.nextLine();
                    out.println(s);

                    if (s.equals(&quot;q&quot;) || s.equals(&quot;Q&quot;) )
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    System.out.println(&quot;예외S1:&quot;+e);                
                }
            }

            out.close();
            socket.close();
        }
        catch (Exception e)
        {
            System.out.println(&quot;예외S2:&quot;+e);
        }

        sc.close();
    }
}</code></pre>
<h2 id="step7-발전을-위한-문제풀이-kama_code-출제">&lt;Step.7&gt; 발전을 위한 문제풀이 (kama_code 출제)</h2>
<ul>
<li>아래 기능을 만족하는 채팅 프로그램을 만드시오.</li>
</ul>
<blockquote>
<ol>
<li>가입
중복 아이디 처리 : 데이터베이스 연동</li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>접속
중복 아이디 처리 : 데이터베이스 연동
접속거부 : 블랙리스트 처리</li>
</ol>
</blockquote>
<blockquote>
<ol start="3">
<li>공통
대화상대 차단
대화 금칙어 처리
서버 적용 금칙어 (공용, 관리자) 
개인 추가 금칙어 
귓속말
1회용 설정 
고정 설정
공지사항 전달 (대기실 + 대화방 전체, 관리자) </li>
</ol>
</blockquote>
<blockquote>
<ol start="4">
<li>대기실 명령어 :
공개방만들기
타이틀 설정 
정원 설정
비공개방만들기
타이틀 설정
정원 설정
비밀번호 설정
방리스트보기
전체 보기
공개방만 따로 보기
비공개방만 따로 보기
대화방 참여</li>
</ol>
</blockquote>
<blockquote>
<ol start="5">
<li>룸 명령어 : 
대화방 리스트 보기 
대기실 사용자 리스트 보기
내 룸 사용자 리스트 보기
초대하기
방장만 가능
상대방이 수락시 자동으로 방 참여시키기
강퇴
일회성 강퇴
영구 강퇴
룸 나가기
방장 승계
방 폭파 기능</li>
</ol>
</blockquote>
<blockquote>
<ol start="6">
<li>관리용 
관리자 로그인
원하는 방 모니터링
블랙리스트 처리
방 폭파 처리</li>
</ol>
</blockquote>
<blockquote>
<blockquote>
<p>/list  ← 서버의 접속자 리스트를 자기 화면에 출력하면 됩니다.
/to 홍길동 안녕하세요 (엔터)← 홍길동한테만 메시지를 보여주면 됩니다. (귓속말 기능)</p>
</blockquote>
</blockquote>
<p>[[[ 힌트 ]]]</p>
<p>서버에서...
1.클라이언트에서 대화가 올라옴
s = in.readLine();
현재 “이름 + 입력한 내용” 올라옴 → 입력한 내용만 올라오게 수업에서 만든 클라이언트 파일 수정해야 함
2.올라온 내용이 “/”로 시작하는지 검사
“/”로 시작하면 명령어임
아니면 일반 대화임
/list의 경우 명령어만 올라오므로 분리 없이 통째로 비교 가능함
3.명령어면 substring이나 StringTokenizer 로 내용 분리
분리한 내용에 list 가 있으면 해쉬맵의 키값만 묶어서 해당 사용자에게 내려 보냄
현재 해쉬맵에 키값이 사용자 이름임</p>
<p>4.귓속말 : 분리한 내용의 첫 번째 요소에  to 가 있으면 귓속말 명령임
서버로 올라온 내용이 “/to 이름 내용” 이므로 이름을 분리해 냄
이름이 해쉬맵에서 키값으로 사용되고 있으므로 해당 키값의 밸류를 찾아 냄
현재 밸류값에 사용자와 연결된 Socket의 PrinterWriter 값이 저장되어 있슴
밸류값이 OutputStream 이므로 그걸 이용해서 해당 사용자에게만 내용을 내려보내면 귓속말이 구현됨</p>
<p>/to 홍길동 (엔터)
← 귓속말 고정 설정 / 설정 풀기</p>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>서버 코드</li>
</ol>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;


public class ChatServer2 {

    Map&lt;String, String&gt; listw;
    Map&lt;String, String&gt; inviteM;
    static Connection con;
    static ServerSocket serverSocket = null;
    static Socket socket = null;
    Map&lt;String, PrintWriter&gt; waitUser;                                    //대기방 사용자
    Map&lt;String, PrintWriter&gt; clientMap;                                    // 사용자 아이디와 출력할 내용 -- 대기실용 해시맵        
    Map&lt;String, Map&lt;String, PrintWriter&gt;&gt; roomN;                        // 공개방 해시맵    
    Map&lt;String, Map&lt;String, PrintWriter&gt;&gt; roomP;                        // 비밀방
    Map&lt;String, Integer&gt; capa;                                            // 각방의 정원
    Map&lt;String, String&gt; pwd;                                            // 비밀방의 비밀번호

    //생성자
    public ChatServer2() {
        //client의 출력스트림을 저장할 해시맵 생성.
        inviteM = new HashMap&lt;String, String&gt;();
        waitUser = new HashMap&lt;String, PrintWriter&gt;();
        clientMap = new HashMap&lt;String, PrintWriter&gt;();
        roomN = new HashMap&lt;String, Map&lt;String, PrintWriter&gt;&gt;();
        capa = new HashMap&lt;String, Integer&gt;();
        pwd = new HashMap&lt;String, String&gt;();
        listw = new HashMap&lt;String, String&gt;();
        listw.put(&quot;/list&quot;, &quot;모든 사용자 리스트&quot;);
        listw.put(&quot;/waituser&quot;, &quot;대기방 유저 리스트&quot;);
        listw.put(&quot;/rlist&quot;, &quot;채팅방 리스트 출력&quot;);
        listw.put(&quot;/adword&quot;, &quot;개인 금칙어 설정 추가&quot;);
        listw.put(&quot;/delword&quot;, &quot;개인 설정 금칙어 삭제&quot;);
        listw.put(&quot;/agree&quot;, &quot;채팅방 초대 수락 명령어&quot;);


        //해쉬맵 동기화 설정.
        Collections.synchronizedMap(inviteM);
        Collections.synchronizedMap(waitUser);
        Collections.synchronizedMap(roomN);
        Collections.synchronizedMap(clientMap);
        Collections.synchronizedMap(capa);
        Collections.synchronizedMap(pwd);

    }

    public void init()
    {
        try {
            serverSocket = new ServerSocket(9990);
            System.out.println(&quot;서버가 시작되었습니다.&quot;);

            while(true) {
                socket = serverSocket.accept();
                //System.out.println(socket.getInetAddress()+&quot; : &quot; + socket.getPort());

                Thread mst = new MultiServerR(socket);    //쓰레드 생성(대화방 입장 알림, 대화)
                mst.start();                                    
            }
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            try {
                System.out.println(&quot;서버가 종료됩니다.&quot;);
                serverSocket.close();
            }catch(Exception e) {

            }
        }
    }

    //대기방 사용자 리스트
    public void waitU(PrintWriter out) {
        Iterator&lt;String&gt; it = waitUser.keySet().iterator();
        String msg = &quot;대기방 사용자 리스트 [&quot;;
        while(it.hasNext()) {
            msg += (String)it.next() + &quot;,&quot;;
        }
        msg = msg.substring(0, msg.length()-1) + &quot;]&quot;;

        try {
            out.println(msg);        //리스트 출력
        }catch(Exception e) {
        }
    }

    //사용자 리스트
    public void list(PrintWriter out)
    {
        //출력스트림을 순차적으로 얻어와서 해당 메세지를 출력한다
        Iterator&lt;String&gt; it = clientMap.keySet().iterator();
        String msg = &quot;사용자 리스트 [&quot;;
        while(it.hasNext()) {
            msg += (String)it.next() + &quot;,&quot;;
        }
        msg = msg.substring(0, msg.length()-1) + &quot;]&quot;;

        try {
            out.println(msg);        //리스트 출력
        }catch(Exception e) {
        }
    }

    //대화방 리스트
    public void roomList(PrintWriter out) {
        Iterator&lt;String&gt; it = roomN.keySet().iterator();
        String msg = &quot;방 리스트 [&quot;;
        while(it.hasNext()) {
            msg += (String)it.next() + &quot;,&quot;;
        }
        msg = msg.substring(0, msg.length()-1) + &quot;]&quot;;

        try {
            out.println(msg);        //리스트 출력
        }catch(Exception e) {
        }
    }

    //해당방 사용자
    public void userR(String title, PrintWriter out) {
        Iterator&lt;String&gt; it = roomN.get(title).keySet().iterator();
        String msg = title + &quot;방 사용자 리스트 [&quot;;
        while(it.hasNext()) {
            msg += (String)it.next() + &quot;,&quot;;
        }
        msg = msg.substring(0, msg.length()-1) + &quot;]&quot;;

        try {
            out.println(msg);        //리스트 출력
        }catch(Exception e) {
        }
    }

    //접속된 모든 클라이언트들에게 메세지를 전달
    public void sendAllMsg(String msg, String name) {

        PreparedStatement pstmt2 = null;
        String sql = null;
        ResultSet rs = null;
        String key = null;
        String word = null;
        String query = null;
        int chk = 0;
        int id2 = 0;
        int id1 = 0;

        //해쉬 맵과 이터레이터를 이용해서 출력스트림을 순차적으로 얻어와서 해당 메시지를 각방에 출력한다.
        Iterator&lt;String&gt; it = clientMap.keySet().iterator();

        while(it.hasNext()) {
            chk = 0;
            id2 = 0;
            try {
                key = it.next();
                PrintWriter it_out = (PrintWriter) clientMap.get(key);
                sql = &quot;select * from blackword&quot;;
                pstmt2 = con.prepareStatement(sql);
                rs = pstmt2.executeQuery();
                while(rs.next()) {
                    word = rs.getString(1);
                    if(msg.contains(word)) {
                        chk = 1;
                        for(int i = 0; i &lt; msg.length(); i++) {
                             it_out.print(&quot;*&quot;);
                         }
                         it_out.println();
                         break;
                    }
                }


                sql = &quot;select count(*) from $tablename&quot;;
                query = sql.replace(&quot;$tableName&quot;, key);
                pstmt2 = con.prepareStatement(query);
                rs = pstmt2.executeQuery();
                while(rs.next()) {
                    id1 = Integer.parseInt(rs.getString(1));
                }

                if(id1 &gt; 0) {
                    sql = &quot;select * from $tablename&quot;;
                    query = sql.replace(&quot;$tableName&quot;, key);
                    pstmt2 = con.prepareStatement(query);
                    rs = pstmt2.executeQuery();

                    while(rs.next()) {
                         word = rs.getString(1);
                         if(msg.equals(word)) {
                             id2 = 1;
                             for(int i = 0; i &lt; msg.length(); i++) {
                                 it_out.print(&quot;*&quot;);
                             }
                             it_out.println();
                         }
                    }

                    id1 = 0;
                }
                if(id2 == 0) {
                    if(name.equals(&quot;&quot;))
                            it_out.println(msg);                //받은 메세지 각 방에 출력
                        else
                            it_out.println(name + &quot; &gt; &quot; + msg);
                }
            }catch(Exception e) {
                System.out.println(&quot;예외:&quot; + e);
            }

        }
    }

    //방 내의 클라이언트들에게 메세지 전달
    public void sendMsg(String msg, String name, String i) {

        //해쉬 맵과 이터레이터를 이용해서 출력스트림을 순차적으로 얻어와서 해당 메시지를 각방에 출력한다.

        Iterator&lt;String&gt; it = roomN.get(i).keySet().iterator();
        String sql = null;
        ResultSet rs = null;
        String word = null;
        String query = &quot;&quot;;
        PreparedStatement pstmt2 = null;
        PreparedStatement pstmt3 = null;
        String next = null;
        int chk = 0;
        int id2 = 0;
        int id1 = 0;
        while(it.hasNext()) {
            chk = 0;
            id2 = 0;
            try {
                next = it.next();
                if(!next.equals(name)) {

                    PrintWriter it_out = (PrintWriter) roomN.get(i).get(next);

                    sql = &quot;select * from blackword&quot;;
                    pstmt2 = con.prepareStatement(sql);
                    rs = pstmt2.executeQuery();
                    while(rs.next()) {
                        word = rs.getString(1);
                        if(msg.equals(word)) {
                            chk = 1;
                            for(int j = 0; j &lt; word.length(); j++) {
                                 it_out.print(&quot;*&quot;);
                             }
                             it_out.println();
                             break;
                        }
                    }

                    if(chk == 1) continue;             


                    sql = &quot;select * from &quot; + next ;
                    pstmt2 = con.prepareStatement(sql);
                    rs = pstmt2.executeQuery();

                    while(rs.next()) {
                         word = rs.getString(1);
                         if(msg.equals(word)) {
                             id2 = 1;
                             for(int j = 0; j &lt; msg.length(); j++) {
                                 it_out.print(&quot;*&quot;);
                             }
                             it_out.println();
                             break;
                         }
                    }

                    if(id2 == 1)continue;

                    if(name.equals(&quot;&quot;))
                        it_out.println(msg);                //받은 메세지 각 방에 출력
                    else
                        it_out.println(name + &quot; &gt; &quot; + msg);

                }
            }catch(Exception e) {
                System.out.println(&quot;예외:&quot; + e);
            }

        }
    }

    //관리자용
    public void adlogin(BufferedReader in, PrintWriter out) throws IOException, SQLException {

        String menu = &quot;&quot;;
        String sql = null;
        PreparedStatement pstmt4 = null;
        PreparedStatement pstmt2 = null;
        ResultSet rs = null;
        String id = null;
        String word = null;

        while(true) {
            out.println(&quot;===메뉴===&quot;);
            out.println(&quot;1. 블랙리스트 목록&quot;);
            out.println(&quot;2. 블랙리스트 등록&quot;);
            out.println(&quot;3. 블랙리스트 해제&quot;);
            out.println(&quot;4. 방폭파&quot;);
            out.println(&quot;5. 금칙어 목록&quot;);
            out.println(&quot;6. 금칙어 등록&quot;);
            out.println(&quot;7. 금칙어 삭제&quot;);
            out.println(&quot;8. 나가기&quot;);
            out.println();
            menu = in.readLine();
            //블랙리스트 목록
            if(menu.equals(&quot;1&quot;)) {

                sql = &quot;select id from chatuser where utype = ?&quot;;
                pstmt2 = con.prepareStatement(sql);
                pstmt2.setString(1,  &quot;1&quot;);
                rs = pstmt2.executeQuery();
                out.println(&quot;&lt;&lt;블랙리스트 목록&gt;&gt;&quot;);
                while(rs.next()) {                    
                    word = rs.getString(1);
                    out.println(word);
                }
                out.println();
            }
            //블랙리스트 등록
            else if(menu.equals(&quot;2&quot;)) {

                sql = &quot;select id from chatuser&quot;;
                pstmt2 = con.prepareStatement(sql);
                rs = pstmt2.executeQuery();
                out.println(&quot;&lt;&lt;사용자 아이디&gt;&gt;&quot;);
                while(rs.next()) {                    
                    word = rs.getString(1);
                    out.println(word);
                }

                out.println(&quot;블랙리스트 등록을 원하는 id를 입력하세요.&quot;);
                id = in.readLine();

                sql = &quot;update chatuser set utype = &#39;1&#39; where id = ?&quot;;
                pstmt4 = con.prepareStatement(sql); 
                pstmt4.setString(1,  id);
                rs = pstmt4.executeQuery();
                out.println(&quot;완료되었습니다.&quot;);
                out.println();
            }
            //블랙리스트 해제
            else if(menu.equals(&quot;3&quot;)) {
                out.println(&quot;블랙리스트 해제를 원하는 id를 입력하세요.&quot;);
                id = in.readLine();
                sql = &quot;update chatuser set utype = &#39;0&#39; where id = ?&quot;;
                pstmt4 = con.prepareStatement(sql); 
                pstmt4.setString(1, id);
                rs = pstmt4.executeQuery();
                out.println(&quot;완료되었습니다.&quot;);
                out.println();
            }
            //방폭파
            else if(menu.equals(&quot;4&quot;)) {
                roomList(out);
                out.println(&quot;방폭파를 원하는 방 이름을 입력하세요&quot;);
                id = in.readLine();
                roomN.remove(id);
                out.println(id + &quot;방이 폭파되었습니다.&quot;);
                out.println();
            }
            //금칙어 목록
            else if(menu.equals(&quot;5&quot;)) {
                out.println(&quot;&lt;&lt;금칙어 목록&gt;&gt;&quot;);
                sql = &quot;select * from blackword&quot;;
                pstmt2 = con.prepareStatement(sql);
                rs = pstmt2.executeQuery();
                while(rs.next()) {
                    out.println(&quot;&gt; &quot; + rs.getString(1));
                }
                out.println();
            }
            //금칙어 추가
            else if(menu.equals(&quot;6&quot;)) {
                out.println(&quot;&lt;&lt;금칙어 추가&gt;&gt;&quot;);
                out.println(&quot;금칙어 : &quot;);
                id = in.readLine();
                sql = &quot;insert into blackword values (?)&quot;;
                pstmt4 = con.prepareStatement(sql); 
                pstmt4.setString(1, id);
                rs = pstmt4.executeQuery();
                out.println(&quot;\&#39;&quot; + id + &quot;\&#39;가 금칙어로 추가되었습니다. &quot;);
                out.println();
            }
            //금칙어 삭제
            else if(menu.equals(&quot;7&quot;)) {

                out.println(&quot;삭제할 금칙어 : &quot;);
                id = in.readLine();
                sql = &quot;delete from blackword where word = ?&quot;;
                pstmt2 = con.prepareStatement(sql); 
                pstmt2.setString(1, id);
                rs = pstmt2.executeQuery();
                out.println(&quot;금칙어가 삭제되었습니다.&quot;);
                out.println();
            }

            //페이지 종료
            else if(menu.equals(&quot;8&quot;))
            {
                out.println(&quot;관리자 페이지를 종료합니다.&quot;);
                break;
            }else {
                out.println(&quot;잘못 선택하셨습니다.&quot;);
            }
        }
    }
    //귓속말
    public void secretMsg(String msg, String name, String nameto, String i) {

        PrintWriter p = null;
        try {
            p = (PrintWriter) roomN.get(i).get(nameto);
            if(name.equals(&quot;&quot;))
                p.println(msg);                //받은 메세지 각 방에 출력
            else
                p.println(name + &quot;(귓속말) &gt; &quot; + msg);
        }catch(Exception e) {

        }

    }

    //초대
    public void invite( String name, String nameto, String i) {
        PrintWriter p = null;
        inviteM.put(nameto, i);
        try {
            p = (PrintWriter) clientMap.get(nameto);
            p.println(name + &quot;님께서 &quot; + i + &quot;방으로 초대하셨습니다.&quot;);
            p.println(&quot;수락 --&gt; /수락&quot;);
            p.println(&quot;거부 --&gt; /거부&quot;);

        }catch(Exception e) {

        }
    }


    //강퇴
    public void cutUser(String title, String name, PrintWriter out) {

        roomN.get(title).remove(name);
    }


    public static void main(String[] args) {

        try {
            //오라클과 연결(데이터 제공)
            Class.forName(&quot;oracle.jdbc.driver.OracleDriver&quot;);
        }catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
            System.out.println(&quot;오라클 실패&quot;);
        }

        try {
            con = DriverManager.getConnection(
                    &quot;jdbc:oracle:thin:@localhost:1521:xe&quot;, //localhost = 사용위치(현재는 내컴퓨터)
                    &quot;scott&quot;,
                    &quot;tiger&quot;);
        }catch(SQLException sqle) {System.out.println(&quot;두마이런 실패&quot;);}

        //서버객체 생성
        ChatServer2 ms = new ChatServer2();
        ms.init();

    }


////////////////////////////////////////////////////////////////////////////////////////////
/////////////대기방 --&gt; 방을 생성하거나 방에 입장할 수 있음
    class MultiServerR extends Thread
    {
        String sql1 = null;
        String sql = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        PreparedStatement pstmt3 = null;
        PreparedStatement pstmt4 = null;
        ResultSet rs = null;

        Socket socket;
        PrintWriter out = null;
        BufferedReader in = null;
        String name = &quot;&quot;;
        String title = null;

        //생성자
        public MultiServerR(Socket socket) {
            this.socket = socket;

            try {
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            }catch(Exception e) {

            }
        }

        //쓰레드를 사용하기 위해 run()메서드 재정의
        @Override
        public void run()
        {
            int type = 0;
            String s = &quot;&quot;;
            String id = null;            //아이디
            String pw = null;            //비밀번호
            int th = 0;
            Iterator&lt;String&gt; iter = null;
            String ss = &quot;&quot;;
            String key = null;
            String getMenu = &quot;&quot;;

            out.println(&quot;=============================================&quot;);
            out.println(&quot;==================대기실====================&quot;);
            out.println(&quot;=============================================&quot;);
            out.println();

            try {
                String pw1 = null;    //비밀번호 비교에 사용
                int ld =0;
                while(true) {

                    ld = 0;
                    out.println(&quot;관리자 로그인은 /adlogin을 입력해주세요&quot;);
                    out.println(&quot;=============================================&quot;);
                    out.println(&quot;메뉴를 선택하세요&quot;);
                    out.println(&quot;1. 로그인  2. 회원가입 3. 회원탈퇴&quot;);
                    out.println(&quot;=============================================&quot;);

                    try {
                        getMenu = in.readLine();

                    }catch (IOException e) {

                    }

                    if(getMenu.equals(&quot;/adlogin&quot;)) {
                        out.println(&quot;&lt;&lt;관리자 페이지입니다&gt;&gt; \n 비밀번호를 입력해주세요&quot;);
                        pw = in.readLine();
                        sql = &quot;select pw from chatuser where id = ?&quot;;
                        pstmt1 = con.prepareStatement(sql);
                        pstmt1.setString(1, &quot;head&quot;);
                        rs = pstmt1.executeQuery();

                        while(rs.next()){
                            pw1 = rs.getString(1);
                            if(pw.equals(pw1)) {
                                out.println(&quot;환영합니다 관리자님&quot;);
                                adlogin(in, out);
                            }else {
                                out.println(&quot;비밀번호가 틀렸습니다.&quot;);
                            }
                            break;
                        }
                    }
                    else {

                        type = Integer.parseInt(getMenu);
                        //로그인
                        if(type == 1) {    

                            int id1 = 0;
                            String id11 = null;

                            out.println(&quot;&lt;&lt;로그인&gt;&gt;&quot;);
                            out.println(&quot;id&quot;);
                            try {
                                id = in.readLine();

                                if(id.equals(&quot;back&quot;)) continue;
                                sql = &quot;select count(*) from chatuser where id = ?&quot;;
                                pstmt2 = con.prepareStatement(sql);
                                pstmt2.setString(1, id);
                                rs = pstmt2.executeQuery();
                                while(rs.next()) {
                                    id1 = Integer.parseInt(rs.getString(1));
                                }
                                if(id1 == 0) {
                                    out.println(&quot;존재하지 않는 아이디 입니다.&quot;);
                                    continue;
                                }

                                sql = &quot;select utype from chatuser where id = ?&quot;;
                                pstmt1 = con.prepareStatement(sql); 
                                pstmt1.setString(1, id);
                                rs = pstmt1.executeQuery();

                                while(rs.next()) {
                                    int utype = Integer.parseInt(rs.getString(1));
                                    if(utype == 1) {
                                        out.println(&quot;로그인이 금지된 아이디입니다.&quot;);
                                        ld = 1;
                                    }
                                }

                            }catch (IOException e1) {
                                e1.printStackTrace();
                            }
                            if(ld == 1) continue;    

                            id1 = 0;
                            Iterator&lt;String&gt; at = clientMap.keySet().iterator();
                            while(at.hasNext()) {
                                id11 = (String)at.next();
                                if(id.equals(id11)) {
                                    id1 = 1;
                                    break;
                                }
                            }
                            if(id1 == 1){
                                out.println(&quot;이미 활동중인 아이디입니다.&quot;);
                            }
                            else {
                                out.println(&quot;pw &quot;);
                                try {
                                    pw = in.readLine();
                                } catch (IOException e1) {

                                }


                                try {
                                    try {
                                        sql = &quot;select pw from chatuser where id = ?&quot;;
                                        pstmt1 = con.prepareStatement(sql); 
                                        pstmt1.setString(1, id);
                                        rs = pstmt1.executeQuery();

                                        while(rs.next()) {
                                            pw1 = rs.getString(1);
                                        }
                                    }catch(SQLException sqle) {

                                        System.out.println(&quot;sql문 오류&quot;);
                                    }

                                    if(pw.equals(pw1)) {
                                        clientMap.put(id, out);
                                        waitUser.put(id, out);
                                        out.println(&quot;로그인에 성공했습니다&quot;);
                                        Thread mst = new MultiServer2(socket,id,title);    //쓰레드 생성(대화방 입장 알림, 대화)
                                        th = 1;
                                        mst.start();
                                        mst.join();
                                        continue;
                                    }else {
                                        out.println(&quot;로그인에 실패했습니다&quot;);
                                    }
                                }finally {
                                    try {
                                        if(rs != null) rs.close();
                                        if(pstmt1 != null) pstmt1.close();
                                        if(pstmt2 != null) pstmt2.close();
                                    }catch(SQLException sqle){}
                                }
                            } 
                        }

                        //회원가입
                        else if(type == 2) {
                            try {
                                out.println(&quot;&lt;&lt;회원가입&gt;&gt;&quot;);
                                int id1 = 0;

                                while(true) {

                                    out.println(&quot;id: &quot;);
                                    id = in.readLine();        

                                    try {
                                        if(id.equals(&quot;back&quot;)) break;
                                        sql = &quot;select count(*) from chatuser where id = ?&quot;;
                                        pstmt2 = con.prepareStatement(sql);
                                        pstmt2.setString(1, id);
                                        rs = pstmt2.executeQuery();
                                        while(rs.next()) {
                                            id1 = Integer.parseInt(rs.getString(1));
                                        }
                                        if(id1 == 0) {
                                            out.println(&quot;pw: &quot;);
                                            pw = id = in.readLine();    
                                            sql = &quot;insert into chatuser(id, pw, utype) values(?, ?, 0)&quot;;
                                            pstmt3 = con.prepareStatement(sql); 
                                            pstmt3.setString(1, id);
                                            pstmt3.setString(2, pw);
                                            rs = pstmt3.executeQuery();

                                            //개인 금칙어 테이블 생성
                                            String strQuery = &quot;create table $tableName (wordd varchar(10) )&quot;;
                                            String query =strQuery.replace(&quot;$tableName&quot;,id);
                                            pstmt4 =con.prepareStatement(query);       
                                            rs = pstmt4.executeQuery();

                                            out.println(&quot;회원가입 되었습니다.&quot;);
                                            break;

                                        }else {
                                            out.println(&quot;이미 존재하는 아이디입니다.&quot;);
                                            break;
                                        }

                                    }catch(SQLException sqle) {
                                        sqle.printStackTrace();
                                    }finally {
                                        try {
                                            if(rs != null) rs.close();
                                            if(pstmt2 != null) pstmt2.close();
                                            if(pstmt3 != null) pstmt3.close();
                                        }catch(SQLException sqle){}

                                    }
                                }
                                //break;
                            } catch (IOException e) {                            

                            }
                        }
                        //회원탈퇴
                        else if(type == 3) {
                            int id1 = 0;
                            out.println(&quot;&lt;&lt;회원 탈퇴&gt;&gt;&quot;);
                            out.println(&quot;id: &quot;);
                            id = in.readLine();    

                            if(id.equals(&quot;back&quot;)) continue;

                            sql = &quot;select count(*) from chatuser where id = ?&quot;;
                            pstmt2 = con.prepareStatement(sql);
                            pstmt2.setString(1, id);
                            rs = pstmt2.executeQuery();
                            while(rs.next()) {
                                id1 = Integer.parseInt(rs.getString(1));
                            }
                            if(id1 == 0) {
                                out.println(&quot;존재하지 않는 아이디 입니다.&quot;);
                                continue;
                            }
                            out.println(&quot;pw: &quot;);
                            pw = in.readLine();    

                            sql = &quot;select pw from chatuser where id = ?&quot;;
                            pstmt1 = con.prepareStatement(sql); 
                            pstmt1.setString(1, id);
                            rs = pstmt1.executeQuery();

                            while(rs.next()) {
                                pw1 = rs.getString(1);
                            }

                            if(pw.equals(pw1)) {

                                out.println(&quot;정말 탈퇴하시겠습니까? Y/N&quot;);
                                String o = in.readLine();
                                if(o.equals(&quot;Y&quot;) || o.equals(&quot;y&quot;)) {
                                    sql = &quot;delete from chatuser where id = ?&quot;;
                                    pstmt3 = con.prepareStatement(sql); 
                                    pstmt3.setString(1, id);
                                    rs = pstmt3.executeQuery();


                                    sql = &quot;drop table &quot; + id;
                                    pstmt4 = con.prepareStatement(sql);

                                    rs = pstmt4.executeQuery();
                                    out.println(&quot;탈퇴되었습니다.&quot;);
                                    continue;
                                }
                            }
                        }
                    else {
                        System.out.println(&quot; 메뉴를 다시 선택하세요&quot;);
                    }            
                }
            }
            }catch(Exception e) {
                System.out.println(&quot;예외1:&quot; +e);
            }finally {
                //예외가 발생할때 퇴장. 해쉬맵에서 해당 데이터 제거.
                //보통 종료하거나 나가면 java.net.SocketException: 예외발생
                if(th == 0) {
                    clientMap.remove(name);
                    sendAllMsg(name + &quot;님이 퇴장하셨습니다.&quot;, &quot;&quot;);
                    System.out.println(&quot;00현재 접속자 수는 &quot; + clientMap.size()+&quot;명 입니다.&quot;);
                }

                try {
                    serverSocket.close();
                    in.close();
                    out.close();
                }catch(Exception e) {

                }
            }
        }

    }

////////////////////////////////////////////////////////////////////////////////////
///////로그인 이후 방입장 단계
    class MultiServer2 extends Thread
    {

        Socket socket;
        String title = null;
        PrintWriter out = null;
        BufferedReader in = null;
        String id = &quot;&quot;;
        String pw = null;

        //생성자
        public MultiServer2(Socket socket, String name, String title) {
            this.socket = socket;
            this.id = name;
            this.title = title;
            try {
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            }catch(Exception e) {

            }
        }

        //쓰레드를 사용하기 위해 run()메서드 재정의
        @Override
        public void run()
        {    
            String sql1 = null;
            String sql = null;
            PreparedStatement pstmt1 = null;
            PreparedStatement pstmt2 = null;
            PreparedStatement pstmt3 = null;
            PreparedStatement pstmt4 = null;
            ResultSet rs = null;

            Iterator&lt;String&gt; iter = null;
            String ss = &quot;&quot;;
            String menu = null;
            int count = 0;
            int th = 0;
            String type = null;

            try {


                System.out.println(&quot;==============================================&quot;);
                System.out.println(&quot;    &quot; + id + &quot;님이 입장하셨습니다.    &quot;);
                System.out.println(&quot;==============================================&quot;);

                System.out.println();
                System.out.println(&quot;==============================================&quot;);
                System.out.println(&quot;==============================================&quot;);
                System.out.println(&quot;    현재 전체 접속자 수는 &quot; +clientMap.size() + &quot;명 입니다.&quot;);
                System.out.println(&quot;==============================================&quot;);
                System.out.println(&quot;==============================================&quot;);
                System.out.println();

                while(true){


                    out.println(&quot;/* --&gt; 명령어 보기&quot;);
                    out.println(&quot;원하는 메뉴를 선택하세요\n&quot;
                                + &quot;1. 공개채팅방 만들기\n&quot;
                                + &quot;2. 비밀채팅방 만들기\n&quot;
                                + &quot;3. 전체 방 리스트 보기\n&quot;
                                + &quot;4. 채팅방 입장하기\n&quot;
                                + &quot;5. 로그아웃&quot;);
                    menu = in.readLine();
                    type = menu;


                    if(menu.startsWith(&quot;/&quot;)) {
                        if(menu.equals(&quot;/*&quot;)) {
                            iter = listw.keySet().iterator();
                            out.println(&quot;&lt;&lt;명령어&gt;&gt;&quot;);
                            while(iter.hasNext()) {
                                String key = iter.next();
                                out.println(&quot;&gt;&gt; &quot; + key + &quot; :        &quot; + listw.get(key));
                            }
                            out.println(&quot;&gt;&gt; /userlist :        방 참여자 리스트&quot;);


                        }
                        else if(menu.equals(&quot;/수락&quot;)) {
                            title = inviteM.get(id);
                            try {

                                if(id.equals(&quot;&quot;))
                                    sendMsg(&quot;수락하셨습니다&quot;, id, title);
                                else 
                                    sendMsg(&quot;수락&quot;,id, title);
                                Thread mst = new MultiServerT(socket, id, title);    //쓰레드 생성(대화방 입장 알림, 대화)
                                mst.start();
                                mst.join();    
                                //continue;

                            }catch(Exception e) {

                            }
                        }else if(menu.equals(&quot;/거부&quot;)) {
                            try {
                                title = inviteM.get(id);
                                inviteM.remove(id);

                                if(id.equals(&quot;&quot;))
                                    sendMsg(&quot;거부하셨습니다&quot;, id, title);            //받은 메세지 각 방에 출력
                                else
                                    sendMsg(&quot;거부&quot;, id, title);

                            }catch(Exception e) {

                            }

                        }
                        else if(menu.equals(&quot;/list&quot;)) {
                            list(out);

                        }

                        //방리스트
                        else if(menu.equals(&quot;/rlist&quot;)){
                            roomList(out);

                        }
                        //대기실 사용자 리스트
                        else if(menu.equals(&quot;/waituser&quot;)) {
                            waitU(out);
                        }

                        //금칙어 추가
                        else if(menu.equals(&quot;/adword&quot;)) {
                            out.println(&quot;&lt;&lt;금칙어 추가&gt;&gt;&quot;);
                            out.println(&quot;금칙어 : &quot;);
                            ss = in.readLine();
                            sql = &quot;insert into $tableName values (?)&quot;;
                            String query =sql.replace(&quot;$tableName&quot;,id);
                            pstmt1 = con.prepareStatement(query); 
                            pstmt1.setString(1, ss);
                            rs = pstmt1.executeQuery();
                            out.println(&quot;\&#39;&quot; + ss + &quot;\&#39;가 금칙어로 추가되었습니다. &quot;);

                        }

                        //금칙어 삭제
                        else if(menu.equals(&quot;/delword&quot;)) {
                            sql = &quot;select * from $tableName&quot;;
                            String query = sql.replace(&quot;$tableName&quot;, id);
                            pstmt2 = con.prepareStatement(query);
                            rs = pstmt2.executeQuery();
                            while(rs.next()) {
                                out.println(&quot;&gt; &quot; + rs.getString(1));
                            }

                            out.println(&quot;삭제할 금칙어 : &quot;);
                            ss = in.readLine();
                            sql = &quot;delete from $tableName where wordd = ?&quot;;
                            String query1 =sql.replace(&quot;$tableName&quot;,id);
                            pstmt3 = con.prepareStatement(query1); 
                            pstmt3.setString(1, ss);
                            rs = pstmt3.executeQuery();
                            out.println(&quot;금칙어가 삭제되었습니다.&quot;);

                        }

                        else if(menu.equals(&quot;/userlist&quot;)) {
                            userR(title, out);
                        }
                    }

                        //1번 선택시 방추가

                    else if(type.equals(&quot;1&quot;)) {

                        out.println(&quot; 공개방을 생성합니다&quot;);
                        out.println(&quot;========================&quot;);
                            out.println(&quot;방이름을 설정해 주세요: &quot;);
                            title = in.readLine();

                            out.println(&quot;방의 정원을 설정하세요: &quot;);
                            count = Integer.parseInt(in.readLine());

                            //방을 저장해둔 해시맵에 참여자 해시맵 추가
                            roomN.put(title, new HashMap&lt;String, PrintWriter&gt;(count));
                            capa.put(title, count);
                            waitUser.remove(id);

                            th = 1;
                            Thread mst = new MultiServerT(socket, id, title);    //쓰레드 생성(대화방 입장 알림, 대화)
                            mst.start();
                            mst.join();


                        }

                        //2번 선택시 비밀방추가
                        else if(type.equals(&quot;2&quot;)) {


                            out.println(&quot;  비밀방을 생성합니다&quot;);
                            out.println(&quot;========================&quot;);
                            out.println(&quot;방이름을 설정해 주세요: &quot;);
                            title = in.readLine();

                            out.println(&quot;방의 정원을 설정하세요: &quot;);
                            count = Integer.parseInt(in.readLine());


                            out.println(&quot;비밀번호를 입력하세요: &quot;);
                            pw = in.readLine();

                            //방을 저장해둔 해시맵에 참여자 해시맵 추가
                            roomN.put(title, new HashMap&lt;String, PrintWriter&gt;(count));
                            capa.put(title, count);
                            pwd.put(title, pw);
                            waitUser.remove(id);

                            th = 1;
                            Thread mst = new MultiServerT(socket, id, title);    //쓰레드 생성(대화방 입장 알림, 대화)
                            mst.start();
                            mst.join();


                        }

                        //3번 선택시 전체 방 리스트
                        else if(type.equals(&quot;3&quot;)) {
                            roomList(out);
                        }

                        //4번 선택시 선택한 채팅방 입장하기
                        else if(type.equals(&quot;4&quot;)) {
                                menu = null;
                                out.println(&quot;입장을 원하는 방 이름을 입력해 주세요: &quot;);
                                title = in.readLine();
                                out.println();

                                //입력한 방이름 없음
                                if(!(roomN.containsKey(title))) {
                                    out.println(&quot;존재하지 않는 방입니다.&quot;);
                                }

                                ////////정원초과 구현 안됨~~~~~~~~~~~~!!!!!!!!!!!!!!!!
                                else if(roomN.get(title).size() == capa.get(title)) {
                                    out.println(&quot;정원초과로 입장하실 수 없습니다.&quot;);
                                }             

                                //비밀방 입장
                                else if(pwd.containsKey(title)) {

                                    out.println(&quot;비밀번호를 입력해주세요: &quot;);
                                    pw = in.readLine();

                                    //비밀번호 맞음
                                    if(pwd.get(title).equals(pw)) {
                                        //roomN.get(title).put(name, out);
                                        System.out.println(&quot;\&#39;&quot; + title + &quot;\&#39; 방에 입장하셨습니다.&quot;);


                                        Thread mst = new MultiServerT(socket, id, title);    //쓰레드 생성(대화방 입장 알림, 대화)
                                        th = 1;
                                        waitUser.remove(id);
                                        mst.start();
                                        mst.join();

                                        //비밀번호 틀림
                                    }else {
                                            out.println(&quot;비밀번호가 틀렸습니다&quot;);
                                    }

                                //일반방 입장
                                }else {
                                    //roomN.get(title).put(name, out);


                                    Thread mst = new MultiServerT(socket, id, title);    //쓰레드 생성(대화방 입장 알림, 대화)
                                    th = 1;
                                    waitUser.remove(id);
                                    mst.start();
                                    mst.join();

                                }
                        }else if(type.equals(&quot;5&quot;)) {
                            clientMap.remove(id);
                            out.println(&quot;로그아웃 되었습니다.&quot;);
                            out.println();
                            break;
                        }

                }    
            }catch(Exception e) {


            }finally {
                //예외가 발생할때 퇴장. 해쉬맵에서 해당 데이터 제거.
                //보통 종료하거나 나가면 java.net.SocketException: 예외발생
                if(th == 0) {
                    roomN.get(title).remove(id);
                    sendMsg(id + &quot;님이 퇴장하셨습니다.&quot;, &quot;&quot;, title);
                    System.out.println(&quot;현재 접속자 수는 &quot; + roomN.get(title).size()+&quot;명 입니다.&quot;);
                }try {}
                catch(Exception e) {
                    out.println(&quot;방입장 문제&quot;);
                }
            }
        }
    }



/////////////////////////////////////////////////////////////////////////////////////
////////////////내부클래스
////////////////클라이언트로부터 읽어온 메시지를 다른 클라이언트(socket)에 보내는 역할을 하는 메서드

    class MultiServerT extends Thread
    {
        Socket socket;
        String title = null;
        PrintWriter out = null;
        BufferedReader in = null;
        String name = &quot;&quot;;

        //생성자
        public MultiServerT(Socket socket, String name, String title) {
            this.socket = socket;
            this.title = title;
            this.name = name;
            try {
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            }catch(Exception e) {

            }

        }

        //쓰레드를 사용하기 위해 run()메서드 재정의
        @Override
        public void run()
        {
            int th = 0;
            roomN.get(title).put(name, out);
            String s = &quot;&quot;;
            String sss = &quot;&quot;;

            String ss;
            String sql;
            PreparedStatement pstmt1;
            ResultSet rs;

            try {

                //현재 객체가 가지고 있는 소켓을 제외하고 다른 소켓(클라이언트)들에게
                //접속을 알림.
                //sendAllMsg(&quot;!!!!&quot; + name + &quot;님이 입장하셨습니다. !!!!&quot;, &quot;&quot;);

                sendMsg(&quot;------&quot; + name + &quot;님이 입장하셨습니다------&quot;, &quot;&quot;, title);

                out.println(&quot;\&#39;&quot; + title + &quot;\&#39; 방에 입장하셨습니다.&quot;);
                out.println();
                out.println(&quot;\&#39;&quot; + title + &quot;\&#39;방의 정원은 &quot; + capa.get(title) + &quot;명 입니다.&quot;);
                out.println(&quot;\&#39;&quot; + title + &quot;\&#39;방의 현재 접속자 수는 &quot; +roomN.get(title).size() + &quot;명 입니다.&quot;);
                out.println(&quot;퇴장을 원하시면 /나가기,  /퇴장을 입력해주세요&quot;);
                out.println(&quot;명령어 목록을 원하시면 /*를 입력해 주세요&quot;);

                //입력 스트림이 null이 아니면 반복
                while(in != null) {

                    s = in.readLine();
                    //방빠져나가야함
                    //방폭파
                    if(!roomN.keySet().contains(title)) {
                        waitUser.put(name, out);
                        out.println(&quot;퇴장.&quot;);
                        th = 1;
                        break;
                    }
                    //강퇴
                    if(!roomN.get(title).keySet().contains(name)) {
                        waitUser.put(name, out);
                        out.println(&quot;퇴장.&quot;);
                        th = 1;
                        break;
                    }
                    else {

                        if(s.startsWith(&quot;/&quot;)) {
                            String s2 = null;
                            String n = null;
                            String[] s1 = s.split(&quot; &quot;);
                            if(s1.length &gt; 1) {
                                s2 = s1[0];

                                //귓속말 명령어
                                if(s2.equals(&quot;/to&quot;)) {
                                    n = s1[1];
                                    out.println(n + &quot;에게 귓속말&gt;&gt;&quot;);
                                    while(in != null) {
                                        sss = in.readLine();
                                        if(sss.equals(&quot;//stop&quot;)) {
                                            break;
                                        }else {
                                            secretMsg(sss, name, n, title); 
                                        }
                                    }
                                    continue;
                                }
                                //강퇴기능
                                else if(s2.equals(&quot;/강퇴&quot;)) {
                                    for(int j = 1; j &lt; s1.length; j++) {
                                        n = s1[j];
                                        roomN.get(title).remove(n);
                                    }
                                    continue;
                                }
                                //초대
                                else if(s2.equals(&quot;/초대&quot;)) {
                                    n = s1[1];
                                    invite(name, n, title);
                                }
                            }


                            //명령어 리스트
                            else if(s.equals(&quot;/*&quot;)) {
                                Iterator&lt;String&gt; iter = listw.keySet().iterator();
                                out.println(&quot;&lt;&lt;명령어&gt;&gt;&quot;);
                                while(iter.hasNext()) {
                                    String key = iter.next();
                                    out.println(&quot;&gt;&gt; &quot; + key + &quot; :        &quot; + listw.get(key));
                                }
                                out.println(&quot;&gt;&gt; /userlist :        방 참여자 리스트&quot;);
                                out.println(&quot;&gt;&gt; /to 사용자이름:    귓속말&quot;);
                                out.println(&quot;&gt;&gt; /초대 사용자이름:사용자 초대하기&quot;);
                                out.println(&quot;&gt;&gt; /강퇴 사용자아이디:        강퇴기능&quot;);

                            }

                            else if(s.equals(&quot;/list&quot;)) {
                                list(out);

                            }

                            //방리스트
                            else if(s.equals(&quot;/rlist&quot;)){
                                roomList(out);

                            }
                            //대기실 사용자 리스트
                            else if(s.equals(&quot;/waituser&quot;)) {
                                waitU(out);

                            }

                            //금칙어 추가
                            else if(s.equals(&quot;/adword&quot;)) {
                                out.println(&quot;&lt;&lt;금칙어 추가&gt;&gt;&quot;);
                                out.println(&quot;금칙어 : &quot;);
                                ss = in.readLine();
                                sql = &quot;insert into $tableName values (?)&quot;;
                                String query =sql.replace(&quot;$tableName&quot;,name);
                                pstmt1 = con.prepareStatement(query); 
                                pstmt1.setString(1, ss);
                                rs = pstmt1.executeQuery();
                                out.println(&quot;\&#39;&quot; + ss + &quot;\&#39;가 금칙어로 추가되었습니다. &quot;);

                            }

                            //금칙어 삭제
                            else if(s.equals(&quot;/delword&quot;)) {
                                sql = &quot;select * from $tableName&quot;;
                                String query = sql.replace(&quot;$tableName&quot;, name);
                                PreparedStatement pstmt2 = con.prepareStatement(query);
                                rs = pstmt2.executeQuery();
                                while(rs.next()) {
                                    out.println(&quot;&gt; &quot; + rs.getString(1));
                                }

                                out.println(&quot;삭제할 금칙어 : &quot;);
                                ss = in.readLine();
                                sql = &quot;delete from $tableName where wordd = ?&quot;;
                                String query1 =sql.replace(&quot;$tableName&quot;,name);
                                pstmt1 = con.prepareStatement(query1); 
                                pstmt1.setString(1, ss);
                                rs = pstmt1.executeQuery();
                                out.println(&quot;금칙어가 삭제되었습니다.&quot;);

                            }
                            else if(s.equals(&quot;/userlist&quot;)) {
                                userR(title, out);

                            }

                            else if(s.equals(&quot;/나가기&quot;)|| s.equals(&quot;/퇴장&quot;)) {
                                roomN.get(title).remove(name);
                                waitUser.put(name, out);
                                if(roomN.get(title).isEmpty()) {
                                    roomN.remove(title);
                                }
                                th = 1;
                                break;
                            }else {
                                out.println(&quot;올바르지 않은 명령어 입니다.&quot;);
                            }


                        }
                        else {
                            //sendAllMsg(s, title);
                            sendMsg(s, name, title);

                        }    
                    }

                }


            }catch(Exception e) {


            }finally {
                //예외가 발생할때 퇴장. 해쉬맵에서 해당 데이터 제거.
                //보통 종료하거나 나가면 java.net.SocketException: 예외발생
                if(th != 1) {
                    roomN.get(title).remove(name);
                }
                if(!roomN.get(title).isEmpty())
                    sendMsg(name + &quot;님이 퇴장하셨습니다.&quot;, &quot;&quot;, title);            
                try {
                }catch(Exception e) {

                }
            }

        }
    }
}</code></pre>
<ol start="2">
<li>클라이언트 코드</li>
</ol>
<pre><code>import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ChatClient
{
    public static void main(String[] args) throws UnknownHostException, IOException
    {
        try
        {
            String ServerIP = &quot;localhost&quot;;
            if (args.length &gt; 0)
                ServerIP = args[0];
            Socket socket = new Socket(ServerIP, 9990); // 소켓 객체 생성
            System.out.println(&quot;서버와 연결이 되었습니다....&quot;);

            // 서버에서 보내는 메시지를 사용자의 콘솔에 출력하는 쓰레드.
            Thread receiver = new Receiver(socket);
            receiver.start();

            // 사용자로부터 얻은 문자열을 서버로 전송해주는 역할을 하는 쓰레드
            Thread sender = new Sender(socket);
            sender.start();

        } catch (Exception e)
        {
            System.out.println(&quot;예외[MultiClient class]:&quot; + e);
        }
        // }
    }
}</code></pre><ol start="3">
<li>Receiver 코드<pre><code class="language-java">import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
</code></pre>
</li>
</ol>
<p>public class Receiver extends Thread{</p>
<pre><code>Socket socket;
BufferedReader in = null;

//Socket을 매개변수로 받는 생성자
public Receiver(Socket socket)
{
    this.socket = socket;

    try {
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }catch(Exception e) {
        System.out.println(&quot;예외1: &quot; + e);
    }
}

//run() 메소드 재정의
@Override
public void run() {
    while(in != null) {
        try {
            System.out.println(in.readLine());
        }catch(java.net.SocketException ne) {
            //여기서 while문을 멈춰 주어야 한다.
            break;
        }        
        catch(Exception e) {
            System.out.println(&quot;예외3:&quot;+e);
        }
    }

    try {
        in.close();
    }catch (Exception e) {
        System.out.println(&quot;예외3:&quot; + e);
    }
}</code></pre><p>}</p>
<pre><code>
4. Sender 코드
```java
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class Sender extends Thread
{
    Socket socket;
    PrintWriter out = null;
    String name;

    //생성자
    public Sender(Socket socket)
    {
        this.socket = socket;
        try {
            out = new PrintWriter(this.socket.getOutputStream(), true);

        }catch(Exception e) {
            System.out.println(&quot;예외S3: &quot; + e);
        }
    }

    //run()메소드 재정의
    @Override
    public void run() {

        Scanner sc = new Scanner(System.in);

        try {
            //입력한 사용자이름을 서버에 보내준다
            //out.println(name);

            while(out != null)
            {
                try {
                    String s = sc.nextLine();
                    out.println(s);

                    if(s.equals(&quot;q&quot;) || s.equals(&quot;Q&quot;)){
                        break;
                    }
                }catch(Exception e) {
                    System.out.println(&quot;예외S1:&quot; + e);
                }
            }

            out.close();

            socket.close();
        }catch(Exception e) {
            System.out.println(&quot;예외S2: &quot; + e);
        }
        sc.close();
    }

}</code></pre><blockquote>
<p>이렇게 쓰레드까지 java 정식 교육은 모두 마치게 되었다.
  그동안 짧았다면 짧았고 길었다면 긴 과정동안 포스팅을 봐주신 분들께
  감사를 보내며 다음 포스팅부터는 java가 아닌 새로운 프로그래밍 언어로
  찾아뵙겠다! </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[velog] 벨로그 글쓰기 양식⭐]]></title>
            <link>https://velog.io/@kama_code/velog-%EB%B2%A8%EB%A1%9C%EA%B7%B8-%EA%B8%80%EC%93%B0%EA%B8%B0-%EC%96%91%EC%8B%9D</link>
            <guid>https://velog.io/@kama_code/velog-%EB%B2%A8%EB%A1%9C%EA%B7%B8-%EA%B8%80%EC%93%B0%EA%B8%B0-%EC%96%91%EC%8B%9D</guid>
            <pubDate>Fri, 28 Jul 2023 19:34:53 GMT</pubDate>
            <description><![CDATA[<h2 id="마크다운이란">마크다운이란?</h2>
<blockquote>
<ol>
<li>온갖 태그로 범벅된 HTML 문서 등과 달리, 읽기도 쓰기도 쉬운 문서 양식을 지향한다. </li>
<li>흔히 볼 수 있는 문서(파일명)은 &quot;README.md&quot;, 파일의 확장자는 .md 또는 .markdown을 쓴다.</li>
</ol>
</blockquote>
<ul>
<li><p>글자크기 : #으로 크기를 키운다.</p>
<pre><code># 가장 큰 크기의 제목 (h1)
###### 가장 작은 크기의 제목 (h6)</code></pre></li>
<li><p>앞에 불릿은 +을 붙인 후 작성한다..</p>
</li>
<li><p>인용하고 싶을 때는 맨 앞에 &gt; 기호를 쓴다.</p>
</li>
<li><p>이미지 크기조절</p>
<pre><code>&lt;img src = &quot;이미지주소.PNG&quot; width = &quot;60%&quot; height = &quot;60%&quot;&gt;</code></pre></li>
<li><p>코드 블럭 : Tab 두번
```python : 언어이름을 소문자로 작성
여기에 코드작성 
}
```</p>
</li>
<li><p>인라인 박스 
`라인 박스`</p>
</li>
<li><p>가로선 넣기
-----</p>
</li>
<li><p>\ 역슬래쉬 : 그대로 출력하기를 원한다면 를 넣으면 된다.</p>
</li>
<li><p>표 그리기
수직선 기호(|)로 열을 구분할 수 있다
하이픈 기호(-)를 여러 개 붙여서 th와 tr을 구분할 수 있다.
콜론 기호(:)로 정렬을 표현할 수 있다.
왼쪽 정렬 |:—|
오른쪽 정렬 |—:|
가운데 정렬 |:—:|</p>
</li>
<li><p>이모티콘
<a href="https://kr.piliapp.com/twitter-symbols/">https://kr.piliapp.com/twitter-symbols/</a>
windows: 윈도우 키 + 마침표(.)</p>
</li>
<li><p>체크박스
- [ ] 체크되지 않은 박스
- [x] 체크된 박스</p>
</li>
<li><p>줄바꿈
&lt;\br/&gt;</p>
</li>
<li><p>폰트 스타일
~<del>취소선</del>
**굵게**
*기울여 쓰기*</p>
</li>
<li><p>폰트 색상
&lt;\span style=&quot;color:red&quot;&gt;red</span>
&lt;\span style=&quot;color:#d3d3d3&quot;&gt;#d3d3d3</span>
&lt;\span style=&quot;color:rgb(245, 235, 13)&quot;&gt;rgb(245, 235, 13)</span></p>
</li>
<li><p>형광펜
&lt;\span style=&#39;background-color: yellow&#39;&gt;내용 </span></p>
</li>
<li><p>밑줄
&lt;\u&gt;밑줄 있는 텍스트입니다&lt;/u&gt;</p>
</li>
<li><p>내용을 접고 숨기기</p>
<pre><code>&lt;details&gt;
&lt;summary&gt;여기를 눌러주세요&lt;/summary&gt;
&lt;div markdown=&quot;1&quot;&gt;       
😎숨겨진 내용😎
</code></pre></li>
</ul>
</div>
</details>
```

<ul>
<li>버튼
Default Button](#){: .btn .btn--primary }
&lt;\a href=&quot;#&quot; class=&quot;btn--success&quot;&gt;Success Button</a></li>
</ul>
<blockquote>
<p><a href="https://drive.google.com/file/d/1mw6nucadMSuM85eNnF4wT-EwVooRfWiq/view?usp=sharing">벨로그 단축키 프로그램 다운로드</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.14] 람다식(Lambda)과 입출력 스트림(I/O Stream)]]></title>
            <link>https://velog.io/@kama_code/JAVA.14-%EB%9E%8C%EB%8B%A4%EC%8B%9DLambda%EA%B3%BC-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%8A%A4%ED%8A%B8%EB%A6%BCIO-Stream</link>
            <guid>https://velog.io/@kama_code/JAVA.14-%EB%9E%8C%EB%8B%A4%EC%8B%9DLambda%EA%B3%BC-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%8A%A4%ED%8A%B8%EB%A6%BCIO-Stream</guid>
            <pubDate>Wed, 26 Jul 2023 16:27:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>드디어 자바(JAVA) 공부에서 정식 교육의 끝이 보인다..
그동안 자바(JAVA)를 사용하다보면 객체 지향 프로그래밍에서 메소드를 선언하기 위해 
반드시 클래스를 정의해야 되고 다른 언어에 비해 써야 하는 식의 절차도 너무 많고
따져야 하는 게 너무 많아서 복잡해보임을 느끼는 경우가 많다 
그래서 자바(JAVA)가 도입한 것이 람다식이다.</li>
</ul>
</blockquote>
<h3 id="step1-람다식-lambda-expression">&lt;Step.1&gt; 람다식 (lambda expression)</h3>
<blockquote>
<ul>
<li>메소드를 간단한 식으로 표현하여 함수형 프로그래밍에 적합한 문법</li>
</ul>
</blockquote>
<ul>
<li>객체화보다 기능 하나가 필요한 상황에서 주로 사용한다.</li>
<li>입력 받은 자료를 기반으로 수행되고 외부에 영향을 미치지 않으므로 병렬처리등에 가능
안정적인 확장성 있는 프로그래밍 방식</li>
<li>클래스를 생성하지 않고 함수의 호출만으로 기능을 수행</li>
</ul>
<h3 id="step2-람다식-문법lambda-grammar">&lt;Step.2&gt; 람다식 문법(lambda grammar)</h3>
<blockquote>
<p>(매개변수목록) -&gt; { 함수몸체 }</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/7aa2d8c8-f9c2-49e1-88b4-79fe23620181/image.PNG" width = "90%" height = "90%">

<ol>
<li><p>매개변수가 하나인 경우 자료형과 소괄호를 생략할 수 있다.</p>
</li>
<li><p>중괄호 안의 구현부가 한 문장인 경우 중괄호를 생략할 수 있다.</p>
</li>
<li><p>메소드 몸체가 둘 이상의 문장으로 이뤄져있거나, 매개변수의 수가 둘 이상인 경우에는
ㄴ각각 중괄호와 소괄호의 생략이 불가능하다</p>
</li>
<li><p>중괄호 안의 구현부가 한 문장이라도 return 문이 있다면 중괄호를 생략할 수 없다.</p>
</li>
<li><p>메소드 몸체에 해당하는 내용이 return 문이면 그 문장이 하나이더라도 중괄호 생략이 불가능하다.</p>
</li>
<li><p>Unit10 unit = () -&gt; { // 매개변수 없으면 &#39;()&#39; 생략 불가능</p>
</li>
<li><p>중괄호 안의 구현부가 반환문 하나라면 return 과 중괄호 모두 생략할 수 있다.</p>
</li>
</ol>
<h3 id="step3-함수형-인터페이스functional-interface">&lt;Step.3&gt; 함수형 인터페이스(functional interface)</h3>
<blockquote>
<p>@FunctionalInterface
함수형 인터페이스라는 의미, 여러 개의 메소드를 선언하면 에러남</p>
</blockquote>
<ul>
<li>람다식을 사용하기 위해서 먼저 인터페이스를 만들고 
람다식으로 구현할 추상메소드를 선언합니다.</li>
<li>익명 함수와 매개 변수만으로 구현되므로 단 하나의 메소드만을 가져야 함
ㄴ두 개 이상의 메소드인 경우 어떤 메소드의 호출인지 모호해 짐</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/2df16adc-4c29-4ace-8f14-121569bc7382/image.PNG" width = "60%" height = "60%">

<pre><code class="language-c">@FunctionalInterface

interface Calc { // 함수형 인터페이스의 선언

    public int min(int x, int y);

}

public class Lambda02 {
public static void main(String[] args){
        Calc minNum = (x, y) -&gt; x &lt; y ? x : y; // 추상 메소드의 구현
        System.out.println(minNum.min(3, 4));  // 함수형 인터페이스의 사용
    }
}</code></pre>
<p>▣ 미리 정의된 함수형 인터페이스</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/3fa31606-bd07-420f-bff2-b06817bb00e0/image.PNG" width = "90%" height = "90%">

<img src = "https://velog.velcdn.com/images/kama_code/post/d1541a27-0462-496d-9f26-3d58c7b2b8c5/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/6d0aa34a-eb28-4abb-b3ec-aa566b8e6a54/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/0f2fe208-503e-41ea-b933-6c0552e254d1/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/ebccdae9-3b2b-4c83-97b8-90317b0e4c3d/image.PNG" width = "70%" height = "70%">

<h3 id="step4-메소드-참조">&lt;Step.4&gt; 메소드 참조</h3>
<ul>
<li>메소드 참조(method reference)??
ㄴ메소드 참조(method reference)는 람다 표현식이 단 하나의 메소드만을 호출하는 경우에 해당 람다 표현식에서 불필요한 매개변수를 제거하고 사용할 수 있도록 해줍니다.</li>
</ul>
<p>▣ 문법:
클래스이름::메소드이름
또는
참조변수이름::메소드이름</p>
<blockquote>
<p>MyClass obj = new MyClass;
Function&lt;String, Boolean&gt; func = (a) -&gt; obj.equals(a); // 람다 표현식
Function&lt;String, Boolean&gt; func = obj::equals(a);       // 메소드 참조</p>
</blockquote>
<h3 id="step5-스트림stream">&lt;Step.5&gt; 스트림(Stream)</h3>
<ul>
<li>스트림(Stream)이란?
ㄴ데이터의 흐름을 가리켜 (스트림) 이라고 한다.</li>
</ul>
<blockquote>
<ul>
<li>입력스트림(Input Stream) : 프로그램으로 부터 데이터를 읽어들이는 스트림</li>
</ul>
</blockquote>
<ul>
<li><p>출력스트림(Output Stream) : 프로그램으로 부터 데이터를 내보내는 스트림</p>
</li>
<li><p>스트림의 특징</p>
<blockquote>
<ol>
<li>스트림 연산은 기존 자료를 변경하지 않는다.</li>
<li>스트림 연산은 중간 연산과 최종 연산으로 구분된다.</li>
<li>한 번 생성하고 사용한 스트림은 재사용 할 수 없다.</li>
</ol>
</blockquote>
</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/acd34ce9-bc77-4302-a561-398331733ec7/image.PNG" width = "60%" height = "60%">

<ul>
<li><p>sort() 중간 연산은 스트림을 구성하는 데이터를 조건에 따라 정렬하는 연산을  한다.</p>
</li>
<li><p>map() 중간 연산은 스트림을 구성하는 데이터를 조건에 따라 변환하는 연산을 한다.</p>
</li>
<li><p>reduce() : 정의된 연산이 아닌 프로그래머가 직접 구현한 연산
최종 연산으로 스트림의 요소를 소모하여 연산을 수행한다
최종 연산이기에 1회만 사용 가능하다</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/317d7498-c04f-4eab-97fd-56c003525362/image.PNG" width = "70%" height = "70%">


</li>
</ul>
<pre><code class="language-c">        // 합
        int sum = IntStream.of(1, 3, 5, 7, 9) // 1회만 사용이 가능하므로 계속 선언
                            .sum();
        System.out.println(&quot;sum = &quot; + sum);

        // 개수
        long cnt = IntStream.of(1, 3, 5, 7, 9)
                            .count();
        System.out.println(&quot;count = &quot; + cnt);

        // 평균
        IntStream.of(1, 3, 5, 7, 9)
                .average() // 자동 double 형 변환
                .ifPresent(avg -&gt; System.out.println(&quot;avg = &quot; + avg));
                    // ifPresent =&gt; 값이 존재하면 실행할 것

        // 최소
        IntStream.of(1, 3, 5, 7, 9)
                .min()
                .ifPresent(min -&gt; System.out.println(&quot;min = &quot; + min));

        // 최대
        IntStream.of(1, 3, 5, 7, 9)
                .max()
                .ifPresent(max -&gt; System.out.println(&quot;max = &quot; + max));</code></pre>
<p>※ 파이프라인 구성
Stream 인터페이스가 제공하는 메소드는 대부분 반환 타입이 Stream 이므로 
메소드를 연속적으로 호출할 수 있다.
따라서 스트림 연산을 연결해 파이프라인으로 구성할 수 있다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ffbfad15-b0ab-4a8f-86ed-4a70d47360ad/image.PNG" width = "40%" height = "40%">

<p>스트림을 사용하면 컬렉션을 사용한 것보다 코드가 간결하고, 쉽게 의미를 알 수 있다.  배열에서 홀수만 골라내서 정렬하여 출력하는 코드</p>
<h3 id="step6-입출력-필터-스트림io-filter-stream">&lt;Step.6&gt; 입출력 필터 스트림(I/O filter Stream)</h3>
<img src = "https://velog.velcdn.com/images/kama_code/post/f3c500c9-4127-4910-b4e0-04e3a20736e9/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/b1b863e1-00c4-4a1a-8470-0d6f5ac3f17e/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/16df7c5e-d6cd-42cd-8482-e37b8f7016df/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/6c92ced6-d8a4-4ac3-a92e-e325823cd24e/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/6f57a880-8500-45d6-9331-0dc344e5307b/image.PNG" width = "60%" height = "60%">


<p>◈ 바이트스트림
 데이터를 있는 그대로 송수신한다.
 바이트 스트림을 이용해서 문자를 파일에 저장하는것이 가능하다.
 단, 자바가 아닌 Windows, Linux에서 읽을때 문제가 발생한다.
 입출력 스트림이 필요한 대부분의 프로그램에서 바이트 스트림을 사용한다. </p>
 <img src = "https://velog.velcdn.com/images/kama_code/post/5150f55c-f624-4033-8a87-eaa960116238/image.PNG" width = "90%" height = "90%">

<p> ◈ 문자스트림
 2바이트의 유니코드를 입출력 할 수 있는 문자기반의 스트림이다.
해당 운영체제에 따른 인코딩방식을 지원한다. 
 따라서 자바에서 생성된 파일을 Windows, Linux에서 읽을수 있다.
대부분의 문자스트림은 바이트스트림과 1대 1의 대응을 이룬다.</p>
 <img src = "https://velog.velcdn.com/images/kama_code/post/c273ed99-a76f-458d-9535-c491d9beac50/image.PNG" width = "90%" height = "90%">

<p>▶ Fileinputstream -&gt; 한글이 깨진다.
ㄴ1바이트씩 읽기 때문이다. (한글은 2바이트)</p>
<blockquote>
<ul>
<li>해결방법- FileReader나 FileWriter 클래스를 사용하면 2바이트씩 읽기에
한글이 깨지지 않는다 (예시: UTF-8)</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/798d086e-4512-4f61-a2e5-dd62de642c80/image.PNG" width = "70%" height = "70%">

<p>▶ Buffer : 보조스트림 : 좀 더 편하고 빨라진다.
ㄴBuffered(Input/Output)Stream : 1바이트 기반의 버퍼 입출력 스트림이다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/d344daa8-52c3-4a30-9a06-5d7a6dd1e324/image.PNG" width = "80%" height = "80%">

<blockquote>
<ul>
<li>BufferedReader나 BufferedWriter는 문자 기반 버퍼 입출력 스트림이며
데이터를 모아서 전송하기에 반드시 ★★★ throw IOException 예외처리가 필수이다.</li>
</ul>
</blockquote>
<blockquote>
<p>☆ public String readLine() throws IOException
-&gt; 문자열을 반환, 반환할 문자열이 없으면 null
ㄴBufferedReader 메소드이다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/67530a4a-a8ba-4177-b7ac-cde4335d215e/image.PNG" width = "70%" height = "70%">

<blockquote>
<p>★ public void write(String s, int off, int len) throws IOException
-&gt; 문자열 s를 인덱스 off부터 len개의 문자까지 저장한다.
ㄴBufferedWriter 메소드이다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/3709c9bc-a760-4ee0-8067-e9b71a4cb641/image.PNG" width = "70%" height = "70%">

<ul>
<li>개행 줄바꿈은 newLine()을 쓴다.</li>
</ul>
<h3 id="step7-스트림을-통한-객체의-저장">&lt;Step.7&gt; 스트림을 통한 객체의 저장</h3>
<p>＃ 직렬화(Serialization)란 객체가 파일의 형태로 저장되는 것을 
&#39;직렬화&#39; 라고 한다.</p>
<blockquote>
<ul>
<li>직렬화를 하는 이유
우리가 컴퓨터로 작업할 때 zip 파일을 사용하는 것과 비슷하다고 볼 수 있다. 
그냥 폴더자체는 이메일에 첨부하거나 온라인에 업로드하는 게 쉽지 않다. 
파일이 깨지는 경우도 있다. 하지만 zip 파일을 사용하면 안전하게 파일을 첨부하거나 업로드할 수 있다. 필요할 때 가져다쓰는 것도 쉽다.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>객체 직렬화 serialization ; 객체의 데이터(필드값)를 연속적인 바이트로 변경하는 작업 -&gt; 작업 후 [쓰기] 가능 = 스트림에 객체를 출력 = ObjectOutputStream 사용</li>
</ul>
</blockquote>
<ul>
<li><p>객체 역직렬화 deserialization ; 연속적인 바이트를 객체의 데이터(필드값)로 복원하는 것 -&gt; 작업 후 [읽기] 가능 = 스트림으로부터 객체를 입력 = ObjectInputStream 사용</p>
</li>
<li><p>Serializable 인터페이스
객체를 직렬화할 때 모든 필드를 바이트로 변환해도 문제없다는 마크를 붙이는 역할
Serializable 인터페이스를 구현한 클래스만 직렬화를 할 수 있다
Serializable 인터페이스 자체에는 필드와 메소드 없음</p>
</li>
</ul>
<pre><code class="language-c">class Circle implements Serializable {
    int xPos, yPos;
    double radian;
    ...코드생략
}</code></pre>
<p>직렬화의 대상이 되는 인스턴스의 클래스는 java.io.Seiralizable 
인터페이스를 구현해야 한다. ( 필수 상속 )
이 인터페이스는 ‘직렬화의 대상임을 표시’하는 기능을 가진다. </p>
<h3 id="step8-발전을-위한-문제풀이-kama_code-출제">&lt;Step.8&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<p>Q. 5명의 연예인(이름, 성별, 키)을 입력받아서 인터페이스에 정의된 test() 추상메서드를 오버라이딩해서 
람다식으로 정의 후 남자 연예인, 여자 연예인 평균키를 구하는 프로그램을 만드시오
Q. Supplier<T>로 0~99까지 랜덤 난수를 10개 생성하는 프로그램을 만드시오
Q. Function&lt;T, E&gt;을 적용하여 람다식을 적용한 후 &quot;kama_code fighting!&quot;의 문자열의 길이를 출력하시오<br>Q. 사용자로부터 영어로 된 단어 3가지를 입력받고 
람다식을 사용하여 map과 forEach문을 통해 대문자로 출력하는 프로그램을 만드시오
Q. 사용자로부터 검색어 아이디와 비밀번호를 입력받아 계정 저장 프로그램을 만드시오</p>
</blockquote>
<ol>
<li>추가 2. 검색 3. 삭제 4. 전체보기 5. 종료로 메뉴는 구성한다.
입력된 정보는 TXT 파일에 저장되어 읽고 쓸 수 있어야 한다.</li>
</ol>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>중요한 것은 흐름을 따라가며 람다식의 문법과 배열에 담은 것을 가지고 
문자열을 인식하여 평균을 구하는 아이디어이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/7cc8dd0f-2feb-4dd9-9e98-1f46e23ea6b3/image.PNG" width = "60%" height = "60%">


<pre><code class="language-c">class Entertain 
{
    String name,gender; int tall;
    // 생성자
    public Entertain(String name, String gender, int tall) 
    { 
        this.name = name;
        this.gender = gender;
        this.tall = tall;
    }
    // 성별 getter
    public String getGender()
    {
        return gender;
    }
    // 키 getter
    public int gettall()
    {
        return tall;
    }
}

public class Lamda01
{
    public static void main(String[] args)
    {
        /*
        Q. 5명의 연예인(이름, 성별, 키)을 입력받아서 인터페이스에 정의된 
        test() 추상메서드를 오버라이딩해서 람다식으로 정의 후 
        남자 연예인, 여자 연예인 평균키를 구하는 프로그램을 만드시오
         */
        // 입력값을 받는 scan
        Scanner scan = new Scanner(System.in);
        // 번째를 안내하기 위한 변수
        int count = 1;
        Entertain [] et = new Entertain[5]; // et 배열 선언

             // 0부터 4까지 = 5번 반복
            for(int i=0; i&lt;et.length; i++) 
            {
                System.out.println(&quot;[&quot;+count+&quot;번쨰] 연예인의 이름을 입력해주세요.&quot;);
                System.out.print(&quot;&gt;&gt;&quot;);
                String name = scan.nextLine().trim(); // 공백 제거하여 name에 저장
                System.out.println(&quot;[&quot;+count+&quot;번쨰] 연예인의 성별을 입력해주세요.&quot;);
                System.out.print(&quot;&gt;&gt;&quot;);
                String gender = scan.nextLine().trim(); // 공백 제거하여 gender에 저장
                System.out.println(&quot;[&quot;+count+&quot;번쨰] 연예인의 키(cm)를 숫자만 입력해주세요.&quot;);
                System.out.print(&quot;&gt;&gt;&quot;);
                String tall = scan.nextLine().trim(); // 공백 제거하여 tall에 저장

                // et[i] 배열에 담아서 객체 생성하기
                et[i] = new Entertain(name, gender, Integer.parseInt(tall)); // 배열 원소 객체 생성
                count++; // 카운트 1씩 증가
            }

        // list 형식으로 변환
        List&lt;Entertain&gt; list = Arrays.asList(et[0], et[1], et[2], et[3],et[4]);
//        람다식을 정의하고 참조변수는 aaa를 전달하는 것
        // 리스트 안에서 남자라는 것을 인식하여 평균을 구하기 위한 메소드 avg
        double maleAvg = avg((Entertain h) -&gt; h.getGender().equals(&quot;남자&quot;), list);
        System.out.println(&quot;남자 평균:&quot;+ maleAvg);
        // 리스트 안에서 여자라는 것을 인식하여 평균을 구하기 위한 메소드 avg
        double femaleAvg = avg((Entertain b) -&gt; b.getGender().equals(&quot;여자&quot;), list);
        System.out.println(&quot;여자 평균:&quot;+ femaleAvg);
    }

    /*
    매개변수로 성별을 판단하는 람다식과 list 컬렉션을 전달 받는다
     */
    public static double avg(Predicate&lt;Entertain&gt; ph, List&lt;Entertain&gt; li)
    {
        int pCount = 0;
        int tCount = 0;
        //컬렉션에 저장된 Entertain 객체의 갯수만큼 5번 반복
        for(Entertain h : li)
        {
            // 람다식을 통해 각 Entertain 객체의 성별을 판단
            // test()이 실제 일치하는지 확인
            if(ph.test(h)== true)
            {
                // 각 성별을 판단한 후 + 합니다
                pCount++;
                tCount += h.gettall();
                //키를 누적해가며 더합니다.
            }
        }
        return (double)tCount / pCount; // 키를 인원수만큼 나눈다(평균)
    }
}</code></pre>
<ol start="2">
<li><p>여기서 핵심은 람다식의 문법에 맞게 함수 인터페이스(Supplier)를 통해 
랜덤을 생성해준 후 get()을 통해 값을 얻어오는 것이다.</p>
<p>그리고 10개의 난수를 얻어오기 위해 makeRandomNum 메소드를 생성해준 후
반복문을 통해 출력하는 것이 핵심이다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/369f40a6-90ec-4673-b0fd-959ac20c0699/image.PNG" width = "60%" height = "60%">

</li>
</ol>
<pre><code class="language-c">public static void main(String[] args) {

        //0~99까지 난수를 생성한 후 반환해주는 람다식 정의
        Supplier&lt;Integer&gt; sup = () -&gt; {
            Random random = new Random();
            return random.nextInt(100);
        };        

        //추상메서드인 get()을 호출
        int rNum = sup.get();  
        System.out.println(&quot;생성된난수=&quot;+ rNum);        

        //난수를 생성하는 람다식 sup과 정수 10을 인수로 전달
        List&lt;Integer&gt; list = makeRandomNum(sup, 10);
        Collections.sort(list); // 오름차순 정렬
    //리스트 자체를 반복문 없이 출력할 수 있다. toString() 메소드가 이미 오버라이딩 되어 있어서 출력
        System.out.println(list);
    }

    /*
     매개변수로 전달된 람다식을 통해 난수를 생성한다. 이때 cnt만큼 반복하게 되므로
     결국 난수 10개를 생성하여 list컬렉션에 저장한 후 반환
     */
    public static List&lt;Integer&gt; makeRandomNum(Supplier&lt;Integer&gt; s, int cnt)
    {
        List&lt;Integer&gt; li = new ArrayList&lt;Integer&gt;();
        for(int i=1 ; i&lt;=cnt ; i++)
        {
            /*
            람다식의 get()메서드 호출을 통해 난수를 생성하게 된다.
             */
            li.add(s.get());
        }
        return li;
    }
}
</code></pre>
<ol start="3">
<li><p>함수 인터페이스 Function을 사용해서 문자열 길이를 출력하는 것이다.
람다식 문법에 맞게 String 형태의 길이를 오버라이딩하여 길이를 얻어온다.</p>
<pre><code>                     apply()를 통해서..</code></pre><img src = "https://velog.velcdn.com/images/kama_code/post/efd69a10-7399-424e-a5fe-bb799fb3a10f/image.PNG" width = "60%" height = "60%">

</li>
</ol>
<pre><code class="language-c">public static void main(String[] args)
    {
        /*
        Q. Function&lt;T, E&gt;을 적용하여 람다식을 적용한 후 
        &quot;kama_code fighting!&quot;의 문자열의 길이를 출력하시오  
        */

        //매개변수는 String, 반환값은 Integer인 람다식을 정의
        //문자열의 길이(.length)를 반환
        Function&lt;String, Integer&gt; func = (String s) -&gt; {
            return s.length(); // 오버라이딩
        };
        System.out.println(&quot;kama_code fighting! 문자열길이=&quot;+ func.apply(&quot;kama_code fighting!&quot;)); // 길이 19개
    }

}</code></pre>
<ol start="4">
<li><p>해당 프로그램 역시 간단하다. 문제 그대로 사용자로부터 3개의 영단어를
입력 받도록 한다. 그리고 그 내용을 배열에 담는다.
스트림으로 변경하여 map을 통해 toUpperCase()로 대문자로 바꾸는 메소드를 사용한다.
마지막으로 반복문을 통해서 출력하는 문제이다.
람다식으로 사용하니 굉장히 코드가 짧아진다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/975f56d7-dfc5-48dd-95e5-182f8ea454fc/image.PNG" width = "50%" height = "50%">

</li>
</ol>
<pre><code class="language-c">public static void main(String[] args)
    {
        /*
         * Q. 사용자로부터 영어로 된 단어 3가지를 입력받고 람다식을 사용하여 
         * map과 forEach문을 통해 대문자로 출력하는 프로그램을 만드시오
         */
        Scanner scan =new Scanner(System.in);
        System.out.println(&quot;[첫번째] 영어단어를 입력해주세요&quot;);
        String ineng1 = scan.nextLine();
        System.out.println(&quot;[두번째] 영어단어를 입력해주세요&quot;);
        String ineng2 = scan.nextLine();
        System.out.println(&quot;[세번째] 영어단어를 입력해주세요&quot;);
        String ineng3 = scan.nextLine();
        List&lt;String&gt; list = Arrays.asList(ineng1, ineng2, ineng3); // 변경이 안되는 배열

        list.stream() // 스트림으로 변환
                .map(s -&gt; s.toUpperCase()) // 대문자로 변환
                // map은 data 원형을 변경하는데 사용
                .forEach(n -&gt; System.out.print(n + &quot;\t&quot;));

        System.out.println(); // 한줄 띄기
    }</code></pre>
<ol start="5">
<li>필자가 실제 현재까지도 애용하고 있는 프로그램중 하나이다.
&quot;src/text.txt&quot;라는 텍스트파일을 입력하고 출력하고를 다루는 프로그램이다.
주석으로 해설을 담았다. 자세히 읽어보자!</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/d22e924a-b51a-4ad0-a932-73547d0fcd6e/image.PNG" width = "50%" height = "50%">


<pre><code class="language-c">public static void main(String[] args) throws IOException
    {
        ArrayList&lt;Idfinder&gt; idf = new ArrayList&lt;Idfinder&gt;();
        //Idfinder의 데이터를 가지는 ArrayList의 변수를 idf이라고 만들고
        //Idfinder의 데이터를 가지는 ArrayList의 객체를 만들어서 변수 idf에 대입

        Controller c = new Controller();
        //Controller 라는 클래스 변수 이름을 c로 하고 Controller 객체를 생성해서 대입

        File f = new File(&quot;src/text.txt&quot;);
        if(f.exists()) // 파일 존재여부를 확인하는 메소드
        {
//            idf.clear(); 
            //ArrayList idf의 내용 클리어해서 idf을 비움
            FileReader fr = new FileReader(&quot;src/text.txt&quot;);
            //FileReader fr에 FileReader 객체를 생성 생성자 인자에는 파일경로를 문저열로 넣어서 객체 생성

            BufferedReader reader1 = new BufferedReader(fr);
            // BufferReader reader1에 BufferedReader 객체를 생성 생성자 인자에는 FileReader을 넣어서 객체 생성

            String line1;
            //문자열 line1 생성

            String[] splitLine1 = null;
            //문자열 배열 splitLine을 생성 하고 null 값 대입

            while((line1=reader1.readLine()) != null)
                //BufferReader reader1을 이용해 한줄을 읽어 와서 문자열 line1에 대입하고 line1이 널이 아니면 반복
            {
                //System.out.println(line1);
                splitLine1 = line1.split(&quot;\t\t&quot;);
                //문자열 splitLine 배열에 line1을 &quot;\t\t&quot;로 자른 문자열들을 대입
                //               System.out.println(splitLine.length);
                idf.add(new Idfinder(splitLine1[0], splitLine1[1], splitLine1[2]));
                //ArrayList idf 추가할때 Idfinder 객체를 생성 하고 생성자는 문자열 splitLine1 배열을 대입
            }
        } 


        while(true) //무한반복
        {
            try
            {
                Scanner sc = new Scanner(System.in); //입력
                FileWriter fw; //FileWriter의 fw라는 변수 선언
                System.out.println(&quot;========== 아이디 보관 프로그램 ==========&quot;);
                System.out.println(&quot;1.추가 2.검색 3.삭제 4.전체보기 5.종료&quot;); //출력
                int num = sc.nextInt(); // 입력
                if(c.idf.size() &lt; 0)
                    //Controller의 변수 c의 객체변서 idf의 사이즈가 0이면 실행
                {
                    fw = new FileWriter(&quot;src/text.txt&quot;,false);
                    // fw 변수에 FileWriter 객체를 생성해서 대입 
                    // 객체 생성시 파일 경로명 문자열 생성자 인자에 넣어서 객체 생성 대입
                    //덮어쓰기
                }
                else //if문이 아니면
                {
                    //System.out.println(&quot;11&quot;);
                    fw = new FileWriter(&quot;src/text.txt&quot;,true);
                    //fw 변수에 FileWriter 객체를 생성해서 대입
                    // 객체 생성시 파일 경로명 문자열 생성자 인자에 넣어서 객체 생성 대입
                    //이어쓰기
                }

                switch (num) 
                { //num의 값에 따라 분기
                case 1: //num 1이면
                    c.input(fw); 
                    // Controller의 변수 c의 input 함수에 FileWriter 객체 fw를 인자로 넣어서 호출
                    break; //탈출
                case 2: //num 2이면
                    c.search();
                    //Controller의 변수 c의 search 함수 호출
                    break; // 탈출
                case 3: //num 3이면
                    FileWriter fw1 = new FileWriter(&quot;src/text.txt&quot;,false);
                    //FileWriter의 변수명 fw1로 선언 후 FileWriter 객체 생성
                    //객체 생성시 파일 경로명을 문자열로 인자로 전달해서 객체 생성
                    c.delete(fw1);
                    //Controller의 변수 c의 deleter 함수에 FileWriter 객체 fw1를 인자로 넣어서 호출
                    break;//탈출
                case 4://num 3이면
                    System.out.println(&quot;[검색어]        [아이디]        [비밀번호]&quot;);
                    c.allPrint(); 
                    //Controller의 변수 c의 allPrint 함수 호출
                    break;// 탈출
                case 5:
                    System.out.println(&quot;========== 프로그램을 종료합니다 ==========&quot;);//입력
                    return;//탈출

                default: //위에게 다아니면 
                    System.out.println(&quot;잘못된 입력입니다.&quot;);
                    System.out.println(&quot;1~5번까지의 숫자만 입력해주세요.&quot;);//출력
                    break;//탈출
                }
            }
            catch (InputMismatchException num)
            {
                System.out.println(&quot;잘못된 입력입니다.&quot;);
                System.out.println(&quot;1~5번까지의 숫자만 입력해주세요.&quot;);//출력
            }
        }    
    }
}

class Idfinder //클래스 Idfinder
{
    String name; // 문자열 변수 name
    String idNum; // 문자열 변수 idNum
    String password; // 문자열 변수 password

    public Idfinder(String name, String idNum, String password) {
        //Idfinder 생성자 인자로 문자열 name, 문자열 idNum, 문자열 password 받아서 생성
        this.name = name;
        //인자 name을 객체 변수 name에 대입
        this.idNum = idNum;
        //인자 idNum을 객체 변수 idNum에 대입
        this.password = password;
        //인자 password을 객체 변수 password에 대입
    }
}
class Controller //class Controller
{
    ArrayList&lt;Idfinder&gt; idf;    // Idfinder이 있는 ArrayList를 idf이라고 선언
    FileWriter fw; // FileWriter를 fw라고 선언
    Scanner sc; // Scanner를 sc라고 선언
    FileReader fr; // FileReader를 fr이라고 선언

    public Controller() throws IOException 
    {
        idf = new ArrayList&lt;Idfinder&gt;();
        // idf 변수에 ArrayList&lt;Idfinder&gt;객체 생성 해서 대입
        sc = new Scanner(System.in); // 입력

    }

    void input(FileWriter fw) throws IOException
    //인자를 FileWriter로 받고 리턴이 없는 input이라는 함수
    {
        if(idf.size() &lt; 0) // ArrayList 변수 idf의 크기가 0이면 실행
        {
            String opn1 = &quot;검색어&quot;+&quot;\t\t&quot;+&quot;아이디(ID)&quot;+&quot;\t\t&quot;+&quot;비밀번호(PW)&quot;+&quot;\r\n&quot;;
            //문자열 변수 opn1에 위에 문자열 대입
            idf.add(new Idfinder(&quot;검색어&quot;,&quot;아이디(ID)&quot;,&quot;비밀번호(PW)&quot;));
            //ArrayList 변수 idf의 리스트 추가 Idfinder 객체를 생성해서 추가 
            fw.write(opn1); 
            // FileWrite의 변수 fw를 이용해 write 함수 호출 파일에 문자열 쓰기
        }


        System.out.print(&quot;검색어 :&quot;); //입력
        String name = sc.next(); // String name에 입력 값 대입
        System.out.print(&quot;아이디(ID) :&quot;); //입력
        String number=sc.next(); // String number에 입력 값 대입
        System.out.print(&quot;비밀번호(PW) :&quot;); // 입력
        String password = sc.next(); // String password에 입력 값 대입

        idf.add(new Idfinder(name,number,password)); 
        //ArrayList 변수 idf의 리스트 추가 Idfinder 객체를 생성해서 추가 Idfinder은 입력받은 값을 생성자에 추가

        String tatal = name+&quot;\t\t&quot;+number+&quot;\t\t&quot;+password+&quot;\r\n&quot;;
        // 문자열 tatal 에 입력 받은 문자열을 더해서 대입
        fw.write(tatal);
         // FileWrite의 변수 fw를 이용해 write 함수 호출 파일에 tatal문자열 쓰기
        System.out.println(&quot;============ 아이디 등록완료 ============&quot;);
        System.out.println(&quot;[&quot;+name+&quot;] 성공적으로 추가되었습니다&quot;);
        System.out.println(&quot;아이디(ID) : [&quot;+number+&quot;]&quot;);
        System.out.println(&quot;비밀번호(PW) : [&quot;+password+&quot;]&quot;);
        System.out.println();
        fw.close();
        //FileWriter 끄기
    }
    void search() throws IOException
    //인자가 없고 리턴이 없는 search 함수
    {
        System.out.print(&quot;검색어를 입력해주세요 : &quot;); //입력
        String search = sc.next(); // 문자열 search에 입력 문자열 대입

        idf.clear(); 
        //ArrayList idf의 내용 클리어해서 idf을 비움
        FileReader fr = new FileReader(&quot;src/text.txt&quot;);
        //FileReader fr에 FileReader 객체를 생성 생성자 인자에는 파일경로를 문저열로 넣어서 객체 생성
        BufferedReader reader1 = new BufferedReader(fr);
        // BufferReader reader1에 BufferedReader 객체를 생성 생성자 인자에는 FileReader을 넣어서 객체 생성
        String line1;
        //문자열 line1 생성
        String[] splitLine1 = null;
        //문자열 배열 splitLine을 생성 하고 null 값 대입

        while((line1=reader1.readLine()) != null)
         //BufferReader reader1을 이용해 한줄을 읽어 와서 문자열 line1에 대입하고 line1이 널이 아니면 반복
        {
        //System.out.println(line1);
        splitLine1 = line1.split(&quot;\t\t&quot;);
         //문자열 splitLine 배열에 line1을 &quot;\t\t&quot;로 자른 문자열들을 대입
        //               System.out.println(splitLine.length);
        idf.add(new Idfinder(splitLine1[0], splitLine1[1], splitLine1[2]));
        //ArrayList idf 추가할때 Idfinder 객체를 생성 하고 생성자는 문자열 splitLine1 배열을 대입
        }    

        boolean check = false; // boolean check 변수를 false로 초기화
        int index = -1; // int index 변수를 -1로 초기화

        for(int i = 0;i&lt;idf.size();i++)
        //int i 변수를 0으로 대입 i는 ArrayList idf의 크기보다 작으면 반복 반복 때마다 i는 1씩 증가
        {
            if(idf.get(i).name.equals(search))
            //ArrayList idf에 i 인덱스에 이름이 search와 같으면 아래 명령어 실행
            {
                index = i; // 변수 index에 i를 대입
                check = true; // 변수 check에 true 대입
            }
        }

        if(check == true)
        // 변수 check가 true 라면 아래 명령어 실행
        {
            System.out.println(&quot;========== 성공적으로 찾았습니다 ==========&quot;);
            System.out.println(&quot;[검색어]        [아이디]        [비밀번호]&quot;);
            System.out.println(idf.get(index).name +&quot;        &quot;+ idf.get(index).idNum+&quot;        &quot;+idf.get(index).password );//출력
        }
        else
        {
            System.out.println(&quot;▶▷ 등록된 아이디(ID)가 없습니다.&quot;);//출력
            System.out.println();
        }
    }

    void delete(FileWriter fw) throws IOException
    //인자를 FileWriter를 받고 리턴값이 없는 delete라는 함수
    {
        System.out.print(&quot;삭제 할 검색어를 입력해주세요 : &quot;);// 출력
        String search1 = sc.next(); 
        //문자열 search1 에 입력 값 대입
        for(int i = 0;i&lt;idf.size();i++)
        //int i 변수를 0으로 대입 i는 ArrayList idf의 크기보다 작으면 반복 반복 때마다 i는 1씩 증가
        {
            if(idf.get(i).name.equals(search1))
            //ArrayList idf에 i 인덱스에 이름이 search와 같으면 아래 명령어 실행
            {
                System.out.println(&quot;▶▷ 성공적으로 삭제되었습니다.&quot;);//출력
                System.out.println();
                idf.remove(i);//ArrayList idf 에 i 인덱스 삭제
            }
        }
        for(int i =0;i&lt;idf.size();i++)
        //int i 변수를 0으로 대입 i는 ArrayList idf의 크기보다 작으면 반복 반복 때마다 i는 1씩 증가
        {
            String tatal1 = idf.get(i).name+&quot;\t\t&quot;+idf.get(i).idNum+&quot;\t\t&quot;+idf.get(i).password+&quot;\r\n&quot;;
            //문자열 tatal1에 ArrayList idf에 i인덱스 문자열 이름, 전화번호, 주소를 더해서 대입
            fw.write(tatal1);
             // FileWrite의 변수 fw를 이용해 write 함수 호출 파일에 tatal1문자열 쓰기
        }
        fw.close();
        //FileWriter 끄기
    }
    void allPrint() throws IOException
    //인자는 없고 리턴값도 없는 allPrint라는 함수
    {
        idf.clear(); 
        //ArrayList idf의 내용 클리어해서 idf을 비움
        FileReader fr = new FileReader(&quot;src/text.txt&quot;);
        //FileReader fr에 FileReader 객체를 생성 생성자 인자에는 파일경로를 문저열로 넣어서 객체 생성
        BufferedReader reader1 = new BufferedReader(fr);
        // BufferReader reader1에 BufferedReader 객체를 생성 생성자 인자에는 FileReader을 넣어서 객체 생성
        String line1;
        //문자열 line1 생성
        String[] splitLine1 = null;
        //문자열 배열 splitLine을 생성 하고 null 값 대입

        while((line1=reader1.readLine()) != null)
        //BufferReader reader1을 이용해 한줄을 읽어 와서 문자열 line1에 대입하고 line1이 널이 아니면 반복
        {
            //System.out.println(line1);
            splitLine1 = line1.split(&quot;\t\t&quot;);
            //문자열 splitLine 배열에 line1을 &quot;\t\t&quot;로 자른 문자열들을 대입
            //               System.out.println(splitLine.length);
            idf.add(new Idfinder(splitLine1[0], splitLine1[1], splitLine1[2]));
            //ArrayList idf 추가할때 Idfinder 객체를 생성 하고 생성자는 문자열 splitLine1 배열을 대입
        }

        for(int i = 0;i&lt;idf.size();i++)
        //int i 변수를 0으로 대입 i는 ArrayList idf의 크기보다 작으면 반복 반복 때마다 i는 1씩 증가
        {
            System.out.println(idf.get(i).name + &quot;\t\t&quot;+idf.get(i).idNum +&quot;\t\t&quot;+ idf.get(i).password);
            //출력
        }
    }
}</code></pre>
<blockquote>
<p>이렇게 람다식과 스트림까지도 끝이 났다. 
  자바(Java)공부 초기 때는 숫자와 문자 하나만 넣고 다루고 그랬는데
  후반부로 오니까 클래스를 넣고 파일을 넣고 다루게 된다.
  원리는 초기때와 같다는 것! 자바(java)는 기본이 중요하다는 것을 명심하다!
  기본에서 파생되어 심화되고 응용되는 것이다.
  tip] 스트림을 다루다가 가끔 한글이 깨지고 그러는 경우가 있는데
  이클립스에서 실행하지 말고 notepad++에서 넣으면 정상적으로 한글이 안깨질때도 있다
  그렇게 불러와서 전체 선택하여 가지고 오는 것도 팁이다.
  그리고 위 문제에서 클래스를 하나로 쭉 써넣었는데
  왠만하면 클래스는 파일 안에서 나누는 것이 좋다.
  class1.java // class2.java 이런식으로 말이다. 그래야 코딩하는데 
  가독성도 좋아지고 객체 지향처럼 나뉘게 되니까 구분하기도 편리하다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.13] 제네릭(generic)과 컬렉션 프레임워크(Collection)⚡]]></title>
            <link>https://velog.io/@kama_code/JAVA.13-%EC%A0%9C%EB%84%A4%EB%A6%ADgeneric%EA%B3%BC-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%ACCollection</link>
            <guid>https://velog.io/@kama_code/JAVA.13-%EC%A0%9C%EB%84%A4%EB%A6%ADgeneric%EA%B3%BC-%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%ACCollection</guid>
            <pubDate>Sun, 23 Jul 2023 12:02:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>자바(JAVA) 후반부의 첫 파트이다.
제네릭.. 컬렉션 프레임워크.. 이름이 굉장히 거창하고 멋있게 느껴진다.
이런 것들이 탄생한 이유는 다 개발자들이 편하라고 나온 방식이니
이것저것 많다고 불평말고 반드시 꼭 학습하여 넘어가자!</p>
</blockquote>
<h2 id="step1-제네릭generic">&lt;Step.1&gt; 제네릭(generic)</h2>
<ul>
<li>제네릭(generic)이란?
ㄴ데이터의 타입(data type)을 일반화한다(generalize)는 것을 의미한다
ㄴ클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법이다.</li>
</ul>
<p>※ 제네릭이 없다면 겪는 문제점</p>
<ul>
<li>이름만 다르고 구조는 같은 코드일시 코드가 중복된다는 단점
그렇게 코드가 복잡해지면 개발시 어려움을 헤깔리는 불편함을 겪게 된다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/927835df-bd5c-484d-aa1c-15a191e999b1/image.PNG" width = "65%" height = "65%">

<hr>
<ul>
<li>OrangeBox 클래스는 Orange 객체만 저장할 수 있다. </li>
<li>단순하기에 자료형에 안전한 구조를 가지고 있다. </li>
<li>단, 다른 객체를 저장하기 위해서는 클래스를 추가해야 하는 번거로움 발생.</li>
</ul>
<pre><code class="language-C">class OrangeBox {
    Orange item; // 오렌지 아이템만 들어갈 수 있음
    public void store(Orange item) {
        this.item = item;
    }
    public Orange pullOut() {
        return item;
    }
}</code></pre>
<hr>
<ul>
<li>FruitBox는 모든 객체를 저장할 수 있는 클래스이다. </li>
<li>구현의 편의성이 보장된다. </li>
<li>단, 자료형에는 안전하지 못하다는 단점이 있다. </li>
</ul>
<pre><code class="language-C">class FruitBox{
    Object item;
    public void store(Object item) {
        this.item = item;
    }
    public Object pullOut() {
        return item;
    }
}</code></pre>
<hr>
<p>▣ 제네릭 클래스의 설계 및 인스턴스 생성</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/db2c2b77-7dca-4a60-8bf6-a5700cb8b131/image.PNG" width = "65%" height = "65%">

<blockquote>
</blockquote>
<pre><code>1. 타입 매개변수 (Type Parameter): Camp&lt;T&gt;에서 T를 말한다.
2. 타입 인자 (Type Argument): Camp&lt;Npc&gt;에서 Npc를 말한다.
3. 매개변수화 타입 (Parameterized Type): Camp&lt;Npc&gt;를 말한다.  </code></pre><img src = "https://velog.velcdn.com/images/kama_code/post/7f70d78a-b140-48d1-9c1a-5c4a582adc9e/image.PNG" width = "50%" height = "50%">

<p>▣ 다중 매개변수 기반 제네릭 클래스의 정의</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/be58f741-1d02-44fd-b38a-ddf7bb9e79a5/image.PNG" width = "50%" height = "50%">

<p>▣ 타입 변수의 제한
제네릭은 &#39;T&#39;와 같은 타입 변수(type variable)를 사용하여 타입을 제한합니다.
이때 extends 상속 키워드를 사용하면 타입 변수에 특정 타입만을 
사용하도록 제한할 수 있다</p>
<pre><code>class AnimalList&lt;T extends LandAnimal&gt; { ... }</code></pre><p>타입 변수에 제한을 걸어 놓으면 클래스 내부에서 사용된 모든 타입 변수에 제한이 걸린다.</p>
<p>이때 인터페이스를 구현할 경우에도 implements 키워드가 아닌 extends 키워드를 
사용해야만 한다.</p>
<hr>
<ul>
<li>클래스와 인터페이스를 동시에 상속받고 구현해야 한다면 엠퍼센트(&amp;) 기호를 사용한다.<pre><code>class AnimalList&lt;T extends LandAnimal &amp; WarmBlood&gt; { ... }</code></pre></li>
</ul>
<h2 id="step2-제네릭-메소드generic-method">&lt;Step.2&gt; 제네릭 메소드(generic method)</h2>
<ul>
<li>제네릭 메소드란? 
ㄴ메소드의 선언부에 타입 변수를 사용한 메소드를 의미한다.
ㄴ이때 타입 변수의 선언은 메소드 선언부에서 반환 타입 바로 앞에 위치한다.</li>
</ul>
<p>클래스 전부가 아닌 메소드 하나에 대해 제네릭으로 정의
제네릭 메서드의 T는 메서드 호출 시점에 결정한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/b320b242-e1d6-4def-9d5e-cc20b4f1b0b2/image.PNG" width = "70%" height = "70%">

<pre><code>public static &lt;T&gt; void sort( ... ) { ... }</code></pre><h2 id="step3-와일드카드">&lt;Step.3&gt; 와일드카드</h2>
<p>와일드카드(wild card)란 이름에 제한을 두지 않음을 표현하는 데 사용되는 기호를 의미
제네릭에서는 물음표(?) 기호를 사용하여 이러한 와일드카드를 사용할 수 있다.</p>
<pre><code>&lt;?&gt;           // 타입 변수에 모든 타입을 사용할 수 있음.

&lt;? extends T&gt; // T 타입과 T 타입을 상속받는 자손 클래스 타입만을 사용할 수 있음.

&lt;? super T&gt;   // T 타입과 T 타입이 상속받은 조상 클래스 타입만을 사용할 수 있음.</code></pre><h2 id="step4-컬렉션-프레임워크">&lt;Step.4&gt; 컬렉션 프레임워크</h2>
<ul>
<li>다수의 객체 저장과 참조를 위해 정의된 클래스들의 집합</li>
<li>별도의 구현과 이해없이 자료구조와 알고리즘을 적용할 수 있다.
즉, 데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 
클래스로 구현해 놓은 것이다.</li>
</ul>
<p>컬렉션 프레임워크는 자바의 인터페이스(interface)를 사용하여 구현된다.</p>
<hr>
<ul>
<li>배열
배열은 크기가 고정되어 있어 데이터를 추가하거나 삭제할 수 없다.
ㄴ리스트와 반대이다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/0bdf2835-3eec-44b6-b393-7f3683eebc4d/image.PNG" width = "60%" height = "60%">

<hr>
<ul>
<li>리스트
떨어진 곳에 존재하는 데이터를 화살표로 묶어서 관리하는 자료구조
데이터가 추가되거나 삭제될 때 연결하는 정보만 바꾸면 쉽게 추가, 삭제가 된다.
ㄴ배열과 반대이다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/5ce18377-c340-4cf7-9e3a-3d832e2296dc/image.PNG" width = "60%" height = "60%">

<hr>
<ul>
<li>스택
입력(Push) 꺼낸다(Pop) -&gt; 마지막에 입력된 것이 먼저 출력된다.<img src = "https://velog.velcdn.com/images/kama_code/post/0077fd86-98bb-44ab-8017-98dae5c461ab/image.PNG" width = "70%" height = "70%">

</li>
</ul>
<hr>
<ul>
<li>큐
먼저 들어간 것을 먼저 출력한다 -&gt; 슈퍼마켓 줄을 선 사람들을 생각하면 된다.<img src = "https://velog.velcdn.com/images/kama_code/post/efb3d693-5f53-40b3-bb94-9b1a481d2a58/image.PNG" width = "70%" height = "70%">

</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/71f0c890-efa1-4f36-b220-a9fd024666eb/image.PNG" width = "90%" height = "90%">

<hr>
<ul>
<li>덱
ㄴ 덱(Deque)은 어떤 쪽으로 입력하고 어떤 쪽으로 출력하느냐에 따라
ㄴ 스택(Stack)으로 사용할 수도 있고 큐(queue)로 사용할 수 있다
ㄴ 한쪽으로만 입력 가능하도록 설정한 것을 스크롤(scroll)
ㄴ 한쪽으로만 출력 가능하도록 설정한 덱은 셀프(shelf)</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/d519cfb5-43ad-4ace-a6a1-dd7c4f01be9b/image.PNG" width = "80%" height = "80%">

<pre><code class="language-c">public static void main(String[] args)
    {
        // 둘 다 사용 가능
        Deque&lt;String&gt; deq = new ArrayDeque&lt;&gt;();
//        Deque&lt;String&gt; deq = new LinkedList&lt;&gt;();

        // 앞으로 넣고 : 
        deq.offerFirst(&quot;A&quot;);
        deq.offerFirst(&quot;B&quot;);
        deq.offerFirst(&quot;C&quot;);

        // 리스트 확인
        for(String s : deq)
            System.out.print(s.toString() + &#39;\t&#39;);
        System.out.println();

        // 앞으로 꺼내기
        System.out.println(deq.pollFirst());
        System.out.println(deq.pollFirst());
        System.out.println(deq.pollFirst());

        System.out.println(&quot;---------------------&quot;); // 이것이 스택

        // 뒤로 넣고
        deq.offerLast(&quot;A&quot;);
        deq.offerLast(&quot;B&quot;);
        deq.offerLast(&quot;C&quot;);

        // 리스트 확인
        for(String s : deq)
            System.out.print(s.toString() + &#39;\t&#39;);
        System.out.println(); // A먼저 넣고 B C 순서대로 넣음

        // 뒤에서 꺼내기
        System.out.println(deq.pollLast());
        System.out.println(deq.pollLast());
        System.out.println(deq.pollLast());

        System.out.println(&quot;---------------------&quot;); // 이것이 스택

        // 뒤로 넣고
        deq.offerLast(&quot;A&quot;);
        deq.offerLast(&quot;B&quot;);
        deq.offerLast(&quot;C&quot;);

        // 리스트 확인
        for(String s : deq)
            System.out.println(s.toString() + &#39;\t&#39;);
        System.out.println();

        // 앞으로 꺼내기
        System.out.println(deq.pollFirst());
        System.out.println(deq.pollFirst());
        System.out.println(deq.pollFirst());

        System.out.println(&quot;---------------------&quot;); // 이것이 큐
    }
}</code></pre>
<hr>
<ul>
<li>트리<img src = "https://velog.velcdn.com/images/kama_code/post/a676e20a-3840-4797-8b5a-b5763d6d77a0/image.PNG" width = "70%" height = "70%">

</li>
</ul>
<hr>
<p>▣ 컬렉션의 인터페이스 구조</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/566840ce-4dd9-4bee-a381-df2c6ffecf39/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/8969e004-9827-4ec5-b88a-565990c7fcda/image.PNG" width = "80%" height = "80%">

<p>▣ Arrays.AsList()</p>
<blockquote>
<ul>
<li>일반적인 배열을 List컬렉션으로 변환해준다.</li>
</ul>
</blockquote>
<ul>
<li>컬렉션의 모든 메소드를 사용할 수 있어 편리하다</li>
<li>단, 값만 참조할 수 있다.</li>
<li>변경을 하고 싶다면 객체를 복사후 진행한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/6fa231fa-f307-45e9-a17e-1a24b23fd71e/image.PNG" width = "30%" height = "30%">

<pre><code class="language-c">▣ List&lt;E&gt; 인터페이스: 순서가 있는 데이터의 집합(중복 허용)
배열과 같은 특성을 기반으로 객체를 저장
중복저장이 허용되며 저장 순서가 유지된다.
  + ArrayList&lt;E&gt; : 배열 기반 자료구조, 배열을 이용하여 인스턴스 저장  
  + LinkedList&lt;E&gt; : 리스트기반 자료구조, 리스트를 구성하여 인스턴스 저장

1. ArrayList&lt;E&gt; : 추가 및 수정시 새로 배열을 만들고 전체를 옮겨야 한다.
- 데이터 중복 저장을 허용한다
- 데이터의 저장 순서를 보장한다
- 데이터 접근시 get() 혹은 iterator()를 이용한다
- Array라는 이름처럼 &#39;배열&#39;의 특성을 가지고 있어서 인덱스를 통한 저장 및 접근이 가능
- 탐색 또는 정렬을 자주 사용하는 경우에 많이 사용
- 추가가 가능하나 시간이 오래걸린다. 이사하여 처음부터 다 쓰여지기 때문
</code></pre>
 <img src = "https://velog.velcdn.com/images/kama_code/post/47362171-ca9d-425d-b9fc-93ce3dd3bf8a/image.PNG" width = "80%" height = "80%">



<pre><code class="language-c">public static void main(String[] args)
{
    ArrayList&lt;Integer&gt; list=new ArrayList&lt;Integer&gt;();
    list.add(new Integer(11));
    list.add(new Integer(22));
    list.add(new Integer(33));

    for(int i=0; i&lt;list.size(); i++)
        System.out.println(list.get(i));
    list.remove(0);    
}</code></pre>
<hr>
<pre><code class="language-c">2. LinkedList&lt;E&gt; : 객체가 추가될 때 사이에 끼워넣기만 하면 된다.
- 데이터의 중복 저장을 허용한다
- 데이터의 저장 순서를 보장한다
- 데이터 접근시 get() 혹은 iterator()를 이용한다
- linked라는 연결기반 자료 구조, 앞의 자료 구조에서 본 리스트를 구성하여 객체를 저장
- arraylist()보다 데이터 추가 및 삭제가 용이하다
</code></pre>
 <img src = "https://velog.velcdn.com/images/kama_code/post/b06c1aac-0499-4f67-b10a-7a160f0e5ba5/image.PNG" width = "70%" height = "70%">


<pre><code class="language-c">public static void main(String[] args)
{
    ArrayList list = new ArrayList();
    list.add(&quot;소녀시대&quot;);
    list.add(&quot;빅뱅&quot;);

    Iterator itr = list.iterator();
    while(itr.hasNext()) {
        System.out.print(itr.next() +&quot; &quot;);
    }
}</code></pre>
<pre><code>▣ List&lt;E&gt; 관련 메소드</code></pre><img src = "https://velog.velcdn.com/images/kama_code/post/524de87b-8ff6-4ef7-bdb7-e553a68dbce4/image.PNG" width = "60%" height = "60%">


<img src = "https://velog.velcdn.com/images/kama_code/post/96caf791-aa78-4092-a0bd-7833e9d0da0e/image.PNG" width = "80%" height = "80%">

<p>▣ 저장된 인스턴스의 순차적 접근 방법 1 : 향상된 for 문</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/64ef23f8-02a9-4129-9b23-131dd3113278/image.PNG" width = "90%" height = "90%">

<p>▣ 저장된 인스턴스의 순차적 접근 방법 2 : Iterator(반복자)를 통한 순차접근</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/4167ff6f-97d9-4997-8ad7-c80032c7ce7d/image.PNG" width = "80%" height = "80%">

<blockquote>
<ul>
<li>이터레이터, 반복자라고 한다.
컬렉션에 저장된 인스턴스를 순차적으로 접근할 수 있다.
컬렉션의 종류에 상관없이 동일한 형태의 데이터 참조방식을 유지할 수 있다.
컬렉션을 변경하더라도 별도의 참조방식을 확인할 필요가 없다.</li>
</ul>
</blockquote>
<pre><code class="language-c">public static void main(String[] args)
{
    ArrayList list = new ArrayList();
    list.add(&quot;소녀시대&quot;);
    list.add(&quot;빅뱅&quot;);

    Iterator itr = list.iterator();
    while(itr.hasNext()) {
        System.out.print(itr.next() +&quot; &quot;);
    }
}</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/a52d4567-b864-4edd-81cf-d00f0d706600/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/81b955f2-b5b8-4d9b-998d-9e2133e5ae90/image.PNG" width = "80%" height = "80%">

<p>▣ 배열 기반 리스트를 연결 기반 리스트로 바꾸기</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/16af4eac-c91e-4b21-8141-8692445d1470/image.PNG" width = "80%" height = "80%">

<p>▣ 기본 자료형 데이터의 저장과 참조
ㄴ오토 박싱과 오토 언박싱 덕분에 컬렉션 인스턴스에 기본 자료형의 값도 저장 가능하다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/84ad513a-4a6a-4334-acba-d9acdfe617eb/image.PNG" width = "70%" height = "70%">


<pre><code>▣ Set&lt;E&gt; 인터페이스: 순서가 없는 데이터의 집합(중복 불가)
집합과 같은 특성을 기반으로 객체를 저장한다
중복저장이 허용되지 않으며, 저장 순서가 유지되지 않는다.
</code></pre><pre><code class="language-c">public static void main(String[] args)
{
    HashSet&lt;String&gt; hSet=new HashSet&lt;String&gt;();

    hSet.add(&quot;First&quot;);
    hSet.add(&quot;Second&quot;);
    hSet.add(&quot;Third&quot;);
    hSet.add(&quot;First&quot;);

    System.out.println(&quot;저장된 데이터 수: &quot;+hSet.size());
}</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/3e31d9c9-8c63-4fe7-a301-de4c102bbe0b/image.PNG" width = "60%" height = "60%">


<pre><code class="language-c">1. HashSet&lt;E&gt; : Set계열의 컬렉션 
- 분류를 하면서 속도가 빨라진다.
- Set 계열의 인터페이스를 구현한 컬렉션
- 객체가 순서없이 저장된다
- 객체의 중복저장을 허용하지 않는다.
- List가 배열의 특성을 가진다면, Set은 집합의 특성을 가진다
</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/74588154-fc60-4183-a76f-95d3aaaade51/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/31176655-ad84-49bd-9cf7-a2ea24d08d3b/image.PNG" width = "90%" height = "90%">


<p>▣ 특성을 이용해서 중복제거 하는 방법</p>
<ol>
<li>크기의 변경이 안되는 배열(Arrays.asList)</li>
<li>set 특성을 이용한 HashSet으로 바꿔준다 
( 중복을 쓸 수 없는 특성으로 중복 자동 삭제 )</li>
<li>다시 list로 변환해준다.</li>
<li>중복이 제거되어 있다. </li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/04e8688e-49b4-40fb-8ec0-9679a8660f7e/image.PNG" width = "80%" height = "80%">


<pre><code class="language-c">2. TreeSet&lt;T&gt; : 트리라는 자료구조를 기반으로 한 Set계열의 컬렉션
- 가장 많이 쓰인다.
- Set의 기본적인 특성은 동일하다.
- 중복은 허용되지 않는다
- 단 객체가 정렬되어 저장된다. 정렬의 기준은 개발자가 직접 정의</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/9e6c6fb6-11e7-43bf-8eee-fd8a8ff6ac12/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/d9b03309-05d6-420d-b280-4527bd5b4953/image.PNG" width = "80%" height = "80%">

<pre><code class="language-c">▣ Comparator&lt;T&gt; 인터페이스 기반으로 TreeSet&lt;E&gt;의 정렬 기준 제시하기
public interface Comparator&lt;T&gt;
→ int compare(T o1, T o2) 의 구현을 통해 정렬 기준을 결정할 수 있다.
＃ x1이 x2보다 크면 양의 정수
# x1이 x2보다 작으면 음의 정수
# x1이 x2와 일치하면 0

▣ CompareTo() 메소드를 오버라이딩 하여 정렬의 기준을 결정한다. 
+ 인자로 전달된 obj가 작다면 양의정수반환
+ 인자로 전달된 obj가 크다면 음의정수반환
+ 인자로 전달된 obj가 같다면 0반환
</code></pre>
<pre><code class="language-c">@Override
public int compareTo(MyString paramStr) {    
    if(getLength() &gt; paramStr.getLength())
        return 1;
    else if(getLength() &lt; paramStr.getLength())
        return -1;
    else
        return 0;
}</code></pre>
<hr>
<p>▣ Map&lt;K,V&gt; 계열의 컬렉션: 키와 값 한쌍으로 이루어진 데이터의 집합</p>
<ul>
<li>Map&lt;K,V&gt; 인터페이스를 구현하는 컬렉션은 key-value 방식으로
데이터를 저장한다.</li>
<li>key는 value를 찾기 위한 식별자를 의미한다.</li>
<li>value는 실제 저장될 데이터를 의미한다.</li>
<li>입력된 순서를 보장하지 않는다. </li>
</ul>
<p>★★★ 객체의 key 값은 유일하며 value 값은 중복될 수 있다.</p>
<pre><code class="language-c">public static void main(String[] args)
{
    HashMap&lt;Integer, String&gt; hMap
        =new HashMap&lt;Integer, String&gt;();
    hMap.put(new Integer(3), &quot;나삼번&quot;);
    System.out.println(&quot;6학년 3반 3번 학생: &quot;+hMap.get(3));
}
</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/aeb7bdee-2ec9-4bf2-99a6-647c2e8aa927/image.PNG" width = "60%" height = "60%">

<ul>
<li><p>HashMap 클래스 : 내부적으로 해쉬 알고리즘에 의해 구현되어 있다.</p>
</li>
<li><p>TreeMap 클래스 : TreeSet 과 마찬가지로 이진 탐색 트리로 구현되어 있다. 
key 값으로 정렬하므로 key 값에 해당하는 클래스에 Comparable 이나 Comparator 
인터페이스가 구현되어 있어야 한다.</p>
</li>
<li><p>HashMap&lt;K, V&gt; 클래스는 Iterable<T> 인터페이스를 구현하지 않으니 
for-each문을 통해서, 혹은 ‘반복자’를 얻어서 순차적 접근을 진행할 수 없다.</p>
</li>
<li><p>TreeMap&lt;K, V&gt; 클래스는 Iterable<T> 인터페이스를 구현하지 않았지만, Tree 자료구조의 특성상  반복자가 정렬된 순서대로 key들에 접근을 하고 있다.</p>
</li>
</ul>
<hr>
<ul>
<li>정렬</li>
</ul>
<pre><code>클래스 생성시 정렬의 기준을 만들어주기 위해서 Comparable&lt;T&gt; 인터페이스를 구현해야 한다</code></pre><pre><code class="language-c">//정렬 순서 정하기
class Student2 implements Comparable&lt;Student2&gt;
{
    private String name;
    private int age;

    // 소스를 통해 만듬
    public Student2(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    @Override // 생략 Object 클래스에서 제공하는 메소드를 오버라이딩
    public String toString()
    {
        return name + &quot;:&quot; + age;
    }
    /*
    TreeSet&lt;T&gt;객체를 저장할 때 정렬을 위해 compareTo()메소드를 오버라이딩한다
    정렬의 기준은 단순하게 가나다와 같은 순서가 될 수도 있다. 문자열의 길이에 따른 될 수도 있다
     */

    @Override // 생략
    public int compareTo(Student2 p) // 이것을 통해 원하는 정렬을 해줄 수 있다.
    {
//        return this.age - p.age; //나이 오름차순 정렬
//        return p.age - this.age; //나이 내림차순 정렬
        return this.name.compareTo(p.name); //이름 가나다 순 정렬
//        return p.name.compareTo(this.name); //이름 역순으로 정렬
    }
}

public class Ex09_Comparable
{
    public static void main(String[] args)
    {
        Set&lt;Student2&gt; tree = new TreeSet&lt;&gt;();
        tree.add(new Student2(&quot;홍길동&quot;, 30));
        tree.add(new Student2(&quot;전우치&quot;, 40));
        tree.add(new Student2(&quot;손오공&quot;, 20));

        //Set 컬렉션이므로 중복저장은 허용되지 않는다.
        tree.add(new Student2(&quot;손오공&quot;, 20)); // 안나옴

        for(Student2 s : tree)
            System.out.println(s);
    }
}</code></pre>
<pre><code>Comparator&lt;T&gt;:
  기본 정렬 조건이 있다고 하더라도 새로운 정렬 조건을 주고 싶을 때 사용</code></pre><pre><code class="language-c">class MyStringComparator implements Comparator&lt;String&gt;
{
    @Override
    public int compare(String s1, String s2)
    {
        //길이가 동일한 데이터는 추가되지 않는다. &lt;= 이 조건을 적용
        //길이가 같으면 0으로 출력되어 빠진다
        return s1.length() - s2.length();
    }
}
public class Ex10_Comparator
{

    public static void main(String[] args)
    {
//        Set&lt;String&gt; tree = new TreeSet&lt;&gt;();
        Set&lt;String&gt; tree = new TreeSet&lt;&gt;(new MyStringComparator());
        tree.add(&quot;홍길동&quot;);
        tree.add(&quot;전우치&quot;);
        tree.add(&quot;전우치&quot;);
        tree.add(&quot;멀린&quot;);
        tree.add(&quot;해리포터&quot;);

        for(String s : tree)
            System.out.println(s.toString() + &#39;\t&#39;);

        System.out.println();
    }

}</code></pre>
<blockquote>
<p>List<E>를 구현한 컬렉션 클래스들은 저장된 인스턴스를 정렬된 상태로 유지하지 않는다. 
  대신에 정렬을 해야 한다면 다음 메소드를 사용할 수 있다</p>
</blockquote>
<pre><code>public static &lt;T extends Comparable&lt;T&gt;&gt; void sort(List&lt;T&gt; list)
→ Collections 클래스에 정의되어 있는 제네릭 메소드
→ 인자로 List&lt;T&gt;의 인스턴스는 모두 전달 가능
→ 단, T는 Comparable&lt;T&gt; 인터페이스를 구현한 상태이어야 한다.</code></pre><h2 id="step5-발전을-위한-문제풀이-kama_code-출제">&lt;Step.5&gt; 발전을 위한 문제풀이 (kama_code 출제)</h2>
<blockquote>
<p>Q. 컬렉션을 이용한 로또번호 생성기를 구현하시오.</p>
</blockquote>
<ol>
<li>배열을 이용한 버전과 동일한 조건으로 제작하되 Set<E> 컬렉션을 이용한다.</li>
<li>Set<E> 계열의 컬렉션은 중복이 자동으로 제거된다. </li>
<li>하지만 순서를 보장하지 않으므로 TreeSet<E>을 사용하면 된다.</li>
</ol>
<blockquote>
<p>Q. 사용자로부터 이름을 입력받아 그 이름으로 검색해서 인덱스 위치(indexOf사용)를 알아내서 
해당 인덱스로 그 객체를 삭제하고 삭제된 객체의 정보(이름,나이,학번)를 출력하여라.
1.검색할 이름을 입력받음
2.확장for문으로 컬렉션 전체를 접근
3.검색결과 유/무에 따라 
ㄴ검색결과 있을때…검색된 데이터 삭제
ㄴ검색결과 없을때...검색결과가 없다고 출력
4.전체정보 출력</p>
</blockquote>
<blockquote>
<p>Q, 컬렉션 set에 저장된 객체를 이름으로 검색하자. 
  [필수 추가]
HashSet<QuHashSet> set = new HashSet<QuHashSet>();
QuHashSet hero1 = new QuHashSet(&quot;토니스타크&quot;, &quot;아이언맨&quot;, &quot;Mark-48 수트&quot;);
QuHashSet hero2 = new QuHashSet(&quot;스티브로져스&quot;, &quot;캡틴아메리카&quot;, &quot;비브라늄 방패&quot;);
QuHashSet hero3 = new QuHashSet(&quot;브루스배너&quot;, &quot;헐크&quot;, &quot;강한피부&amp;점프&quot;);
QuHashSet hero4 = new QuHashSet(&quot;토니스타크&quot;, &quot;아이언맨&quot;, &quot;Mark-48 수트&quot;);
set.add(hero1);
set.add(hero2);
set.add(hero3);
set.add(hero4);
해당 정보가 있으면 해당 어벤져스의 정보를 출력하고 없으면 &quot;해당 영웅은 없어요ㅜㅜ&quot; 라는 메시지 출력해야 한다. 
검색 부분은 Iterator를 통해 구현하도록 한다.
set계열의 컬렉션은 기본적으로 중복저장을 허용하지 않는다. 
그러나 아래와 같이 새롭게 정의한 클래스에 대해서는 hashCode() 메소드를 적
절히 오버라이딩 처리해야 중복을 제거할 수 있다. 
메소드 오버라이딩을 통해 hero4 는 입력되지 않도록 Avengers 클래스를 업데이트 하시오.
▷ 실행결과:
[최초 전체 정보출력]
Avengers [본명=스티브로져스, 닉네임=캡틴아메리카, 능력=비브라늄 방패]
Avengers [본명=브루스배너, 닉네임=헐크, 능력=강한피부&amp;점프]
Avengers [본명=토니스타크, 닉네임=아이언맨, 능력=Mark-48 수트]
검색할 이름을 입력하세욤:브루스배너
Avengers [본명=브루스배너, 닉네임=헐크, 능력=강한피부&amp;점프]
요청하신 정보를 찾았습니다</p>
</blockquote>
<blockquote>
<p>Q. &quot;그만&quot;이 입력될 때까지 입력키, 아이디, 비밀번호 정보를 가진 ID 클래스를 작성하고 
입력키를 &#39;키&#39;로 하는 HashMap&lt;String, ID&gt; 컬렉션을 만들어서 사용자로부터 입력받아 
입력키: 네이버, 다음, 쿠팡, 티몬, 애플로 계정을 저장하시오.
그리고 입력키로 아이디, 비밀번호를 출력하는 프로그램을 만드시오 </p>
</blockquote>
<blockquote>
<p>Q. 게임설명 : 가위바위보 게임을 메소드를 통해 구현한다. 
1.난수생성기를 이용하여 1, 2, 3중 하나의 숫자를 생성한다. 
2.사용자가 가위(1),바위(2),보(3) 중 하나를 낸다. 
3.승부를 판단하여 출력한다. 4.1,2,3 이외의 숫자를 입력하면 
잘못된 입력을 알려주고 재입력을 요구한다. 
5.숫자입력을 잘못한 경우는 게임횟수에 포함하지 않는다. 
6.게임은 몇번 진행할 것인지 게임시작하기 전 코인을 입력받고(최대 5번) 
재시작(1), 종료(0) 
7.0, 1 이외의 숫자를 입력하면 재입력을 요구해야 한다.</p>
</blockquote>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>분명히 이전의 로또 생성기보다 코드가 짧아졌다. 
기존에는 번거로운 과정들이 많았으나 컬렉션을 이용해서 핵심 기능만 가지고 
사용하니 짧은 코드로 구현이 가능해진다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/f15ebaa4-e2b9-46f7-ba12-1991852f3abd/image.PNG" width = "60%" height = "60%">

<pre><code class="language-c">public class Coll01
{
    public static void main(String[] args)
    {
        /*
        Q. 컬렉션을 이용한 로또번호 생성기를 구현하시오. 
        1. 배열을 이용한 버전과 동일한 조건으로 제작하되 Set 컬렉션을 이용한다. 
        2. Set 계열의 컬렉션은 중복이 자동으로 제거된다. 
        3. 하지만 순서를 보장하지 않으므로 TreeSet을 사용하면 된다.
        */
        // HashSet으로 구현하기!

        // Set 계열의 HashSet lotto 변수 생성
        Set lotto = new HashSet();
        for (int i=0; lotto.size()&lt;6; i++) // 6개 출력하기(0번째~5번째)
        {
            Random lottor = new Random(); // 난수 객체 생성
            int bunho = lottor.nextInt(45)+1; // 1~45까지의 난수 생성하여 int형 bunho에 담기
            lotto.add(new Integer(bunho)); // lotto HashSet에 난수 번호를 집어넣기

        }
        // list 계열의 ArrayList로 HashSet lotto 변수를 가진 객체 생성
        List list = new ArrayList(lotto);
        Collections.sort(list); // 오름차순으로 정렬

        System.out.println(&quot;오늘의 로또번호: &quot; + list);        
    }

}</code></pre>
<ol start="2">
<li>Linkedlist를 통해 삭제 기능을 구현한 문제이다.
핵심은 흐름을 잘 따라가야 한다. 1번부터 차근차근 하나 하나 기능을 만드는 것이 중요하다
동시에 자바(java)의 문법까지 지켜야 해서 쉬운 일은 아니다.
Coll02 클래스로부터 생성할 데이터가 3개씩이나 있어서(이름, 나이, 학번)
이것을 나누어서 생성자를 통해 재정의하였다.
그리고 이름만 반환하는 메소드를 만들어서 입력값과 비교하여 
일치하면 문제대로 흘러가는 프로그램이다. </li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/0e0f3039-b80a-441b-953d-993af5d0647c/image.PNG" width = "50%" height = "50%">


<pre><code class="language-c">import java.util.LinkedList;
import java.util.Scanner;

public class Coll02
{
    private String name;
    private int age;
    private String stu;
    // 생성자
    public Coll02(String name, int age, String stu)
    {
        this.name = name;
        this.stu = stu;
        this.age = age;
    }
    //객체에 저장된 문자열을 저장하여 재정의
    @Override
    public String toString()
    {
        return &quot;이름: &quot;+ name + &quot; 나이: &quot; + age +&quot; 학번:&quot;+ stu;
    }    
    public String getName()
    {
        return name;
    }
    /*
     * Q. 사용자로부터 이름을 입력받아 그 이름으로 검색해서 인덱스 위치(indexOf사용)를 알아내서 
     * 해당 인덱스로 그 객체를 삭제하고 삭제된 객체의 정보(이름,나이,학번)를 출력하여라. 
     * 1.검색할 이름을 입력받음 
     * 2.확장for문으로 컬렉션 전체를 접근 
     * 3.검색결과 유/무에 따라 검색결과 있을때 검색된 데이터 삭제되고
     * 검색결과 없을때...검색결과가 없다고 출력 
     * 4.전체정보 출력
    */

    public static void main(String[] args)
    {

//        ArrayList&lt;Coll02&gt; list = new ArrayList&lt;Coll02&gt;();
        LinkedList&lt;Coll02&gt; list = new LinkedList&lt;Coll02&gt;();

        // 저장할 객체 생성
        Coll02 st1 = new Coll02(&quot;가길동&quot;, 10, &quot;2018&quot;);
        Coll02 st2 = new Coll02(&quot;나길동&quot;, 20, &quot;2017&quot;);
        Coll02 st3 = new Coll02(&quot;다길동&quot;, 30, &quot;2016&quot;);
        Coll02 st4 = new Coll02(&quot;마길동&quot;, 40, &quot;2015&quot;);
        // 객체 추가(컬렉션에 저장)
        list.add(st1);
        list.add(st2);
        list.add(st3);
        list.add(st4);

        // 1.검색할 이름을 입력받음
        System.out.println(&quot;삭제할 이름을 입력해주세요: &quot;);
        Scanner scan = new Scanner(System.in);
        String name = scan.nextLine();
        // 2.확장for문으로 컬렉션 전체를 접근
        for(Coll02 e : list)
        {
            // 3. 반복문을 돌다가 이름이 일치한 부분을 만나면?
            if(name.equals(e.getName()))
            {
                System.out.println(&quot;[검색되었습니다]&quot;);
                // 정보가 일치하는 객체를 찾았다면 참조값을 통해 삭제한다
                list.remove(e);
                // 객체를 삭제하면 즉시 반복문 완전 탈출 
                System.out.println(&quot;현재 객체수:&quot; + list.size());
                //4.전체정보 출력
                for(Coll02 e1 : list)
                {
                    System.out.println(e1);
                }
                return;
            }
        }
        // 없을 경우: 말하기
        System.err.println(&quot;그런 이름은 없습니다.&quot;);
    }        
}</code></pre>
<ol start="3">
<li>어려우면서도 중요한 문제이다.
프로젝트 내에 존재하는 모든 클래스의 조상이 되는 클래스가 있다. 
바로 Object 클래스다. Object 클래스는 
따로 만들지 않아도 JDK에 기본적으로 존재한다. 
즉 class A {}는 class A extends Object {} 와 같다는 것<h3 id="★-모든-클래스는-object를-상속받는다">★ 모든 클래스는 Object를 상속받는다</h3>
그러기에 Object는 생략 가능한 것이다.</li>
</ol>
<p>하지만 우리는 중복을 제거하기 위해 숨어있는 Object 클래스를 불러낼 것이다.</p>
<p>equals(Object obj)</p>
<ul>
<li>a와 b 두 변수에는 결론적으로 같은 값이 들어 있다. 
사람이 보기엔 딱 봐도 둘은 같다. 그러나 컴퓨터는 가리키는 주소 값이 
다르면 둘을 다르다고 결론짓는다. 
난감한 상황이지만 equals(Object obj)를 사용하면 문제를 해결할 수 있다.</li>
</ul>
<p>추가로 Hash Code란, 객체를 식별할 수 있는 유니크한 값을 의미한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/aa90a811-9bed-459c-846a-924abbf277c2/image.PNG" width = "70%" height = "70%">


<pre><code class="language-c">class QuHashSet
{
    // 이름, 닉네임, 무기로 멤버 변수를 나눠준다.
    String name;
    String heroName;
    String weapon;

    // 생성자(매개변수)
    public QuHashSet(String name, String heroName, String weapon)
    {
        this.name = name;
        this.heroName = heroName;
        this.weapon = weapon;
    }

    @Override // (이름, 닉네임 이런 식으로 구분하기 위해 오버라이딩이 필요하다)
    public String toString()
    {
        return &quot;Avengers [본명=&quot; + name + &quot;, 닉네임=&quot; + heroName + &quot;, &quot; + &quot;능력=&quot; + weapon + &quot;]&quot;;
    }

    @Override
    public int hashCode() 
    {
        int num = java.util.Objects.hash(name); 
        //Object 클래스에 상속된 name을 nume에 넣고 해쉬코드를 반환한다.
        // here1 : -566707385, here2 : 431106087, here3 : -853886273, here4 :-566707385
        return num;
    }

    // ★★ 데이터 타입이 Object인 obj 값을 받는 equals 메서드
    // 중복을 제거해주는 중요한 역할
    // 비교할 값이 있고 obj를 QuHashSet 타입으로 형변환할 수 있다면
    // return name == ((QuHashSet)obj).name;  변수에 저장된 값과 참조변수를 통해 접근한 
    // 주소 값을 같게 한다는 의미다.

    public boolean equals(Object obj)
    {
        //Object 타입의 obj를 QuHashSet 타입으로 형변환할 수 있는지 여부(값이 같다면 형변환이 가능할 것)
        //그렇지 않을 경우엔 return false;를 반환하여 출력되지 않는다.
        if (obj instanceof QuHashSet)
        {
//            QuHashSet tmp = (QuHashSet) obj;
//            return name.equals(tmp.name);
            return name == ((QuHashSet)obj).name;         
        }
        return false;
    }


    // 마지막으로 출력할 양식을 만들어준다.
    public void showAllData()
    {
        System.out.println(&quot;Avengers [본명=&quot; + name + &quot;, 닉네임=&quot; + heroName + &quot;, 능력=&quot; + weapon + &quot;]&quot;);
    }

    public static void main(String[] args)
    {

        HashSet&lt;QuHashSet&gt; set = new HashSet&lt;QuHashSet&gt;();

        QuHashSet hero1 = new QuHashSet(&quot;토니스타크&quot;, &quot;아이언맨&quot;, &quot;Mark-48 수트&quot;);
        QuHashSet hero2 = new QuHashSet(&quot;스티브로져스&quot;, &quot;캡틴아메리카&quot;, &quot;비브라늄 방패&quot;);
        QuHashSet hero3 = new QuHashSet(&quot;브루스배너&quot;, &quot;헐크&quot;, &quot;강한피부&amp;점프&quot;);
        QuHashSet hero4 = new QuHashSet(&quot;토니스타크&quot;, &quot;아이언맨&quot;, &quot;Mark-48 수트&quot;);

        set.add(hero1);
        set.add(hero2);
        set.add(hero3);
        set.add(hero4);
        System.out.println(&quot;[최초 전체 정보출력]&quot;);
        // 향상된 for문 HashSet set 변수를 av 변수를 통해 차례대로 값을 가져온다
        for (QuHashSet av : set)
        {
            System.out.println(av.toString());
        }
        //검색한 정보가 존재하는지 확인하기 위한 변수
        boolean isFind = false;
        System.out.println(&quot;검색할 이름을 입력하세요: &quot;);
        Scanner scan = new Scanner(System.in);
        String heroc = scan.nextLine();

        // 문제의 조건에 따라 Iterator로 전체 조회를 한다.
        Iterator&lt;QuHashSet&gt; itr = set.iterator();
        while (itr.hasNext())
        {
            QuHashSet fr = itr.next();
            /*
             * 배열의 각 인덱스에 저장된 객체의 참조값을 통해 멤버변수에 접근한다. 
             * 검색을 위해 입력한 이름과 비교해서 일치하는 경우에만 정보를
             * 출력한다. 이때 compareTo() 대신 equals() 를 사용해도 된다.
             */

            // compareTo(fr.name)==0 또는 equals(fr.name) 둘중 하나 아무거나 가능
            // ★★★ 매우 중요, Iterator에서 compareTo을 통해 값을 비교할 수 있다
            // compareTo -&gt; 값이 같다면 0 , 다르다면 음수
            if (heroc.compareTo(fr.name) == 0) // 사용자가 입력한 이름과 HashSet 안의 값, 이름과 같다면?
            {
                fr.showAllData();
                System.out.println(&quot;**귀하가 요청하는 정보를 찾았습니다.**&quot;);
                // 그리고 변수를 true로 변경한다.
                isFind = true;
            }
        }
        // 만약 검색된 정보가 없다면 아래와같이 출력한다.
        if (isFind == false)
            System.out.println(&quot;해당 영웅은 없어요ㅜㅜ&quot;);
    }
};</code></pre>
<ol start="4">
<li><p>계정을 담는 프로그램이다.
중요한 핵심은 private로 선언했기에 간접적으로만 데이터를 얻어올 수 있어서
getter 메소드를 사용했다는 점
입력을 받고 , 쉼표를 통해 값을 쪼개어 저장한 후
입력 실수를 방지하기 위해 공백제거를 넣어준 점
그리고 키 - 값 하나가 아닌 전체 리스트를 출력하기 위해
set 컬렉션으로 변환해준 이후 get()을 통해 검색을 하여 조회를 한 점이 핵심이다.</p>
<p>흐름을 놓치지 않고 따라가면서 
하나하나 기능을 차근차근 만들어가면서 
자바(java)의 문법을 잘 지켜야 하는 점이 핵심이다.</p>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/84b59b81-dc25-49d3-adb8-84c52145d4ec/image.PNG" width = "40%" height = "40%">

<pre><code class="language-c">class ID
{
    // private 개인정보 은닉화
    private String key; 
    private String ida, pass; // 아이디, 비번

    //생성자(매개변수)
    public ID(String key, String ida, String pass)
    {
        this.key = key;
        this.ida = ida;
        this.pass = pass;
    }
    // private을 간접적으로 얻어오기 위한 getter
    public String getkey()
    {
        return key;
    }
    // private을 간접적으로 얻어오기 위한 getter
    public String getida()
    {
        return ida;
    }
    // private을 간접적으로 얻어오기 위한 getter
    public String getpass()
    {
        return pass;
    }
}

public class Coll04
{
    public static void main(String[] args)
    {
        // 입력값을 받고 HashMap 컬렉션 생성
        Scanner sc = new Scanner(System.in);
        HashMap&lt;String, ID&gt; info = new HashMap&lt;String, ID&gt;();

        System.out.println(&quot;▶ 등록할 키값, 아이디, 비밀번호 입력: &quot;);

        //값을 저장하기 위한 반복문 생성
        for (int i = 0; i &lt; 5; i++)
        {
            System.out.print(&quot;&gt;&gt; &quot;);
            String text = sc.nextLine();
            // ,(쉼표를 기준으로) 문자열을 쪼갬
            StringTokenizer st = new StringTokenizer(text, &quot;,&quot;); 
            // 앞뒤 공백을 제거(trim), 입력한 값을 변수에 저장한다.
            String key = st.nextToken().trim(); 
            String ida = st.nextToken().trim();
            String pass = st.nextToken().trim();

            // 생성자 id로 매개변수를 호출
            ID ID = new ID(key, ida, pass);
            // key와 ID는 HASHMAP 컬렉션에 넣는다.
            info.put(key, ID);
        }

        Set&lt;String&gt; key01 = info.keySet(); // 해시맵 info에 있는 모든 키 Set 컬렉션으로 변환
        Iterator&lt;String&gt; it = key01.iterator(); // Set을 순차검색하는 이터레이터 생성
        System.out.println(&quot;---------------------------&quot;);
        while (it.hasNext())
        {
            String key1 = it.next();
            ID ID = info.get(key1); // ID를 키로 하여 객체를 얻는다.
            System.out.println(&quot;정상적으로 저장했습니다.&quot;);
            System.out.print(ID.getkey() + &quot; &quot;);
            System.out.print(ID.getida() + &quot; &quot;);
            System.out.println(ID.getpass() + &quot; &quot;);
        }
        System.out.println(&quot;---------------------------&quot;);

        while (true)
        {
            System.out.print(&quot;★ 조회할 키값 입력 &gt;&gt; &quot;);
            String key1 = sc.nextLine();
            if (key1.equals(&quot;그만&quot;))
                break;

            ID ID = info.get(key1); // 해시맵에서 이름을 키로 검색
            if (ID == null)
            { // 이름이 해시맵에 없다면
                System.out.println(key1 + &quot;라는 데이터는 존재하지 않습니다.&quot;);
            } else
            { // 해시맵에서 검색된 목록 출력
                System.out.println(&quot;====================&quot;);
                System.out.println(&quot;키값(key): &quot;+ID.getkey());
                System.out.println(&quot;아이디(id): &quot;+ID.getida());
                System.out.println(&quot;비밀번호(pw): &quot;+ID.getpass());
                System.out.println(&quot;====================&quot;);
            }
        }
        sc.close();
    }
}</code></pre>
<ol start="5">
<li>이 프로그램은 매우 디테일하게 구현된 가위바위보이다.
중요한 점은 오류가 날만한 경우의 수를 생각하고 그에 따라 기능과 흐름을
놓치지 말고 따라가며 하나하나 구현하는 것이다.
게임중일때도 게임의 틀에 벗어나는 입력시에는
카운팅되지 않아 원인을 친절하게 안내하고 재입력을 요구하여 게임을 끝까지
진행시키는 것이 목적이다. 
주석에 코드 설명이 나와있으니 꼭 참고하자!</li>
</ol>
<pre><code class="language-c">public class Coll05
{
    public static void main(String[] args)
    {
        // 가위바위보게임만들기
        Scanner input = new Scanner(System.in);

        // 게임결과 값을 표현한 변수
        int win = 0, lose = 0, draw = 0, fail = 0, count=0; 
        // 게임횟수 변수
        String coin;

        System.out.print(&quot;동전을 넣으세요(최대 5): &quot;);

        // 값이 숫자가 아닐 경우 무한반복
        while (!input.hasNextInt())
        {
            input.next();// 값이 숫자가 아니면 다음으로 넘어간다.
            System.out.println(&quot;============================================&quot;);
            System.out.println();
            System.out.println(&quot;※ 동전을 잘못 넣으셨습니다. 재실행해주세요!&quot;);
            System.out.println();
            System.out.println(&quot;================GAME END====================&quot;);
        }

        coin = input.next();// 정상 입력된 숫자라면, 게임횟수 값 저장
        int coinInt = Integer.valueOf(coin);// 정수형 값(int)로 형변환

        // 예외인 경우 게임실행 x
        if (coinInt &gt; 5)
        {
            System.out.println(&quot;============================================&quot;);
            System.out.println();
            System.out.println(&quot;※ 최대 5판까지만 게임이 가능합니다.&quot;);
            System.out.println();
            System.out.println(&quot;================GAME END====================&quot;);
            return;
        } 
        // 코인을 넣지 않았을 경우
        else if (coinInt == 0)
        {
            System.out.println(&quot;============================================&quot;);
            System.out.println();
            System.out.println(&quot;※ 동전을 넣어주셔야 게임 실행이 가능합니다.&quot;);
            System.out.println();
            System.out.println(&quot;================GAME END====================&quot;);
            return;
        } 
        // 음수값일 경우
        else if (coinInt &lt; 0)
        {
            System.out.println(&quot;============================================&quot;);
            System.out.println();
            System.out.println(&quot;※ 동전이 들어가지 않았습니다. 재실행해주세요.&quot;);
            System.out.println();
            System.out.println(&quot;================GAME END====================&quot;);
            return;
        }
        // 이상없으면 게임 정상적으로 실행

        // GAME START
        System.out.println(&quot;===============GAME START================&quot;);
        System.out.println();
        System.out.println(&quot;▶ 무엇을 내시겠습니까? 가위[1] 바위[2] 보[3]&quot;);

        // 코인에 입력한 횟수만큼 반복하는 게임창
        for (int i = 0; i &lt; coinInt; i++)
        {
            String npc = &quot;&quot;, user = &quot;&quot;; // 컴퓨터와 사용자의 가위,바위,보 선택 변수
            int computer = (int) Math.ceil(Math.random() * 3);// 난수 생성(랜덤)

            while (!input.hasNextInt())
            { // 값이 숫자인지 판별,입력값이 숫자가 아니라면 while문 실행
                input.next();// 값이 숫자가 아니면 버린다.
                System.out.println(&quot;=========================================&quot;);
                System.out.println(&quot;▶ 잘못 입력하셨습니다.&quot;);
                System.out.println(&quot;▷ 가위[1] 바위[2] 보[3] 재입력: &quot;);
                System.out.println(&quot;=========================================&quot;);
            }

            String userInput = input.next();// 사용자의 입력값
            int userInputInt = Integer.parseInt(userInput);
            // 유저의 가위바위보
            switch (userInputInt)
            {
            case 1:
                user = &quot;가위&quot;;
                count++;
                break;
            case 2:
                user = &quot;바위&quot;;
                count++;
                break;
            case 3:
                user = &quot;보&quot;;
                count++;
                break;
            default:
                user = &quot;손가락 오류&quot;;
            }
            // 컴퓨터의 가위바위보
            switch (computer)
            {
            case 1:
                npc = &quot;가위&quot;;
                break;
            case 2:
                npc = &quot;바위&quot;;
                break;
            case 3:
                npc = &quot;보&quot;;
                break;
            default:
                npc = &quot;시스템 오류&quot;;
            }
            System.out.println(&quot;===============[&quot;+ coin + &quot;판/&quot;+ count +&quot;판中]===============&quot;);
            System.out.println(&quot;[유저] &quot; + user + &quot; VS &quot; + npc + &quot; [컴퓨터]&quot;);

            // 가위바위보 승패 설정
            if (userInputInt &gt;= 1 &amp;&amp; userInputInt &lt;= 3)
            {// 유저의 가위바위보 입력값이 1~3일 때만 정상 진행
                // 가위=1,바위=2,보=3
                if ((computer == 1 &amp;&amp; userInputInt == 2) || (computer == 2 &amp;&amp; userInputInt == 3)
                        || (computer == 3 &amp;&amp; userInputInt == 1))
                {// 유저가 이긴경우
                    win++;
                    System.out.println(&quot;[승리]&quot;);
                } 
                else if (computer == userInputInt)
                {// 무승부인경우
                    draw++;
                    System.out.println(&quot;[무승부]&quot;);
                } 
                else
                {
                    lose++;
                    System.out.println(&quot;[패배]&quot;);
                }
            } 
            else
            {// 오류상황
                fail++;
                coinInt++; //게임횟수에 포함하지 않는 재입력 요구
                System.out.println(&quot;가위[1] 바위[2] 보[3] 재입력: &quot;);
            }
            System.out.println(&quot;=========================================&quot;);
        }
        float wins = ((float) win / (float) (coinInt)) * 100; // 승률변수 =(이긴횟수/총 경기)x100

        System.out.println(&quot;[결과] 총 게임수 : &quot; + coin);
        System.out.println(&quot;[전적] win:&quot; + win + &quot;번, lose:&quot; + lose + &quot;번, draw:&quot; + draw + &quot;번, 무효:&quot; + fail + &quot;번&quot;);
        System.out.printf(&quot;[승률] %.2f%% \n&quot;, wins);
        System.out.println(&quot;================GAME END=================&quot;);
        input.close();
    }
}</code></pre>
<blockquote>
<ul>
<li>이렇게 자바(JAVA) 공부의 후반부 시작을 알리는 
제네릭과 컬렉션 프레임워크가 끝이 났다.
이는 자바(JAVA)가 정한 규칙이며 형식 및 틀이기에 암기할 것도 많고
아이디어도 중요할 뿐아니라 논리적으로 생각할 것도 많은 어려운 파트이다.
한번보고 모두 익힐 수 없는 것이 당연하기에 지속적으로 여러번
많이 복습이 필요한 파트이다!</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.12] 유용한 클래스(Useful Class)와 예외처리(Exception Handling) +어노테이션👀]]></title>
            <link>https://velog.io/@kama_code/JAVA.12-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EC%82%AC%EC%9A%A9Useful-Class%EA%B3%BC-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%ACException-Handling</link>
            <guid>https://velog.io/@kama_code/JAVA.12-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EC%82%AC%EC%9A%A9Useful-Class%EA%B3%BC-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%ACException-Handling</guid>
            <pubDate>Sat, 22 Jul 2023 19:38:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>이전에 기초 클래스에서 배웠다. 
이번 파트는 디테일이 들어가게 된다. 
프로그램의 생각치 못한 오류가 났을때 처리 방법과 
클래스의 다양한 사용에 대해 다뤄볼 것이다.</li>
</ul>
</blockquote>
<h3 id="step1-유용한-클래스useful-class">&lt;Step.1&gt; 유용한 클래스(Useful Class)</h3>
<ol>
<li>java.lang 클래스
ㄴimport 하지 않아도 자동으로 Import되는 java 안에 내장되어 있는 라이브러리
ㄴ많이 사용하는 기본 클래스들이 속한 패키지</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/e58b9356-161f-4435-a249-a8bedf975590/image.PNG" width = "70%" height = "70%">

<ol start="2">
<li>Object 클래스
ㄴ모든 자바 클래스의 최상위 클래스이다
ㄴ모든 자바 클래스는 Object 클래스로부터 상속을 받는다.
ㄴ컨트롤 + T를 누르면 족보를 확인할 수 있는데 최상단에 위치함을 볼 수 있다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/76970c43-b512-4c92-844d-81018a4f0427/image.PNG" width = "70%" height = "70%">


<ol start="3">
<li>toString() 메소드
ㄴObject 클래스에 정의된 형태: public String toString() { … }
ㄴ객체 정보를 String으로  바꿔서 사용할 때 많이 사용된다.
ㄴprintln()메소드로 인자가 전달되면 자동으로 toString() 메소드가 호출된다. </li>
</ol>
<pre><code class="language-C">class MyFriends extends Object {
    String myName=&quot;성유겸&quot;;
    @Override
    public String toString() {
        return &quot;이름:&quot;+ myName;
    }
}
실행결과

public static void main(String[] args) {
    myFriends fnd1 = new myFriends();
    System.out.println(fnd1);
}</code></pre>
<p>★ [이름: 성유겸] 이 출력된다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/3b2c1bcb-1f5f-4436-b301-3e0babe19295/image.PNG" width = "80%" height = "80%">

<ol start="4">
<li>equals() 메소드
ㄴ상속받은 클래스에서 오버라이딩으로 비교하고 싶은 항목을 재정의해서 비교하라는 것.
ㄴ간단하게 참조값(주소값) 안에 있는 실제 값을 본다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/5ceecfb7-40ac-46e1-8ac4-0f3aa13c6059/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/8c72c5d6-9865-466d-9475-dc1cf10d3241/image.PNG" width = "50%" height = "50%">

<blockquote>
<ul>
<li>myBook1과 myBook2의 equals 비교는 id만 있기에 id로 비교한다.
myBook1.author과 myBook2.author의 equals 비교는 값이 있기에 값을 비교한다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/3708de32-95f8-460c-a55e-894529cfcf2e/image.PNG" width = "90%" height = "90%">

<img src = "https://velog.velcdn.com/images/kama_code/post/d9baa5cf-e982-4db2-87bd-9f7dbd2365d2/image.PNG" width = "50%" height = "50%">

<ol start="5">
<li>내부 클래스(Inner class) : 클래스 안에 정의된 클래스로 static이 없는 클래스를 말한다<ul>
<li>외부 클래스의 모든 멤버를 사용할 수 있다</li>
<li>정적 멤버를 가질 수 없다. 단 상수는 가질 수 있다</li>
<li>이벤트 기반의 프로그래밍에서 사용된다.</li>
<li>컴파일시 외부클래스 이름 $내부클래스 이름.class 형식으로 파일이 만들어진다</li>
</ul>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/71c011c8-6ceb-47d0-a935-ec481cad1133/image.PNG" width = "90%" height = "90%">

<ul>
<li>멤버 내부 클래스의 객체는 외부 클래스의 객체에 종속적이다 .</li>
<li>외부 클래스는 내부클래스를 멤버변수처럼 사용할 수 있고, 
내부 클래스는 외부 클래스의 자원을 직접 사용할 수 있는 장점이 있다.</li>
</ul>
<p>▣ 선언 방법</p>
<pre><code class="language-c">class OuterClass
{
    ...
    class InnerClass
    {
        ...
    }
}</code></pre>
<ul>
<li>OuterClass의 객체를 생성한 후 InnerClass의 객체를 생성할 수 있다.</li>
<li>InnerClass 내에서는 OuterClass의 멤버에 직접 접근할 수 있다.</li>
<li>InnerClass의 객체는 자신이 속할 OuterClass의 객체를 기반으로 생성된다. </li>
<li>정적멤버를 가질 수 없다. 단 상수(final)는 가능하다.</li>
</ul>
<p>▣ 객체생성 방법</p>
<pre><code class="language-c">public static void main(String[] args) {

    OuterClass outerClass = new OuterClass();
    #내부클래스 생성방법1
    OuterClass.InnerClass in1 = outerClass.new InnerClass();
    #내부클래스 생성방법2
    OuterClass.InnerClass in2 = new OuterClass().new InnerClass();
}</code></pre>
<ol start="6">
<li>익명 클래스(Anonymous class) - 이름이 없는 클래스<ul>
<li>내부클래스처럼 이벤트 기반의 프로그래밍에서 많이 사용</li>
<li>부모클래스의 메소드를 오버라이딩 하는 것이 목적이다</li>
<li>★★ 마지막에 <strong>세미콜론을 반드시 기술</strong>해야 한다.</li>
<li>형식: 부모클래스명 참조변수 = new 부모클래스명() {
익명 클래스의 실행부;
부모클래스의 메소드 오버라이딩();</li>
</ul>
</li>
</ol>
<p>▣ 선언 방법</p>
<pre><code class="language-c">class Person {
    String name;
    public Person(String n) {
        name = n;
    }
    void printInfo() {
        System.out.printf(&quot;이름:%s&quot;, name);
    }
}
public class AnonymousClass {
    public static void main(String[] args) {        
        Person anonyPerson = new Person(&quot;이사람&quot;){
            @Override
            void printInfo() {
                System.out.println(&quot;익명클래스에서 오버라이딩&quot;);
            }
        };
        anonyPerson.printInfo();
    }
}
</code></pre>
<ul>
<li>이름이 없는 클래스이므로 익명클래스라고 한다. </li>
<li>부모클래스의 메소드를 <strong>오버라이딩 하는것이 주된 목적</strong>이다.</li>
<li>익명클래스에서 확장한 멤버는 익명클래스 내에서만 접근가능하다.</li>
<li>익명 내부 클래스는 예전에 자바 UI에서 이벤트를 처리하는 데 많이 사용했다.  </li>
<li>현재는 안드로이드 프로그래밍에서 위젯의 이벤트 처리하는 핸들러를 구현할 때 사용한다.</li>
</ul>
<ol start="7">
<li>Wrapper 클래스<blockquote>
<ul>
<li>기본자료형의 데이터를 객체화할 때 사용하는 클래스</li>
<li>제네릭 클래스에서는 Box&lt;T, S&gt; 형태의 타입매개변수를 사용하게 되는데
이때 반드시 Wrapper클래스가 필요하다</li>
</ul>
</blockquote>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/f12f1bf7-a745-4fc2-8939-8dbf9c205fa1/image.PNG" width = "40%" height = "40%">

<ul>
<li>Wrapper 클래스는 보통 이렇게 사용한다.</li>
</ul>
<pre><code class="language-c">public static void main(String[] args) {
    // 정수 34를 객체화 해서 showDate라는 메소드의 인자로 전달한다. 
    Integer integer = new Integer(34); 
    showData(integer);
    showData(new Integer(99));
}
</code></pre>
<ul>
<li>parseInt()
: 숫자형식의 문자열을 숫자로 변경한다. </li>
</ul>
<p>intValue -&gt; 정수형으로 씌운다. (변환)
doubleValue -&gt; 실수형으로 씌운다. (변환)</p>
<ul>
<li><p>codePointAt()
: 문자열에서 index에 해당하는 한 문자의 아스키코드값을 반환한다.</p>
</li>
<li><p>isDigit()
: 문자열이 숫자인지 판단한다.</p>
</li>
<li><p>isLetter()
: 문자 여부를 판단하는 메소드로 특수기호나 숫자형은 false를 반환</p>
</li>
<li><p>isWhietspace()
: 공백문자인지 판단</p>
</li>
<li><p>isLowerCase(), isUpperCase()
: 대소문자를 판단. 단 영문자에만 적용되며 알파벳이 아닌 문자에 적용시 false를 반환</p>
</li>
</ul>
<p>※ 왜 이것을 쓸까?</p>
<pre><code class="language-c">public static void myFunc(Object obj) {    
    System.out.println(obj);
}</code></pre>
<ul>
<li>myFunc() 메소드는 호출시 기본자료형 데이터 전달이 불가능하다. </li>
<li>이러한 상황에 Wrapper 클래스를 사용하여 아래처럼 데이터를 객체화(인스턴스화) 한다. </li>
</ul>
<p>▼ int정수형 자료를 가지고 Wrapper 클래스 정의한 예시 ▼</p>
<pre><code class="language-c">class IntWrapper
{
    private int num;
    public IntWrapper(int data)
    {
        num=data;
    }
    public String toString()
    {
        return &quot;&quot;+num;
    }
}</code></pre>
<ol start="8">
<li>Number 클래스<blockquote>
<p>java.lang.Number 클래스는 모든 래퍼 클래스가 상속하는 추상 클래스이다 .</p>
</blockquote>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/56810bf4-db4d-4dbf-837d-a5ed7600290d/image.PNG" width = "50%" height = "50%">

<ol start="9">
<li>박싱(Boxing)과 언박싱(Boxing)<blockquote>
<p>박싱은 인스턴스의 생성을 통해서 이뤄지지만
언박싱은 래퍼 클래스에 정의된 메서드의 호출을 통해 이뤄진다.</p>
</blockquote>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/8840ec10-ef78-46be-bcf7-931f0e34357e/image.PNG" width = "90%" height = "90%">


<p>예시 :</p>
<ul>
<li>Boxing : 기본자료형의 데이터를 Wrapper객체로 감싸는것</li>
<li>Unboxing : Wrapper객체에서 기본자료 형의 데이터를 꺼내는것</li>
</ul>
<pre><code class="language-c">// 10이라는 정수를 suja라는 상자에 박싱(포장했다!)
Integer suja = new Integer(10);    // 박싱
// suja라는 박스 안에 정수형 값을 꺼내어 정수형 unboxing 변수에 꺼냈다!
int unboxing = suja.intValue(); // 언박싱
System.out.println(unboxing);
</code></pre>
<ol start="10">
<li>오토박싱(Auto Boxing)과 오토언박싱(AutoBoxingUnboxing)</li>
</ol>
<ul>
<li><p>Auto Boxing - 기본자료형의 데이터를 자동 으로 Wrapper객체로 감싸는 것을 뜻함</p>
</li>
<li><p>Auto Unboxing - Wrapper객체에서 기본자료 형의 데이터가 자동으로 꺼내 지는것을 뜻함</p>
</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/054ee810-442d-4010-92cb-7832c3855adc/image.PNG" width = "70%" height = "70%">

<pre><code class="language-c">Integer integer = 10;    
System.out.println(integer);

// 객체생성을 하지 않아도 박싱이 된다.
Character ch = &#39;X&#39;; // Character ch = new Character(&#39;X&#39;); : 오토박싱
// 언박싱하지 않아도 값을 꺼낼 수 있다.
char c = ch;        // char c = ch.charValue();           : 오토언박싱</code></pre>
<ul>
<li>인스턴스가 와야하는데 기본자료형 데이터가 있다면 자동으로 Boxing된다.</li>
<li>데이터를 꺼낼때도 별도의 처리없이 자동으로 Unboxing된다.</li>
<li>Auto Boxing, Unboxing은 JDK1.5 이상 부터 지원된다. </li>
</ul>
<ol start="11">
<li>Math 클래스<blockquote>
<ul>
<li>Math클래스는 수학 관련 연산 기능을 제공한다.</li>
</ul>
</blockquote>
</li>
</ol>
<ul>
<li>Math클래스에 정의된 메서드는 모두 static으로 선언되어 있다.</li>
<li>즉 Math는 기능의 제공이 목적일 뿐, 인스턴스의 생성을 목적으로 정의된 클래스는
아니다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/eda12a01-e8b1-471d-9d2a-d329f0a4e0ba/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/fc5a7123-0e2a-45fa-a65d-a68fadb1a814/image.PNG" width = "80%" height = "80%">

<img src = "https://velog.velcdn.com/images/kama_code/post/3bee6241-cced-4366-8ba3-ef692f5c0b76/image.PNG" width = "80%" height = "80%">

<ol start="12">
<li>Random 클래스</li>
</ol>
<ul>
<li>씨드(Seed)를 기반으로 난수생성</li>
<li>정수형, 실수형, boolean 등 모든 형태의 난수 생성가능</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/cabff218-99ec-4a8d-a857-cc3dba5f1128/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/338be952-0900-48d6-960a-67561588a9b8/image.PNG" width = "80%" height = "80%">

<ol start="13">
<li>▣ BigInteger &amp; BigDecimal 클래스</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/83d36e88-9284-4216-8e81-319cc7d2ec03/image.PNG" width = "80%" height = "80%">

<ol start="14">
<li>Arrays 클래스</li>
</ol>
<ul>
<li>배열의 비교는 두 배열에 저장된 데이터 수, 순서, 그리고 내용 모두가 같을 때 
true를  반환한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/10f2c23e-56bf-41aa-b089-c5c98f71b845/image.PNG" width = "80%" height = "80%">

<p>※ 오름차순 정렬? ( 밑에서부터 산을 올라간다.)
ㄴ값이 작은 순에서 큰 순으로 세워 나가는 정렬
ex) 1, 2, 3, 4, 5, 6, 7</p>
<p>※ compareTo 메소드</p>
<pre><code class="language-c">interface Comparable
→ int compareTo(Object o)

인자로 전달된 o가 작다면 양의 정수 반환  
인자로 전달된 o가 크다면 음의 정수 반환  
인자로 전달된 o와 같다면 0을 반환
</code></pre>
<ol start="15">
<li>Calendar 클래스</li>
</ol>
<ul>
<li>java.util.Calendar 클래스</li>
<li>날짜와 시간에 관한 데이터를 손쉽게 처리할 수 있도록 제공하는 추상 클래스</li>
</ul>
<blockquote>
<ul>
<li>add() 메소드
전달된 Calendar 필드에서 일정 시간 만큼을 더하거나 빼줍니다.
즉, 특정 시간을 기준으로 일정 시간 전후의 날짜와 시간을 알 수 있습니다.</li>
</ul>
</blockquote>
<pre><code class="language-c">Calendar time = Calendar.getInstance();
System.out.println(time.getTime());

time.add(Calendar.SECOND, 120);
System.out.println(time.getTime());</code></pre>
<blockquote>
<ul>
<li>before()와 after() 메소드
두 시간상의 전후 관계만을 알고 싶을 경우에는 before()와 after() 메소드를 사용</li>
</ul>
</blockquote>
<pre><code class="language-c">Calendar time1 = Calendar.getInstance();
Calendar time2 = Calendar.getInstance();
Calendar time3 = Calendar.getInstance();

time2.set(1982, 2, 19);
time3.set(2020, 2, 19);

System.out.println(time1.before(time2));
System.out.println(time1.before(time3));</code></pre>
<blockquote>
<ul>
<li>get() 메소드
전달된 Calendar 필드에 저장된 값을 반환합니다.</li>
</ul>
</blockquote>
<pre><code class="language-c">Calendar time = Calendar.getInstance();

System.out.println(time.getTime());
System.out.println(time.get(Calendar.DAY_OF_WEEK));
System.out.println(time.get(Calendar.MONTH) + 1);
System.out.println(time.get(Calendar.DAY_OF_MONTH));
System.out.println(time.get(Calendar.HOUR_OF_DAY));
System.out.println(time.get(Calendar.MINUTE));
System.out.println(time.get(Calendar.SECOND));
System.out.println(time.get(Calendar.YEAR));</code></pre>
<blockquote>
<ul>
<li>roll() 메소드
전달된 Calendar 필드에서 일정 시간 만큼을 더하거나 빼줍니다.</li>
</ul>
</blockquote>
<pre><code class="language-c">Calendar time1 = Calendar.getInstance();
Calendar time2 = Calendar.getInstance();
System.out.println(time1.getTime());


time1.add(Calendar.SECOND, 60);
System.out.println(time1.getTime());


time2.roll(Calendar.SECOND, 60);
System.out.println(time2.getTime());</code></pre>
<blockquote>
<ul>
<li>set() 메소드
전달된 Calendar 필드를 특정 값으로 설정합니다.</li>
</ul>
</blockquote>
<pre><code class="language-c">Calendar time = Calendar.getInstance();
System.out.println(time.getTime());

time.set(Calendar.YEAR, 2020);
System.out.println(time.getTime());

time.set(1982, 1, 19); // 1은 2월을 나타냄.
System.out.println(time.getTime());

time.set(1982, 1, 19, 12, 34, 56);
System.out.println(time.getTime());</code></pre>
<h3 id="step2-열거형-가변-인자-어노테이션">&lt;Step.2&gt; 열거형, 가변 인자, 어노테이션</h3>
<ul>
<li>열거형이란?
ㄴ관련된 상수(final)들을 같이 묶어 놓은 것. </li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/201f4dc3-dba4-4c5c-bcc9-b29decd69c58/image.PNG" width = "80%" height = "80%">

<img src = "https://velog.velcdn.com/images/kama_code/post/361edced-323f-4623-aaf5-9a77ccbd0404/image.PNG" width = "70%" height = "70%">

<p>※ Enum 클래스 : enum 열거체이름 { 상수1이름, 상수2이름, ... }</p>
<blockquote>
<ol>
<li>열거체를 비교할 때 실제 값뿐만 아니라 타입까지도 체크합니다.</li>
<li>열거체의 상숫값이 재정의되더라도 다시 컴파일할 필요가 없습니다.</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/4fca282c-bea2-492a-9702-9c271b0a3263/image.PNG" width = "80%" height = "80%">

<ul>
<li>가변 인자란?
ㄴ기존에는 메서드의 매개변수 개수가 고정적이었나 JDK1.5부터 동적으로 
지정해 줄 수 있게 되었으며, 이 기능을 가변 인자라고 한다.
ㄴ가변인자를 나타내는 기호(...)를 사용한다.
ㄴ변수 타입뒤에 붙여주고 변수명을 쓰면 끝</li>
</ul>
<pre><code>public PrintStream printf(String format, Object... args) { ... }</code></pre><img src = "https://velog.velcdn.com/images/kama_code/post/54299ece-e8a1-40e0-829f-b362d129ed59/image.PNG" width = "90%" height = "90%">

<p>-&gt; 가변인자는 매개변수 중에서 제일 마지막에 선언해야 한다.</p>
<ul>
<li>어노테이션(Annotation)이란? </li>
</ul>
<ol>
<li>사전적 의미로는 주석이라는 뜻이다.</li>
<li>자바에서 Annotation은 코드 사이에 주석처럼 쓰이며 특별한 의미, 기능을 수행하도록 하는 기술이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/a2f132b1-630d-471b-9bc8-7b2db8c16554/image.PNG" width = "80%" height = "80%">

<p>@Override
    - 선언한 메서드가 오버라이딩 되었다는 것을 나타냄
    - 만약 상위(부모) 클래스( 또는 인터페이스)에서 해당 메서드를 찾을 수 없다면
    컴파일 에러를 발생시킵니다.</p>
<pre><code>   @Deprecated
 - 해당 메서드가 더이상 사용되지 않음을 표시
 - 만약 사용할 경우 컴파일 경고를 발생시킵니다.</code></pre><p>   @SuppressWarnings
     - 선언한 곳의 컴파일 경고를 무시하도록 합니다.</p>
<h3 id="step3-예외처리exception-handling">&lt;Step.3&gt; 예외처리(Exception Handling)</h3>
<blockquote>
<ul>
<li>프로그램을 만들다보면 사람이 만들다보니 완벽할 수만은 없어서 에러가 날 수 있다
프로그램을 실행했을때 에라가 발생하면 프로그램이 멈추게 되는데
멈추지 않고 에러를 던져서 프로그램을 계속 이어나가게 하는 매우매우 중요한 내용이다!</li>
</ul>
</blockquote>
<ul>
<li>예외란?
예측 가능한 런타임 에러를 예외exception라고 부른다. 
그리고 개발자가 다음과 같은 목적을 위해 제어하고 처리를 한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/2d8be786-c1b8-4f4b-b3f1-792b35ef4eba/image.PNG" width = "50%" height = "50%">

<p>※ 에러의 종류</p>
<ol>
<li>컴파일 에러(문법 에러)</li>
</ol>
<ul>
<li>문법을 잘못 작성하여 발생하며 실행시 오류를 일으키게 됩니다.</li>
<li>어느 곳에 문제가 있는지 컴파일러가 정확한 위치를 알려줍니다.</li>
<li>오류가 발생한 부분을 표시해주기에 수정하고 다시 실행하면 비교적 쉽게 해결할 수 있습니다.</li>
</ul>
<p>해결방법: try~catch문으로 감싸서 해결이 가능합니다.</p>
<ol start="2">
<li>런타임 에러</li>
</ol>
<ul>
<li>프로그램 실행중 발생하는 에러</li>
</ul>
<p>해결방법: 프로그래머의 논리력으로 추적해서 문제가 있는 부분을 찾아야 합니다.</p>
<h3 id="◆-논리-error">◆ 논리 Error</h3>
<ul>
<li>프로그래머의 논리적 오류에 의해 발생</li>
<li>나눗셈을 할 때 0으로 나눈 경우 발생</li>
</ul>
<h3 id="◆-시스템-error">◆ 시스템 Error</h3>
<ul>
<li>시스템 자체의 문제에 의해 발생되며 프로그래머가 처리하기 어려운 에러</li>
<li>운영체제, 시스템, 네트워크, 데이터베이스를 확인 후 해결해야 합니다.</li>
</ul>
<h3 id="◆-syntax-error">◆ Syntax Error</h3>
<ul>
<li>실행 자체가 되지 않는 문법상 오류가 있는 코드
ㄴ컴파일에러와 비슷합니다.</li>
</ul>
<h3 id="◆-semantic-error">◆ Semantic Error</h3>
<ul>
<li>프로그램이 오류를 내지 않고 실행되지만 올바르게 동작하지 않은 상태</li>
</ul>
<h3 id="◆-로지컬-error">◆ 로지컬 Error</h3>
<ul>
<li>프로그램이 오류를 내지 않고 실행되지만 프로그래머가 설계한 방향이 아닌
다른 방향으로 실행이 되는 에러</li>
</ul>
<h3 id="실행-예외-">실행 예외 :</h3>
<img src = "https://velog.velcdn.com/images/kama_code/post/30c9af9c-0f19-4eaa-85e0-35c76ba8f7a6/image.PNG" width = "80%" height = "80%">

<p>InputMismatchException : 정수형의 자료를 입력받을때 문자를 입력하면 발생</p>
<p>ArrayIndexOutOfBoundsException : 배열의 크기를 벗어난 인덱스를 사용할 경우 발생</p>
<p>ClassCastException : 객체의 형변환이 불가능한 경우 발생</p>
<h3 id="일반-예외-">일반 예외 :</h3>
<img src = "https://velog.velcdn.com/images/kama_code/post/f4e185de-22c4-47ff-b450-4223d2216565/image.PNG" width = "80%" height = "80%">

<ul>
<li>▣ try ~ catch 문
try는 예외가 발생할 가능성이 있는 지역을 감싸는 목적
catch는 발생한 예외를 처리하기 위한 목적</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/5472b592-4f46-46c9-b3bb-21b7b18be3a4/image.PNG" width = "90%" height = "90%">

<ul>
<li>▣ e.getMessage()
예외가 발생한 원인을 문자열로 반환한다
모든 예외 클래스는 Throwable 클래스를 상속하므로 getMessage()메소드를 사용할 수 있다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/bb79a249-08f3-46cb-a4a4-2955b78ac294/image.PNG" width = "50%" height = "90%">

<ul>
<li>▣ 예외처리 방법</li>
</ul>
<p>메소드에 예외선언: throws를 클래스 뒤에 써서 어떤 예외를 처리하면 되는지
쉽게 알 수 있다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/e3009efd-342d-4a2f-9c5d-aa61e2a0f3e2/image.PNG" width = "60%" height = "60%">

<ul>
<li><p>▣ 여러개의 catch 블럭 정의 (디테일 catch)
하나의 try블럭에 둘 이상의 catch블럭을 구성할 수 있다. 
컴파일러는 catch블럭을 순차적으로 실행하면서 해당하는 예외가 있는지 검사한다. 
단, Exception클래스나 Throwable클래스는 가장 마지막에 기술해야 한다. </p>
</li>
<li><p>Exception
모든 예외 한 번에 처리하기
어떤 예외가 발생할지 모를 때 모든 예외의 최상위 클래스를 이용해서 
예외를 처리해줄 수 있다. 
ㄴ단점은 사용자에게 어떤 오류가 발생했는지 디테일한 오류 설명이 불가능하다.</p>
</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/713640d4-8e1b-403c-ae80-13849de83e03/image.PNG" width = "50%" height = "50%">

<ul>
<li>항상 실행되는 finally 블럭</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/23fbfce7-753c-4105-b40e-fd61988e19ab/image.PNG" width = "70%" height = "70%">

<ul>
<li>▣ 개발자정의 예외 클래스
ㄴ개발자가 논리적으로 직접 예외를 처리해야 하는 것도 있다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/eb0eb1eb-691e-4dbf-a810-ac4139c5ecde/image.PNG" width = "70%" height = "70%">

<h2 id="step4-발전을-위한-문제풀이-kama_code-출제">&lt;Step.4&gt; 발전을 위한 문제풀이 (kama_code 출제)</h2>
<blockquote>
<p>업다운 게임을 만들고 예외처리를 추가하여 잘못된 입력에도 
프로그램이 종료되지 않도록 구현하시오. 
a.입력시 숫자가 아닌 문자를 입력하는 경우
b.1~100 사이의 숫자가 아닌 경우</p>
</blockquote>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<img src = "https://velog.velcdn.com/images/kama_code/post/ce422cef-6fdc-416e-8f5a-82eaf87e2922/image.PNG" width = "50%" height = "50%">

<pre><code class="language-c">import java.util.Scanner;

class UpDownGame 
{
    private static int COUNT = 7;
    private int[] arrInput;// 사용자 입력
    private int answer;

    public UpDownGame() 
    {
        arrInput = new int[COUNT];
        answer = (int) (Math.random() * 100 + 1);
    }
    public void run() 
    {
        boolean forEnd = false;
        try 
        {
            for (int i = 0; i &lt; arrInput.length; i++) 
            {
                Scanner sc = new Scanner(System.in);

                System.out.print(&quot;숫자를 입력해주세요 : &quot;);
                int num = sc.nextInt();

                if (num &gt; answer) 
                {
                    System.out.println(&quot;Down ===&gt; &quot; + (COUNT - i - 1) + &quot;번 남아 있습니다.&quot;);
                } 
                else if (num &lt; answer) 
                {
                    System.out.println(&quot;Up ====&gt; &quot; + (COUNT - i - 1) + &quot;번 남아 있습니다.&quot;);
                } 
                else 
                {
                    System.out.println(&quot;일치====&gt; &quot; + (i+1) + &quot;번만에 정답!!&quot;);

                    //사용자가 숫자를 맞추었을 때만 true로 변경한다
                    forEnd = true;

                    break;
                }
            }
            // false를 유지하고 있다면 맞추지 못한 경우이므로 실패처리
            if (forEnd == false)
            {
                System.out.println(&quot;당신은 실패하셨습니다. 노력하세요!&quot;);
                return;
            }
        } 
        catch (Exception e) 
        {
            System.out.println(&quot;잘못된 입력입니다. 처음부터 다시 입력하세요&quot;);
            return;
        }
    }
}
    public class QuUpDownException 
    {
        public static void main(String[] args) 
        {
            Scanner sc;
            UpDownGame game;

        while (true) 
        {
            try 
            {
                sc = new Scanner(System.in);
                System.out.println(&quot;게임시작 1&quot;);
                System.out.println(&quot;게임종료 2&quot;);
                System.out.println(&quot;&gt;&gt;&quot;);

                int num = sc.nextInt();
                if (num == 1) 
                {
                    game = new UpDownGame();
                    game.run();
                } 
                else if (num == 2) 
                {
                    System.out.println(&quot;게임을 종료합니다.&quot;);
                    break;
                }
                else
                {
                    System.out.println(&quot;잘못된 입력입니다.&quot;);
                    System.out.println(&quot;게임을 다시 시작 합니다.&quot;);
                    continue;
                }
            } 
            catch (Exception e) 
            {
                System.out.println(&quot;잘못된 입력입니다.&quot;);
                System.out.println(&quot;게임을 다시 시작 합니다.&quot;);
            }
        }
    }
}</code></pre>
<blockquote>
<p>여기까지 자바(java) 공부의 중반부까지 끝났다.
다음 파트부터는 자바(java) 공부의 후반부로 들어간다.
앞으로 코드는 점점 짧아진다. 
점점 코드는 발전하고 좀 더 쉽게 좀 더 효율적으로 좀 더 편리함을 계속 
추구하여 발전하기 때문이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.11] 상속(Inheritance)🐇]]></title>
            <link>https://velog.io/@kama_code/JAVA.11-%EC%83%81%EC%86%8DInheritance-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%8A%A4%ED%83%9C%ED%8B%B1%EC%9D%98-%EC%8B%AC%ED%99%94static</link>
            <guid>https://velog.io/@kama_code/JAVA.11-%EC%83%81%EC%86%8DInheritance-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%8A%A4%ED%83%9C%ED%8B%B1%EC%9D%98-%EC%8B%AC%ED%99%94static</guid>
            <pubDate>Sun, 16 Jul 2023 19:44:28 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>객체지향의 꽃은 바로 재활용일 것이다. 
상속은 객체지향의 재활용성을 극대화시킨 프로그래밍 기법이라고 할 수 있다.<br>효율성을 위한 프로그래밍이라 사고력이 필요하며 어려운 내용이기도 하다.</li>
</ul>
</blockquote>
<h2 id="step1-상속inheritance">&lt;Step.1&gt; 상속(Inheritance)</h2>
<blockquote>
<ul>
<li>상속(Inheritance)이란 물려준다는 의미가 있다. 
어떤 객체가 있을 때 그 객체의 변수와 메소드를 
다른 객체가 물려 받을 수 있는 기능을 말한다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/2c0d4712-4130-4075-baac-4234d2a24531/image.PNG" width = "80%" height = "80%">

<ul>
<li>여기서 Unit 클래스는 부모를 뜻하고 Marine Medic Firebat은 자식을 뜻한다.</li>
</ul>
<blockquote>
<ul>
<li>상속을 표현하기 위해선 extends를 붙인다.<img src = "https://velog.velcdn.com/images/kama_code/post/f6b1a8f9-3718-4000-977d-f1123119a6a1/image.PNG" width = "80%" height = "80%">
</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/6b3df76b-93e4-479d-9bd2-85438fb09dff/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/0afa43ad-86eb-4f26-8f45-6169698a76c3/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/951d938c-8d70-460b-b856-03549b3e8d51/image.PNG" width = "60%" height = "60%">

<h2 id="step2-상속관계에-있는-클래스의-객체-생성">&lt;Step.2&gt; 상속관계에 있는 클래스의 객체 생성</h2>
<blockquote>
<p>부모 클래스를 호출하기 위해선 부모 클래스의 생성자가 오버라이딩(재정의) 되어야 한다
ㄴsuper()을 통해 상속관계에 있는 부모클래스의 생성자를 호출할 수 있다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/765c0a2e-387c-4397-ae98-d28e73da0313/image.PNG" width = "60%" height = "60%">

<blockquote>
<ul>
<li>상속 관계에서 자식 클래스의 변수 삽입시 반드시 부모클래스의 생성자가 호출이 된다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/e7a6dc9d-cc22-48b8-b6cf-dba30a70404d/image.PNG" width = "60%" height = "60%">

<blockquote>
<p>접근지정자에 따라 protected와 public은 상속 관계에서 접근이 가능하나
private은 getter/setter에 의한 간접접근 외에 접근이 불가능하다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/f2485aa6-9825-4b2d-a40f-6a57de8e761d/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/4c095eeb-82d1-4df6-8262-567b7cbcad54/image.PNG" width = "50%" height = "50%">


<h2 id="step3-오버라이딩overriding">&lt;Step.3&gt; 오버라이딩(Overriding)</h2>
<blockquote>
<ul>
<li>부모것을 덮어 쓴것, 재정의 또는 변경하는 것을 말한다.
ㄴ메소드를 정의하여 덮어쓰는 것이다. 반환값의 형도 같아야만 한다.
ㄴ단, final은 클래스든 메소드든 변수든 오버라이딩을 할 수 없다. </li>
</ul>
</blockquote>
<p>★ 오버라이딩의 목적</p>
<ol>
<li>부모 클래스 메서드의 기능 변경</li>
<li>부모 클래스 메서드의 기능 추가 </li>
</ol>
<blockquote>
<p>showState()는 자식 클래스에서 오버라이딩되었다. (바꾼 것이다)
스피커의 볼륨의 크기를 베이스의 볼륨의 크기로 변경한 것(재정의) =&gt; 오버라이딩</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/5ddab346-fbb3-46df-a682-27aa65fdeca2/image.PNG" width = "60%" height = "60%">

<blockquote>
<ul>
<li>클래스 B는 부모 클래스 A를 오버라이딩하고
클래스 C는 클래스B를 오버라이딩했다.
클래스 A B C를 출력하면 전체 C 클래스의 출력문만 나온다. 
<span style='background-color: #fff5b1'>★ 오버라이딩으로 인해 A와 B가 모두 가려졌기 때문이다</span></li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/e9cf2563-69c9-49eb-8cc0-c1a8e42fb6ab/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/0db2cbfd-b94b-4333-9c15-ed90dd02a28b/image.PNG" width = "50%" height = "50%">

<h2 id="step4-가변인자variable-arguments">&lt;Step.4&gt; 가변인자(Variable Arguments)</h2>
<blockquote>
<ul>
<li>오버로딩을 대채할 수 있는 문법이다.</li>
</ul>
</blockquote>
<ul>
<li>메소드의 여러가지의 호출 형식으로 대체할 수 있다.</li>
</ul>
<p>ㅁ public PrintStream printf(String format, Object ...args) { ... }
ㄴ매개변수의 개수를 동적으로 지정해주는 방법이다.
ㄴ매개변수가 몇개가 올지 모르는 변수로 둔다는 뜻이다.</p>
<blockquote>
<p>ㅁ 사용법(규칙):</p>
</blockquote>
<ol>
<li>가변인자를 매개변수 중 제일 마지막에 사용해야 한다
ㄴ가변인자를 앞에 두면 메소드에서 매개변수를 가지고 올 때 
ㄴ어디까지가 가변인자인지 구분을 할 수 없게 되므로 오류 발생</li>
<li>같은 형식의 매개변수가 존재하는 오버로딩에서는 피해야 한다
ㄴ호출하여 전달해줄때 어떤 메소드로 전달해야하는지 애매모호해져서 오류 발생</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/41b02fec-6185-473d-8f3c-564239a55b38/image.PNG" width = "60%" height = "60%">

<h2 id="step5-추상-클래스abstract-class">&lt;Step.5&gt; 추상 클래스(Abstract Class)</h2>
<blockquote>
<ul>
<li>기능 구현이 없이 호출방법(이름)만 클래스에 표시된 클래스이다.
ㄴ<strong>무조건 오버라이딩</strong>해서 재정의하여 사용해야만 한다.</li>
</ul>
</blockquote>
<ul>
<li>추상 클래스는 어떻게 동작해야 하는지 알 수 없으므로 객체를 생성할 수 없다.
즉, new를 사용 할 수 없다.<img src = "https://velog.velcdn.com/images/kama_code/post/4e0c51d9-eb6a-48d7-9be3-b32b7119d1ec/image.PNG" width = "60%" height = "60%">

</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/a1c39184-4d3e-4a60-b324-1f250e736f6e/image.PNG" width = "60%" height = "60%">

<h2 id="step6-인터페이스interface">&lt;Step.6&gt; 인터페이스(Interface)</h2>
<blockquote>
<ul>
<li>상속 관계가 아닌 클래스에 기능을 제공하는 구조이다. <img src = "https://velog.velcdn.com/images/kama_code/post/6678bb74-cbe6-4854-98b1-2720dc2f2016/image.PNG" width = "60%" height = "60%">
</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>인터페이스의 특징 </li>
</ul>
</blockquote>
<ol>
<li>인터페이스끼리 상속도 가능하다</li>
<li>인터페이스가 일반 클래스를 상속할 수는 없다.</li>
<li>Java는 다중상속이 없다. 인터페이스는 기능만 있어 다중상속이 가능하다.</li>
<li>인터페이스로 선언한 변수는 public static final로 선언한다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/64780bd1-aeb1-4979-b8b5-3ca0fb32df76/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/54973b29-939a-4907-a0ec-11e6cbd4783e/image.PNG" width = "60%" height = "60%">

<h2 id="step7-추상-클래스와-인터페이스">&lt;Step.7&gt; 추상 클래스와 인터페이스</h2>
<blockquote>
<ul>
<li>그렇다면 인터페이스와 추상 클래스의 차이가 무엇일까?</li>
</ul>
</blockquote>
<ol>
<li>추상클래스는 오버라이딩을 통해 재정의하여 사용해야 하며 상속과 관련이 있다.</li>
<li>인터페이스는 단순히 기능만을 의미한다.</li>
<li>추상클래스는 다중상속이 불가능하지만, 인터페이스는 다중 상속이 가능하다.</li>
<li>추상클래스는 상속 관계를 쭉 타고 올라갔을때 같은 조상클래스를 상속하는데 
기능까지 완변히 똑같은 기능이 필요한 경우 주로 사용한다.</li>
<li>인터페이스는 상속 관계를 쭉 타고 올라갔을때 다른 조상클래스를 상속하는데 
같은 기능이 필요할 경우 인터페이스 사용한다.</li>
<li>추상클래스는 IS - A &quot;~이다&quot;식으로 해석된다.</li>
<li>인터페이스는 HAS - A &quot;~을 할 수 있는&quot;식으로 해석된다.</li>
</ol>
<ul>
<li>(추상클래스)는 해당 추상클래스를 상속받아서 기능을 이용하고 확장시키는데 목적</li>
<li>(인터페이스)는 함수의 껍데기만 있고 그 함수의 구현을 강제한다</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/7f40bd20-8458-42e6-8fe7-dde79cb19b8d/image.PNG" width = "70%" height = "70%">

<blockquote>
<ul>
<li>그렇다면 인터페이스와 추상 클래스의 공통점은 무엇일까?</li>
</ul>
</blockquote>
<ol>
<li>추상 메소드를 가지고 있어야 한다.</li>
<li>인스턴스화 할 수 없다 (new 생성자 사용 X)</li>
<li>인터페이스 혹은 추상 클래스를 상속받아 구현한 구현체의 객체를 사용해야 한다.</li>
<li>인터페이스와 추상클래스를 구현, 상속한 클래스는 추상 메소드를 반드시 구현하여야 한다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/adf3c13a-0fbe-4483-8816-03fb0b3f6696/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/619dba0b-ec59-44e5-b6fc-94fe8639f7e2/image.PNG" width = "60%" height = "60%">

<h2 id="step8-다형성polymorphism">&lt;Step.8&gt; 다형성(polymorphism)</h2>
<blockquote>
<ul>
<li>하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미</li>
</ul>
</blockquote>
<ul>
<li>동일한 조작방법으로 동작시키지만 동작방법은 다른 것. 
ㄴ키보드를 누른다 → 결과는 다 다르다는 것과 같음.</li>
<li>자바에선 대표적으로 오버로딩, 오버라이딩, 업캐스팅, 다운캐스팅, 
인터페이스, 추상메소드, 추상클래스가 모두 다형성에 해당한다.</li>
</ul>
<blockquote>
<ul>
<li>다형성의 장점</li>
</ul>
</blockquote>
<ol>
<li>유지보수 : 여러 객체를 하나의 타입으로 관리할 수 있어 유지보수가 용이하다.</li>
<li>재사용성 : 객체의 재사용이 쉬워 재사용성이 높아진다.</li>
<li>느슨한 결합 : 클래스 간의 의존성을 줄여 확장성은 높아지고 결합도는 낮아진다.</li>
</ol>
<blockquote>
<ul>
<li>다형성의 활용
카페에서 커피를 주문하는 것을 예로 Coffee 클래스에는 가격 정보를 담고 있다.
Coffee 클래스를 상속받는 Amercano 클래스와 CaffeLatte 클래스가 존재한다.
손님은 5만 원을 가지고 있다고 가정한다.</li>
</ul>
</blockquote>
<pre><code class="language-c">class Coffee {
    int price;

    public Coffee(int price) {
        this.price = price;
    }
}

class Americano extends Coffee {
    public Americano() {
        super(4000); // 상위 메서드 생성자 호출
    }
    // Object 클래스 toString() 메서드 오버라이딩
    public String toString() { 
        return &quot;아메리카노&quot;;
    }
}

class CaffeLatte extends Coffee {
    public CaffeLatte() {
        super(5000);
    }
    // Object 클래스 toString() 메서드 오버라이딩
    public String toString() {
        return &quot;카페라떼&quot;;
    }
}

class Customer {
    int money = 50000;

    // 커피 구매 메서드(다형성 활용)
    void buyCoffee(Coffee coffee) {
        if (money &lt; coffee.price) {
            System.out.println(&quot;잔액이 부족합니다.&quot;);
            return;
        }
        money -= coffee.price;
        System.out.println(coffee + &quot;를 구매하였습니다.&quot;);
    }

    /* 아메리카노, 카페라떼 구매 메서드를 따로 구현하지 않아도 됨
    (생략가능하므로 주석처리)
    void buyCoffee(Americano americano) {
        money -= americano.price;
    }

    void buyCoffee(CaffeLatte caffeLatte) {
        money -= caffeLatte.price;
    } */
}
public class PolymorphismEx {
    public static void main(String[] args) {
        Customer me = new Customer();
        me.buyCoffee(new Americano());
        me.buyCoffee(new CaffeLatte());

        System.out.println(&quot;현재 잔액: &quot; + me.money);
    }
}</code></pre>
<ul>
<li>다형성 사용의 효과</li>
</ul>
<ol>
<li>개별적인 커피의 구매 메서드를 따로 구현하지 않고, 
상위 클래스인 Coffee의 자료형을 매개변수로 전달받으면, 
하위 클래스 타입의 참조 변수는 매개변수로 전달될 수 있다.</li>
<li>반복적인 코드를 줄일 수 있다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/c4ef89bb-d8eb-4c2c-85f3-31586295535c/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/659bc968-09c5-45f3-b047-1be7e6c768af/image.PNG" width = "80%" height = "80%">

<h2 id="step9-instanceof-연산자">&lt;Step.9&gt; Instanceof 연산자</h2>
<blockquote>
<p>객체가 어떤 클래스인지, 어떤 클래스를 상속받았는지 확인하는데 사용하는 연산자</p>
</blockquote>
<pre><code class="language-c">class A { }
class B extends A { }   

public static void main(String[] args) {
  A mc1 = new A();
  B mc2 = new B();

  // mc1변수는 A 클래스에게 상속받았나요? true 출력
  System.out.println(mc1 instanceof A);   
  // mc2변수는 A 클래스에게 상속받았나요? A를 상속 받았기 때문(true 출력)
  System.out.println(mc2 instanceof A); 
  // mc1변수는 B 클래스에게 상속받았나요? false 출력
  System.out.println(mc1 instanceof B);   
  // mc2변수는 B 클래스에게 상속받았나요? true 출력
  System.out.println(mc2 instanceof B);   </code></pre>
<ul>
<li>모든 클래스는 Object를 상속하기 때문에 Object Instanceof Object 는 
ㄴ항상 true라는 값이 나온다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/1d1145d5-c320-4445-b200-8d45e3b15ae7/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/98cdd286-fc19-434c-8a7b-3728ba36bc4a/image.PNG" width = "70%" height = "70%">

<h3 id="step10-발전을-위한-문제풀이-kama_code-출제">&lt;Step.10&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ol>
<li>상속관계에 놓여있는 클래스의 생성자 정의 및 호출방식을 기본으로 
남은 고기량(돼지고기 180g, 소고기 600g, 양고기 540g)을 출력하는 메인 메소드를 정의하시오.</li>
<li>사용자로부터 입력을 받아 상속관계에 있는 두 클래스를 만들어 적절한 생성자와 함께
이름, 나이, 주소, 전화번호를 인자로 출력되는 프로그램을 만드시오.</li>
<li>가로와 세로를 사용자로부터 입력을 받아서 
정사각형을 의미하는 Square클래스와 직사각형을 의미하는 Rectangle클래스를 정의하고
둘의 면적을 출력하는 프로그램을 만드시오.</li>
<li>불고기버거 단품 4500원, 식재료: 쇠고기패티, 케찹, 피클, 세트구매시 
콜라 1000원, 감자튀김 1500원 고정으로 추가
치킨버거 단품 4200원, 식재료 닭고기패티, 마요네즈, 양상추, 
세트구매시 500원 할인이 되는
클래스의 상속 관계를 사용하여 출력되는 프로그램을 만드시오.</li>
<li>사용자로부터 이름을 입력받아 캐릭터를 생성하고 다양한 몬스터와 전투를 펼쳐
아이템을 떨어뜨리는 간단한 RPG 게임을 만드시오.</li>
</ol>
</blockquote>
<h3 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h3>
<ol>
<li>기본적인 상속을 사용한 코드이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/a392e89a-0e51-4a28-962c-9a15453c3bf0/image.PNG" width = "40%" height = "40%">

<pre><code class="language-c">/*
상속관계에 놓여있는 클래스의 생성자 정의 및 호출방식을 기본으로 
남은 고기량(돼지고기 180g, 소고기 600g, 양고기 540g)을 출력하는 메인 메소드를 정의하시오.
*/

class Meat // 부모 클래스 Meat
{        
    int pig; // int형 pig 변수
    public Meat(int pig) // 생성자 오버라이딩(매개변수 pig)
    {
        this.pig=pig; // 자신의 객체 접근
    }    
}
class Cow extends Meat // Meat에 상속된 Cow 자식 클래스
{
    int cow; // int형 cow 변수
    public Cow(int pig, int cow)
    {
        super(pig); // 부모 클래스로 pig를 보냄
        this.cow = cow; // 자신의 객체 접근
    }
}

class Sheep extends Cow
{
    int sheep;
    public Sheep(int pig, int cow, int sheep)
    {
        super(pig, cow);
        this.sheep = sheep;
    }

    public void show()
    {
        System.out.println(&quot;남은 돼지고기: &quot;+ pig + &quot;g&quot;);
        System.out.println(&quot;남은 소고기: &quot;+ cow + &quot;g&quot;);
        System.out.println(&quot;남은 양고기: &quot;+ sheep + &quot;g&quot;);
    }

}
public class Put01
{
    public static void main(String[] args)
    {
        Sheep first = new Sheep(180,600,540);
        first.show();
    }
}
</code></pre>
<ol start="2">
<li>역시 1번과 마찬가지로 기본적인 상속을 사용한 코드이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/1f7e299e-2334-4d41-a020-10eb16c220aa/image.PNG" width = "30%" height = "30%">


<pre><code class="language-c">/*
사용자로부터 입력을 받아 상속관계에 있는 두 클래스를 만들어 적절한 생성자와 함께
이름, 나이, 주소, 전화번호를 인자로 출력되는 프로그램을 만드시오.
*/

import java.util.Scanner;

class Person01
{
    public String name;
    int age;

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

    public void PersonShow()
    {
        System.out.println(&quot;=====================&quot;);
        System.out.println(&quot;이름: &quot;+name);
        System.out.println(&quot;나이: &quot;+age);
    }
}

class Person02 extends Person01
{
    private String address;
    private String number;

    public Person02(String name,int age,String address, String number)
    {
        super(name,age);
        this.address = address;
        this.number = number;
    }

    public void show()
    {
        PersonShow();
        System.out.println(&quot;주소: &quot;+address);
        System.out.println(&quot;전화번호: &quot;+number);
        System.out.println(&quot;=====================&quot;);
    }
}

public class Put02
{
    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);
        System.out.println(&quot;이름 입력: &quot;);
        String name = scan.nextLine();
        System.out.println(&quot;주소 입력: &quot;);
        String address = scan.nextLine();
        System.out.println(&quot;전화번호 입력: &quot;);
        String number = scan.nextLine();
        System.out.println(&quot;나이 입력: &quot;);
        int age = scan.nextInt();
        Person02 info = new Person02(name, age, address, number);
        info.show();
    }
}
</code></pre>
<ol start="3">
<li>역시 기본적인 상속을 이용한 코드이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/226376ee-f373-49f6-9015-780a5a117a80/image.PNG" width = "30%" height = "30%">

<pre><code class="language-c">/*
가로와 세로를 사용자로부터 입력을 받아서 
정사각형을 의미하는 Square클래스와 직사각형을 의미하는 Rectangle클래스를 정의하고
둘의 면적을 출력하는 프로그램을 만드시오.
*/

class Square // 정사각형 부모 클래스
{
    // 멤버 변수
    private int x; // 한변 정보 은닉

    public Square(int x) // 생성자
    {
        this.x=x;
    }    
    public void ShowSquare()
    {
        System.out.println(&quot;정사각형의 면적: &quot;+x*x);
    }
}

class Rectangle
{
    // 멤버 변수
    private int width; // 가로 정보 은닉
    private int height; // 세로 정보 은닉

    public Rectangle(int width, int height) // 생성자
    {
        this.width = width;
        this.height = height;
    }

    public void ShowRectangle()
    {
        System.out.println(&quot;직사각형의 면적: &quot;+width*height);
    }
}

public class Put03
{
    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);
        System.out.println(&quot;직사각형의 가로: &quot;);
        int w = scan.nextInt();
        System.out.println(&quot;직사각형의 세로: &quot;);
        int h = scan.nextInt();
        System.out.println(&quot;정사각형의 한 변: &quot;);
        int j = scan.nextInt();
           Rectangle rec = new Rectangle(w,h);
           rec.ShowRectangle();

         Square sqr = new Square(j);
           sqr.ShowSquare();    
    }
}
</code></pre>
<ol start="4">
<li>조금 복잡해진 프로그램이다. 프로그램은 이벤트 또는 친절이 들어가면 
난이도가 상승한다. 
중요한 건 기능이 있다면 놓치지 말고 하나하나 추가하는 것이다.
치킨 버거는 세트를 주문시 500원을 할인하는데 
super.price()-500 =&gt; 부모 클래스의 계산식에서 500원 할인하는 포인트 중요하다.
결국 상속은 왔다갔다 하면서 재활용을 잘 사용하는데 중요성이 있다.</li>
</ol>
<pre><code class="language-c">/*
불고기버거 단품 4500원, 식재료: 쇠고기패티, 케찹, 피클, 세트구매시 
콜라 1000원, 감자튀김 1500원 고정으로 추가
치킨버거 단품 4200원, 식재료 닭고기패티, 마요네즈, 양상추, 
세트구매시 500원 할인이 되는
클래스의 상속 관계를 사용하여 출력되는 프로그램을 만드시오.
*/

//햄버거를 추상화
class Burger
{
    /*
     * 멤버변수 : 버거명, 가격, 패티, 소스, 야채 인자생성자 멤버메소드 : 
     * 가격반환(getter), 햄버거정보출력
     */
    private String burgerName; //버거명 정보 은닉
    private int price; //버거명 정보 은닉
    private String patty; //패티 정보 은닉
    private String sauce; //소스 정보 은닉
    private String vegetable; //야채 정보 은닉

    // 인자생성자
    public Burger(String burgerName, int price, String patty, String sauce, String vegetable)
    {
        super();
        this.burgerName = burgerName;
        this.price = price;
        this.patty = patty;
        this.sauce = sauce;
        this.vegetable = vegetable;
    }

    // getter/setter : private으로 간접 접근하기 위해
    public String getBurgerName()
    {
        return burgerName;
    }

    public void setBurgerName(String burgerName)
    {
        this.burgerName = burgerName;
    }

    public int getPrice()
    {
        return price;
    }

    public void setPrice(int price)
    {
        this.price = price;
    }

    public String getPatty()
    {
        return patty;
    }

    public void setPatty(String patty)
    {
        this.patty = patty;
    }

    public String getSauce()
    {
        return sauce;
    }

    public void setSauce(String sauce)
    {
        this.sauce = sauce;
    }

    public String getVegetable()
    {
        return vegetable;
    }

    public void setVegetable(String vegetable)
    {
        this.vegetable = vegetable;
    }

    // 햄버거 정보 출력
    public void showBurger()
    {
        System.out.println(burgerName);
        System.out.println(&quot;가격:&quot; + price);
        System.out.printf(&quot;식재료:%s, %s, %s\n&quot;, patty, sauce, vegetable);
    }

}

// 햄버거의 기본가격 추상화
class HamburgerPrice
{
    // 멤버변수
    Burger burger;// 디폴트(default) 접근지정자로 설정
    final int COKE = 1000; // 최종 상수처리 
    final int POTATO = 1500; // 최종 상수처리 

    // 인자생성자 : 상수는 이미 초기화되어 있으므로 햄버거 객체만 초기화한다.
    public HamburgerPrice(Burger burger)
    {
        this.burger = burger;
    }

    // 기본가격계산 : 햄버거 + 콜라 + 프렌치프라이 가격의 합
    public int price()
    {
        // 햄버거의 price는 private 이므로 getter를 통해 가져와야 함.
        int total = burger.getPrice() + COKE + POTATO;
        return total;
    }

    // 햄버거와 결제금액 출력
    public void showPrice()
    {
        burger.showBurger();// 햄버거의 정보 출력
        System.out.println(&quot;세트결제금액:&quot; + price());
        System.out.println(&quot;==========================&quot;);
    }
}

// 햄버거의 세트가격 (기본가격을 상속)
class SetPrice extends HamburgerPrice
{

    // 인자생성자
    public SetPrice(Burger burger)
    {
        // 부모클래스에 정의된 인자생성자 호출
        super(burger);
    }

    // 세트가격계산(오버라이딩) : 500원 할인된 가격으로 계산함.
    @Override
    public int price()
    {
        // 부모의 기본가격 계산식에서 500원 차감
        return super.price() - 500;
    }

    // 햄버거와 세트가격을 출력(오버라이딩)
    @Override
    public void showPrice()
    {
        // 디폴트 접근지정자는 동일 패키지에서는 접근을 허용함.
        burger.showBurger();
        System.out.println(&quot;세트할인금액:&quot; + price());
        System.out.println(&quot;============================&quot;);
    }
}

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

        // 치즈버거 객체 생성
        Burger burger1 = new Burger(&quot;불고기버거&quot;, 4500, &quot;쇠고기패티&quot;, &quot;케챱&quot;, &quot;피클&quot;);
        // 치킨버거 객체 생성
        Burger burger2 = new Burger(&quot;치킨버거&quot;, 4200, &quot;닭고기패티&quot;, &quot;마요네즈&quot;, &quot;양상추&quot;);

        // 치즈버거를 기본가격으로 구매
        HamburgerPrice price1 = new HamburgerPrice(burger1);
        price1.showPrice(); // 4500원

        // 치킨버거를 세트가격으로 구매
        HamburgerPrice price2 = new SetPrice(burger2);
        price2.showPrice(); // 4200원
    }
}</code></pre>
<ol start="5">
<li>코드와 클래스가 굉장히 많고 길다.
게임을 만드는데는 원래 어마어마한 코드가 필요하다.
자바에서 핵심은 클래스를 한 파일안에 모두 몰아넣을 수 있지만 
클래스는 반드시 다른 파일에 나누어서 하나씩 담는 것이 개발에 헤깔리지도 않을뿐더러
장점이 많다. </li>
</ol>
<p>핵심은 상속! 큰 그룹이 무엇이며, 그 안에 어떠한 상속 관계에 있는 클래스들이 있는지를
짜야한다. 그 다음 그 그룹 클래스마다 작은 디테일한 기능들을 만들어주면 된다.</p>
<ul>
<li>게임의 메인 코드이다. 패키지명 Main 안에 만들어준다.</li>
</ul>
<pre><code class="language-c">package Main;

import java.util.Scanner;

import Character.*;

import Map.*;

public class GameMain {

    public static void main(String[] args) {
        // 사용자로부터 입력을 받는다.
        Scanner sc = new Scanner(System.in);
        // hero 객체를 생성
        Hero hero = new Hero();
        // 메뉴
        System.out.println(&quot;*******RPG GAME*******&quot;);
        System.out.println(&quot;1. 전사&quot;);
        System.out.println(&quot;2. 마법사&quot;);
        System.out.println(&quot;3. 궁사&quot;);
        System.out.printf(&quot;직업의 번호를 입력하세요. : &quot;);
        int num = sc.nextInt();

        // 1번, 전사를 선택시 초기화 셋팅
        if(num == 1) {

            System.out.println(&quot;전사가 선택되었습니다.&quot;);
            hero = new Warrior(); // 캐릭터는 전사
            hero.defense = 25; // 방어력
            hero.power = 15; // 공격력
            hero.level = 1; // 레벨
            hero.hp = 80; // 체력
            hero.mp = 0; // 마력

        }
        // 2번, 마법사를 선택시 초기화 셋팅
        else if(num == 2) {

            System.out.println(&quot;마법사가 선택되었습니다.&quot;);
            hero = new Magician();// 캐릭터는 마법사
            hero.defense = 10; // 방어력
            hero.power = 18; // 공격력
            hero.level = 1; // 레벨
            hero.hp = 60; // 체력
            hero.mp = 60; // 마력

        }
        // 3번, 궁사를 선택시 초기화 셋팅
        else if(num == 3) {

            System.out.println(&quot;궁사가 선택되었습니다.&quot;);
            hero = new Archer();// 캐릭터는 궁사
            hero.defense = 5; // 방어력
            hero.power = 20; // 공격력
            hero.level = 1; // 레벨
            hero.hp = 50; // 체력
            hero.mp = 0; //마력

        }

        // 이름을 선택할 값을 받는다.
        System.out.printf(&quot;영웅의 이름을 입력하세요. : &quot;);
        hero.name = sc.next();
        System.out.println(&quot;이름이 정상적으로 입력되었습니다.&quot;);
        System.out.println(&quot;게임에 입장하였습니다.&quot;);

        // 게임 틀에서 나가지 못하도록 무한루프
        while(true) {

            System.out.println(&quot;*********************&quot;);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 이름 : &quot; + hero.name);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 레벨 : &quot; + hero.level);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 힘 : &quot; + hero.power);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 방어력 : &quot; + hero.defense);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 HP : &quot; + hero.hp);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 MP : &quot;  + hero.mp);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 경험치 : &quot;  + hero.experience);
            System.out.println(&quot;현재 &quot;+ hero.name + &quot;의 돈 : &quot;  + hero.money + &quot;원&quot;);
            System.out.println(&quot;*********************&quot;);

            System.out.println(&quot;1. 사냥터&quot;);
            System.out.println(&quot;2. 무기 상점&quot;);
            System.out.println(&quot;3. 포션 상점&quot;);
            System.out.printf(&quot;입장할 장소를 입력하세요. : &quot;);
            num = sc.nextInt();

            // 사냥터 입장
            if(num == 1) {
                // 몬스터 객체 생성
                Monster monster = new Monster();
                System.out.println(&quot;사냥터에 입장하였습니다.&quot;);
                System.out.println(&quot;1. 너구리&quot;);
                System.out.println(&quot;2. 살쾡이&quot;);
                System.out.println(&quot;3. 들개&quot;);
                System.out.println(&quot;4. 멧돼지&quot;);
                System.out.printf(&quot;사냥한 몬스터를 입력하세요. : &quot;);
                num = sc.nextInt();

                // 너구리 몬스터 초기화
                if(num == 1) {

                    monster = new Racoon();
                    monster.name = &quot;너구리&quot;;
                    monster.hp = 100;
                    monster.mp = 0;
                    monster.level = 1;
                    monster.power = 20;
                    monster.defense = 5;
                    monster.money = 10;
                    monster.experience = 10;
                    System.out.println(monster.name + &quot;과 전투를 시작합니다.&quot;);
                }

                // 살쾡이 몬스터 초기화
                if(num == 2) {

                    monster = new WildCat();
                    monster.name = &quot;살쾡이&quot;;
                    monster.hp = 2000;
                    monster.mp = 0;
                    monster.level = 5;
                    monster.power = 100;
                    monster.defense = 20;
                    monster.money = 30;
                    monster.experience = 50;
                    System.out.println(monster.name + &quot;과 전투를 시작합니다.&quot;);
                }

                // 들개 몬스터 초기화
                if(num == 3) {

                    monster = new WildDog();
                    monster.name = &quot;들개&quot;;
                    monster.hp = 3000;
                    monster.mp = 0;
                    monster.level = 15;
                    monster.power = 300;
                    monster.defense = 30;
                    monster.money = 50;
                    monster.experience = 100;
                    System.out.println(monster.name + &quot;과 전투를 시작합니다.&quot;);
                }

                // 멧돼지 몬스터 초기화
                if(num == 4) {

                    monster = new WildPig();
                    monster.name = &quot;멧돼지&quot;;
                    monster.hp = 10000;
                    monster.mp = 0;
                    monster.level = 30;
                    monster.power = 1000;
                    monster.defense = 80;
                    monster.money = 200;
                    monster.experience = 300;
                    System.out.println(monster.name + &quot;과 전투를 시작합니다.&quot;);
                }
                // 공격의 틀을 벗어나지 못하도록 무한루프
                while(true) {

                    System.out.println(hero.name + &quot;의 공격입니다.&quot;);
                    // 여기서 처리하기 위해서 호출한다.
                    monster.attacked(hero.attack()); 

                    // 몬스터의 체력이 0이면
                    if(monster.hp &lt;= 0) {

                        System.out.println(monster.name + &quot;가 죽었습니다.&quot;);
                        // 경험치와 돈이 증가
                        hero.experience += monster.experience;
                        hero.money += monster.money;
                        break;
                    }

                    System.out.println(monster.name + &quot;의 공격입니다.&quot;);
                    // 여기서 처리하기 위해서 호출한다.
                    hero.attacked(monster.attack());

                    // 죽으면 게임을 이어나가기 위해 체력 1로 부활한다
                    if(hero.hp &lt;= 0) {

                        System.out.println(hero.name + &quot;이 죽었습니다.&quot;);
                        hero.hp = 1;
                        System.out.println(hero.name + &quot;이 체력&quot; + hero.hp + &quot;으로 부활했습니다.&quot;);
                        break;
                    }
                }
                // 무기 상점
            }else if(num == 2) {
                // 무기상점 객체 생성
                WeaponStore weaponstore = new WeaponStore();
                System.out.println(&quot;무기 상점에 입장하였습니다.&quot;);
                System.out.println(&quot;1. 공동 무기 (50원)&quot;);
                System.out.println(&quot;2. 공동 방패 (50원)&quot;);
                System.out.println(&quot;현재 돈이 &quot; + hero.money  + &quot;있습니다.&quot;);
                System.out.printf(&quot;원하시는 물건을 입력하세요. : &quot;);

                num = sc.nextInt();
                // 상점 거래를 위해 플레이어의 돈을 temp 변수에 넣는다.
                int temp = hero.money;

                // 플레이어의 돈이 음수가 아닐 경우 구매가 가능
                if((hero.money = weaponstore.show(hero.money,num)) != -1) 
                {

                    System.out.println(&quot;구입이 완료되었습니다.&quot;);
                    // 무기를 구매할 경우
                    if(num == 1) {
                        // 공격력 5가 증가
                        hero.power += 5;
                    }
                    // 방패를 구매할 경우
                    if(num == 2) {
                        // 방어력 5가 증가
                        hero.defense += 5;

                    }

                    System.out.println(temp + &quot;원 남았습니다.&quot;);

                }else {
                    System.out.println(&quot;돈이 부족합니다.&quot;);
                    System.out.println(temp + &quot;원 남았습니다.&quot;);
                }
                // 포션 상점 입장
            }else if(num == 3) {

                // 포션 상점 객체 생성
                PotionStore potionstore = new PotionStore();
                System.out.println(&quot;포션 상점에 입장하였습니다.&quot;);
                System.out.println(&quot;1. 공격력 증가 포션 (30원)&quot;);
                System.out.println(&quot;2. 방어력 증가 포션 (30원)&quot;);
                System.out.println(&quot;3. 경험치 증가 포션 (100원)&quot;);
                System.out.println(&quot;4. HP 증가 포션 (10원)&quot;);
                System.out.println(&quot;5. MP 증가 포션 (10원)&quot;);
                System.out.printf(&quot;원하시는 물건을 입력하세요. : &quot;);

                // 입력값을 int 정수 num 변수에 저장한다.
                num = sc.nextInt();
                // 돈을 temp 에 역시 넣는다.
                int temp = hero.money;
                // 플레이어의 돈이 음수가 아닐 경우 구매가 가능
                if((hero.money = potionstore.show(hero.money,num)) != -1) {

                    System.out.println(&quot;구입이 완료되었습니다.&quot;);


                    if(num == 1) {
                        // 공격력 증가 +3 
                        hero.power += 3;
                    }

                    if(num == 2) {
                        // 방어력 증가 +3 
                        hero.defense += 3;    
                    }
                    if(num == 3) {
                        // 경험치 증가 +50 
                        hero.experience += 50;    
                    }
                    if(num == 4) {
                        // 체력 증가 +50 
                        hero.hp += 50;
                    }
                    if(num == 5) {
                        // 마력 증가 +50 
                        hero.mp += 50;
                    }

                    System.out.println(temp + &quot;원 남았습니다.&quot;);

                }else {
                    System.out.println(&quot;돈이 부족합니다.&quot;);
                    System.out.println(temp + &quot;원 남았습니다.&quot;);
                }
            }
            // 레벨에 x80한만큼 경험치를 가지고 있을 경우를 레벨업 기준
            if(hero.experience  &gt;= hero.level * 80) 
            {
                // 레벨이 1 오른다.
                hero.level += 1;
                System.out.println(hero.name + &quot;의 레벨이&quot; + hero.level + &quot;이 되었습니다.&quot;);
                // 돈은 레벨의 x50한 만큼 준다
                hero.money += hero.level * 50;
                System.out.println(&quot;레밸업 기념으로 돈이 &quot; + hero.level * 50 + &quot;원 증가하여 &quot;);
                System.out.println(hero.money + &quot;원이 되었습니다.&quot;);
                hero.experience = 0; // 경험치 초기화
            }

        }
    }
}        </code></pre>
<ul>
<li><p>Map 클래스이다. 패키지명 Map을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Map;
// 지도 클래스는 이름을 반환한다
public class Map {
 String  name;
}</code></pre>
</li>
<li><p>PotionStore 클래스이다. 패키지명 Map을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
</li>
</ul>
<pre><code class="language-c">package Map;
//Map 부모 클래스에 상속된 PotionStore
public class PotionStore extends Map
{
    // 멤버 변수와 초기화를 직접한다
    int powerPotion = 30;
    int defensePotion = 30;
    int experiencePotion = 100;
    int hpPotion = 10;
    int mpPotion = 10;

    // 멤버 메소드
    public int show(int money, int num) 
    {

        name = &quot;포션 상점&quot;;
        System.out.println(name + &quot;에서 물건을 구매 시도하는 중입니다.&quot;);
        // 힘포션을 샀을때
        if(num == 1) 
        {
            // 돈이 있어야 하며
            if(powerPotion &lt;= money) 
            {
                // 가진 돈에서 값을 뺀다
                return money - powerPotion;
            }
        }

        if(num == 2) {
            if(defensePotion &lt;= money) {
                return money - defensePotion;
            }
        }

        if(num == 3) 
        {
            if(experiencePotion &lt;= money) 
            {
                return money - experiencePotion;
            }
        }

        if(num == 4) 
        {
            if(hpPotion &lt;= money) 
            {
                return money - hpPotion;
            }
        }

        if(num == 5) 
        {
            if(mpPotion &lt;= money) 
            {
                return money - mpPotion;
            }
        }
        return money;
    }
}
</code></pre>
<ul>
<li><p>WeaponStore 클래스이다. 패키지명 Map을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Map;
//Map 부모 클래스에 상속된 WeaponStore
public class WeaponStore extends Map 
{
 // 직접 초기화한 멤버변수
 int commonWeapon = 50;
 int commonShield = 50;

 // 멤버 메소드
 public int show(int money, int num) {

     name = &quot;무기 상점&quot;;
     System.out.println(name + &quot;에서 물건을 구매 시도하는 중입니다.&quot;);
     // 공통 무기를 살 경우
     if(num == 1) {
         // 돈이 있을 경우 -&gt; 가격을 뺀 값을 반환
         if(commonWeapon &lt;= money) {
             return money - commonWeapon;
         }
     }

     if(num == 2) {
         if(commonShield &lt;= money) {
             return money - commonShield;
         }
     }

     return money;
 }
}</code></pre>
</li>
<li><p>패키지명 Character을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Character;
</code></pre>
</li>
</ul>
<p>import java.util.Scanner;</p>
<p>// hero 부모 클래스에 상속된 Archer
public class Archer extends Hero {
    // 멤버 메소드
    public int attack() {</p>
<pre><code>    Scanner sc = new Scanner(System.in);
    System.out.println(&quot;1. 화살 공격&quot;);
    System.out.println(&quot;2. 연속 화살 공격&quot;);
    System.out.printf(&quot;공격 번호를 입력하세요 : &quot;);
    int num = sc.nextInt();
    // 능력치를 0으로 초기화 해 놓는다.
    int sum = 0;
    // 화살공격
    if(num == 1) {
        // 레벨의 15배+공격력 15배+방어력 15배의 데미지로 들어간다.
        sum += level * 15;
        sum += power * 15;
        sum += defense * 15;
        System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
        return sum;
        // 연속 화살 공격
    }else if(num == 2) {
        // 레벨의 10배+공격력 20배+방어력 10배의 데미지로 들어간다.
        sum += level * 10;
        sum += power * 20;
        sum += defense * 10;
        System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
        return sum;

    }
    System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
    return sum;
}

//Archer.attacked을 불렀을 경우
public void attacked(int sum) {
    // 방어력이 더 크면 피해를 입지 않는다.
    if(defense &gt;= sum) {
        hp = hp - 0;
    }else 
    {
        //체력+방어력에서 데미지를 뺀 값이 체력으로 남는다.
        hp = hp + defense - sum;
    }
}</code></pre><p>}</p>
<pre><code>+ 패키지명 Character을 먼저 만들어주고 그 안에 만들어주는 것 주의!
```c
package Character;
// 캐릭터 클래스
public class Character {
// 이름과 hp mp 레벨이 멤버변수로 은닉화
    public String name;
    public int hp;
    public int mp;
    public int level;
}
</code></pre><ul>
<li><p>패키지명 Character을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Character;
//Character 부모 클래스에 상속된 Hero
public class Hero extends Character {
  // 직접적으로 멤버변수 선언과 초기화
  public int power;
  public int defense;
  public int money = 0;
  public int experience = 0;
  // 멤버 메소드를 불렀을때 공격력을 반환
  public int attack() {
      return power;
  }
  //Hero.attacked을 불렀을 경우
  public void attacked(int sum) {
      // 값보다 방어력이 더 크면
      if(defense &gt;= sum) {
          // 피해를 입지 않는다
          hp = hp - 0;
      }else 
      {
          // 그 외는 체력과 방어력을 더한 값에서 데미지만큼 빼서 체력으로 남음
          hp = hp + defense - sum;
      }
  }
}</code></pre>
</li>
<li><p>패키지명 Magician을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Character;
</code></pre>
</li>
</ul>
<p>import java.util.Scanner;
//hero 부모 클래스에 상속된 Magician
public class Magician extends Hero {
    // 멤버 메소드
    public int attack() {
        // 능력치를 초기화
        int sum = 0;</p>
<pre><code>    // 마력이 10보다 크거나 같을때만 사용 가능
    if(mp &gt;= 10) {

        Scanner sc = new Scanner(System.in);
        System.out.println(&quot;1. 파이어볼&quot;);
        System.out.println(&quot;2. 워터볼&quot;);
        System.out.printf(&quot;공격 번호를 입력하세요 : &quot;);
        int num = sc.nextInt();

    // 파이어볼 : 레벨의 10배+공격력의 15배+방어력의 5배가 데미지로
    if(num == 1) {

        sum += level * 10;
        sum += power * 15;
        sum += defense * 5;
        System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
        //마력이 5 깎인다
        mp = mp - 5;
        return sum;

    // 워터볼 : 레벨의 8배+공격력의 13배+방어력의 10배가 데미지로    
    }else if(num == 2) {

        sum += level * 8;
        sum += power * 13;
        sum += defense * 10;
        System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
        //마력이 5 깎인다
        mp = mp - 5;
        return sum;
    }

    System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
    return sum;

    // 마력이 10보다 작을 경우
    }else 
    {
        System.out.println(&quot;MP가 남아있지 않습니다.&quot;);
        return sum;
    }
}
//Magician.attacked을 불렀을 경우
public void attacked(int sum) {
    // 방어력이 데미지보다 크면 데미지 없음
    if(defense &gt;= sum) {
        hp = hp - 0;
    }else 
    {
        // 그 외는 체력과 방어력을 더한 값에 데미지를 뺀 값이 체력으로 남아 반환
        hp = hp + defense - sum;
    }
}</code></pre><p>}</p>
<pre><code>+ 패키지명 Monster을 먼저 만들어주고 그 안에 만들어주는 것 주의!
```c
package Character;

//Character 부모 클래스에 상속된 Monster
public class Monster extends Character{
    // 멤버변수 은닉화
    public int power;
    public int defense;
    public int money;
    public int experience;

    // 어택 멤버 메소드를 불렀을때 공격력을 반환한다
    public int attack() {
        return power;
    }

    public void attacked(int sum) {

        if(defense &gt;= sum) 
        {
            hp = hp - 0;
        }
        else {
            hp = hp + defense - sum;
        }
    }
}</code></pre><ul>
<li>패키지명 Racoon을 먼저 만들어주고 그 안에 만들어주는 것 주의!<pre><code class="language-c">package Character;
</code></pre>
</li>
</ul>
<p>public class Racoon extends Monster {</p>
<pre><code>public int attack() {

    System.out.println(&quot;데미지는 &quot; + power + &quot; 입니다.&quot;);
    return power;

}

public void attacked(int sum) {

    if(defense &gt;= sum) {
        hp = hp - 0;
    }else {
        hp = hp + defense - sum;
    }
}</code></pre><p>}</p>
<pre><code>+ 패키지명 Warrior을 먼저 만들어주고 그 안에 만들어주는 것 주의!
```c
package Character;

import java.util.Scanner;
//Hero 부모 클래스에 상속된 Warrior
public class Warrior extends Hero {

    public int attack() {

        Scanner sc = new Scanner(System.in);
        System.out.println(&quot;1. 쓰러스트&quot;);
        System.out.println(&quot;2. 삼단 베기&quot;);
        System.out.printf(&quot;공격 번호를 입력하세요 : &quot;);
        int num = sc.nextInt();

        int sum = 0;

        if(num == 1) {

            sum += level * 10;
            sum += power * 30;
            System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
            return sum;
        }else if(num == 2) {

            sum += level * 20;
            sum += power * 15;
            sum += defense * 15;
            System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
            return sum;
        }
        System.out.println(&quot;데미지는 &quot; + sum + &quot; 입니다.&quot;);
        return sum;
    }

    public void attacked(int sum) {

        if(defense &gt;= sum) {
            hp = hp - 0;
        }else {
            hp = hp + defense - sum;
        }
    }
}</code></pre><ul>
<li><p>패키지명 WildCat을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Character;
//WildCat 클래스는 Monster가 부모 클래스 상속
public class WildCat extends Monster {
  // 멤버 메소드
  public int attack() {

      System.out.println(&quot;데미지는 &quot; + power + &quot; 입니다.&quot;);
      return power;

  }
  //WildCat.attacked을 불렀을 경우
  public void attacked(int sum) {
      // 데미지가 방어력보다 작으면 피해 없음
      if(defense &gt;= sum) {
          hp = hp - 0;
      }else {
          // 그 이외는 체력+방어력-데미지 = 체력으로 남는다.
          hp = hp + defense - sum;
      }
  }
}</code></pre>
</li>
<li><p>패키지명 WildDog을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Character;
//WildDog 클래스는 Monster가 부모 클래스 상속
public class WildDog extends Monster {
  // 멤버 메소드
  public int attack() {

      System.out.println(&quot;데미지는 &quot; + power + &quot; 입니다.&quot;);
      return power;

  }
  //WildDog.attacked을 불렀을 경우
  public void attacked(int sum) {
      // 데미지가 방어력보다 작으면 피해 없음
      if(defense &gt;= sum) {
          hp = hp - 0;
      }else {
          // 그 이외는 체력+방어력-데미지 = 체력으로 남는다.
          hp = hp + defense - sum;
      }
  }
}</code></pre>
</li>
<li><p>패키지명 WildPig을 먼저 만들어주고 그 안에 만들어주는 것 주의!</p>
<pre><code class="language-c">package Character;
// WildPig 클래스는 Monster가 부모 클래스 상속
public class WildPig extends Monster {
  // 멤버 메소드
  public int attack() {

      System.out.println(&quot;데미지는 &quot; + power + &quot; 입니다.&quot;);
      return power;

  }
  //WildPig.attacked을 불렀을 경우
  public void attacked(int sum) {
      // 데미지가 방어력보다 작으면 피해 없음
      if(defense &gt;= sum) {
          hp = hp - 0;
      }else {
          // 그 이외는 체력+방어력-데미지 = 체력으로 남는다.
          hp = hp + defense - sum;
      }
  }
}</code></pre>
</li>
</ul>
<blockquote>
<ul>
<li>이렇게 상속까지 끝이 났다. 상속은 효율을 극대화하고 알고리즘을 짜는 것이기 때문에
지능과 논리 사고가 필요한 파트이다. 
다음 포스팅에도 역시 꿀 떨어지는 포스팅은 계속된당!</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.10] 문자열 클래스(String class)⚡]]></title>
            <link>https://velog.io/@kama_code/JAVA.10-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%81%B4%EB%9E%98%EC%8A%A4String-class%EC%99%80-%EC%83%81%EC%86%8DInheritance-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%8A%A4%ED%83%9C%ED%8B%B1%EC%9D%98-%EC%8B%AC%ED%99%94static</link>
            <guid>https://velog.io/@kama_code/JAVA.10-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%81%B4%EB%9E%98%EC%8A%A4String-class%EC%99%80-%EC%83%81%EC%86%8DInheritance-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%8A%A4%ED%83%9C%ED%8B%B1%EC%9D%98-%EC%8B%AC%ED%99%94static</guid>
            <pubDate>Sat, 15 Jul 2023 20:09:06 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>이제 자바(JAVA) 공부의 절반까지 왔다!
문자열 클래스는 암기해야 할 것들이 대부분인데
문자열을 파싱하는데 굉장히 중요한 내용이다.
그럼 다시 힘차게 시작해본다.</li>
</ul>
</blockquote>
<h3 id="step1-문자열-클래스-string-class">&lt;Step.1&gt; 문자열 클래스 (String class)</h3>
<blockquote>
<ul>
<li>자바는 문자열을 사용할 때 String 클래스를 사용한다
char(문자) : 작은 따옴표를 사용하며 ‘A’, ‘가&#39;, ‘0’ … 이렇게 하나씩...
String(문자열) : 큰 따옴표를 사용하며 
&quot;A&quot;, &quot;가&quot;, &quot;0&quot;, &quot;홍길동&quot;, &quot;안녕하세요 ?&quot; ... 이런식...</li>
</ul>
</blockquote>
<h3 id="step2-문자열-객체-string-object">&lt;Step.2&gt; 문자열 객체 (String object)</h3>
<blockquote>
<ul>
<li>String 객체 생성은 다음과 같다
String str1 = new String(“홍길동”); // new는 새로운 객체를 생성을 의미한다.
String str2 = “전우치”;</li>
</ul>
</blockquote>
<p>둘 다 객체(인스턴스) 생성하는 방법이며 
str1 ,str2는 참조값(주소값)이 생성되며 &quot;홍길동&quot; &quot;전우치&quot;는 힙 영역에 저장된다.
ex) str1이라는 주소를 찾아가니 &quot;홍길동&quot;이라는 문자가 있네?</p>
<p>그러면, 아래를 한번 살펴보자
String str1 = new String(&quot;누구인가?&quot;);
String str2 = new String(&quot;누구인가?&quot;);
str1 == str2는 true일까? ( str1와 str2가 같을까? )</p>
<p>ㄴ 정답은 false이다.(다르다)</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ca0f72c9-cd7d-4bdc-ad9a-a232edfa0490/image.PNG" width = "80%" height = "80%">

<blockquote>
<ul>
<li>Str1과 Str2는 내용이 같더라도 new이기 때문에 다른 공간을 만든다.
Str1은 id=20이라는 주소값(참조값)
Str2는 id=26이라는 주소값(참조값)이 생성된다.
Str3과 Str4는 기존에 있는 값을 사용한다.</li>
</ul>
</blockquote>
<p>이처럼 String은 == 비교 연산자를 통해 내용을 비교할 수 없다.
그러므로 String은 String 관련된 메소드를 사용해야만 내용을 비교할 수 있다.
다음 step에서 방법이 밝혀진다..</p>
<h3 id="step3-문자열-메소드-string-method">&lt;Step.3&gt; 문자열 메소드 (String method)</h3>
<blockquote>
<ul>
<li>여기부터는 String을 다루는데 굉장히 유용하면서도 중요한 암기이다.
암기를 하더라도 이해를 하면서 암기를 하면 더 효율적으로 자기화 시킬 수 있을 것이다.</li>
</ul>
</blockquote>
<ul>
<li><p>equals() : 문자열의 내용을 비교하는 메소드이다. 
ㄴ&quot;내용이 단순히 완전히 똑같은가&quot;를 비교할때 사용한다.
ㄴ일부만 같은 것을 비교하는 거라면 쓸 수 없다. 
ㄴ완전히 100% 일치함을 비교할 때 많이 사용한다.</p>
</li>
<li><p>compareTo() : 숫자를 비교한다면 크다(1), 같다(0), 작다(-1)로 반환하지만
문자열의 비교 같은 경우는 같다(0), 그 외는 양수/음수값으로 반환해준다.</p>
</li>
</ul>
<pre><code class="language-c">예시: 숫자)
Integer x = 3;
Integer y = 4;
System.out.println( x.compareTo(y) ); 
//x가 y보다 더 큰가? - 작으므로 -1이 출력된다.</code></pre>
<pre><code class="language-c">예시: (문자열)
String str = &quot;abcd&quot;;
        // 1) 비교대상에 문자열이 포함되어있을 경우!
        // ★ 서로의 문자열 길이의 차이값을 반환해준다.
        System.out.println( str.compareTo(&quot;abcd&quot;) );  // 4-4 = 0 출력
        System.out.println( str.compareTo(&quot;ab&quot;) );  //  4-2 = 2 출력
        System.out.println( str.compareTo(&quot;a&quot;) );  //  4-1 = 3 출력

        System.out.println( str.compareTo(&quot;c&quot;) );  //  97-99= -2 출력??
        /*
        ★ comparTo는 같은 위치의 문자만 비교하기 때문에, 
        첫번째 문자(a)부터 순서대로 비교해서 다를 경우 바로 아스키값을 기준으로 
        비교처리를 한다.
        아스키코드 :  a = 97 / c = 99
        */

        &quot;abhg&quot;.compareTo(&quot;h&quot;); // a = 97, h = 104 이므로 97-104 = -7
        &quot;abcd&quot;.compareTo(&quot;abfd&quot;); 
        // 비교가 불가능한 시점 c와 f를 비교한다.
        c = 99, f =102이므로 99-102 = -3

        // 2) 비교대상과 전혀 다른 문자열인 경우
        ㄴ비교가 불가능한 지점의 문자열 아스키값을 기준

        System.out.println( str.compareTo(&quot;zefd&quot;) );  //  -25
        // a = 97 / z = 122 이기 때문에 차이값인 -25
        System.out.println( str.compareTo(&quot;ABCD&quot;) );  //  32
        // a = 97 / A = 65 이므로 차이값인 32</code></pre>
<ul>
<li><p>length : 배열의 길이를 알고자 할 때 사용된다. </p>
</li>
<li><p>length() : 문자열의 길이를 알고자 할때 사용된다.</p>
</li>
<li><p>size() : 컬렉션프레임워크 타입의 길이를 알고자 할때 사용된다.</p>
<pre><code class="language-c">      int[] lengthT1 = new int[5];
      System.out.println( lengthT1.length );  // 5 출력 : 배열의 길이

      String lengthT2 = &quot;WOW-GOOD&quot;;
      System.out.println( lengthT2.length() );  // 8 출력 : 문자열 길이

      ArrayList&lt;Object&gt; st = new ArrayList&lt;Object&gt;();
      System.out.println( st .size() );  // 0 출력 : 리스트 길이</code></pre>
</li>
</ul>
<ul>
<li>concat( ) : 문자열을 연결하는 메소드이다. 
ㄴ + 기호와 동일한 역할이다.
ㄴ 아래 사진과 같이 누적하여 연산할 수도 있다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/a650329a-51e2-43af-b44a-9300cdf7f763/image.PNG" width = "50%" height = "50%">

<blockquote>
<ul>
<li>단, 기본자료형과의 연산은 아래 사진처럼 사용한다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/e05d6be8-558a-4503-a200-aad80f61ed69/image.PNG" width = "60%" height = "60%">



<ul>
<li><p>indexOf( ) : 문자열에서 문자를 찾는 메소드이다.
ㄴ특정 문자나 문자열이 앞에서부터 첫 발견되는 인덱스를 반환하며
ㄴ만약 찾지 못했을 경우 &quot;-1&quot;을 반환한다.</p>
<pre><code class="language-c">      String startOne = &quot;Hello world&quot;;   

      System.out.println( startOne.indexOf(&quot;l&quot;) );  
      // 0,1,인덱스[2]번째이므로 2가 출력된다.
      System.out.println( startOne.indexOf(&quot;z&quot;) );  
      // 없으므로 -1이 출력된다.
      System.out.println( startOne.indexOf(&quot;o&quot;,5) );  
      // indexOf( &quot;찾을 특정 문자&quot; , &quot;시작할 위치&quot; )로 지정할 수 있다.
      // 인덱스 5번째부터 찾기 시작하여 o를 찾는다면?
      // world의 o인 [7]이 출력된다.</code></pre>
</li>
<li><p>lastIndexOf() : 문자열에서 문자를 찾는 메소드이다.
ㄴ특정 문자나 문자열이 뒤에서부터 처음 발견되는 인덱스를 반환하며
ㄴ만약 찾지 못했을 경우 &quot;-1&quot;을 반환한다.</p>
<pre><code>String startOne = &quot;Hello world&quot;;

      System.out.println( startOne.lastIndexOf(&quot;l&quot;) );  
      // 뒤에서부터 l를 찾으므로 인덱스 9가 출력된다.
      System.out.println( startOne.lastIndexOf(&quot;z&quot;) );  
      // 뒤에서 찾아도 없으므로 -1이 출력된다.
      System.out.println( startOne.lastIndexOf(&quot;o&quot;,5) );  
      // 인덱스 5번째(공백)을 시작으로 뒤에서부터 찾으므로
      // Hello의 o인 인덱스 4가 출력된다.</code></pre></li>
<li><p>substring( ) : 문자열을 자르는 메소드이다.
ㄴ입력받은 위치를 기준으로 문자열을 잘라 반환하는 함수이다.</p>
<pre><code class="language-c">      String str1 = &quot;재미있는 자바 공부&quot;;
      System.out.println( str1.substring(5) );  
      // 인덱스 5번째부터 끝까지 출력하라!이므로 &#39;자바 공부&#39;가 출력된다.
      System.out.println( str1.substring(0,2) );  
      // 인덱스 0번째부터 (인덱스 2가 되기전까지) 출력하라!이므로 &#39;재미&#39;가 출력된다. </code></pre>
</li>
<li><p>charAt(): 입력받은 인자값(index)의 위치에 있는 문자를 추출하는 메소드</p>
<pre><code class="language-c">      String str = &quot;chatGPT&quot;;
      System.out.println( str.charAt(5) );  
      // 인덱스 5번째인 P가 출력된다.</code></pre>
</li>
<li><p>String.valueOf( ): 괄호 안에 있는 것이 무엇이든 문자열로 바꾸는 메소드이다.</p>
</li>
<li><p>contains(): 대상 문자열에 특정 문자열이 포함되어 있는지 확인하는 메소드
ㄴ대소문자를 구분한다.</p>
<pre><code class="language-c">String str = &quot;hello my name is...&quot;;

      System.out.println( str.contains(&quot;Hello&quot;) );  
      // 대소문자를 구분하므로 H는 없기에 false 출력
      System.out.println( str.contains(&quot; hello&quot;) );  
      // 앞에 공백도 구분하기에 false 출력
      System.out.println( str.contains(&quot;my name&quot;) );  
      // 일치하기에 true 출력 </code></pre>
</li>
<li><p>startsWith(): 대상 문자열이 특정 문자 또는 문자열로 시작하는지 체크하는 메소드</p>
<pre><code class="language-c">String study = &quot;자바 공부 재밌다&quot;;
      System.out.println( study.startsWith(&quot;자바&quot;) );  // true
      System.out.println( study.startsWith(&quot;자&quot;) );// true
      System.out.println( study.startsWith(&quot; 자&quot;) );
      // 앞에 공백도 취급하므로 false가 출력된다.</code></pre>
</li>
<li><p>endsWith(): 대상 문자열이 특정 문자 또는 문자열로 끝나는지 체크하는 메소드</p>
<pre><code class="language-c">String study = &quot;자바 공부 재밌다&quot;;
      System.out.println( study.endsWith(&quot;재밌다 &quot;) );  
      // 뒤에 공백이 없으므로 false가 출력된다.
      System.out.println( study.endsWith(&quot;재밌다&quot;) );
      // 일치하므로 true가 출력된다.
      System.out.println( study.endsWith(&quot;다&quot;) );
      // 역시 일치하므로 true가 출력된다.
      System.out.println( study.endsWith(&quot;밌&quot;) );
      // 밌으로 끝나지 않으므로 false가 출력된다.</code></pre>
</li>
<li><p>isEmpty() : 문자열의 길이가 0이면 true를 반환
ㄴJAVA 6 이후에 추가된 메소드</p>
</li>
<li><p>isBlank() : 문자열이 비어 있거나, 빈 공백으로만 이루어져 있으면, true를 반환
ㄴJAVA 11 이후에 추가된 메소드</p>
<pre><code class="language-c">System.out.println(&quot;&quot;.isEmpty() + &quot;,&quot; + &quot;&quot;.isBlank()); // true, true
System.out.println(&quot;  &quot;.isEmpty() + &quot;,&quot; + &quot;  &quot;.isBlank()); // false, true</code></pre>
</li>
<li><p>toLowerCase() : 문자열을 모두 소문자로 변환하는 메소드</p>
</li>
<li><p>toUpperCase() : 문자열을 모두 대문자로 변환하는 메소드</p>
</li>
<li><p>trim() : 문자열 맨 앞 맨 뒤에 있는 공백만 제거한 후 반환</p>
</li>
<li><p>codePointAt() : 문자열에서 해당 index의 아스키코드(유니코드)를 반환한다.</p>
<pre><code class="language-c">String alpa = &quot;abcde&quot;;
System.out.println(alpa.codePointAt(2));
// c의 아스키코드가 99이므로 99가 출력된다.</code></pre>
</li>
<li><p>replace() : 대상 문자열을 원하는 문자 값으로 변환하는 메소드</p>
<pre><code class="language-c">String rt = &quot;우리의 믿음 우리의 사랑 그 영원한&quot;;
System.out.println( rt.replace(&quot;믿음&quot;,&quot;축복&quot;) );
// &quot;우리의 축복 우리의 사랑 그 영원한&quot; 이 출력된다.

String rt2 = &quot;agdfk;aababbbbaaaaab&quot;;
System.out.println( rt2.replace(&quot;ab&quot;,&quot;*&quot;) );
// ab가 정확히 일치해야 바꾼다. =&gt; agdfk;a**bbbaaaa*</code></pre>
</li>
<li><p>replaceAll() : 대상 문자열을 원하는 문자 값으로 변환하는 메소드</p>
<pre><code class="language-c">String rt2 = &quot;agdfk;aababbbbaaaaab&quot;;
System.out.println( allTest.replaceAll(&quot;[ab]&quot;,&quot;*&quot;) );
// a나 b가 포함되면 무조건 다 별로 바꿔버린다 =&gt; *gdfk;************** 

[replaceAll을 이용한 전체 공백 제거하기]
String hellostr = &quot; 안 녕 하 세 요    반  갑습니   당 &quot;;
</code></pre>
</li>
</ul>
<p>// (&quot;\p{Z}&quot;,&quot;&quot;) 스페이스바를 &quot;&quot; 없애라는 뜻이다.
String changeStr = hellostr.replaceAll(&quot;\p{Z}&quot;,&quot;&quot;);
System.out.println(changeStr);
// 전체 공백이 제거되어 =&gt; 안녕하세요반갑습니당 출력!</p>
<pre><code>
+ replaceFirst() : 처음 나오는 단어를 찾아서 바꿔주는 메소드
```c
String rt3 = &quot;사랑 사랑 사랑 사랑 사랑이야~&quot;;

System.out.println( rt3.replaceFirst(&quot;사랑&quot;,&quot;믿음&quot;) );
//  &quot;믿음 사랑 사랑 사랑 사랑이야~&quot; 가 출력된다.</code></pre><ul>
<li>split() : 입력받은 정규표현식 또는 특정 문자를 기준으로 문자열을 나누어 
배열에 저장하여 반환하는 메소드</li>
</ul>
<pre><code class="language-c">1. [단순한 기준으로 자르기]
String str1 = &quot;hello my name&quot;;

// 공백을 기준으로 문자열을 자른다.
String[] spt = str1.split(&quot; &quot;); 
System.out.println( spt[0] );  // hello
System.out.println( spt[1] );  // my
System.out.println( spt[2] );  // name</code></pre>
<pre><code class="language-c">2. [한정된 배열의 크기 안에서 기준을 잡아 자르기]
String str2 = &quot;hello my name&quot;;

// 공백을 기준으로 문자열을 자르되 2묶음으로 나눈다.
String[] spt = str2.split(&quot; &quot; , 2); 
System.out.println( spt[0] );  // hello
System.out.println( spt[1] );  // my name</code></pre>
<pre><code class="language-c">3. [메타 문자 기준으로 자르기]
String str3 = &quot;hello.my.name&quot;;
String[] spt = str3.split(&quot;.&quot;);
System.out.println( spt[0] ); // 에러 발생!
System.out.println( spt[1] ); // 에러 발생!</code></pre>
<blockquote>
<ul>
<li>3번은 왜 아무것도 출력이 안되는 걸까?
ㄴ바로 자바에서 .은 다른 의미가 있기 때문이다. - 이를 메타 문자라고 한다
ㄴ ^ $ . ? + * | 
ㄴ해당 문자를 기준으로 split()을 사용한다면 이스케이프 처리를 해주어야 한다.
ㄴ바로 \\ (역슬래쉬 두번) 을 앞에 입력해주면 된다.</li>
</ul>
</blockquote>
<pre><code class="language-c">String str4 = &quot;hello.my.name&quot;;
// .를 기준으로 잘라 2묶음으로 나눈다
String[] spt = str4.split(&quot;\\.&quot;,2);
System.out.println( spt[0] ); // hello
System.out.println( spt[1] ); // my.name</code></pre>
<ul>
<li>equalsIgnoreCase() : 대소문자 무시하고 비교를 하는 메소드<pre><code class="language-c">String callT = &quot;WoWGood&quot;;
</code></pre>
</li>
</ul>
<p>callT.equals(&quot;woWGood&quot;);  // false 반환
callT.equalsIgnoreCase(&quot;woWgood&quot;); // true 반환</p>
<pre><code>
compareToIgnoreCase() : 대소문자를 무시하고 비교해주는 메소드
```c
String str = &quot;abcd&quot;;
System.out.println( str.compareToIgnoreCase(&quot;ABCD&quot;) );  //  0
System.out.println( str.compareToIgnoreCase(&quot;abCD&quot;) );  //  0</code></pre><p>String.format() : 문자열 형식을 지정하는 메소드
ㄴ 출력 형식을 지정하여 문자열로 반환하고 싶을 때
ㄴ 주로 웹어플리케이션 제작에서 자주 사용된다.</p>
<pre><code class="language-c"> String str = &quot;hellomynameis&quot;;
 String result = String.format(&quot;%s, %S&quot;, str, str);
 System.out.println(result); 
 // hellomynameis, HELLOMYNAMEIS</code></pre>
<img src = "https://velog.velcdn.com/images/kama_code/post/268cbaea-d378-4b9d-b5cc-49580c731af8/image.PNG" width = "50%" height = "50%">

<p>String: 문자열 연산이 적고 멀티쓰레드 환경일 경우
StringBuffer: 문자열 연산이 많고 멀티쓰레드 환경일 경우
StringBuilder: 문자열 연산이 많고 단일쓰레드이거나 동기화를 고려하지 않아도 되는 경우 </p>
<pre><code>문자열의 추가,수정,삭제가 빈번하게 발생할 경우라면 String 클래스가 아닌 
StringBuffer/StringBuilder를 사용해야 한다.</code></pre><blockquote>
<ul>
<li>String은 문자열을 수정, 추가할때마다 메모리 공간을 매번 새로 만들어서
추가하기 때문에 메모리 낭비가 많을 수 있다. </li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/980db13c-98bf-4308-ad71-7c74a4d80cac/image.PNG" width = "50%" height = "50%">

<blockquote>
<ul>
<li>StringBuffer/StringBuilder는 문자열을 수정, 추가하더라도 같은 메모리 안에서
문자열을 추가하고 수정하기에 메모리 낭비가 발생하지 않는다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/f5ea787d-8518-4254-98e1-5d6bd9de69fc/image.PNG" width = "60%" height = "60%">

<blockquote>
<ul>
<li>StringTokenizer(): 문자열을 분할하는 클래스이다 . 
ㄴ 분할한 문자열을 토큰이라고 한다.</li>
</ul>
</blockquote>
<pre><code class="language-c">String str = &quot;네이버 &gt;링크 타고 바로가기 :www.naver.com&quot;;
StringTokenizer st = new StringTokenizer(str, &quot;&gt;:&quot; );

while (st.hasMoreTokens()) {
System.out.println(st.nextToken());

//네이버
//링크 타고 바로가기 
//www.naver.com</code></pre>
<ul>
<li><p>hasMoreTokens(): 토큰이 있으면 true를 반환합니다.</p>
</li>
<li><p>nextToken(): 토큰을 차례로 가져옵니다.</p>
</li>
<li><p>insert(): 특정 위치의 문자열을 추가할 수 있는 메소드
ㄴ(위치, 문자열) 반환값은 StringBuffer 입니다.</p>
<pre><code class="language-c">      StringBuffer sb = new StringBuffer();

      sb.append(&quot;Simple is Best&quot;);
      sb.insert(9, &quot;n&#39;t&quot;);
      // Simple isn&#39;t Best 가 출력된다.</code></pre>
</li>
<li><p>delete(): 특정 위치의 문자열을 삭제할 수 있는 메소드
ㄴ(위치) 반환값은 StringBuffer 입니다.</p>
<pre><code class="language-c">      StringBuffer sb = new StringBuffer();

      sb.append(&quot;Simple isn&#39;t Best&quot;);
      sb.delete(9,12); // 인덱스 9번째부터 12가 되기 전까지 문자열이 삭제된다.
      // Simple is Best 가 출력된다.</code></pre>
</li>
<li><p>reverse() : 문자열을 역순으로 바꾸는 메소드
ㄴ반환값은 StringBuffer 입니다.</p>
<pre><code class="language-c">      StringBuffer sb = new StringBuffer();
      sb.append(&quot;Simple is Best&quot;);
      StringBuffer rsb = sb.reverse();
      // tseB si elpmiS 가 출력된다.</code></pre>
</li>
</ul>
<h3 id="step4-발전을-위한-문제풀이-kama_code-출제">&lt;Step.4&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ol>
<li>사용자로부터 입력을 받아 &quot;개&quot; 가 포함되었을 경우 
ㄴ &quot;나는 멍멍이&quot;로 출력되는 프로그램을 만드시오</li>
<li>사용자로부터 입력을 받아 &quot;사실&quot;을 입력할 경우 &quot;(힘들지만 파이팅..)&quot;이 
ㄴ 출력되는 프로그램을 만드시오</li>
<li>주민등록번호 앞자리를 입력받아 &quot;몇년 몇월 몇일에 태어나셨군요~&quot;가 
ㄴ 출력되는 프로그램을 만드시오</li>
<li>사용자로부터 아이디를 입력받은 후 다음 조건에 만족하는지 
확인할 수 있는 프로그램을 만드시오
ㄴ아이디는 8~12자 사이로만 사용할 수 있다. (length() 메서드 활용)
ㄴ영문과 숫자로만 입력할 수 있다. (charAt() 메서드 활용)
ㄴ특수기호, 공백, 그 외 모든 문자는 입력할 수 없다. 
ㄴ위 조건에 만족하면 true, 만족하지 않으면 false를 반환한다. </li>
<li>참가자의 이름을 입력받아 끝말잇기 게임을 만드시오
(끝말을 이으면 게임을 이어가고 끝말이 틀리면 패배한다)</li>
</ol>
</blockquote>
<h3 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h3>
<ol>
<li>여기서 핵심은 포함되었느냐? 이다.
사용자로부터 입력을 받고 contains() 메소드를 통해 조건식이 일치하면
&quot;나는 멍멍이&quot;로 바꿔주는 것이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/e5866fb9-a8c3-4ac7-9baa-fe7240e6af74/image.PNG" width = "70%" height = "70%">

<ol start="2">
<li>핵심은 append() 메소드를 사용하기 위해선 반드시
StringBuffer()을 사용해야 된다는 것이다.
입력값을 input이라는 변수에 저장한 후
그 input을 StringBuffer 형태의 str 변수로 다시 저장하는 것이다.
그리고 사실이라는 문자열이 포함되었을때 괄호를 통해 문자열의 끝부분에 붙여넣게 된다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/283fb189-bb1d-4f37-8a18-e66894cfb662/image.PNG" width = "70%" height = "70%">

<ol start="3">
<li>핵심은 insert() 메소드를 사용해서 인덱스 사이에 문자열을 끼워넣는 것이다.
단, 주의점은 문자열을 끼워넣는 순간 인덱스 길이가 늘어나므로 이를 생각해서
다음 끼워넣을 인덱스와 문자열을 잘 넣어야 한다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/b66b3a05-03a0-47d8-a256-7c08bfc87eac/image.PNG" width = "70%" height = "70%">

<ol start="4">
<li>해당 코드의 핵심은 알고리즘(흐름)을 잘 짜는 것이다.
입력값을 받고 사용할 수 있는 아이디, 없는 아이디를 가려내기 위해
스위치 형식으로 true false로 가른다.</li>
</ol>
<p>입력값이 true false를 결정하기 위해 매개변수가 있는 idView 메소드를 생성후
조건에 걸리면 false로 넘어가버리게 한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/e245f84c-778d-4cb7-98fd-6d4435fe7648/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/d870dcd8-e540-4e2a-b0c5-2aefc328223d/image.PNG" width = "50%" height = "50%">

<pre><code class="language-c">public class StringID
{
    public static void main(String[] args)
    {
        // 문제1] 파일명 : QuValidateId.java
        // 사용자로 부터 아이디를 입력받은 후 다음 조건에 만족하는지 확인할 수 있는 프로그램을 작성하시오.
        // 아이디는 8~12자 사이로만 사용할 수 있다. (length() 메서드 활용)
        // 영문과 숫자로만 입력할 수 있다. (charAt() 메서드 활용)
        // 특수기호, 공백, 그 외 모든 문자는 입력할 수 없다.
        // 위 조건에 만족하면 true, 만족하지 않으면 false를 반환한다.S

        // 1. 사용자로부터 아이디 입력받고 저장하기
        System.out.print(&quot;아이디를 입력하세요:&quot;);
        Scanner scan = new Scanner(System.in);
        String id = scan.nextLine();

        // 2. 아이디어: 
        // 3개 이상의 다양한 조건이 있다. 조건을 모두 담아서 
        // 일치하면 스위치 켜짐(true)로 보내고
        // 불일치하면 스위치 꺼짐(false)로 보낸다.
        boolean isOk = idView(id); // 메소드명(매개변수)로 생성한다,
        if (isOk == true)
        {
            System.out.println(&quot;사용할 수 있는 아이디입니다.&quot;);
        } else
        {
            System.out.println(&quot;사용할 수 없습니다.&quot;);
        }
    }

    // 3. 메소드 생성후 헤깔릴 수 있으니 매개변수(스트링 형태) 변경
    static boolean idView(String inputId)
    {
        // 4. 아래 조건들에 걸리지 않으면 그대로 true로 반환된다.
        boolean isOk = true;

        // 5. 조건1] 아이디 길이 탐색(8~12)
        if (inputId.length() &gt;= 8 &amp;&amp; inputId.length() &lt;= 12)
        {
            // 6. 조건 통과시 다음 조건을 확인하기 위해 반복문
            for (int i = 0; i &lt; inputId.length(); i++) // 반복해서 확인한다
            {
                // 7. 각 문자가 영문 또는 숫자인지 확인한다.
                char idchr = inputId.charAt(i);
//                        System.out.printf(&quot;인덱스%d:%c\n&quot;, i, idchr); // 디버깅 확인용

                // 8. 아이디가 영문 또는 숫자가 아니라면 false로 반환(아스키코드)
                if (!((idchr &gt;= &#39;0&#39; &amp;&amp; idchr &lt;= &#39;9&#39;) || (idchr &gt;= &#39;a&#39; &amp;&amp; idchr &lt;= &#39;z&#39;)
                        || (idchr &gt;= &#39;A&#39; &amp;&amp; idchr &lt;= &#39;Z&#39;)))
                {
                    System.out.println(idchr + &quot;=&gt; 사용불가!&quot;);
                    isOk = false;
                    // 문자열에서 허용되지 않은 문자를 찾으면 뒷 부분은 검사할 필요가 없다
                    // 즉시 반복문 for를 탈출한다
                    break;
                }
            }
        } 
        else
        {
            // 길이가 잘못되었다면 사용불가 false로 반환
            isOk = false;
        }
        return isOk; 
    }
}
</code></pre>
<ol start="5">
<li>역시 중요한 건 프로그램의 흐름이다. 플레이어가 여러명이므로 배열에 담는다.
그리고 모든 플레이어가 게임을 진행해야 하니까 
역시 반복문을 통해 돌아가면서 게임을 하게 한다.
그 이후는 끝말잇기 단어를 입력할 것이므로 무한반복의 게임 틀을 만든다.
( 빠져나가면 게임이 끝나므로 여기서 돌려야 한다.)
로직을 짜주고 적용!</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/97bef001-745e-42fa-9468-26dc90d479bd/image.PNG" width = "40%" height = "40%">

<pre><code class="language-c">public class StringGame
{
    public static void main(String[] args)
    {
        /*
        5.참가자의 이름을 입력받아 끝말잇기 게임을 만드시오
        (끝말을 이으면 게임을 이어가고 끝말이 틀리면 패배한다)
        */
        System.out.println(&quot;끝말잇기 게임을 시작합니다.&quot;);
        System.out.println(&quot;참가할 인원은 몇명?(숫자만): &quot;);
        //1. 입력값을 받고 player라는 변수에 저장한다.
        Scanner scan = new Scanner(System.in);
        int player = scan.nextInt();

        //2. arr 배열에 입력한 변수 player를 넣는다.
        String arr[] = new String[player];

        //3. 변수 player 명만큼 반복탐색
        for(int i=0; i&lt;player; i++)
        {
            //4. 참가자 데이터 받기
            System.out.println(&quot;참가자 이름&gt;&gt;&quot;);
            //5. 문자열 형의 name 변수를 입력받아 arr[i]번째 배열에 차곡차곡 넣기
            String name = scan.next();
            arr[i] = name;
        }
        String str = &quot;컴퓨터&quot;;
        System.out.println(&quot;시작 단어는 &gt;&gt; [&quot; + str + &quot;]&quot;);

        //6. 무한반복: 게임의 틀
        while(true)
        {
            //7. 플레이어의 인원수만큼 반복 탐색
            for(int i=0; i&lt;arr.length; i++)
            {
                int lastsu = str.length()-1; //컴퓨터:끝글자의 위치를 숫자로 저장
                char lastchar = str.charAt(lastsu); // 끝글자를 문자로 뽑아냄 

                //8. 차례를 만들어줌
                System.out.println(arr[i] + &quot;&gt;&gt; &quot;);
                //9. 여기서부터는 입력할 단어를 받음
                String word = scan.next();

                //10. 입력값 미달(길이가 1자만 입력하면?)
                if(word.length()&lt;2)
                {
                    System.out.println(arr[i]+&quot;: 길이가 짧아 패배!&quot;);
                    System.exit(0);
                }
                //11. 마지막 글자와 입력한 시작 글자가 일치하지 않으면?
                if(word.charAt(0) != lastchar)
                {
                    System.out.println(arr[i]+&quot;: 끝말을 잇지 못해 패배!&quot;);
                    System.exit(0);
                }
                //12. 입력 글자도 게임에 적용되기 위해 넣는다.
                str=word;
            }
        }

    }
}
</code></pre>
<blockquote>
<ul>
<li>비록 암기이나 문자열을 파싱하면서 자유롭게 다루는데 굉장히 중요한
String 클래스가 끝이 났다. 다음 포스팅은 
역시 매우 중요한 상속에 대해 알아본다!
꿀 떨어지는 포스팅은 앞으로도 계속</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.09] 배열(array) 그리고 향상된 for문🕊]]></title>
            <link>https://velog.io/@kama_code/JAVA.09-%EB%B0%B0%EC%97%B4array</link>
            <guid>https://velog.io/@kama_code/JAVA.09-%EB%B0%B0%EC%97%B4array</guid>
            <pubDate>Thu, 13 Jul 2023 17:33:20 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>어떤 한 프로그램이 있다. 
1+1= 2 만 계산할 수 있는 프로그램이라면 아무도 사용하지 않을 것이다. 
하지만 다양한 수를 계산하는 프로그램이라면 사용할 것이다.
배열도 마찬가지다. 하나만 다루는 것이라면 그리 
효율이 좋지 못한 프로그램이 될 것이다. 그래서 개인적으로 배열을 통해 
다수의 데이터를 효과적으로 다루는 경우가 많다.</li>
</ul>
</blockquote>
<h3 id="step1-1차원-배열">&lt;Step.1&gt; 1차원 배열</h3>
<blockquote>
<ul>
<li>1차원 배열: 타입이 같은 둘 이상의 데이터를 저장할 수 있는 
1차원 구조의 메모리 공간을 말한다.</li>
</ul>
</blockquote>
<ul>
<li>배열도 메소드(함수)의 매개변수를 통해 다른 메소드(함수)를 호출할 때 전달할 수 있다.</li>
<li>랜덤 생성하기 : Random random = new Random();
ㄴmath.random -&gt; 0~1사이의 실수를 랜덤 반환하는 메소드다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/a573d635-d327-4b56-bd10-0215656ce149/image.PNG" width = "70%" height = "70%">

<blockquote>
<ul>
<li>위 사진에서 korScore은 주소값(참조값)으로 stack 영역에 저장되며,
new, 배열, 스트링은 heap 영역에 저장된다.<img src = "https://velog.velcdn.com/images/kama_code/post/88381a4d-ff19-4bf0-9e6a-d61f6d5654c4/image.PNG" width = "60%" height = "60%">
</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/4aa9dd8e-e652-4f8b-8a0e-1d49883a95bb/image.PNG" width = "50%" height = "50%">

<blockquote>
<ul>
<li>배열은 인덱스가 항상 0부터 시작한다. 
( 0번째가 1번째라는 것이다. ) - 이것을 주의해야 한다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/1df96efa-601c-4d3d-b5c2-cb70971573fc/image.PNG" width = "70%" height = "70%">

<blockquote>
<ul>
<li>배열에 초기값을 넣을 때는 아래 사진과 같이 선언한다. </li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/325dc2b0-36d9-48c7-b546-93ef43e127a9/image.PNG" width = "65%" height = "65%">

<h3 id="step2-main-메소드의-매개-변수">&lt;Step.2&gt; main() 메소드의 매개 변수</h3>
<blockquote>
<ul>
<li>메인 메소드도 매개변수를 설정해줄 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>상단 메뉴 - run - run configurations</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/58ee6c0c-5bc9-4a70-8f92-6b0efec8334a/image.PNG" width = "60%" height = "60%">

<h3 id="step3-call-by-호출">&lt;Step.3&gt; call by 호출</h3>
<blockquote>
<ul>
<li>매우 중요한 내용이다. </li>
</ul>
</blockquote>
<ol>
<li>Call by value(값에 의한 호출)
ㄴ스택영역만 사용하는 호출방식이다.
ㄴ파라미터(인수)가 전달될때 메모리의 복사를 통해 값 전달
※ 쉽게 말해서 메인 메소드에서 A 라는 이름을 가진 메소드를 호출하고 
int 자료형 값을 복사해서 보낸다. (하지만 서로 다른 영역이고 복사한 값이 들어가므로 
변수의 값에 실제 영향을 미치지 않는다)
int형 -&gt; 스택 영역 저장 // 배열 arr -&gt; 힙 영역에 저장</li>
</ol>
<blockquote>
<ul>
<li>main의 first = 100과 sencond = 200이 복사하여
callbyValue 메소드의 매개변수 fNum과 sNum에 들어간다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/9de5e04b-3a6e-4672-93fb-23efaffe2485/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/0c39d2f4-4e53-44c2-be6a-2d00910c6691/image.PNG" width = "60%" height = "60%">

<blockquote>
<ul>
<li>매우 중요한 내용이다. </li>
</ul>
<ol start="2">
<li>Call by reference(참조에 의한 호출)
ㄴ값이 아닌 객체의 참조값(주소값)을 전달한다
ㄴ스택영역과 힙영역을 동시에 사용하는 호출방식이다.
ㄴ매개변수가 전달될때 객체의 참조값(주소)이 전달
ㄴ참조값이 복사되어 전달되는 방식이므로 서로 다른 지역의 메소드에서 
동일한 객체를 참조하게 됨
ㄴJAVA에서 객체를 다루는 일반적인 방식이다.</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/b6763baa-0a16-4c03-b873-6d49d48c53f5/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/5d403143-f78f-4b8c-a167-5224fb4cd74d/image.PNG" width = "60%" height = "60%">

<h3 id="step4-for--each-문-향상된-for문">&lt;Step.4&gt; for ~ each 문 (향상된 for문)</h3>
<blockquote>
<ul>
<li>배열을 이용한 반복문을 사용하다 보면 for문 안에 항상 배열의 길이만큼 
반복을 하는 코드를  작성하게 된다.</li>
</ul>
</blockquote>
<ul>
<li>배열의 일부가 아닌 전체를 참조할때 주로 사용되는 for문이다. 
코드가 짧고 간결하여 빈번히 사용된다.</li>
<li>배열의 원소를 참조의 형태로 가져와서 사용한다.
따라서 참조의 목적으로만 사용해야하고, 값의 변경은 허용하지 않는다.
( 통째로 복사될 뿐이므로.. )</li>
<li>형식]
   for(자료형 참조변수 : 배열명(주소값을 확인한다){<pre><code>       실행문장;
       참조변수를 통해 배열의 원소 출력가능함;
      ㄴ하나씩 확인한다. </code></pre></li>
<li>향상된 for문은 복사해서 보는 것</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/5b70b78d-1e36-4d1b-a0d5-d0181fa49eaa/image.PNG" width = "50%" height = "50%">

<h3 id="step5-2차원-배열">&lt;Step.5&gt; 2차원 배열</h3>
<blockquote>
<ul>
<li>2차원이란 말이 들어가면 평면(2d)를 생각하는 것이 좋다.
ㄴ자연스럽게 행열(가로축, 세로축)을 떠올려주는 것이 TIP이다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/781d5000-8960-4c8d-9748-597ed80c8309/image.PNG" width = "70%" height = "70%">

<blockquote>
<ul>
<li>2차원 배열의 초기값은 이렇게 넣어준다. (초기화를 해준다)</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/502cd236-5a51-4fc7-996e-6d6262771fee/image.PNG" width = "70%" height = "70%">

<blockquote>
<ul>
<li>2차원 배열의 초기화 주의사항이 있다.</li>
</ul>
</blockquote>
<ol>
<li>공간이 있을 경우 - 자연스럽게 0으로 채워주지만</li>
<li>아래처럼 자리(공간)이 없을 경우 - null로 들어가게 된다.
여기서 0과 null은 완전히 다르다. 
▶ 0은 숫자라서 추후 값을 넣을 수 있지만 null은 공간 자체가 없어서
별도의 공간을 만들어줘야 숫자가 들어갈 수 있다. </li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/d2cae16e-f56d-433b-9885-a83a07677098/image.PNG" width = "70%" height = "70%">

<h3 id="step6-배열에-관련된-유틸리티-메소드">&lt;Step.6&gt; 배열에 관련된 유틸리티 메소드</h3>
<blockquote>
<ul>
<li>[ java.util.Arrays 클래스에 정의되어 있는 메서드 ]
원하는 값으로 배열 전부 또는 일부를 채울 때 사용하는 메서드</li>
</ul>
</blockquote>
<p>[해석] fill :
public static void fill(int[] a, int val)</p>
<p>→ 두 번째 인자(int val)로 전달된 값으로 배열 초기화</p>
<p>public static void fill(int[] a, int fromIndex, int toIndex, int val)
→ 인덱스 fromIndex ~ (toIndex-1)의 범위까지 val의 값으로 배열 초기화
: (toIndex-1)인 이유는 배열은 인덱스 시작이 0부터 시작하기에..</p>
<blockquote>
<ul>
<li>[ java.util.Arrays 클래스에 정의되어 있는 메서드 ]
원하는 값으로 배열 전부 또는 일부를 채울 때 사용하는 메서드</li>
</ul>
</blockquote>
<p>[해석] copyOf :
public static int[] copyOf(int[] original, int newLength)</p>
<p>→ original에 전달된 배열을 첫 번째 요소부터 newLength 길이만큼 복사</p>
<p>public static int[] copyOfRange(int[] original, int from, int to)</p>
<p>→ original에 전달된 배열을 인덱스 from부터 to 이전 요소까지 복사</p>
<blockquote>
<ul>
<li>[ java.util.Arrays 클래스에 정의되어 있는 메서드 ]
한 배열에 저장된 값을 다른 배열에 복사할 때 사용하는 메서드</li>
</ul>
</blockquote>
<p>[해석] arraycopy :</p>
<p>public static void
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)</p>
<p>→ 복사 원본의 위치 : 배열 src의 인덱스 srcPos
→ 복사 대상의 위치 : 배열 dest의 인덱스 destPos
→ 복사할 요소의 수 : length</p>
<blockquote>
<ul>
<li>비교 및 정렬을 해주는 메소드도 있다</li>
</ul>
</blockquote>
<h3 id="배열을-비교해주는-equals-메서드가-있다">배열을 비교해주는 equals() 메서드가 있다.</h3>
<p>equals()는 배열 안에 내용을 비교해주는 메소드이다.
boolean 조건은 두 배열에 저장된 데이터의 수, 순서 그리고 
내용이 같을 때 true를 반환한다.<br>(배열 길이가 다르면 false를 반환한다.)</p>
<p>ex) A컵에 담긴 내용물 오렌지 주스를 비교</p>
<h3 id="배열을-정렬해주는-sort-메서드가-있다">배열을 정렬해주는 sort() 메서드가 있다.</h3>
<p>public static void sort(int[] a)
→ 매개변수 a로 전달된 배열을 오름차순으로 정렬</p>
<h3 id="step7-정렬">&lt;Step.7&gt; 정렬</h3>
<p><a href="https://www.youtube.com/watch?v=-2xbwH569GA">★ 버블 정렬 내용보기</a></p>
<img src = "https://velog.velcdn.com/images/kama_code/post/571d42cb-5ef5-41a8-a073-24ffe8b2bcf2/image.PNG" width = "70%" height = "70%">

<p><a href="https://www.youtube.com/watch?v=KqtZoMWd75o">★ 삽입 정렬 내용보기</a></p>
<p><a href="https://www.youtube.com/watch?v=dyEEXdLTl9M">★ 선택 정렬 내용보기</a></p>
<h3 id="step8-발전을-위한-문제풀이-kama_code-출제">&lt;Step.8&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ol>
<li>길이가 5인 int형 배열을 선언해서 사용자로부터 5개의 정수를 입력받는다.<br>그리고 최대값, 최소값, 모든 수의 합을 구하라. 함수(최대,최소,합)를 정의하여 구현하시오.</li>
<li>길이가 10인 배열을 선언하고 총 10개의 정수를 입력받아서 홀수와 짝수를
구분해서 출력하시오.</li>
<li>과목 이름을 입력받아 해당 과목 점수를 출력해주는 프로그램을 작성해보자. 
없는 과목을 입력하면 &quot;입력한 과목&quot;은 없는 과목입니다.를 출력하면서 
무한반복을 하다가 &quot;그만&quot;을 입력받으면, 프로그램이 종료된다.</li>
<li>String 2차원 배열을 이용하여 자바 용어 맞추기 게임을 만들어라!
정답이면 정답입니다. 오답이면 틀렸습니다. 정답은 ~입니다 라고 출력되어야 한다. </li>
<li>주민등록번호 번호를 입력 받아 char 배열에 저장한 후 출력하세요.
단, char 배열 저장 시 성별을 나타내는 숫자 이후부터 * 로 출력하세요</li>
<li>좌석 예약 프로그램을 만드시오.
예약 완료 후, 같은 자리를 다시 예약하려고 할 때
예약이 불가하다는 메세지와 함께 남아있는 좌석의 목록도 출력해야 합니다.</li>
<li>숫자야구게임을 만드시오.</li>
</ol>
</blockquote>
<ul>
<li>1~9 사이의 중복되지 않는 3개의 정수를 생성한다.</li>
<li>사용자는 3개의 숫자를 입력한다.</li>
<li>생성된 3개의 숫자를 맞추는데 위치까지 정확히 맞춰야 한다.</li>
<li>숫자와 숫자의 위치까지 일치하면 strike 로 판정한다.</li>
<li>숫자는 맞지만 위치가 틀렸다면 ball 로 판정한다.</li>
<li>숫자3개가 모두 일치하지 않으면 out 으로 판정한다.</li>
<li>3 strike 가 되면 게임은 종료된다.</li>
<li>시도한 횟수를 표시한다.</li>
<li>계속할지 종료할지 여부를 물어보고 다음 진행을 한다.</li>
</ul>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>중요한 점은 입력을 받는 기능, 배열 안에서 최대값, 최소값, 합을 구하는 메소드를 
잘 만들어서 잘 부르는 것이다. 자세한 해설은 아래에서</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/7e7936f0-6c6e-42d3-bdba-bccf55b5c5ba/image.PNG" width = "50%" height = "50%">

<pre><code class="language-c">public class ArrayOne
{
    public static void main(String[] args)
    {
        /*
        1. 길이가 5인 int형 배열을 선언해서 사용자로부터 5개의 정수를 입력받는다.
        그리고 최대값, 최소값, 모든 수의 합을 구하라. 함수(최대,최소,합)를 정의하여 구            현하시오.
        */
        System.out.println(&quot;5개의 정수를 입력해주세요: &quot;); // 안내 메세지
        Scanner scan = new Scanner(System.in); // 사용자로부터 입력값을 받음
        int[] arr = new int[5]; // int형 배열 5칸 생성

        for (int i=0; i&lt;5; i++) // 배열의 내용을 확인하기 위한 반복문
        {
            arr[i] = scan.nextInt(); // 전체 베열 scan에 저장함
        }
        System.out.println(&quot;======================&quot;); // for문이 끝나면 출력되게 함
        System.out.println(&quot;최대값은 : &quot; + maxN(arr));
        System.out.println(&quot;최소값은 : &quot; + minN(arr));
        System.out.println(&quot;모든수의 합 : &quot; + sum(arr));
        System.out.println(&quot;======================&quot;);
    }

    public static int sum(int[] arr) // 합계를 출력하는 메소드
    {
        int num = arr[0]; // 지역변수를 사용하기 위해 num을 초기화 시킨다.
        for(int i=0; i&lt;5; i++)
        {
            num += arr[i]; // 누적해서 더해간 것을 반환
        }
        return num;
    }

    public static int minN(int[] arr)
    {
        int num = arr[0]; // 지역변수를 사용하기 위해 num을 초기화 시킨다.
        for (int i=0; i&lt;5; i++)
        {
            if(num &gt; arr[i]) // 배열을 비교해서 작은 것을 minN 메소드에 num에 넣어 반환 
            {
                num = arr[i];
            }
        }        
        return num;
    }

    public static int maxN(int[] arr)
    {
        int num = arr[0]; // 지역변수를 사용하기 위해 num을 초기화 시킨다.
        for (int i=0; i&lt;5; i++)
        {
            if(num &lt; arr[i]) // 배열을 비교해서 큰 것을 maxN 메소드에 num에 넣어 반환 
            {
                num = arr[i];
            }
        }
        return num;
    }
}

</code></pre>
<ol start="2">
<li>정수 10개를 입력받아 홀수 짝수를 구분하는 간단한 프로그램이지만
보기 좋게 선을 넣고 안내를 하기 위해 잘 생각하고 흐름을 놓치지 말고 따라가야 한다.
특히 배열은 반복문과 굉장히 친하다. 
※ 배열하면? -&gt; 반복문하고 친구지! 라고 기억하면 좋다
왜냐하면 배열은 여러개의 데이터가 들어가 있는데 그 전체를 탐색하기 위해선
반복문으로 탐색하는 것이 필수이기 때문이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/820fd63a-cfcd-4190-957f-3d1331585684/image.PNG" width = "50%" height = "50%">

<pre><code class="language-c">public class ArrayTwo
{
    public static void main(String[] args)
    {
        /* 
            2. 길이가 10인 배열을 선언하고 총 10개의 정수를 입력받아서 홀수와 짝수를
            구분해서 출력하시오.
         */

        Scanner scan = new Scanner(System.in); // 사용자로부터 정수를 입력받는다
        int[] arr = new int[10]; // 정수 int형 10개 숫자가 들어갈 수 있는 배열 생성
        System.out.println(&quot;정수 10개를 입력하시오: &quot;);
        for(int i=0; i&lt;10; i++) // 전체 배열을 확인한다 (반복문으로)
        {
            arr[i] = scan.nextInt(); //(사용자가 입력한 값을 arr배열에 저장한다.)

        }
        System.out.println(&quot;========================&quot;); // 보기 좋게 구분하기 위한 선
        System.out.print(&quot;나는 홀수: &quot;); // 홀수 안내하기 위한 문자열 (for문 밖에다 만듬)
        for(int i=0; i&lt;10; i++) // 전체 배열을 다시 확인한다 (반복문으로)
        {
            if(arr[i] % 2 == 1) // 홀수의 조건: 2로 나누었을때 나머지가 1
            {
                System.out.print(arr[i] + &quot; &quot;); // 연속되어 입력하기 위해 print로 사용 후 스페이스바
            }
        }
        System.out.println(&quot; &quot;); // 한줄 띄기 위한 공백
        System.out.println(&quot;========================&quot;); // 보기 좋게 구분하기 위한 선
        System.out.print(&quot;나는 짝수: &quot;); // 짝수 안내하기 위한 문자열 (for문 밖에다 만듬)
        for(int i=0; i&lt;10; i++) // 전체 배열을 다시 확인한다 (반복문으로)
        {
            if(arr[i] % 2 == 0) // 짝수의 조건: 2로 나누었을때 나머지가 0
            {
                System.out.print(arr[i] + &quot; &quot;); // 연속되어 입력하기 위해 print로 사용 후 스페이스바
            }
        }
        System.out.println(&quot; &quot;); // 한줄 띄기 위한 공백
        System.out.println(&quot;========================&quot;); // 보기 좋게 구분하기 위한 선
    }
}
</code></pre>
<ol start="3">
<li>배열을 생성하여 그냥 무한반복만 돌려주면서 점수만 출력해주는 프로그램은 
간단하고 쉽다. 
하지만 프로그래밍 세계에서 이런 말이 있다.
<span style='background-color: #fff5b1'><strong>&quot;좋은 프로그램과 개발자의 고생은 비례한다.&quot;</strong></span></li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/d92c4d1f-1b3e-4736-8a7a-248550211a37/image.PNG" width = "80%" height = "70%">

<p>더 친절하게 더 편리한 프로그램을 만들기 위해선 더 섬세해야 한다.
어떤 부분은 반복을 하고 반복문 안에서도 어떤 부분은 반복을 하지 않고 
1번만 출력하여 다시 처음으로 돌아가여 물어보는 프로그램은 
단순한 프로그램보다 당연히 훨씬 어렵다.
아래 필자가 직접 짠 코드를 잘 읽어보고 흐름을 반드시 눈에 읽혀보자!</p>
<pre><code class="language-c">public class ArrayThree
{
    public static void main(String[] args)
    {
        /*
        3. 과목 이름을 입력받아 해당 과목 점수를 출력해주는 프로그램을 작성해보자.
        없는 과목을 입력하면 &quot;입력한 과목&quot;은 없는 과목입니다.를 출력하면서
        무한반복을 하다가 &quot;그만&quot;을 입력받으면, 프로그램이 종료된다.*/

        System.out.println(&quot;점수를 조회할 과목명을 입력하세요: &quot;);
        //문자열 형태 subject 배열 목록
        String[] subject = {&quot;국어&quot;, &quot;영어&quot;, &quot;수학&quot;, &quot;사회&quot;, &quot;과학&quot;, &quot;도덕&quot;}; 
        //int 정수 형태 score 배열 목록
        int[] score = {80, 81, 94, 56, 14, 25};
        Scanner scan = new Scanner(System.in); // 입력값 받기

        while(true) // 무한반복하면 while을 떠올려라!
        {        
            String input = scan.next(); // 입력한 값을 input이란 문자열 형태로 저장
            for(int i=0; i&lt;subject.length; i++) // subject 배열 길이만큼 반복 탐색
            {                
                if (subject[i].equals(input)) // subject 안의 문자열이 입력한 문자열과 일치할 경우
                {
                    //그 배열의 i번째과 score배열의 i번쨰 내용을 출력
                    System.out.println(subject[i]+&quot;의 점수는? &quot; + score[i]+&quot;점!&quot;);

                }                        
            }  
            // 반복 출력되지 않도록 for문 밖에다가 적는다
            // subject의 배열 내용인 input 그리고 그만이 아닐경우(!) 
            if (!(Arrays.asList(subject).contains(input)) &amp;&amp; (!(input.equals(&quot;그만&quot;))))
            {
                // 출력!
                System.out.println(input + &quot;은(는) 없는 과목입니다.&quot;);    
            }
            if (input.equals(&quot;그만&quot;)) // 그만이면
            {
                System.out.println(&quot;프로그램이 종료됩니다.&quot;);    
                scan.close(); // 사용자 입력값 그만 받기(프로그램 끄기!!)
                break;
            }

        }    
    }
}
</code></pre>
<ol start="4">
<li>역시 이번에도 흐름이 중요하다. 
순서대로 생각한 흐름을 1~5번까지 주석으로 적어두었다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/9cea9878-5c5c-4fda-8b83-f2aea6df0802/image.PNG" width = "90%" height = "90%">


<pre><code>오랜만에 나온 printf 
%d는 정수를 의미한다. %s는 문자열(string)을 의미한다.
,(쉼표) 다음으로 순서대로 들어갈 자리를 적어주는 것이다.</code></pre><p>javas[i][0]은 첫번째 문제라면 javas[1][0]의 문제가 출력될 것이다.
if (good.equals(javas[i][1]))는 good이라는 입력한 값과 
javas[i][1] : 정답이 똑같은지 다른지 판별하는 조건이다.</p>
<pre><code class="language-c">public class ArrayFour
{
    public static void main(String[] args)
    {
        /*
         * 4. String 2차원 배열을 이용하여 자바 용어 맞추기 게임을 만들어라! 정답이면 정답입니다. 오답이면 틀렸습니다. 정답은 ~입니다
         * 라고 출력되어야 한다.
         */
        // 1. 문제와 정답이 담긴 2차원 배열 생성
        String[][] javas = { { &quot;프로그램에서 사용되는 데이터 유형(data type)&quot;, &quot;자료형&quot; }, { &quot;변수의 아무것도 안들어간 더미데이터(빈 데이터)&quot;, &quot;null&quot; },
                { &quot;힙 영역의 값을 호출하기 위해 객체의 메모리 위치의 어떤 것을 찾아야 할까?(ㅈㅅㄱ)&quot;, &quot;주소값&quot; }, { &quot;데이터가 저장되는 메모리의 기억장소에 붙인 이름&quot;, &quot;변수&quot; },
                { &quot;메소드 안에서 선언되어 메소드 안에서만 사용되는 변수&quot;, &quot;지역변수&quot; }, { &quot;데이터를 전달하면서 메소드를 호출할 때 전달 데이터를 저장할 변수&quot;, &quot;매개변수&quot; },
                { &quot;데이터 저장을 위한 메모리 공간을 확보해달라고 가상머신에게 부탁하는 행위&quot;, &quot;변수선언&quot; }, { &quot;변수 선언 이후 처음으로 데이터를 저장하는 행위&quot;, &quot;초기화&quot; },
                { &quot;조건문이 true일때만 실행(?문)&quot;, &quot;if문&quot; }, { &quot;변수값이 설정한 데이터가 같을때 실행(?문)&quot;, &quot;switch문&quot; },
                { &quot;true면 다음, false면 주로 한정된 반복문 탈출(?문)&quot;, &quot;for문&quot; }, { &quot;조건식이 true면 실행, false면 주로 무한반복문 탈출(?문)&quot;, &quot;while문&quot; },
                { &quot;일단 실행구문 수행하고 조건식 true면 반복, false면 탈출(?-?문)&quot;, &quot;do-while문&quot; },
                { &quot;배열객체참조변수 안에 데이터를 저장하고 실행구문 반복(?-?문)&quot;, &quot;향상된-for문&quot; },
                { &quot;조건식이 false면 반복진행, true면 실행구문 계속 실행하지 않고 반복문 탈출&quot;, &quot;break&quot; }, { &quot;강제로 다음 반복 구문으로 건너뜀&quot;, &quot;continue&quot; },
                { &quot;패시브! 클래스가 객체화가 되어야 속성변수가 메소드가 호출한 실행구문이 이루어짐&quot;, &quot;생성자&quot; }, { &quot;행동! 실행구문을 대표하는 방법 이름(ㅔㅗㅡ)&quot;, &quot;메소드&quot; },
                { &quot;클래스를 실행하면 메모리 공간(Heap)으로 올라간다. 같은말로 인스턴스&quot;, &quot;객체&quot; }, { &quot;메소드 실행 후에 아무런 값도 반환하지 않는다.&quot;, &quot;void&quot; },
                { &quot;메소드 실행을 중지하고 데이터를 호출한 곳으로 반환하라.&quot;, &quot;return&quot; }, { &quot;클래스가 소유한 고유멤버(속성변수, 메소드, 생성자)를 지칭&quot;, &quot;this&quot; },
                { &quot;클래스의 특성 중 정보 은닉을 가장 잘 보여주는 메소드(영어/영어)&quot;, &quot;getter/setter&quot; },
                { &quot;같은 이름의 생성자를 2개 이상 정의하는 것(한글로)&quot;, &quot;오버로딩&quot; }, 
                };
        // 2. 사용자로부터 입력값을 받는다.
        Scanner scan = new Scanner(System.in);

        // 3. 만든 배열의 전체를 탐색한다.
        for (int i = 0; i &lt; javas.length; i++)
        {
            System.out.printf(&quot;문제%d] %s 는 무엇일까요? &quot;, i + 1, javas[i][0]);
            // 4. 사용자로부터 입력값을 저장한다.
            String good = scan.nextLine();

            // 5. 정답인지 틀렸는지 판별한다
            if (good.equals(javas[i][1]))
            {
                System.out.printf(&quot;대단한데요~? 정답입니다!%n%n&quot;);
            } 
            else 
            {
                System.out.printf(&quot;아쉽게도 틀렸어요! 정답은 [%s]입니다.%n%n&quot;, javas[i][1]);        
            }            
        }
        scan.close();
    }
}
</code></pre>
<ol start="5">
<li>주민번호를 입력받아 성별 이후는 마스킹으로 변환하는 코드이다.
핵심은 아래와 같다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/c5a969a4-cda5-4ff3-b4c9-f1433bc1b254/image.PNG" width = "50%" height = "50%">

<p>1] char[] bunho = new char[jumin.length()]; 
사용자의 입력한 값의 길이만큼 배열에 담는 것!
2] if(i &gt;= 8) 인덱스0부터 시작해서 성별 다음에 오는 번째를 계산하여 참을 만드는 것
3] bunho[i] = jumin.charAt(i); 그 외는 chatAt을 이용해서 하나하나 값을 넣는 것
ㄴcharAt(0)이라면 문자열의 0번째 문자를 char타입으로 변환</p>
<pre><code class="language-c">public class ArrayFive
{
    public static void main(String[] args)
    {
        /*
        5.주민등록번호 번호를 입력 받아 char 배열에 저장한 후 출력하세요.
        단, char 배열 저장 시 성별을 나타내는 숫자 이후부터 * 로 출력하세요.*/

        // 1. 사용자로부터 입력값 받기
        Scanner scan = new Scanner(System.in);

        // 2. -를 포함한 주민등록번호 입력받기
        System.out.println(&quot;주민등록번호 입력해주세요(-포함): &quot;);
        // 3. 문자열 형태의 jumin 변수에 입력값을 저장
        String jumin = scan.nextLine();
        // 4. char 배열인 변수 bunho에 입력값만큼 하나하나 배열에 담기
        char[] bunho = new char[jumin.length()];

        // 5. 반복문 밖에서 출력된 결과 첫 안내
        System.out.print(&quot;변환된 주민번호: &quot;);
        // 6. 출력하기 위한 char 배열 탐색
        for (int i=0; i&lt;bunho.length; i++)
        {
            // 7. 성별 다음번째부터 *로 바꿔준다.
            if(i &gt;= 8)
            {
                //8. 성별 번쨰부터 *을 반복해서 바꿔준다.
                bunho[i] = &#39;*&#39;;
            }
            // 8. 그 외는 char[] 변수에 담긴 문자를 출력한다.
            else
                bunho[i] = jumin.charAt(i);
            // 9. 총 결과는?
            System.out.print(bunho[i]);
        }
        scan.close(); // 입력을 그만 받는다.
    }
}
</code></pre>
<ol start="6">
<li>좌석 예약 프로그램이다.
엄청나게 중요한 코드이다. 
10x10인 2차원 배열을 생성한 후</li>
</ol>
<ul>
<li><p>공간을 만들어주었다면 자바는 자동으로 그 안에 값을 0으로 채워준다는 특성이 있다는 것!</p>
<p>그래서 이 특성을 이용하여 0일 경우 빈좌석으로 생각하여 예약을 할 수 있는 
프로그램을 만들 수 있는 것이다.</p>
</li>
</ul>
<p>또 배열은 인덱스 0번째부터 시작한다는 사실!</p>
<ul>
<li>사람은 첫번째 두번째 순으로 말하지만</li>
<li>배열은 0번째 첫번째로 하나가 밀리게 된다. 
→ 우리가 말하는 기준을 자바 순번으로 바꿀땐 -1
→ 자바가 말하는 기준을 우리 순번으로 바꿀땐 +1을 해주어야 한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/94d0cd7e-a1d3-441d-b111-e6182b72d519/image.PNG" width = "50%" height = "50%">

<pre><code class="language-c">public class ArraySix
{
    public static void main(String[] args)
    {
        /*
         * 6. 좌석 예약 프로그램을 만드시오. 예약 완료 후, 같은 자리를 다시 예약하려고 할 때 예약이 불가하다는 메세지와 함께 남아있는 좌석의
         * 목록도 출력해야 합니다.
         */
        // 1. 사용자로부터 입력값을 받는다.
        Scanner res = new Scanner(System.in);

        // 2. 총 좌석을 만든다.10x10의 100석이다.
        int[][] seat = new int[10][10];
        // 3. 입력한 값을 행열에 저장하기 위해 2개의 int형 변수를 선언한다.
        int x, y;
        // 4. 총 좌석수는 100석이다.
        int full = 100;

        // 5. 좌석이 있다면 무한 반복한다.
        while (full &gt; 0)
        {
            System.out.println(&quot;[총 100석] 예약할 좌석 &#39;(행 열)&#39;로 입력: &quot;);
            x = res.nextInt(); // 행을 입력한 값 저장
            y = res.nextInt(); // 열을 입력한 값 저장

            // 6. 존재하지 않는 좌석 입력시 걸러내기
            if (x &gt; 10 || x &lt; 1 || y &gt; 10 || y &lt; 1)
            {
                System.out.println(&quot;▶ 존재하지 않는 좌석입니다. \n▷ 1행 2열 예약시 &#39;1 2&#39;를 입력해주세요!)&quot;);
                continue;
            }
            // 7. 자바의 매우 중요한 특성: 배열 생성하여 공간만 만들어주면 자동으로 전부 0으로 채워준다
            // 그 특성을 이용해서 입력한 번째의 배열이 0일 경우 빈 좌석이 된다.
            // 입력한 값에 -1을 해주는 이유는 배열의 인덱스는 0번부터 시작하며 우리는 1번째부터 부르기 때문이다.
            // 10인 배열을 생성해주면 0~9까지가 생성되며, 우리는 1~10까지로 부르는 차이때문에 -1을 해준다.
            if (seat[x - 1][y - 1] == 0)
            {
                System.out.println(&quot;성공적으로 예약이 완료되었습니다.&quot;);
                // 8. 예약되었으니 0에서 1로 채워준다.
                seat[x - 1][y - 1] = 1;
            } else
            {
                System.out.println(&quot;이미 예약된 좌석입니다.&quot;);
                System.out.print(&quot;↓ 비어있는 좌석 ↓&quot;);
                // 9. 좌석의 행을 전체 탐색한다.(배열은 인덱스 0번째부터 시작)
                for (int i = 0; i &lt; 10; i++)
                {
                    // 10. 좌석의 열을 전체 탐색한다.(배열은 인덱스 0번째부터 시작)
                    for (int j = 0; j &lt; 10; j++)
                    {
                        // 11. 좌석의 행열이 빈 좌석이라면?
                        if (seat[i][j] == 0)
                        {
                            // 12. 배열의 0번쨰를 우리는 1번째로 말하므로 +1을 해준다.
                            System.out.printf(&quot;\n→ %d행 %d열\n&quot;, i + 1, j + 1);
                        }
                    }
                }
            }
        }
    }
}
</code></pre>
<ol start="7">
<li>해당 게임의 핵심은 모든 기능을 하나하나 
모든 경우의 수를 따져서 만들어줘야 한다는 것이다.
무한반복 while문 2개를 겹쳐서 게임중 게임 상태를 벗어나지 않도록 했다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/5e536b35-3cea-40d1-b963-c6386fb27c8d/image.PNG" width = "60%" height = "60%">

<pre><code class="language-c">public class ArraySev
{
    public static void main(String[] args)
    {
        /*
        7. 숫자야구게임을 만드시오. 
         + 1~9 사이의 중복되지 않는 3개의 정수를 생성한다. 
         + 사용자는 3개의 숫자를 입력한다. 
         + 생성된
         + 3개의 숫자를 맞추는데 위치까지 정확히 맞춰야 한다. 
         + 숫자와 숫자의 위치까지 일치하면 strike 로 판정한다. 
         + 숫자는 맞지만 위치가 틀렸다면 ball 로 판정한다. 
         + 숫자3개가 모두 일치하지 않으면 out 으로 판정한다. 
         + 3 strike 가 되면 게임은 종료된다. 
         + 시도한 횟수를 표시한다. 
         + 계속할지 종료할지 여부를 물어보고 다음 진행을 한다.
        */

        // 1. 랜덤을 생성하며 사용자로부터 입력값을 받는다.
        Random random = new Random();
        Scanner scanner = new Scanner(System.in);

        // 2. 게임에서 사용할 변수(첫게임, 2게임, 3게임 변수)
        int com1, com2, com3;
        int user1, user2, user3;
        int randomCnt = 0;// 난수생성 카운트
        int gameCount = 0;// 게임 카운트
        int strikeCnt = 0, ballCnt = 0;// 스크라이크,볼 카운트

        // 3. 게임을 전체 무한 반복
        while (true)
        {
            // 3. 게임을 전체 무한 반복2
            while (true)
            {
                // 4. 몇번째 게임인지 카운트 체크
                randomCnt++;

                // 5. 첫~세번째 게임의 1~9사이의 난수생성
                com1 = random.nextInt(100) % 9 + 1;
                com2 = random.nextInt(100) % 9 + 1;
                com3 = random.nextInt(100) % 9 + 1;
                if (!(com1 == com2 || com2 == com3 || com3 == com1))
                {
                    // 6, 중복되지 않아야만 탈출하게끔 가두는 if문 조건 
                    break;
                }
            } //// while end

            // 7. 컴퓨터 정답: 회차 + 첫게임 + 2게임 + 3게임 구분 출력(실게임에선 지워야함)
            System.out.println(randomCnt + &quot;회:&quot; + com1 + &quot; &quot; + com2 + &quot; &quot; + com3);

            while (true)
            {
                // 8. 사용자로부터 3게임의 정수를 저장한다.
                System.out.println(&quot;3게임의 정수를 입력하세요(1~9)&quot;);
                System.out.println(&quot;스페이스로 구분하며 마지막에 Enter를 눌러주세요&quot;);
                user1 = scanner.nextInt();
                user2 = scanner.nextInt();
                user3 = scanner.nextInt();

                // 9, 게임카운트 1회 증가
                gameCount++;

                // 10. 스크라이크 모든 경우(숫자와 위치까지 일치해야만 정답)
                if (com1 == user1)
                    strikeCnt++;
                if (com2 == user2)
                    strikeCnt++;
                if (com3 == user3)
                    strikeCnt++;

                // 11. 볼의 모든 경우(숫자는 일치하나 위치가 다를때)
                if (com1 == user2 || com1 == user3)
                    ballCnt++;
                if (com2 == user1 || com2 == user3)
                    ballCnt++;
                if (com3 == user1 || com3 == user2)
                    ballCnt++;

                // 12. 승리로 종료 선언
                if (strikeCnt == 3)
                {
                    System.out.println(&quot;홈런!!~~~&quot;);
                    System.out.println(gameCount + &quot;번만에 홈런을 쳤습니다.&quot;);
                    break;// 루프탈출
                } 
                else // 그외의 경우
                {
                    // 13. 하나도 못맞추는 경우
                    if (strikeCnt == 0 &amp;&amp; ballCnt == 0)
                    {
                        System.out.println(&quot;아웃입니다&quot;);
                    } 
                    else // 14. 그 외를 출력해준다.
                    {
                        System.out.printf(&quot;%d 스트라이크, %d 볼\n&quot;, strikeCnt, ballCnt);
                    }
                    // 15. 스트라이크, 볼 카운트 초기화
                    strikeCnt = 0;
                    ballCnt = 0;
                    // continue문은 필요없음.
                }
            } //// while end

            //16. 게임이 끝났다면 나오는 출력문
            System.out.println(&quot;한게임 더 하시겠습니까?(0:종료,1:재시작)&quot;);
            int restart = scanner.nextInt();
            if (restart == 0)
            {
                // 17. 게임종료
                System.out.println(&quot;\n==게임이 종료되었습니다.==\n&quot;);
                // 실행되는 즉시 main함수가 종료된다.
                System.exit(0);
            } 
            else if (restart == 1)
            {
                // 18. 게임을 재시작하기 위해 카운트변수 초기화
                strikeCnt = 0;
                ballCnt = 0;
                gameCount = 0;
                System.out.println(&quot;\n==게임을 재시작합니다.==\n&quot;);
            }
        } // 게임 전체 반복 while end
    }// main 메서드 end
}// class 끝</code></pre>
<blockquote>
<p>이렇게 배열까지 끝이 났다. 
배열은 매우매우 중요하면서도 응용할 수 있는 부분이 많아서
문제를 좀 빡세게 넣었다.
다음 시간에도 꿀 떨어지고 중요한 자바(JAVA) 포스팅은 계속된다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.08] 클래스의 기초와 클래스패스 그리고 스태틱의 이해⭐]]></title>
            <link>https://velog.io/@kama_code/JAVA.08-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EA%B8%B0%EC%B4%88%EC%99%80-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%A8%EC%8A%A4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%8A%A4%ED%83%9C%ED%8B%B1%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@kama_code/JAVA.08-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EA%B8%B0%EC%B4%88%EC%99%80-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%A8%EC%8A%A4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%8A%A4%ED%83%9C%ED%8B%B1%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Wed, 12 Jul 2023 19:11:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>자바(Java)는 클래스이다! 해도 과언이 아닌 만큼 굉장히 중요한 파트이다.
오늘은 클래스의 기초를 배운다. 추후에 클래스에 대해 다시 깊이 다룰 것이다.</li>
</ul>
</blockquote>
<h2 id="step1-객체지향-프로그래밍object-oriented-programming">&lt;Step.1&gt; 객체지향 프로그래밍(Object Oriented Programming)</h2>
<blockquote>
<ul>
<li>데이터를 추상화시켜 속성과 행위를 가진 객체를 만들고 
그 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법</li>
</ul>
</blockquote>
<p>▶ 우리가 표현할 수 있는 실제 세계의 모든 사물들을 <span style='background-color: #fff5b1'><strong>객체(오브젝트Object)</strong></span> 라고 한다.
▶ 객체 만들기를 <span style='background-color: #fff5b1'><strong>인스턴스(Instance)</strong></span>화 한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/57e154ca-396b-46e8-9369-f1d8ea20f594/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/da10768a-35b0-4004-a55d-f8840efac820/image.PNG" width = "70%" height = "70%">

<h2 id="step2-클래스의-기초class">&lt;Step.2&gt; 클래스의 기초(Class)</h2>
<blockquote>
<ul>
<li>자바(JAVA)는 클래스가 전부이다.</li>
</ul>
</blockquote>
<ul>
<li>클래스는 데이터와 처리동작을 하나로 모아놓은 것이다.</li>
<li>데이터를 필드, 처리동작을 메소드라고 한다.</li>
<li>필드와 메서드를 클래스의 멤버라고 한다.</li>
<li>★★ 객체지향 프로그래밍에서는 큰 하나의 클래스보다
작은 열개의 클래스가 더 큰 힘과 위력을 발휘한다.</li>
</ul>
<p>========== 규칙 ==========</p>
<blockquote>
<ul>
<li>클래스 이름은 대문자로 시작</li>
</ul>
</blockquote>
<ul>
<li>하나의 java파일에 여러개의 클래스를 정의 가능하다</li>
<li>단, 소스 파일 1개당 public 클래스 선언은 단 하나만 가능하다.</li>
<li>자바 파일명과 public 클래스명은 동일해야함 and 패키지는 폴더명과 일치</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/c722e07e-6fbf-47bf-9f0b-0c84e5d0352e/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/2317985a-1a74-42f7-aa0f-e723c7c568cd/image.PNG" width = "70%" height = "70%">

<h2 id="step3-객체-만들기인스턴스화">&lt;Step.3&gt; 객체 만들기(인스턴스화)</h2>
<img src = "https://velog.velcdn.com/images/kama_code/post/ea9ccfdc-1d97-49ad-bd4a-c6d6af9a3a66/image.PNG" width = "70%" height = "70%">

<p>Book(클래스 타입) myBook 주소값(참조값) = new (객체생성) Book(); (생성자)</p>
<ul>
<li>new는 무조건 힙 영역에 저장된다. 스택 영역은 기본 자료형 저장</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/38b44fa9-d70c-4712-ae13-819ad7c7a9ac/image.PNG" width = "70%" height = "70%">

<h2 id="step4-생성자constructor">&lt;Step.4&gt; 생성자(constructor)</h2>
<blockquote>
<ul>
<li>생성자(constructor)란 객체 생성을 할 때만 호출하는 특수한 메서드</li>
</ul>
</blockquote>
<ul>
<li>생성자 이름은 클래스 이름하고 똑같다.</li>
<li>메소드이지만 반환형이 없는 형태이다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/02b81005-ea6c-4ef1-ac4a-823ea66d3222/image.PNG" width = "50%" height = "50%">

<blockquote>
<p>⚡ 디폴트 생성자(Default Constructor)</p>
</blockquote>
<ul>
<li>클래스는 반드시 하나 이상의 생성자가 존재</li>
<li>개발자가 생성자를 정의하지 않으면 컴파일러에 의해 디폴트 생성자가 코드에 삽입</li>
<li>매개변수와 실행부가 없는 형태로 정의</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/e12e26d3-8dfd-44da-8bd7-e1a77757ae42/image.PNG" width = "60%" height = "60%">

<ul>
<li>생성자는 클래스명과 동일</li>
<li>주로 멤버변수 초기화에 사용</li>
<li>멤버상수를 초기화 할 수 있다.</li>
<li>상속되지 않는다.</li>
<li>리턴값이 없다. 즉 값을 반환할 수 없다.</li>
<li>객체 생성시 딱 한번만 호출되고, 개발자가 임의로 호출할 수 없다.</li>
<li>메소드 오버로딩이 가능하다.</li>
<li>생성자 내에서 다른 생성자를 호출할 수 있다.</li>
</ul>
<h2 id="step5-생성자-오버로딩constructor-overloding">&lt;Step.5&gt; 생성자 오버로딩(Constructor overloding)</h2>
<ul>
<li>하나의 클래스 내에 매개변수 개수나 자료형이 다른 동일한 이름의 
메소드를 여러개 정의하는 것</li>
<li>매개변수의 개수, 타입을 다르게 기술하여 여러개를 정의할 수 있다. </li>
<li>오버로딩이 된 생성자가 있으면 디폴트 생성자를 무조건 만들어야 한다.
( 가장 순수한 생성자가 무엇인지 기준을 알아야 하므로 )</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/14eeb8e3-d341-4b13-9eeb-144c1079056f/image.PNG" width = "50%" height = "50%">

<h2 id="step6-접근-제한자">&lt;Step.6&gt; 접근 제한자</h2>
<blockquote>
<ul>
<li>변수나 메서드에 접근 제한자를 지정하면 접근을 제한할 수 있다.  </li>
<li>데이터의 안정을 위해 // 권한이 있는 사람만 볼 수 있다</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/53d77719-f7a6-41bb-b077-f676a474bbb0/image.PNG" width = "70%" height = "70%">

<p>정보은닉화(private)을 많이 사용한다.
단, 정보은닉화를 하게 되면 메소드 호출할시 getter(출력) setter(입력)을 만들어서 
간접으로 호출해야 한다.</p>
<p>💧 <span style='background-color: #fff5b1'><strong>getter &amp; setter</strong></span> 생성법
get set은 우클릭 - source - general getter and setter로 자동 생성 가능</p>
<h2 id="step7-this의-사용">&lt;Step.7&gt; this의 사용</h2>
<blockquote>
<p>변수마다 이름을 각각 정의하는 것은 생각보다 쉽지  않다. 그래서 
보통은 같은 이름을 사용하는데 멤버변수임을 구분해주는 데 this를  사용한다.</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/4188b32f-6b5b-4179-b0a5-2914e0525daf/image.PNG" width = "80%" height = "80%">

<h2 id="step8-디버깅">&lt;Step.8&gt; 디버깅</h2>
<blockquote>
<p>main &gt; 번호 줄 우크릭 &gt; toggle breakpoint
ㄴ 오류 체크할 때 좋다
ㄴ 다음줄 넘어가는 것 (Step over)
ㄴ 메소드 안으로 들어가는 것 (Step into)</p>
</blockquote>
<h2 id="step9-스태틱static">&lt;Step.9&gt; 스태틱(static)</h2>
<blockquote>
<ul>
<li>스태틱 영역의 변수 및 메서드는 어떤 객체에서도 접근해서 사용할 수 있다. </li>
</ul>
</blockquote>
<ul>
<li>그래서 스태틱을 <span style='background-color: #fff5b1'>전역변수</span>라고도 불리운다.</li>
<li>main 보다도 먼저 실행된다.</li>
<li>하나만 선언이 가능하다. </li>
<li>특정 기능이 필요한데 자주 사용된다면 많은 클래스에서 중복되어 만들어 지지 않게 하려는 의도에서 스태틱을 많이 사용한다. .</li>
</ul>
<blockquote>
<ul>
<li>스태틱(static)의 특징</li>
</ul>
</blockquote>
<ol>
<li>메모리에 고정적으로 할당된다. </li>
<li>객체 생성 없이 사용할 수 있다.</li>
<li>프로그램이 시작되면 메모리의 static 영역에 적재되고, 프로그램이 종료될 때 해제된다.</li>
<li>Static 메서드 내에서는 인스턴스 변수를 사용할 수 없다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/275244b2-e703-4308-b7d4-15a6fbd38761/image.PNG" width = "80%" height = "80%">

<h2 id="step10-패키지와-클래스패스">&lt;Step.10&gt; 패키지와 클래스패스</h2>
<blockquote>
<ul>
<li>JVM(자바 가상 머신)이 클래스를 실행시키는 방법
ㄴ같은 폴더에서 클래스 파일을 찾아서 기억한다.
ㄴ경로를 지정했다면 그 경로에 있는 클래스 파일을 찾아서 실행한다.
ㄴJava.class - 실행(확장자가 class여야 실행이 가능하다.)</li>
</ul>
</blockquote>
<ul>
<li>패키지는 폴더명과 같다.(폴더 이름은 소문자로 구성한다)
ㄴ .은 안에 있는 폴더를 의미한다. 예시) com.study</li>
<li>클래스패스는 자바 가상머신의 클래스 탐색 경로를 의미한다. </li>
<li>java.lang 패키지만 예외적으로 임포트가 필요 없이, 클래스 이름만 적어서 사용할 수 있다.</li>
<li>클래스 이름이 같아서 충돌이 일어나는 경우가 아니라면 왠만하면 import해서 사용한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/92436170-6548-4ac8-a7c3-67d5949471f9/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/7a60b967-8949-4aa3-ae0f-f63fe2231705/image.PNG" width = "80%" height = "80%">

<blockquote>
<p>cmd (명령 프롬프트) 기초 명령어</p>
</blockquote>
<ol>
<li>cd + &quot;주소&quot; : cd는 들어간다를 의미한다.</li>
<li>dir : 목록 보기</li>
</ol>
<h2 id="step11-발전을-위한-문제풀이-kama_code-출제">&lt;Step.11&gt; 발전을 위한 문제풀이 (kama_code 출제)</h2>
<blockquote>
<ol>
<li>밑변과 높이 정보를 저장할 수 있는 Triangle클래스를 정의해보자. 
init메소드를 통해 밑변과 높이를 초기화한다.
그리고 밑변과 높이를 변경시킬수 있는 메소드와 삼각형의 넓이를 계산해서 반환하는 메소드도 함께 정의해보자.</li>
<li>구슬치기 하는 아이들을 추상화하여 클래스로 정의해보자.</li>
</ol>
<p>*어린아이가 보유하고 있는 구슬의 개수 정보를 담는다
*놀이를 통해 구슬을 획득 또는 상실하는 것을 표현한다.
*어린이의 현재 보유하고 있는 구슬의 개수를 표현한다.
초기화는 다음과 같이 진행한다.
◆어린이1의 보유갯수 : 구슬 20개
◆어린이2의 보유갯수 : 구슬 15개
게임은 다음과 같이 진행한다.
◆1차게임 : 어린이1은 어린이2의 구슬 5개를 획득한다.
◆2차게임 : 어린이2는 어린이1의 구슬 9개를 획득한다.
ㄴ어린이 객체를 생성시 구슬의 보유갯수는 생성자를 통해 초기화 되어야 한다.
3. 성적 클래스를 작성해보자. 국어,영어, 수학 과목의 3개의 점수를 입력받아 
객체를 생성하고 성적 평균을 출력하는 프로그램을 만들어라.</p>
</blockquote>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>여기서 핵심은 다양한 메소드를 위 아래로 왔다갔다를 잘하는 것이다.
메소드 이름을 컨트롤+좌클릭 하면 그 메소드로 이동한다.
private는 직접 접근이 안되므로 getter setter을 만들어줘서 다뤄야 하며,
멤버 메소드를 별도로 만들어줌으로써 간접적으로 불러오는 방법도 있다.
(단, 반드시 클래스 Triangle 안에 모두 넣어줘야 한다.)
그리고 getArea를 통해 계산을 하는 메소드를 만들어준다.
(단, 0.5라는 소수를 다루므로 double형으로 반환해야 오류가 나지 않는다)</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/1ddf22ff-1f42-4871-9a34-2b601d7e1a09/image.PNG" width = "50%" height = "50%">

<pre><code>import java.util.Scanner;

class Triangle
{
    //멤버변수 : 밑변, 높이
    /*
    멤버변수의 직접적인 접근을 차단하기 위해 private으로 선언하는 것을
    정보은닉이라고 한다
     */
    private int bottom;
    private int height;

    //멤버 메서드
    //멤버 변수 전체를 초기화 한다
    public void init(int _bottom, int height)
    { // private을 간접적으로 불러오기 위해 해당 메소드를 만든다

        //매개변수와 멤버변수명이 다르므로 혼선이 없기에 this가 없어도 된다
        bottom = _bottom;
        //this는 멤버변수를 가리키는 키워드이다. height은 
        //Triangle의 멤버변수와 일치하기에 this를 붙여서 구분해준다.
        this.height = height;            
    }

    // 우클릭 소스 - getter, setter를 누른다 - setter만 생성한다.
    // private이므로 간접적으로 접근하기 위해 필요하다.
    public void setBottom(int bottom)
    {
        this.bottom = bottom;
    }

    public void setHeight(int height)
    {
        this.height = height;
    }

    /*
    삼각형의 넓이는 밑변*높이*0.5 이므로 계산의 결과가 소수점으로 나올 수 있다
    따라서 int가 아닌 double형으로 설정해주어야 한다.
     */
    public double getArea(int bottom2, int height2)
    {
        return bottom2 * height2 * 0.5;
    }

}

public class ClassOne
{

    public static void main(String[] args)
    {
        /*
        1. 밑변과 높이 정보를 저장할 수 있는 Triangle클래스를 정의해보자. 
        init메소드를 통해 밑변과 높이를 초기화한다.
        */
        Triangle t = new Triangle(); //Triangle을 불러와준다. t라는 객체로 담는다.
        Scanner scan = new Scanner(System.in); // 사용자로부터 입력값을 받는다.
        System.out.println(&quot;밑변은 몇인가요? : &quot;);
        int bottom = scan.nextInt(); // bottom(밑변)으로 저장
        System.out.println(&quot;높이은 몇인가요? : &quot;);
        int height = scan.nextInt(); // height(높이)로 저장
        t.getArea(bottom, height); // t클래스 객체에 포함된 getArea를 호출해서 밑변과 높이를 보낸다.
        System.out.println(&quot;삼각형의 넓이 : &quot;+ t.getArea(bottom, height));
        System.out.println(&quot;임의로 변경한 값의 삼각형 넓이 : &quot;+ t.getArea(5, 10));
    }

}</code></pre><ol start="2">
<li>===========================================================</li>
</ol>
<ul>
<li>천리길도 한 걸음부터라는 말이 있다. 
하나하나 차근차근 기능을 만들어주는 것이 중요하다.
그리고 만들려는 것이 어떤 근본의 규칙을 가지고 있는지 파악하는 것이 
무엇보다 중요하다.</li>
<li>구슬게임은 누군가 얻으면 누군가 잃으므로 상호작용할 수 있는 메소드를 만들어주고
그 메소드를 불러서 값을 변하게 하는 원리이다.<img src = "https://velog.velcdn.com/images/kama_code/post/28cbe38b-52dc-41cf-b94a-32d12cc1b8f9/image.PNG" width = "40%" height = "40%">

</li>
</ul>
<pre><code>class gusle 
{
    // 멤버변수 : 어린이가 보유한 구슬의 개수
    int bead;

    // 멤버 변수를 초기화 할 목적으로 정의한다.
    public gusle(int bead) // 생성자, 매개변수 1개 있는 생성자 ( 이름 같으면 )
    {
        // this는 멤버변수와 매개변수
        this.bead = bead; // 멤버변수 안에 매개변수를 넣는다
        /*
         this의 활용법
         1. 해당 클래스의 멤버를 가리킬때 사용한다
         2. 오버로딩으로 정의된 또 다른 생성자를 호출할 때 사용한다
         이 때는 this(인수1, 인수2)와 같이 기술한다
         */
    }

    // 어린이가 보유한 구슬의 개수를 출력한다
    public void showProperty()
    {
        System.out.println(&quot;보유한 구슬의 개수 : &quot; + bead);
    }

    /*
    구슬게임을 위한 멤버 메소드
    ▶ 구슬의 총 개수는 한정적이므로 한 사람이 잃으면 한 사람은 얻게 되어 있다. 
     */
    public void obtainBead(gusle child, int beadCount)
    {
        // this는 객체 자신이 되므로, 호출의 주체는 구슬이 증가한다.
        this.bead += beadCount; // 한 아이가 구슬을 얻으면 

        // 매개변수로 전달된 어린이의 구슬은 잃게 되므로 .(닷)으로 접근
        //하여 잃게 하면 된다
        child.bead -= beadCount; // 다른 아이는 구슬을 잃는다        
    }

}

public class ClassTwo
{

    public static void main(String[] args)
    {
//        2. 구슬치기 하는 아이들을 추상화하여 클래스로 정의해보자.
//        *어린아이가 보유하고 있는 구슬의 개수 정보를 담는다
//        *놀이를 통해 구슬을 획득 또는 상실하는 것을 표현한다.
//        *어린이의 현재 보유하고 있는 구슬의 개수를 표현한다.
//        초기화는 다음과 같이 진행한다.
//        ◆어린이1의 보유갯수 : 구슬 20개
//        ◆어린이2의 보유갯수 : 구슬 15개
//        게임은 다음과 같이 진행한다.
//        ◆1차게임 : 어린이1은 어린이2의 구슬 5개를 획득한다.
//        ◆2차게임 : 어린이2는 어린이1의 구슬 9개를 획득한다.
//        ㄴ어린이 객체를 생성시 구슬의 보유갯수는 생성자를 통해 초기화 되어야 한다.

        gusle child1 = new gusle(20); // 구슬 20개를 가진 어린이1 객체 생성
        gusle child2 = new gusle(15); // 구슬 15개를 가진 어린이2 객체 생성

        System.out.println(&quot;게임 전 구슬의 보유 개수&quot;);
        System.out.print(&quot;어린이1 : &quot;);
        child1.showProperty(); //어린이1에 해당하는 호출하는 멤버 메소드를 부른다.
        System.out.print(&quot;어린이2 : &quot;);
        child2.showProperty(); //어린이2에 해당하는 호출하는 멤버 메소드를 부른다.    

        /*1차게임 : 어린이1은 어린이2의 구슬 5개 획득*/
        child1.obtainBead(child2, 5); // 전달된 어린이1은 +5, 어린이2는 -5

        System.out.println(&quot;\n1차 게임 후 구슬의 보유 개수&quot;);
        System.out.print(&quot;어린이1 : &quot;);
        child1.showProperty(); 
        System.out.print(&quot;어린이2 : &quot;);
        child2.showProperty();

        /*2차게임 : 어린이2가 어린이1의 구슬 9개 획득*/
        child2.obtainBead(child1, 9); // 전달된 어린이2는 +9, 어린이1는 -9

        System.out.println(&quot;\n2차 게임 후 구슬의 보유 개수&quot;);
        System.out.print(&quot;어린이1 : &quot;);
        child1.showProperty(); 
        System.out.print(&quot;어린이2 : &quot;);
        child2.showProperty();
    }
}</code></pre><ol start="3">
<li>================================================</li>
</ol>
<p>먼저 데이터 보호를 위해 private으로 선언해준 이후
직접 접근이 안되므로 매개변수가 있는 생성자를 만들어준다.
생성자를 통해 자유롭게 간접적으로 접근이 가능해진다!</p>
<p>곧바로 단도직입적으로 계산하는 멤버메소드를 생성해준 후</p>
<p>메인 메소드에서 사용자로부터 입력값을 받고 차례대로 저장한 후
계산하는 멤버 메소드로 값을 보내어 반환을 받는 것이다. 
그 값을 출력하는 간단한 프로그램이다.</p>
<pre><code>import java.util.Scanner;

class ClassThree
{
    // 정보은닉화 private
    private int kor, eng, math;

    // 매개변수가 있는 생성자 : 
    // 직접 접근이 안되어서 간접적으로 불러오기 위해 
    public ClassThree(int kor, int eng, int math)
    {
        this.kor = kor;
        this.eng = eng;
        this.math = math;
    }

    // 계산하는 멤버 메소드
    public int avgr() 
    {
        return ( kor + eng + math ) / 3;
    }

    public static void main(String[] args)
    {
//        3. 성적 클래스를 작성해보자. 국어,영어, 수학 과목의 3개의 점수를 입력받아 
//        객체를 생성하고 성적 평균을 출력하는 프로그램을 만들어라.
        // 사용자로부터 입력값을 받고
        Scanner scan = new Scanner(System.in);

        // 각 변수에 저장한다
        System.out.println(&quot;국어 영어 수학 점수를 순서대로 입력하시오:&quot;);
        int kor = scan.nextInt();
        int eng = scan.nextInt();
        int math = scan.nextInt();

        // ClassThree 클래스의 avg 객체를 생성하고 3변수를 담는다.
        ClassThree avg = new ClassThree(kor,eng,math); 
        // avgr() 멤버메소드에 저장된 3변수를 담아서 출력한다. 
        System.out.println(&quot;당신의 평균 점수는 &quot; + avg.avgr() + &quot;점!&quot;);
    }
}</code></pre><blockquote>
<ul>
<li>이렇게 클래스의 기초를 다루어보았다. 
생각해보면 자바(Java)는 중요하지 않는 것이 없는게 사실이다.
앞으로도 꿀 떨어지는 포스팅은 계속된다..</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.07] 메소드(함수)와 변수의 사용 가능한 범위와 메모리 영역 and 꿀팁📣]]></title>
            <link>https://velog.io/@kama_code/JAVA.07-%EB%A9%94%EC%86%8C%EB%93%9C%ED%95%A8%EC%88%98%EC%99%80-%EB%B3%80%EC%88%98%EC%9D%98-%EC%82%AC%EC%9A%A9-%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%B2%94%EC%9C%84%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD-and-%EA%BF%80%ED%8C%81</link>
            <guid>https://velog.io/@kama_code/JAVA.07-%EB%A9%94%EC%86%8C%EB%93%9C%ED%95%A8%EC%88%98%EC%99%80-%EB%B3%80%EC%88%98%EC%9D%98-%EC%82%AC%EC%9A%A9-%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%B2%94%EC%9C%84%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD-and-%EA%BF%80%ED%8C%81</guid>
            <pubDate>Mon, 10 Jul 2023 18:51:37 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>자바(JAVA)는 객체지향언어이다. 
메소드는 프로그래밍을 하는데 매우매우 중요하며 
안정적 그리고 효율성을 증가시키는 메소드(함수)에 대해서 알아본다! </li>
</ul>
</blockquote>
<h3 id="step1-메소드의-정의👀🐣">&lt;Step.1&gt; 메소드의 정의👀🐣</h3>
<blockquote>
<ul>
<li>메소드(함수)란?
ㄴ객체지향 프로그램에서 행동 또는 동작을 의미한다.
ㄴ함수는 무조건 클래스 안에 존재하기 때문에 결국 모든 함수가 메소드가 된다.</li>
</ul>
</blockquote>
<p>→ 상수명은 전체 대문자로 쓴다
→ 패키지명은 전체를 소문자로 기술하고 연결단어는 .(닷)으로 구분한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/7a1560a8-3059-46ce-9a4c-45cd73f5022f/image.PNG" width = "70%" height = "70%"> 

<blockquote>
<ul>
<li>다음처럼 기능을 구현하는 것을 &#39;메소드를 정의한다&#39; 라고 한다</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/aae2ef57-ab2f-45b6-96d1-4048e636df42/image.PNG" width = "70%" height = "70%"> 

<blockquote>
<ol>
<li>메소드 이름: 클래스명 - 대문자로 시작하지만 
ㄴ메소드 및 변수명 - 소문자로 시작한다</li>
<li>매개변수를 통해서 전달된 값이 복사된다. 
ㄴ메소드의 형태는 총 4가지가 있다!</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/8891de5e-15fc-4889-a01c-6f42af6e394f/image.PNG" width = "70%" height = "70%"> 

<blockquote>
<ol start="3">
<li>반환형 : 위 사진에서 int는 정수형 반환값이 있는 메소드를 말하며
void는 반환값이 없는 것을 말한다.</li>
<li>코드 블럭 : 말 그대로 위에서부터 아래로 코드를 실행한다.</li>
<li>return : (반환값이 있을 때의 return)은 호출한 곳으로 값을 반환한다.
(반환값이 없을때 void의 return)은 끝낸다(end)를 의미한다.</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/7fa8d073-1f11-492d-9c02-524c95cef139/image.PNG" width = "60%" height = "60%">

<img src = "https://velog.velcdn.com/images/kama_code/post/f53538a7-70ec-4500-8fb9-b1bfd5424be8/image.PNG" width = "50%" height = "50%">

<h3 id="step2-메소드의-규칙👀🐣">&lt;Step.2&gt; 메소드의 규칙👀🐣</h3>
<blockquote>
</blockquote>
<ul>
<li>Java에서 main메서드는 무조건 public static void로 선언하기로 약속한다.</li>
<li>static으로 선언된 메서드는 static으로 선언된 메서드만 호출할 수 있다.</li>
<li>매소드 호출 후 반환값은 호출한 위치로 반환된다. 
이때 매소드는 메모리에서 소멸된다.</li>
<li>반환값이 없는 void형 메서드는 실행이 완료되면  호출한 위치로 실행의 
  흐름이 돌아온다.</li>
<li>하나의 기능을 수행하는 일련의 코드로 객체의 기능을 제공하기 위해 </li>
<li>반드시 클래스 내부에 구현된다.</li>
</ul>
<h3 id="step3-main-메소드👀🐣">&lt;Step.3&gt; main 메소드👀🐣</h3>
<blockquote>
<ul>
<li>자바(JAVA)는 객체지향언어로 순서가 없다. 그러나, 기준이 있다.
ㄴ바로 !! main (메인)이다. 항상 프로그램의 시작은 main에서부터이다. 
ㄴ코딩이 아무리 복잡하고 뒤죽박죽일지라도 자바(JAVA)언어는 가장 먼저 메인부터 
ㄴ찾아서 위에서부터 순서대로 읽으면 수월하게 읽을 수 있다. 
ㄴ이것이 자바(JAVA) 코드 읽는 법이다. </li>
</ul>
</blockquote>
<ul>
<li>자바(JAVA)는 선입후출 형식이며 MAIN(메인)이 가장 아래에 쌓인다.
다른 메소드가 모두 나가야 메인도 나갈 수 있다. 가장 중요함을 잊지 말자!</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/afc6845c-624f-4c52-8012-82adac6d7376/image.PNG" width = "60%" height = "60%">

<blockquote>
<ul>
<li>아래 사진은 메인 메소드로부터 다른 메소드를 호출하는 과정을 의미한다.
ㄴ메인 메소드가 HiEveryone이라는 다른 메소드를 불렀고 하지만 매개변수 int age가 있다.
ㄴ그래서 호출할때 HiEveryone(age값)이 필수로 들어간다. 
ㄴ매개변수가 있는 메소드를 부를 때 조건에 해당하는 값이 없으면 에러(error)가 난다. </li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/f29267e8-b276-4e88-b3a5-e46eb9378af1/image.PNG" width = "80%" height = "80%">

<h3 id="step4-변수의-사용-가능한-범위👀🐣">&lt;Step.4&gt; 변수의 사용 가능한 범위👀🐣</h3>
<blockquote>
<ul>
<li>변수도 사용 가능한 범위가 있다. 
굉장히 중요한 내용이니까 눈에 꼭 익히자!</li>
</ul>
</blockquote>
<p>자바(JAVA)에서 변수의 구분은 클래스변수, 지역변수, 매개변수가 있다.</p>
<ul>
<li>클래스변수는 클래스 안에서 모두 사용이 가능하다. </li>
<li>매개변수는 메소드를 호출할때 필요한 조건에 해당한다.</li>
<li>지역변수는 그 메소드 지역 안에서만 사용이 가능하다. 
ㄴ지역변수는 해당 지역을 벗어나면 메모리에서 소멸된다. 그러므로 
★ 다른 메소드에서 똑같은 이름으로 변수를 사용할 수 있다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/dc32ea8c-6841-4dc1-a0c4-81f077504a19/image.PNG" width = "60%" height = "60%">

<h3 id="step5-메소드의-오버로딩method-overloading👀🐣">&lt;Step.5&gt; 메소드의 오버로딩(Method Overloading)👀🐣</h3>
<blockquote>
<ul>
<li>동일한 이름의 메서드를 2개 이상 정의하는 것을 말한다.</li>
</ul>
</blockquote>
<ul>
<li>이름만 같고 기능은 다른 메소드이다.</li>
<li>메소드가 같다는 것은 매개변수까지 모두 일치해야 똑같은 메소드로 본다.</li>
<li>예시로는 println - 메소드 이름은 서로 같으나 매개변수가 달라 서로 다른 기능을 한다.</li>
<li>메소드가 같고 다름을 구별할 때 반환값은 상관이 없다. (void든 int든..) 
ㄴ매개변수와 메소드 이름까지만 같다면 같은 메소드로 본다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/f7f6b216-b259-4eed-8a6d-818c274f9af4/image.PNG" width = "70%" height = "70%">

<img src = "https://velog.velcdn.com/images/kama_code/post/70f3f60d-bfce-4959-97a2-d80ab8461546/image.PNG" width = "70%" height = "70%">

<h3 id="step6-메모리-영역👀🐣">&lt;Step.6&gt; 메모리 영역👀🐣</h3>
<blockquote>
<ul>
<li>자바(JAVA) 언어를 사용하다보면 반드시 눈에 익혀야 하고 알아야 하는
메모리 영역이다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/20498753-0efe-444a-9ec9-28480124d6b1/image.PNG" width = "70%" height = "70%">

<blockquote>
<p>자바 가상머신(JVM)은 운영체제(OS)에서 이렇게 실행한다.</p>
</blockquote>
<ol>
<li>자바(JAVA) 소스코드인 .java 파일을 컴파일러가 자바 바이트 코드인 
.class로 변환합니다.</li>
<li>.class 코드를 JVM의 클래스 로더에게 보냅니다.</li>
<li>클래스 토더는 JVM 런타임 데이터 영역으로 로딩하여 JVM의 메모리에 올립니다.</li>
</ol>
<ul>
<li><p>메소드(Method) 영역
ㄴ클래스 정보, static 변수, 변수 정보, 메소드 정보 등을 저장한다.
ㄴstatic 이 선언된 클래스 멤버도 올라갑니다.</p>
</li>
<li><p>스택(Stack) 영역
ㄴ int, long, boolean 등 ★기본 자료형★을 저장하는 공간으로, 
임시적으로 사용되는 변수나 정보들이 저장되는 영역
ㄴ쓰레드 별로 1개만 생성하며, 메소드가 호출될 때마다 생성되며 끝나면 제거된다.</p>
</li>
<li><p>힙(Heap) 영역
ㄴ 인스턴스를 생성할 때 생성되는 메모리 형식
ㄴ new로 된 것은 다 힙 영역이다.(&quot;new&quot;를 사용하여 객체를 만들 때 저장)
ㄴ 참조형(class, interface, enum, Array 등) 자료형도 같이 저장
ㄴ예시) Instance instance = new Instance();  -&gt; heap에 존재</p>
</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/b72cc9fa-98b0-4699-ae4f-e2ea569a5f95/image.PNG" width = "80%" height = "80%">

<blockquote>
<ul>
<li>스택(Stack) 영역은 참조값(주소값)만이 들어있다. = (id = 27) 
실제 값은 힙 영역에 저장되어 있다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/5053468b-b72e-4f63-9c5f-d42bb30df4d9/image.PNG" width = "80%" height = "80%">

<h3 id="step7-재귀호출✨">&lt;Step.7&gt; 재귀호출✨</h3>
<p>재귀 호출(recursive call)이란?</p>
<ul>
<li>재귀 호출(recursive call)이란 메소드 내부에서 해당 메소드가 또다시 호출되는 것을 의미합니다.</li>
</ul>
<p>예시1) 1~n까지의 합을 구한다.</p>
<pre><code class="language-c">int sum(int n) {
    int result = 0;
    for (int i = 1; i &lt;= n; i++) {
        result += i;
    }
    return result;
}</code></pre>
<p>재귀호출 변환) 1~n까지의 합의 구한다.</p>
<pre><code class="language-c">int recursiveSum(int n) {
    if (n == 1) {                 // n이 1이면, 그냥 1을 반환함.
        return 1;
    }
    return n + recursiveSum(n-1); // n이 1이 아니면, n을 1부터 (n-1)까지의 합과 더한 값을 반환함.
}</code></pre>
<h3 id="step8-기타-꿀팁👀🐣">&lt;Step.8&gt; 기타 꿀팁👀🐣</h3>
<blockquote>
<ul>
<li>이클립스를 사용하다가 창이 지워졌다면?
showview에서 사라진 창을 선택하여 다시 불러낸다.</li>
</ul>
</blockquote>
<ul>
<li>불러내기엔 돌이킬 수 없고 너무 멀리 왔다면?
window - Perspective - Reset perspective = 초기화</li>
<li>메소드를 더블클릭 후 [컨트롤 + T] 를 누르면 족보가 나온다.
맨 위에 Object가 보이는데 신이라고 보면 된다. </li>
</ul>
<h3 id="step9-발전을-위한-문제풀이-kama_code-출제">&lt;Step.9&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ol>
<li>두 정수를 입력을 받아서 더하기, 빼기, 곱하기, 나누기, 거듭제곱을 계산하는
계산기 프로그램을 만들어라</li>
<li>원의 반지름을 입력하면 원의 둘레와 원의 넓이를 출력하는 프로그램을 만드시오</li>
<li>삼겹살 몇인분을 먹었는지 정수만 입력할시 인분에 따른 칼로리가 출력되는 프로그램을 만드시오</li>
<li>몸무게와 키를 입력받아 다이어트(BMI) 지수를 출력하는 프로그램을 만드시오
비만: 30이상
과체중: 25이상~30미만
정상:18.5이상 ~25미만
저체중: 18.5미만</li>
<li>현금(원)을 입력받아 달러가 환전되는 프로그램을 만드시오.</li>
</ol>
</blockquote>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>복잡해보이지만 원리는 쉽고 간단하다. 더하는 메소드, 빼는 메소드,
곱하는 메소드, 나누는 메소드, 거듭제곱 메소드를 하나씩 다 만들어서
메인에서 불러주면 된다. </li>
</ol>
<p>✍ 입력 : (코드만 길지.. 잘보면 간단하다.)</p>
<pre><code>public class Method
{
    public static void showMenu()
    {
        System.out.println(&quot;계산을 계속하려면 엔터를 눌러주세요&quot;);
        Scanner scanner = new Scanner(System.in);
        String rp = scanner.nextLine();
        if (rp.isEmpty())
        {
            System.out.println(&quot;================================&quot;);
            System.out.println(&quot;메뉴를 선택하세요.숫자를 입력하세요.꼭이요&quot;);
            System.out.println(&quot;1.더하기&quot;);
            System.out.println(&quot;2.빼기&quot;);
            System.out.println(&quot;3.곱하기&quot;);
            System.out.println(&quot;4.나누기&quot;);
            System.out.println(&quot;5.거듭제곱&quot;);
            System.out.println(&quot;0.끝내기&quot;);
            System.out.println(&quot;================================&quot;);
        }
    }

    public static void add()
    {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;첫번째 숫자 :&quot;);
        int num1 = sc.nextInt();
        System.out.print(&quot;두번째 숫자 :&quot;);
        int num2 = sc.nextInt();

        int result = num1 + num2;
        System.out.println(num1 + &quot; + &quot; + num2 + &quot; = &quot; + result);
        System.out.println();
    }

    public static void substract()
    {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;첫번째 숫자 :&quot;);
        int num1 = sc.nextInt();
        System.out.print(&quot;두번째 숫자 :&quot;);

        int num2 = sc.nextInt();

        int result = num1 - num2;
        System.out.printf(&quot;%d - %d = %d &quot;, num1, num2, result);
        System.out.println();
    }

    public static void multiply()
    {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;첫번째 숫자 :&quot;);
        int num1 = sc.nextInt();
        System.out.print(&quot;두번째 숫자 :&quot;);
        int num2 = sc.nextInt();

        int result = num1 * num2;
        System.out.printf(&quot;%d * %d = %d &quot;, num1, num2, result);
        System.out.println();
    }

    public static void divide()
    {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;첫번째 숫자 :&quot;);
        int num1 = sc.nextInt();
        System.out.print(&quot;두번째 숫자 :&quot;);
        int num2 = sc.nextInt();

        if (num2 == 0)
        {
            System.out.println(&quot;0으로 나눌 수 없습니다.&quot;);
            return; // if문인 경우 continue 대신 사용
        }

        int result1 = num1 / num2;
        System.out.println(num1 + &quot; / &quot; + num2 + &quot; = &quot; + result1 + &quot; (몫)&quot;);
        int result2 = num1 % num2;
        System.out.println(num1 + &quot; % &quot; + num2 + &quot; = &quot; + result2 + &quot; (나머지)&quot;);
        System.out.println();
    }

    public static void power()
    {
        Scanner sc = new Scanner(System.in);
        System.out.print(&quot;첫번째 숫자 :&quot;);
        int num1 = sc.nextInt();
        System.out.print(&quot;두번째 숫자 :&quot;);
        int num2 = sc.nextInt();

        int result = 1;
        for (int i = 0; i &lt; num2; i += 1)
        {
            result *= num1;
        }
        System.out.printf(&quot;%d의 %d 제곱 = %d &quot;, num1, num2, result);
        System.out.println();
    }

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);

        while (true)
        {
            showMenu();

            int num = sc.nextInt(); // 입력받은 수를 가져와서 집어넣는다.
            if (num == 0)
            {
                System.out.println(&quot;계산기를 종료합니다.&quot;);
                break;
            } else
            {
                if (num &gt; 5)
                {
                    System.out.println(&quot;없는 메뉴입니다.&quot;);
                    System.out.println(&quot;메뉴를 다시 선택하세요.&quot;);
                    continue;
                }

                // 계산 진행
                if (num == 1)
                    add();
                else if (num == 2)
                    substract();
                else if (num == 3)
                    multiply();
                else if (num == 4)
                    divide();
                else if (num == 5)
                    power();
            }

        }
        System.out.println(&quot;==========================&quot;);
    }
}</code></pre><ol start="2">
<li>메소드만 나누어질뿐 원리 역시 간단하다.
원의 넓이 구하는 공식과 원의 둘레 구하는 공식이 담긴 메소드만 만들어서
메인에서 호출해주면 끝이다. </li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/718fa9c5-606f-410b-809f-c91a67ac132b/image.PNG" width = "80%" height = "80%">

<ol start="3">
<li>굳이 메소드를 만들지 않아도 연산이 가능하지만
메소드 공부하는 포스팅이므로 연산하는 매개변수 int로 받고 
반환값이 int인 kalo라는 메소드를 만들었다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/cd6c595f-c514-4eeb-840c-603dea491783/image.PNG" width = "80%" height = "80%">

<ol start="4">
<li>키와 몸무게 두개의 값을 받기 위해 매개변수가 2개인 메소드를 생성하여 
여기서 연산을 하고 출력을 하게 했다. 간단간단 <del>~
비만: 30이상, 과체중: 25이상</del>30미만, 정상:18.5이상 ~25미만, 저체중: 18.5미만</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/bc4c57b6-ba5d-4a44-a140-416e6402d0fe/image.PNG" width = "80%" height = "80%">

<ol start="5">
<li>위 내용들과 원리가 같다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/2f02702e-b001-40b7-98cc-df275b660f63/image.PNG" width = "80%" height = "80%">

<blockquote>
<ul>
<li>반복문은 자바(JAVA)의 꽃이라고 했다.
다음 시간에는 자바(JAVA) 그 자체라고도 볼 수 있는 클래스에 대해 배운다.
어~엄청나게 중요한 것이니까 기대 :)</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.06] 조건문(conditional)과 반복문(iteration) 그리고 프로그래밍 방법 ⭐]]></title>
            <link>https://velog.io/@kama_code/JAVA.06-%EC%A1%B0%EA%B1%B4%EB%AC%B8conditional%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8iteration-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@kama_code/JAVA.06-%EC%A1%B0%EA%B1%B4%EB%AC%B8conditional%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8iteration-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sun, 18 Jun 2023 17:44:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>이번 6강은 바로 프로그래밍의 꽃⭐⭐⭐
다 중요하지만 그 중요함 중에서도 더 중요한 제어문이다.</li>
</ul>
</blockquote>
<h3 id="step1-if-문-조건">&lt;Step.1&gt; if 문 &lt;조건&gt;</h3>
<blockquote>
<ul>
<li>참(true)라면 실행문장을 실행하고 거짓(false)라면 실행하지 않는다.</li>
</ul>
</blockquote>
<ul>
<li>if문에서는 비교연산자와 논리연산자를 통한 조건식을 사용한다.</li>
<li>산술연산자를 통한 산술식은 사용할 수 없다. 
ㄴ⭐결과값이 boolean형으로 true 혹은 false를 반환해야 한다. </li>
<li>실행문장이 1개일 경우 {} 괄호를 생략할 수 있다.</li>
<li>조건에 if(true)를 하면 무조건 실행하는 조건문도 만들 수 있다.</li>
<li>※ 주의: if(조건)에는 조건이 시작되는 부분이기에 
ㄴ;(세미콜론)을 붙이지 않는다. 
ㄴ조건문 다음 실행문장 마지막에 ;(세미콜론)이 들어간다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/47365742-a93a-4f7e-8d24-538f7de27b49/image.PNG" width = "70%" height = "70%">  

<h3 id="step2-if--else-문-조건">&lt;Step.2&gt; if ~ else 문 &lt;조건&gt;</h3>
<blockquote>
<ul>
<li>참(true)라면 실행문장1을 실행하고 거짓(false)라면 실행문장2를 실행한다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/5a72c333-7b64-4865-94fe-e6380b4a69e5/image.PNG" width = "70%" height = "70%"> 

<h3 id="step3-if--else-중첩문-조건">&lt;Step.3&gt; if ~ else 중첩문 &lt;조건&gt;</h3>
<blockquote>
<ul>
<li>두가지 이상의 조건을 기술해야 할때 사용한다. 
조건을 끝내는 마지막은 else로 기술하며 
else는 마지막이기에 조건문을 기술할 수 없다. </li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/09507bb4-d0cf-490f-ad5e-5db10eb3801f/image.PNG" width = "70%" height = "70%"> 

<h3 id="step4-조건-연산자삼항-연산자-조건">&lt;Step.4&gt; 조건 연산자(삼항 연산자) &lt;조건&gt;</h3>
<blockquote>
<p>if ~ else 문을 대체하는 용도로 사용된다. 
조건문, true 혹은 false 일때 실행할 문장까지 항이 3개로 구성되어 있다. </p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/7be03265-845e-46c7-9ec4-1565714b20b7/image.PNG" width = "70%" height = "70%"> 

<h3 id="step5-switch-문-조건">&lt;Step.5&gt; switch 문 &lt;조건&gt;</h3>
<blockquote>
<ul>
<li>if문과 같은 조건식이지만 다른 점은 산술식만 사용할 수 있다. </li>
</ul>
</blockquote>
<ul>
<li>논리연산자를 이용한 조건식은 사용할 수 없다.</li>
<li>case 와 default는 실행위치를 표시하는 라벨(Label)로 사용된다.</li>
</ul>
<p>TIP: 자동완성 &gt; 컨트롤+스페이스바</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/e709afe7-8f00-4b97-8654-2a8c664eeda5/image.PNG" width = "50%" height = "50%"> 

<blockquote>
<ul>
<li>case값에 break;가 있다면 그 부분만 실행된다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/974457ab-aa44-4982-bf09-82e2a2088172/image.PNG" width = "60%" height = "60%"> 

<blockquote>
<ul>
<li>case값에 break;가 없다면 차례대로 모두 실행된다.</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/aa630545-6126-4cd6-9a8e-fe8656e2f1ea/image.PNG" width = "70%" height = "70%"> 

<h3 id="step6-while-문-무한반복">&lt;Step.6&gt; while 문 &lt;무한반복&gt;</h3>
<blockquote>
<ul>
<li>조건을 체크한 후 true인 경우에만 실행문이 실행된다. </li>
</ul>
</blockquote>
<ul>
<li>조건이 false라면 한번도 실행되지 않을수도 있다.</li>
<li>반복의 횟수가 명확하지 않은 경우 주로 사용된다. (ex : 중복되지 않는 난수 생성)</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/179345ed-bd08-4fdb-8cac-bd1ae6f1c8fa/image.PNG" width = "70%" height = "70%"> 

<h3 id="step7-do-while-문-무한반복">&lt;Step.7&gt; Do-while 문 &lt;무한반복&gt;</h3>
<blockquote>
<ul>
<li>조건에 상관없이 무조건 한번은 실행(Do)된 후 조건을 검사한다.</li>
</ul>
</blockquote>
<ul>
<li>그 외에는 while문과 동일하다. </li>
<li>조건이 없이 Do(실행문장)을 반복해서 실행하고 [false]여야 빠져나갈 수 있다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/f23340a4-7c68-4d5b-9731-7ff2df97296b/image.PNG" width = "70%" height = "70%"> 

<h3 id="step8-for-문-한정반복">&lt;Step.8&gt; for 문 &lt;한정반복&gt;</h3>
<blockquote>
<ul>
<li>반복문 중 가장 많이 사용하는 구문이다.</li>
</ul>
</blockquote>
<ul>
<li>초기값, 조건식, 증감식을 한줄에 작성하므로 반복의 횟수를 명시적으로 알 수 있다. </li>
<li>반복의 횟수가 명확할때 주로 사용한다. (ex : 구구단, 수열 등)</li>
<li>for문의 변수 i는 빠져나갈때 완전히 없어지므로(지역변수에 해당)
ㄴ다음에 또 사용이 가능하다. </li>
<li>★TIP : 지역변수 = 일부 코드에서만 작동 / 전체변수 = 전체 코드에서 작동</li>
<li>이중 for문으로 사용할시 (0,0) 행렬을 생각하여 행이 기준이 되며,
ㄴ그 다음에 오는 for문은 열이 된다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/7ce3f31e-e1d0-48af-9611-427053972ca2/image.PNG" width = "80%" height = "80%"> 

<h3 id="step9-break--continue">&lt;Step.9&gt; break / continue</h3>
<blockquote>
<ul>
<li>break
ㄴ반복문을 탈출한다. 
ㄴ단, 중첩된 반복문이라면 가장 가까운 반복문 하나만 탈출한다. </li>
</ul>
</blockquote>
<ul>
<li>continue
ㄴ반복문의 처음으로 이동하여 조건을 다시 실행한다. 
ㄴcontinue 하위의 문장의 실행하지 않고 반복하기 위한 용도로 사용된다.</li>
<li>★★★ 반복문 내에서 break / continue 를 사용할때는 
ㄴ반드시 조건문과 함께 기술해야 한다. </li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/5035b6fc-9211-4881-8692-9656fed897cc/image.PNG" width = "80%" height = "80%"> 

<h3 id="step10-라벨을-이용한-중첩된-반복문의-일괄-중지">&lt;Step.10&gt; 라벨을 이용한 중첩된 반복문의 일괄 중지</h3>
<blockquote>
<ul>
<li>중첩된 반복문 가장 안쪽에서 특정 조건을 충족하면
모든 반복문까지 중지하고 그다음 코드를 실행하고 싶을 경우 사용한다</li>
</ul>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/d202271c-504b-4b4d-904d-3b10f210ab22/image.PNG" width = "50%" height = "50%"> 

<h3 id="step11-프로그래밍-방법★★★">&lt;Step.11&gt; 프로그래밍 방법★★★</h3>
<blockquote>
<ol>
<li>시작이 반이다 라고 한다. 프로그래밍 역시 설계가 매우 중요하다.</li>
<li>프로그램을 만들려면 가장 먼저 프로그램의 근본 및 원리(특징)이(가) 
무엇인지 설계를 하라!
그 다음 담을 수 있는 그릇(객체 생성)을 만들어 준 이후 
&quot;입력(기억 및 저장)&quot;과 &quot;출력(결과)&quot;을(를) 생각하라.</li>
<li>예를 들어, 구구단 프로그램 중 2단을 만든다면 2를 입력값으로 주었을 때 
어떻게 출력되어야 할지 생각해 보아야 한다. 그래도 그림이 그려지지 않는다면
다음과 같이 해보아라!</li>
<li>메서드 이름은? twodan으로 짓자!
입력받는 값은? 2
출력하는 값은? 2단(2, 4, 6, 8, …, 18)
결과는 어떤 형태로 저장하지? 연속된 자료형이니까 배열! 이 좋겠다</li>
</ol>
</blockquote>
<h3 id="step12-발전을-위한-문제풀이-kama_code-출제">&lt;Step.12&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
</blockquote>
<ol>
<li>입력을 받아서 월요일~일요일까지 주말과 주중을 판단하는 프로그램을 만드시오</li>
<li>정수를 입력받아서 팩토리얼(!)을 계산하는 프로그램을 만드시오</li>
<li>정수를 입력받아 1부터의 합을 출력하는 프로그램을 만드시오</li>
<li>정수를 계속 입력받아서 0을 입력하면 그 동안의 입력한 숫자를 
모두 더하는 프로그램을 만드시오</li>
<li>입력한 숫자의 구구단을 출력하는 프로그램을 만드시오</li>
<li>문자 하나를 입력받아 숫자인지 숫자가 아닌지 판단하는 프로그램을 만드시오</li>
<li>로또번호를 생성하는 프로그램을 만드시오 ( 정렬 포함 )</li>
<li>&#39;1+1=&#39; 이라는 문제를 내고 2라고 맞출때까지 반복하는 프로그램을 만드시오</li>
<li>두 정수를 입력받아 큰 수에서 작은 수로 뺄셈을 출력하는 프로그램을 만드시오 </li>
<li><ul>
<li>모양을 찍어 다이아몬드 모양을 출력하는 프로그램을 만드시오 </li>
</ul>
</li>
</ol>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li>월 화 수 목 금 토 일을 하나만 입력하면 아래 사진처럼 주중인지 주말인지 알려준다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/dfc7b021-9a76-4f51-91cc-c498c5509530/image.PNG" width = "80%" height = "80%"> 

<ol start="2">
<li>팩토리얼의 특성은 자기 자신을 1씩 빼면서 반복하여 곱해가는 특성이 있다.
EX) 5! = 5x4x3x2x1
ㄴwhile을 반복조건에서 false면 빠져나가므로 [이거면 안되는 조건]을 넣어준다.
ㄴ그러므로, 1씩 빼가되 0이 아닐 때까지 진행하는 것이다.
ㄴlong으로 선언해주는 이유는 20!(팩토리얼)일 때 int 범위를 넘어가서 
ㄴ마이너스(-)가 출력된다. 범위를 넓게 받기 위해서 long을 선언해준다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/9166f2f1-3eb1-4a20-b57c-542a0cfa5fa1/image.PNG" width = "80%" height = "80%"> 

<ol start="3">
<li>해당 프로그램을 만들기 위해서 어떤 재료들이 필요한지 아는 것이 중요하다.
연산을 하려면 최소 2개의 그릇이 필요하여 누적할 sum와 
1씩 더하면서 sum에 집어넣을 su라는 변수를 만든다.
그리고 on라는 입력값보다 커지기전까지 반복하는 것이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/f6f1c83b-409b-4d4f-b0d0-b28db0b7b719/image.PNG" width = "70%" height = "70%"> 

<ol start="4">
<li>중요한 핵심은 필요한 그릇을 잘 만들어 주는 것이다.
입력값, 세는값, 누적값을 만들어주어 실시간으로 계속 계산하고
0을 입력했을때 총 값을 출력할 수 있도록 한다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/a8020222-f5c9-4482-86b5-895a71344a05/image.PNG" width = "70%" height = "70%"> 

<ol start="5">
<li>이중 for문이라면 첫 for문은 행(가로를 뜻하며) 두번째 for문은 열(세로를 뜻함)
이것을 알아야 한다. 2차원이기 때문이다.
아래 사진은 7을 입력했기에 7을 연속으로 열을 출력하는 원리이다.
ㄴ (7,1) (7,2) (7,3) (7,4) ...</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/0042b57d-51b4-4782-87ab-217e8336b271/image.PNG" width = "70%" height = "70%"> 

<ol start="6">
<li>간단한 원리이다. c가 0~9 사이의 문자면 &quot;숫자&quot; 입니다. 
아니라면 &quot;숫자가 아닙니다&quot; 가 출력되는 프로그램이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/6fea97dc-74c2-4e7b-80f6-b1c93f8cd064/image.PNG" width = "70%" height = "70%"> 

<ol start="7">
<li>실제 공정한 로또 프로그램 하나를 만들었다.
대신 인덱스 0부터 시작하니까 5번째까지 첫 for을 돌린다.
중복제거는 첫행의 숫자를 열이 탐색하여 똑같다면 그 숫자를 빼는 식으로 구현을 한 것이다.
그리고 정렬은 <a href="https://www.youtube.com/watch?v=dyEEXdLTl9M">선택정렬</a>을 사용했다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/7ea0f511-9b42-420f-9df3-6e1aabf6284b/image.PNG" width = "80%" height = "80%"> 

<img src = "https://velog.velcdn.com/images/kama_code/post/f8a25189-9937-453e-b7f0-510f0cd7c3f9/image.PNG" width = "80%" height = "80%"> 

<ol start="8">
<li>가장 먼저 그릇을 만들어주어야 하는 것을 잊지 말아야 한다.
입력값을 받아서 해당 답이 아닐 경우 다시 돌아가서 반복되는 프로그램이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/1ea962f6-86fe-4e45-9763-eb078d9cd32d/image.PNG" width = "80%" height = "80%"> 

<ol start="9">
<li>조건문을 통해 큰 수가 무엇인지 먼저 가려내어 출력문에서 출력 형식을 만드는 것이
핵심이다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/5fd24751-49d4-4c72-960d-ec92e9bca7d3/image.PNG" width = "80%" height = "80%"> 

<ol start="10">
<li>심화 문제이다.
원리는 공백을 먼저 찍고, 그 나머지는 별로 한방에 채운다.(총 4파트로 나눔)
왜 이렇게 되는지 원리를 모르겠다면 종이(A4)용지에 공백이 되어야 하는 곳은
(몇,몇)이며 별로 채워져야 하는 부분은 (몇,몇)인지 모두 적는다.
그리고 첫 for문은 행, 두번째 for문은 열이라는 것을 기억하여 규칙성을 찾아 만들면
된다. 아무리 어려운 것도 모두 기초에서 꼬는 것이기 때문에
이렇게만 한다면 어떠한 무늬도 만들 수가 있다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/f9d861fb-f71c-4bd5-b892-0c8d5a80a48c/image.PNG" width = "80%" height = "80%"> 

<p>제어문 반복문은 노가다를 줄여주고 프로그램을 프로그램답게 만들어주기에
굉장히 중요한 파트이다. 프로그래밍의 꽃이라고도 볼 수 있다.
반드시 내 것이 되게 만들고 넘어가야 한다. 그리고 
앞으로도 계속 꿀 떨어지는 포스팅을 많이 기대해주길 바란다.
^^</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.05] 연산자의 모든 것(Operator) 그리고 디버그(debug) 모드🙄]]></title>
            <link>https://velog.io/@kama_code/JAVA.05-%EC%97%B0%EC%82%B0%EC%9E%90%EC%9D%98-%EB%AA%A8%EB%93%A0-%EA%B2%83Operator</link>
            <guid>https://velog.io/@kama_code/JAVA.05-%EC%97%B0%EC%82%B0%EC%9E%90%EC%9D%98-%EB%AA%A8%EB%93%A0-%EA%B2%83Operator</guid>
            <pubDate>Sat, 17 Jun 2023 19:43:25 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>드디어 5강 : 자바 안에서의 연산을 배우게 된다. </li>
</ul>
</blockquote>
<h3 id="step1-연산자란">&lt;Step.1&gt; 연산자란?</h3>
<p>주어진 식을 계산하여 결과를 얻어내는 과정을 연산이라고 하며, 
연산을 수행하는 기호를 연산자라고 한다.</p>
<blockquote>
<ol>
<li>산술 연산자 😎 : 
※ 나눗셈은 몫 구하는 식과 나머지 구하는 식이 따로 존재한다</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/886191a9-1fcf-4269-804c-ef63064c0390/image.PNG" width = "70%" height = "70%">  

<blockquote>
<p>▼▽ 산술 변환 ( 형변환 일치 )🤗 :</p>
</blockquote>
<ol>
<li><p>형변환이 다른 것을 연산했을 때 더 큰 타입으로 자동형변환한다.
▼▽ 연산을 하면 결과는 <strong>큰 놈 기준</strong>으로 항상 따라간다고 기억하자! ▼▽
예시: 
long + int -&gt; long 
long + long -&gt; long
float + int -&gt; float
floar + float -&gt; float</p>
</li>
<li><p>int보다 작은 타입으로 연산하면 결과값은 int로 변환한다.</p>
</li>
</ol>
<p><strong>※ 정수형 계산기는 int만 있으므로</strong>
byte + short -&gt; int</p>
<blockquote>
<ol start="2">
<li>⭐복합 대입 연산자 😎 : 
※ 좌측 변수에 결과값을 누적해야 할 때 주로 사용 (주로 반복문에서 많이 쓰임)
※ 좌측항과 우측항을 연산한 결과값을 좌측에 대입한다. 
※ 기존 변수의 자료형을 그대로 유지하는 특성 -&gt; 연산의 결과는 정수
ㄴ그래서 복합 대입 연산자를 사용하면 형변환을 안해도 되는 최고의 장점이 있다.</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/6d015175-e82c-4a4d-8ce0-2645e9f2062b/image.PNG" width = "50%" height = "50%">

<blockquote>
<ol start="3">
<li>⭐증감 연산자 😎 : 
※ ++x : 전위 증가 -&gt; +1을 하고 연산을 한다.
※ x++ : 후위 증가 -&gt; 연산을 하고 +1을 한다
※ --x : 전위 감소 -&gt; -1을 하고 연산을 한다.
※ x-- : 후위 감소 -&gt; 연산을 하고 +-을 한다</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/a0158889-e641-4685-95e0-33e218db9c64/image.PNG" width = "50%" height = "50%">

<img src = "https://velog.velcdn.com/images/kama_code/post/7481a6c8-d0e5-4775-888b-a7f6988d1a17/image.PNG" width = "50%" height = "50%">

<blockquote>
<ol start="4">
<li>⭐비교 연산자 😎 : 
※ 결과값 true, false를 반환
※ == &lt;깉은지 비교&gt; / != &lt;다른지 비교&gt;</li>
</ol>
</blockquote>
<pre><code>// ★ 만약 x,y를 아래와 같이 선언 후 초기화를 한다면?
int x = 2;
int y = 1;</code></pre><img src = "https://velog.velcdn.com/images/kama_code/post/a3f27ca8-fe27-49e4-9a48-e6b4e27765f0/image.PNG" width = "70%" height = "70%">

<p>▶ 응용식</p>
<ul>
<li><p>20 이상 30이하에 있는지 판단
: x &gt;= 20 &amp;&amp; x &lt;= 30 </p>
</li>
<li><p>20 초과 30미만에 있는지 판단
: x &gt; 20 &amp;&amp; x &lt; 30 </p>
</li>
</ul>
<blockquote>
<ol start="5">
<li>⭐논리 연산자 😎 : 
※ &amp;&amp; (논리and) : 앰퍼샌드(ampersand)라고 하며, 모두 참이여야 참을 반환한다
ㄴ하나라도 거짓이면 거짓! (교집합과 같다)
※ || (논리or) : 파이프(pipe)라고 하며, 하나만 참이면 참을 반환한다
ㄴ모두 거짓이여야 거짓! (합집합과 같다)
※ ! (논리not) : 아니다(not)이라고 하며, 반대의 논리를 반환하는 연산자.
ㄴ참이면 거짓을 반환, 거짓이면 참을 반환한다.</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/82c910d2-4f16-412f-aa8e-e4cf23a59bb8/image.PNG" width = "70%" height = "70%">

<p>▶ 응용식</p>
<ul>
<li><p>2의 배수 또는 3의 배수를 판단(y)
: y % 2 == 0 || y % 3 == 0
ㄴy를 2 또는 3으로 나누었을 때 1개라도 나머지가 0이면 됨</p>
</li>
<li><p>2의 배수와 3의 배수를 판단(z) = 2와 3의 공배수 = 6의 배수
: y % 2 == 0 &amp;&amp; y % 3 == 0
ㄴy를 2 그리고 3으로 나누었을 때 모두 나머지가 0이어야 함
ㄴ6의 배수를 구하는 식</p>
</li>
<li><p>f가 알파벳인지 아닌지 판단
: (&#39;a&#39;&lt;=f &amp;&amp; f&lt;=&#39;z&#39;) || (&#39;A&#39;&lt;=f &amp;&amp; f&lt;=&#39;Z&#39;)
ㄴf가 소문자 범위를 비교하고 대문자 범위를 비교해서 하나라도 일치하면 알파벳</p>
</li>
</ul>
<blockquote>
<ol start="6">
<li>⭐조건 연산자(삼항 연산자) 😎 : 웹 또는 앱에서 많이 사용한다
※ 형식: 조건식 ? 값1 : 값2
: 조건식이 참(true)일 경우 값1가 출력된다.
: 조건식이 거짓(false)일 경우 값2가 출력된다.</li>
</ol>
</blockquote>
<blockquote>
<ol start="7">
<li>⭐ SCE(Short-Circuit Evaluation) : 단락회로평가</li>
</ol>
</blockquote>
<ul>
<li>논리And의 경우 앞의 조건이 false 이면 뒤의 식은 실행조차 하지 않고
무조건 fasle를 반환한다. </li>
</ul>
<pre><code>int num1 = 0, num2 = 0;
boolean result;

result = (num1 += 10 ) &lt; 0 &amp;&amp; (num2 += 10) &gt; 0;

&amp;&amp; = 둘 다 일치해야 참이다. 하지만 num1부터 false이기에 num2는 보지도 않고
false를 반환한다.</code></pre><blockquote>
<ul>
<li>논리Or의 경우 앞의 조건이 true 이면 뒤의 식은 실행조차 하지 않고
무조건 true를 반환한다. 
결과는 뒷 부분의 코드는 실행되지 않는다. (쓰레기 코드가 된다.)
※ 그러므로 쓰레기 코드가 발생하지 않도록 잘 짜야 한다.</li>
</ul>
</blockquote>
<pre><code>int num1 = 0, num2 = 0;
boolean result;
result = (num1 += 10) &gt; 0 || (num2 += 10) &gt; 0;

|| = 둘 중 하나만 일치하면 참을 반환한다. 하지만 num1부터 true이기에
num2는 보지도 않고 true를 반환한다.</code></pre><blockquote>
<ol start="8">
<li>⭐ 연산자 우선순위😎</li>
</ol>
</blockquote>
<ul>
<li>과거 인터넷을 뜨겁게 달군 식이 있다.
48÷2(9+3) = 무엇일까? </li>
<li>어떤 사람은 288 어떤 사람은 2 라고 대답을 한다.
과연 무엇이 정답일까? </li>
<li>이는 대수학을 공부하는 사람에게는 2가 정답이라고 하지만 
일반적인 경우는 288이 정답이다. 
그리고 프로그래밍에서 역시 288을 정답이라고 한다.</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/1078f2e6-6f46-4970-aa1b-4ad8121418d2/image.PNG" width = "60%" height = "60%">

<p>이 갈등은 2(9+3) 이것을 먼저 푸느냐? 48÷2 이것을 먼저 푸느냐에 달려있다.
일반적인 계산에서는 48÷2를 먼저 푸는 것을 정답으로 보고 있다.
이와 같이 연산자에도 우선순위가 있다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/c14cddd2-b46d-4fbc-9e03-78d57e5aba73/image.PNG" width = "60%" height = "60%">

<blockquote>
<ol start="9">
<li>⭐ 심화: 비트 연산자 😎</li>
</ol>
</blockquote>
<ul>
<li>비트 단위(2진수)로 연산을 한다.</li>
<li>&lt;비트 연산자를 사용하는 이유&gt; : 일반적으로 숫자를 곱하거나 나누게 되는 것보다 
10진수보다 컴퓨터랑 친한 비트 연산이기 때문에 속도가 더 빠르다.</li>
</ul>
<p>X = 00001101 (13)
Y = 00000101 (5) </p>
<ul>
<li>|(OR연산자) : 하나라도 값이 1이면 1의 결과, 그 외는 0을 얻는다
답: (2진수) 00001101 (13)이 된다.</li>
<li>&amp;(AND연산자) : 모두 1일 경우면 1로 표현된다.
답: (2진수) 00000101 (5)가 된다.</li>
<li>^(XOR연산자) : 하나가 1, 다른 하나가 0일 경우 결과가 1로 표현된다
답: (2진수) 00001000 (8)이 된다.</li>
<li>~(비트 전환연산자) 0은 1로, 1은 0으로 바꾼다.&lt;논리 부정 연산자 &#39;!&#39;과 비슷하다&gt;
문제 : (2진수) 00001010 (10)
답 : (2진수) 11110101 (245)가 된다.</li>
</ul>
<blockquote>
<p>★ 참고 자료01 : 진수에 대한 용어 정리
Hex : 16진수 ( hexadecimal )
Dec : 10진수 ( decimal )
Oct : 8진수 ( octal )
Bin : 2진수 ( binary ) </p>
</blockquote>
<blockquote>
<p>★ 참고 자료02: 10진수를 2진수로 바꾸는 방법</p>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/8335f443-cb99-47eb-83fb-cfd5220aeebd/image.PNG" width = "50%" height = "50%">

<p>(10진수) 11 = (2진수) 1011이다.</p>
<blockquote>
<p>★ 참고 자료03 : 2진수를 10진수로 바꾸는 방법</p>
</blockquote>
<p>(2진수) 01011000을 10진수로 바꾸면?
자리마다 2^X 제곱을 나열하고 1이 있는 것만 더해주면 된다.
64+16+8 = 88 (10진수)</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/14c35a0e-fcb6-4a13-8b16-f6c1db182cb3/image.PNG" width = "70%" height = "70%">

<blockquote>
<p>★ 참고 자료04 : JAVA에서는 10진수를 2진수로 바꾸는 함수가 존재한다.</p>
</blockquote>
<pre><code>        int x = 10;
        System.out.println(Integer.toBinaryString(x));
        //결과 10을 2진수로 변환한 값이 출력된다.</code></pre><blockquote>
<ol start="10">
<li>⭐ 심화: 쉬프트 연산자 😎</li>
</ol>
</blockquote>
<img src = "https://velog.velcdn.com/images/kama_code/post/625e9ba5-1322-4bb0-9521-05219fbcf640/image.PNG" width = "70%" height = "70%">

<blockquote>
<p>x = 0000001101 (13)
x &gt;&gt; 1 = 0000000110 (6)
x &gt;&gt; 2 = 0000000011 (3)</p>
</blockquote>
<blockquote>
<p>y = 0000000101 (5)
y &lt;&lt; 1 = 0000001010 (10)
y &lt;&lt; 2 = 0000010100 (20)</p>
</blockquote>
<p>왼쪽 쉬프트(&lt;&lt;n)은 2^n을 곱한 결과와 같다.
오른쪽 쉬프트(&gt;&gt;n)은 2^n으로 나눈 결과와 같다.</p>
<h3 id="step2-디버그debug-하는-법">&lt;Step.2&gt; 디버그(debug) 하는 법</h3>
<blockquote>
<ul>
<li>자바(JAVA)에서 디버그는 오타를 찾는 코드를 검사하거나 코드 분석기를 사용한다.
정말 중요하며 로그를 분석하는 것과 비슷하다.
정말 많이 사용합니다.</li>
</ul>
</blockquote>
<ol>
<li>메인 왼쪽 줄을 숫자로 표시한 곳에 마우스 우클릭 
ㄴToggle Breakpoint를 찍는다.</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/2f926c42-0a0f-4c60-8493-d4d182a618f4/image.PNG" width = "70%" height = "70%">

<ol start="2">
<li><p>F11을 누르고 Swich를 클릭하면 디버그 모드로 전환된다.</p>
</li>
<li><p>위쪽에 step into와 step over 버튼이 있다.</p>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/ffd1abad-e876-49cd-87f5-60e74d4f339a/image.PNG" width = "40%" height = "40%">

<blockquote>
<ul>
<li>step over(F6) : 한줄을 실행합니다. 함수가 있다면 건너 띄어버립니다.</li>
</ul>
</blockquote>
<ul>
<li>step into(F5) : 함수 내부로 들어갑니다. 
&lt;다음이 메소드 진입 부분이라면 이 버튼을 눌러야 함&gt;</li>
</ul>
<h3 id="step3-발전을-위한-문제풀이-kama_code-출제">&lt;Step.3&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ol>
<li>정수 2개를 입력받아 사칙연산을 출력하는 프로그램을 만드시오.</li>
<li>국어(kor): 75점 영어(eng): 53점 수학(mat): 81점 사회(sco): 38점
과학(sci): 62점 → 5가지의 과목의 합계 평균을 출력하시오.</li>
<li>현이의 주민등록번호(891009-1577829)이다. 주민등록번호의 앞자리와
뒷자리를 잘라서 따로 출력하는 프로그램을 만드시오.
→ substring(index시작 , index끝);</li>
<li>사용자로부터 시급이 얼마? 하루 근무시간? 한달 근무일수? 인센티브(보너스)?를 
입력받아 세금과 지급액을 출력하는 프로그램을 만드시오.
※ 지급액은 월급에서 세금 3.3%를 빼고 출력한다. 
(월급 x 0.967) &lt; 100에서 0.033을 뺀 값</li>
<li>사용자로부터 입력값을 받아서 사다리꼴의 면적을 구하는 프로그램을 만드시오
<Hint> 사다리꼴 면적: (윗변 + 아랫변) * 높이 / 2</li>
<li>철수와 영희와 민수는 함께 외식을 하고 똑같이 더치페이를 하기로 했다
삼겹살 3인분 된장찌개 2인분 사이다 5개 물냉면 2그릇 돼지껍데기 5인분을 먹었다.
1인당 내야 할 금액을 출력하는 프로그램을 만드시오.</li>
</ol>
</blockquote>
<ul>
<li>삼겹살(1인분) 18750원 / 된장찌개(1인분) 7500원 / 사이다(1개) 1280원
물냉면(1그릇) 9300원 / 돼지껍데기(1인분) 10780원</li>
</ul>
<ol start="7">
<li>x의 반환형이 정수(int)로 선언과 동시에 값을 1234567로 초기화하고 
삼항연산자를 이용해서 x가 3의 배수이면서 7의 배수라면 &#39;야호&#39; 아니면 
&#39;아니여따&#39; 를 출력하는 프로그램을 만드시오.</li>
<li>num01~04는 반환값이 int면서 7로 초기화한다. 
num2는 전위증가, num3은 전위감소
num4는 후위증가, num5은 후위감소를 출력하는 프로그램을 만드시요.</li>
<li>사용자로부터 문자 하나를 입력하는 값을 받고 삼항연산자를 이용해서 
첫번째 문자가 알파벳인지 아닌지 판단하는 프로그램을 만드시오
알파벳이라면 알파벳이다. 아니면 알파벳이 아니다라고 출력되어야 한다.</li>
<li>시프트 연산자를 사용해서 22를 
2배, 0.5배, 4배, n/2의2승배, 8배, n/2의3승배한 값을 출력하시오</li>
</ol>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li><p>정수 2개를 입력하면 아래처럼 사칙연산을 한다.
※ 나눗셈은 /는 몫만 구하며 %는 나머지만 구한다는 것을 주의하자 !</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/1e4eb4c3-1398-4ac6-bedc-de21314107fe/image.PNG" width = "70%" height = "70%">
</li>
<li><p>문제에 국영수사과: 과목에 대한 변수를 정해주었다. 
아래 사진처럼 ,(쉼표)를 통해 한꺼번에 선언과 초기화도 해줄 수 있다.</p>
 <img src = "https://velog.velcdn.com/images/kama_code/post/7a0fadd5-78cf-442f-b3fa-59b192a6e82a/image.PNG" width = "70%" height = "70%">
</li>
<li><p>문자열(String)을 인덱스(index)에 맞춰 자르는 subString()
 주민 앞자리는 첫번째부터 7번째 전까지 끊어준다.
 주민 뒷자리는 8번째부터 끝까지 끊어준다.</p>
</li>
</ol>
<pre><code>  &lt;img src = &quot;https://velog.velcdn.com/images/kama_code/post/815d9904-6496-4300-97dd-18e1423488bd/image.PNG&quot; width = &quot;70%&quot; height = &quot;70%&quot;&gt;</code></pre><ol start="4">
<li><p>세금은 0.033 으로 소수가 들어가므로 int 정수형으로 표현할 수 없다.
그래서 강제형변환이 필요하다.
※ 바로 이 경우가 강제형변환이 필요할 때이며 
강제형변환할 때 데이터 손실이 발생하므로 개발자가 판단하여 
데이터 손실이 발생해도 상관없다! 한다면 강제형변환을 진행한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/254bfb6b-ed80-494b-80e4-caa64365dbcc/image.PNG" width = "60%" height = "60%">
</li>
<li> <img src = "https://velog.velcdn.com/images/kama_code/post/2d6d8afc-314b-4e6a-92ac-18045127294a/image.PNG" width = "60%" height = "60%">

<ol start="6">
<li><img src = "https://velog.velcdn.com/images/kama_code/post/6980a9e2-0596-4192-aad9-6de33fc966f0/image.PNG" width = "60%" height = "60%">
</li>
</ol>
</li>
<li><p>&lt;센스&gt; &#39;3&#39;으로 나누었을때 나머지가 0이면 3의 배수이다.
이는 21의 배수를 묻는 식이다. 1234567은 21로 나누어 떨어지지 않으므로
false로 &quot;아니여따&quot; 라는 뒤의 결과가 출력된다.</p>
 <img src = "https://velog.velcdn.com/images/kama_code/post/133b5b9e-7210-42a6-a4e9-8e4aad810446/image.PNG" width = "60%" height = "60%">

<ol start="8">
<li><p>정~말 중요한 증감 연산자이다. 
앞으로 배울 반복문에서 단골처럼 나온다.
앞에 연산이 붙으면 연산하고 대입해서 출력!
뒤에 연산이 붙으면 출력하고 그 다음 연산을 한다.
num4와 num5는 대입을 먼저 하기에 연산 전의 프린트가 출력되고
실제는 +1,-1이 된 상태이다. ( 보이진 않지만.. )</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/b1a30800-5478-4919-be92-52c253df6dbd/image.PNG" width = "60%" height = "60%">
</li>
<li><p>Scanner는 ※ 문자형(char)을 반환할 수 없다.
그래서 String(문자열)로 받고 그 다음에 
문자열을 문자(char) 형식으로 바꿔주는 것이다.
그리고 0번째 인덱스(첫번째) 문자를 담아서 저장하는 것이다.
아래와 같은 결과가 나온다.
그리고 print는 &#39;싱글쿼테이션과 &quot;더블쿼테이션을 출력할 수 없기에
(백슬래쉬)를 넣어서 실체화하여 출력한다.</p>
</li>
</ol>
<img src = "https://velog.velcdn.com/images/kama_code/post/e70c26d8-bdc6-418d-8cbd-0d0464ec693f/image.PNG" width = "80%" height = "80%">

<img src = "https://velog.velcdn.com/images/kama_code/post/3784da6e-5aef-43af-94e4-8cab002b94fe/image.PNG" width = "80%" height = "80%">
</li>
<li><p>비트연산자를 사용하는 이유는 속도가 더 빠르기 때문이다.</p>
<ul>
<li>&lt;&lt; 2의 배수로 숫자가 커진다는 것을 알 수 있으며</li>
<li><blockquote>
<blockquote>
<p>2의 배수로 숫자가 작아진다는 것을 알 수 있다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/bb55e06b-8992-426c-92f5-c762692706bf/image.PNG" width = "80%" height = "80%">
</blockquote>
</blockquote>
</li>
</ul>
</li>
</ol>
<p>직접 문제를 만들어오면서 정말 긴 포스팅이 되었다.
연산자까지 5분의 1까지 왔다.
앞으로도 꿀 떨어지는 포스팅을 많이 기대해주길 바란다.
<em>^^</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.04] 스캐너(Scanner)와 JAVA의 3요소 및 날짜 클래스🐇]]></title>
            <link>https://velog.io/@kama_code/JAVA.04-%EC%8A%A4%EC%BA%90%EB%84%88Scanner%EC%99%80-JAVA%EC%9D%98-3%EC%9A%94%EC%86%8C-%EB%B0%8F-%EB%82%A0%EC%A7%9C-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@kama_code/JAVA.04-%EC%8A%A4%EC%BA%90%EB%84%88Scanner%EC%99%80-JAVA%EC%9D%98-3%EC%9A%94%EC%86%8C-%EB%B0%8F-%EB%82%A0%EC%A7%9C-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Sat, 17 Jun 2023 16:38:12 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>이번 시간에 신기한 걸 하나 배운다.
바로 화면으로부터 사용자에게 입력값을 받는 기능 !</li>
</ul>
</blockquote>
<h3 id="step1-사용자로부터-화면에서-키보드로-입력-scanner">&lt;Step.1&gt; 사용자로부터 화면에서 키보드로 입력 Scanner</h3>
<ul>
<li>Scanner 객체생성 : 이름은 변수와 마찬가지로 만들어준다.
Scanner 객체명 = new Scanner(System.in);
▶ 객체를 생성했다면 Scanner 기능을 import해야 사용이 가능하다.<h3 id="☞ﾟヮﾟ☞---컨트롤쉬프트o---자동-불러오기-단축키">(☞ﾟヮﾟ)☞ :  &lt;컨트롤+쉬프트+O&gt; - 자동 불러오기 단축키</h3>
</li>
</ul>
<p>★ System.in
키보드에서 사용자로부터 키 입력을 받기 위해서는 System.in을 사용한다.
Scanner하면 따라오는 말이니까 통으로 눈에 익혀놓으면 좋다!</p>
<p>※ 입력을 받고 까먹어버리면 의미가 없으니 다음엔 기억이 자연스럽게 필수로 따라온다.</p>
<blockquote>
<ul>
<li>Scanner scan = new Scanner(System.in); 
이렇게 scan이라는 이름을 가진 입력값을 받는 기능을 만들어주었다.</li>
</ul>
</blockquote>
<p>★ 자주 쓰는 4가지</p>
<blockquote>
<ul>
<li>String str = scan.next(); :  입력받은 문자열 값(변수: scan)을 
문자열 타입(변수:str)으로 기억하여 반환한다.</li>
</ul>
</blockquote>
<ul>
<li>int num = scan.nextInt(); :  입력받은 정수 값(변수: scan)을 
정수형 타입(변수:num)으로 기억하여 반환한다.</li>
<li>double dnum = scan.nextDouble(); :  입력받은 실수 값(변수: scan)을 
실수형 타입(변수:dnum)으로 기억하여 반환한다.</li>
<li>String num2 = scan.nextLine(); :  입력받은 한 줄 전체 값(변수: scan)을 
문자열 타입(변수:dnum)으로 기억하여 반환한다. (&#39;\n&#39;포함 되어 있다.)</li>
</ul>
<p>☆ 자주 안쓰는 나머지</p>
<blockquote>
<ul>
<li>byte btr = scan.nextByte(); : 입력받은 byte 값(변수: scan)을 
byte 타입(변수:btr)으로 기억하여 반환한다.</li>
</ul>
</blockquote>
<ul>
<li>short shr = scan.nextShort(); : 입력받은 short 값(변수: scan)을 
short 타입(변수:shr)으로 기억하여 반환한다.</li>
<li>long lng = scan.nextLong(); : 입력받은 long 값(변수: scan)을 
long 타입(변수:lng)으로 기억하여 반환한다.</li>
<li>float flo = scan.nextFloat(); : 입력받은 float 값(변수: scan)을 
float 타입(변수:flo)으로 기억하여 반환한다.</li>
</ul>
<p>★ String input = scan.nextLine(); 
ㄴnextLine()은 한 줄 전체를 받기에 편리함으로 가장 많이 쓰이는 Scanner이다.</p>
<p>★ int num = Interger.parseInt(input); 
ㄴ만약 input에 저장된 값이 숫자라면 input에 저장된 숫자로 된 문자열을 정수로 변환한다.</p>
<h3 id="step2-java의-3요소">&lt;Step.2&gt; JAVA의 3요소</h3>
<blockquote>
<ol>
<li>packge 선언부 : 클래스를 종류별로 묶어서 관리하기 위한 선언으로
  디렉토리(폴더)의 의미로 이해하면 된다. 주로 관련있는 클래스끼리
  묶어서 관리하기 위한 용도로 사용된다.</li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>import 선언부 : 내가 만든 클래스에 필요한 자바클래스를 가져다가 
 사용하기 위한 선언으로 JDK에서 제공하는 클래스를 사용할 수 있다.
 (개발자들이 라이브러리에 이미 만들어놓은 기능을 불러와서 쓰는 것)</li>
</ol>
</blockquote>
<blockquote>
<ol start="3">
<li>class 선언부 : 자바프로그램은 클래스 단위로 구성되므로 기본적으로 
 필요한 부분으로 클래스는 항상 영문 대문자로 시작하고 파일의 확장자는
 .java로 지정하게 된다.
 또한 public으로 선언된 클래스와 파일명은 반드시 일치해야 한다.</li>
</ol>
</blockquote>
<h3 id="step3-날짜-클래스calendar-class">&lt;Step.3&gt; 날짜 클래스(Calendar class)</h3>
<blockquote>
<p>오늘의 날짜와 시간을 Date클래스를 통해 가져온다.</p>
</blockquote>
<ul>
<li>Date toDayofDate = new Date();
System.out.println(&quot;오늘 날짜:&quot; + toDayofDate);</li>
</ul>
<blockquote>
<p>SimpleDateFormat 클래스를 이용하여 우리가 주로 사용하는
  날짜포멧인 년-월-일 시:분:초 형태로 변환한 후 출력한다.</p>
</blockquote>
<ul>
<li>SimpleDateFormat wetime = new SimpleDateFormat(&quot;yyyy-MM-dd HH:mm:ss&quot;);
&lt; HH : 대문자 24시간 기준, hh : 소문자 12시간 기준 &gt;</li>
</ul>
<blockquote>
<ul>
<li>문자열 반환형 toDaywetime 변수에 
위에서 만들어준 변수 wetime의 날짜 포맷 형식을 넣는다.
String toDaywetime = wetime.format(toDayofDate);
System.out.println(&quot;변형된 날짜:&quot; + toDaywetime);</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>어제 날짜 구하기 (컨트롤+쉬프트+O) - 자동 임포트 필요
Calendar yes = Calendar.getInstance(); // 객체 생성: 달력 yes 
yes.add(Calendar.DATE, -1); // 오늘로부터 -1한 값을 yes에 저장
String wow = wetime.format(yes.getTime()); // wow String으로 저장
System.out.println(&quot;어제: &quot; + wow); // 출력하기</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>지난달 날짜 구하기 (컨트롤+쉬프트+O) - 자동 임포트 필요
Calendar monz = Calendar.getInstance(); // 객체 생성: 달력 monz
monz.add(Calendar.MONTH, -1); // 이번 달로부터 -1한 값을 monz에 저장
String wow1 = wetime.format(monz.getTime()); // wow1 String으로 저장
System.out.println(&quot;지난 달: &quot; + wow1); // 출력하기</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>1년전 날짜 구하기 (컨트롤+쉬프트+O) - 자동 임포트 필요
Calendar yea = Calendar.getInstance(); // 객체 생성: 달력 yea
yea.add(Calendar.YEAR, -1); // 이번 년도로부터 -1한 값을 yea에 저장
String wow2 = wetime.format(yea.getTime()); // wow2 String으로 저장
System.out.println(&quot;전년도: &quot; + wow2); // 출력하기</li>
</ul>
</blockquote>
<h3 id="-따로따로-정보를-출력할-수도-있다">※ 따로따로 정보를 출력할 수도 있다.</h3>
<pre><code>Calendar cal = Calendar.getInstance(); //cal이라는 달력 객체 생성
System.out.println(cal); //cal을 출력하면 

//### ▷ 엄청나게 긴 달력에 대한 정보가 출력된다.
//### java.util.GregorianCalendar[time=1687012935398..]

Calendar oday = Calendar.getInstance(); // 객체 생성: 달력 oday 
oday.add(Calendar.DATE, +1000); // 오늘로부터 -1000한 값
String chunil = okDate.format(oday.getTime()); // chunil String으로 저장

Calendar yday = Calendar.getInstance();
yday.add(Calendar.YEAR, -10); // 이번년도에서 -10 한 값
String sib = okDate.format(yday.getTime()); // sib String으로 저장

int year = cal.get(Calendar.YEAR); // 올해를 year 변수에 넣음
int month = cal.get(Calendar.MONTH) + 1; // 이번 달을 month 변수에 넣음
int date = cal.get(Calendar.DATE); // 오늘을 date 변수에 넣음
int dayweek = cal.get(Calendar.DAY_OF_WEEK); // 요일을 dayweek 변수에 넣음
int hour = cal.get(Calendar.HOUR); // 시간을 hour 변수에 넣음
int minute = cal.get(Calendar.MINUTE); // 분을 minute 변수에 넣음
int second = cal.get(Calendar.SECOND); // 초을 second 변수에 넣음
System.out.println(year+ &quot;+&quot; + month+ &quot;+&quot; 
+ date+ &quot;+&quot; + dayweek+ &quot;+&quot; + hour+ &quot;+&quot; + minute+ &quot;+&quot; + second);
// 전체를 +로 구분 지어서 출력함</code></pre><p>▶▷ 결과 출력😮</p>
<p><img src="https://velog.velcdn.com/images/kama_code/post/831fa943-73a4-4864-a920-1febd3c81d87/image.PNG" alt=""></p>
<p>※ 오류가 난다면?
▶ 대소문자 구분하니까 혹시나 소문자로 썼는지 아니면 뒤에 ;가 없는지 확인</p>
<h3 id="step4-발전을-위한-문제풀이-kama_code-출제">&lt;Step.4&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ul>
<li>nextline을 통해 사용자로부터 입력값을 받는다.
&lt;구정&gt;을 입력하면 &quot;구정은 음력 1월 1일입니다.&quot;가 나오게 하고 
&lt;천일&gt;을 입력하면 년-월-일-시-분-초 12시간 형식으로 오늘에서 +1000일 후가 나오게 하며
&lt;10년&gt;을 입력하면 년-월-일-시-분-초 12시간 형식으로 언제든 10년전 날짜가 나온다.
&lt;웃긴더하기&gt;를 입력하면 년,월,일,요일,시간,분,초를 모두 더한 값을 정수로 나오게 
출력하게 되는 프로그램 만들기</li>
</ul>
</blockquote>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<pre><code>Scanner sc = new Scanner(System.in); // 스캐너 객체 생성
String wow = sc.nextLine(); // 입력한 한 줄을 wow 참조값에 저장 
Date toDate = new Date(); // 날짜 객체 생성
SimpleDateFormat okDate = new SimpleDateFormat(&quot;yyyy년 MM월 dd일 hh시 mm분 ss초&quot;); 
//년도-월-일-시-분-초 형식으로 변환하여 okDate 저장

Calendar cal = Calendar.getInstance(); //cal이라는 달력 객체 생성
int year = cal.get(Calendar.YEAR); // 올해를 year 변수에 넣음
int month = cal.get(Calendar.MONTH) + 1; // 이번 달을 month 변수에 넣음
int date = cal.get(Calendar.DATE); // 오늘을 date 변수에 넣음
int dayweek = cal.get(Calendar.DAY_OF_WEEK); // 요일을 dayweek 변수에 넣음
int hour = cal.get(Calendar.HOUR); // 시간을 hour 변수에 넣음
int minute = cal.get(Calendar.MINUTE); // 분을 minute 변수에 넣음
int second = cal.get(Calendar.SECOND); // 초을 second 변수에 넣음

    if(wow.equals(&quot;구정&quot;))
        System.out.println(&quot;구정은 음력 1월 1일입니다.&quot;);
    if(wow.equals(&quot;천일&quot;))
        System.out.println(&quot;1000일 후: &quot; + chunil);
    if(wow.equals(&quot;10년&quot;))
        System.out.println(&quot;10년 전: &quot; + sib);    
    if(wow.equals(&quot;웃긴더하기&quot;))
        System.out.println(year+month+date+dayweek+hour+minute+second);
    }
}        
</code></pre><p>▶ &#39;구정&#39;을 입력하면?</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/f1fc9757-0953-4772-b564-1c9083560d83/image.PNG" width = "50%" height = "50%">

<p>▶ &#39;천일&#39;을 입력하면?</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/8aa614ed-cecb-4563-a88d-b5ff6e69035d/image.PNG" width = "70%" height = "70%">

<p>▶ &#39;10년&#39;을 입력하면?</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/ccba00a8-e0ed-4ddc-aefb-2b30188909d8/image.PNG" width = "60%" height = "60%">

<p>▶ &#39;웃긴더하기&#39;를 입력하면?</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/9c3bbe0f-b6f7-490e-8d85-6bc6d371a611/image.PNG" width = "30%" height = "30%">

<p>→ 변수로 저장을 했기에 그 때 그 때 값이 다른 값이 나온다.
정말 프로그래밍이라는게 매력적이지 않은가?</p>
<p>★ 여기서 배우지 않은 것이 있는데 바로 조건문(if)이다.
엄~청 중요하기에 미리 예습으로 말을 하자면..</p>
<blockquote>
<p>형식은 if(조건1) { 실행 } 이다.
if 안의 조건1의 내용을 만족(true)하면 실행하고 만족하지 않으면 실행되지 않는다.</p>
</blockquote>
<blockquote>
<p>여기서 의문이 드는 사람도 있을 것이다. 
단순명료하게 (wow == &quot;구정&quot;)만 하면 되지 
왜 equals이라는 생소한 단어를 추가해서 썼을까? </p>
</blockquote>
<ul>
<li>가설1] wow가 구정이라면 이 조건으로 프린트가 출력되지 않을까?</li>
</ul>
<img src = "https://velog.velcdn.com/images/kama_code/post/1f004657-d093-4913-9813-eda81290dec1/image.PNG" width = "50%" height = "50%">

<p>&#39;구정&#39; 입력시 아무것도 출력되지 않는다.
왜 그럴까? 답은 간단하다. 
★ 같을 수가 없어 false이기에 아무것도 출력되지 않은 것이다. </p>
<blockquote>
<p>wow라는 변수는 Scanner에서 입력한 값을 대입(넣는다)한다.
wow라는 변수 안에 값을 그저 넣을 뿐이지 
wow라는 변수 그 자체는 될 수 없는 것이다.</p>
</blockquote>
<blockquote>
<p>wow라는 액체를 담을 수 있는 통(공간)이 있다. 
이 통에 오렌지쥬스를 담으면 오렌지쥬스와 wow가 같아 지는가??
이렇게 생각해보면 쉽게 답이 나올 것이다.</p>
</blockquote>
<p>▶ 결론은 equals() 라는 메소드를 써서 
wow라는 물을 담을 수 있는 통(공간) 안에 있는 내용물을 비교하는 것이다.
equals() 메소드는 객체끼리의 내용물을 비교할 수 있게 하는 함수이다.</p>
<p>＃ 마무리
날짜는 엄청나게 유용한 정보이다.
날짜를 통해 몇 초 몇 분에만 열리는 프로그램을 만들 수도 있고 
프로그램에 &#39;타이밍&#39;이라는 엄청난 기능를 추가할 수도 있는 것이다.  </p>
<p>달력을 만드는 건 쉬운 것이 아니다.
이 외에 우리가 아직 배우지 않은 반복문, 조건문을 통해 
윤달, 음력도 계산하고 공휴일, 법정공휴일도 출력할 수 있는 프로그램을 만들 수 있다.
하지만 쉽지 않은 계산이 될 것이다.</p>
<p>이번 기회에 각 직종의 달력 만드시는 분께 칭찬과 격려를 보내 보는 것이 어떤가?😃</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA.03] printf 와 형변환(type conversion) 📣
]]></title>
            <link>https://velog.io/@kama_code/JAVA.03-printf-%EC%99%80-%ED%98%95%EB%B3%80%ED%99%98type-conversion</link>
            <guid>https://velog.io/@kama_code/JAVA.03-printf-%EC%99%80-%ED%98%95%EB%B3%80%ED%99%98type-conversion</guid>
            <pubDate>Sat, 17 Jun 2023 12:58:40 GMT</pubDate>
            <description><![CDATA[<h3 id="step1-문자열을-조합해서-출력하는-printf">&lt;Step.1&gt; 문자열을 조합해서 출력하는 printf</h3>
<blockquote>
<ul>
<li>우리는 이전에 자바(JAVA)에서 결과를 출력하는 코딩을 배웠다.
바로 println과 print이다. </li>
</ul>
</blockquote>
<ul>
<li>println(); : 내용을 출력한 후 자동으로 줄바꿈 처리한다.
&#39;sysou&#39; -&gt; 컨트롤+스페이스&lt;자동완성 기능&gt;
문자열을 &quot;(더블쿼테이션)으로 감싸서 표현한다.</li>
<li>print(); : 출력 후 줄바꿈 처리를 하지 않는다. 
만약 줄바꿈이 필요하면 \n을 추가해야한다. </li>
</ul>
<p>이 외에도 웹이나 앱에서 정말 많이 쓰는 프린트 출력문이 있다. 
바로 <strong>printf</strong> !
차이는 문자열을 조합하여 출력을 한다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/5fe9be31-e6d3-468c-bbb9-17aaeb9b83c1/image.PNG" width = "70%" height = "30%">  

<img src = "https://velog.velcdn.com/images/kama_code/post/fa2b4bc7-88c6-4ff9-874c-b91a06281fba/image.PNG" width = "70%" height = "30%">  


<h3 id="-자주쓰는-4가지만-꼭-기억하자✨">&gt; + 자주쓰는 4가지만 꼭 기억하자!✨</h3>
<ul>
<li>%d : 10진수 정수 </li>
<li>%f : 실수</li>
<li>%s : 문자열 </li>
<li>%c : 문자 </li>
</ul>
<h3 id="-응용-표현✨">&gt; + 응용 표현✨</h3>
<ul>
<li>%4d : 자리수를 4자리로 지정하고 남은 부분은 공백으로 출력 + &lt;우측 정렬:양수&gt;</li>
<li>%-4d : 자리수를 4자리로 지정하고 남은 부분은 공백으로 출력 + &lt;좌측 정렬:음수&gt;</li>
<li>%04d : 자리수를 4자리로 지정하고 남은 부분은 0으로 출력 + &lt;우측 정렬:양수&gt;</li>
<li>%6.2f : 실수 출력시 자리수는 6자리까지 남은 부분은 공백으로, 소수는 2자리까지만 출력</li>
<li>%.2f : 정렬이 없이 전체 출력, 소수점 아래는 2자리까지만 출력</li>
<li>%s : 문자열 출력</li>
<li>%c : 문자 출력</li>
</ul>
<h3 id="-기타-단축키✨">&gt; + 기타 단축키✨</h3>
<ul>
<li>tab : 스페이스 4칸</li>
<li>shift + tab : 역스페이스 4칸</li>
<li>★☆ 주석 : // -&gt; 줄 단위의 주석처리(컨트롤+/) : 실행되지 않는다.</li>
<li>/&#39;별&#39; 내용 &#39;별&#39;/ -&gt; 여러줄 단위의 주석표현
ㄴ코드가 무슨 뜻인지 설명하기 위함으로 자주 쓴다.</li>
<li>; (세미콜론) : 문장의 뜻을 의미한다.</li>
<li>★☆ 컨트롤 + 알트 + (화살표 위 아래) : 위 아래로 해당 문장을 복사한다.</li>
<li>★☆ 알트 + (화살표 위 아래) : 해당 문장을 위아래로 이동한다.</li>
</ul>
<h3 id="-이스케이프-시퀀스✨">&gt; + 이스케이프 시퀀스✨</h3>
<p>ㄴ특별한 의미로 해석되는 문자 
&lt;\t 탭과, \n 줄바꿈&gt;만 많이 쓰임</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/27ae7e70-41a4-4c4f-af12-20c305640d21/image.PNG" width = "70%" height = "30%">  

<h3 id="step2-자료형-형변환">&lt;Step.2&gt; 자료형 형변환</h3>
<h3 id="1-자동-형변환implicit-conversion">1. 자동 형변환(Implicit Conversion)</h3>
<p>작은 상자의 데이터를 큰 상자에 넣을때는 자동 형변환되며
자료의 손실이 발생하지 않는다.</p>
<p>※ 주의 : 문자형 char과 short는 똑같이 2바이트지만 이는 문자와 숫자 형으로 
유형이 다른 형태이다. 절대 같다고 생각하지 말자!</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/f6df47d9-5308-476c-9967-4e56e5666f88/image.PNG" width = "70%" height = "30%">  

<blockquote>
<ul>
<li>규칙1 : 자료형의 크기가 큰 방향으로 형 변환이 일어난다.
ex) (short) 형과 (int) 형이 연산을 하면 결과는 int형이 된다.</li>
</ul>
</blockquote>
<ul>
<li>규칙2 : 자료형의 크기에 상관없이 정수 자료형보다 <strong>★실수 자료형★</strong>을 우선한다.</li>
<li><blockquote>
<p>실수는 정수보다 크기 때문에</p>
</blockquote>
</li>
<li><blockquote>
<p>실수는 1과 2사이만 해도 무수한 실수가 존재한다.
ex) double num1 = 30;
ex) System.out.println(59L + 34.5); // long과 double의 연산시 double을 따라감</p>
</blockquote>
</li>
</ul>
<h3 id="😁-작은-놈과-큰-놈이-붙으면-큰-놈을-따라간다라고-이해💎">😁 작은 놈과 큰 놈이 붙으면 큰 놈을 따라간다라고 이해💎</h3>
<h3 id="2-명시적-형변환강제-형변환">2. 명시적 형변환(강제 형변환)</h3>
<p>큰 상자의 데이터를 작은 상자에 넣어야 할 때 명시적 형변환을 해야 한다.
단, 자료의 손실이 발생할 수 있다.
명시적 형변환을 위해서 캐스팅 연산자를 사용해야 한다.</p>
<p>예시: 큰 long형을 작은 int형으로 형변환할때 (int)를 붙여주어야 한다. </p>
<pre><code>        long num1 = 2147483648L;
        int num02 = (int)num1;</code></pre><p>결론은 CPU는 int, double형 계산기 밖에 없다고 이해하면 편하다.</p>
<img src = "https://velog.velcdn.com/images/kama_code/post/6b33b8a5-bda4-401c-b14d-2571b963f907/image.PNG" width = "70%" height = "30%">  

<h3 id="step3-발전을-위한-문제풀이-kama_code-출제">&lt;Step.3&gt; 발전을 위한 문제풀이 (kama_code 출제)</h3>
<blockquote>
<ol>
<li>현이가 키우고 있는 게임 세 직업의 캐릭터 
전사(War)의 다음 레벨까지 남은 경험치: 70000.159286
마법사(Wiz)의 다음 레벨까지 남은 경험치 : 5525.7777
도적(thi)의 다음 레벨까지 남은 경험치 69527을
printf를 사용하여 전사는 자리수 -30자리로, 소수점은 3자리까지만
마법사는 소수점 2자리까지만
도적은 정수 자리수를 10으로 출력하시오.*/</li>
<li>철수(cs)는 short형 75점, 영희(yh)는 byte형 55점인데
철수가 영희에게 돈을 주고 시험지를 바꿔치기 했다.
시험지를 바꿔치기 한 이후의 점수 선언을 하고
영희의 점수를 철수한테 집어넣어 printf를 통해 둘의 시험점수가 같게 출력하시오</li>
<li>double형 3.141592를 pi라는 변수에 선언 및 초기화를 하고
int 변수 chan을 선언하여 pi를 집어넣어 printf로 chan의 값을 출력하시오</li>
</ol>
</blockquote>
<p>▲△ 한번 직접 풀어보세요 ▲△</p>
<h2 id="★-정답-및-해설-☆">★ 정답 및 해설 ☆</h2>
<ol>
<li></li>
</ol>
<ul>
<li>전사는 159 소수점 3가지까지 출력됨과 동시에 -30자리수로 공백이 오른쪽부터 채워진다.</li>
<li>마법사는 소수점 2자리까지</li>
<li>도적은 10자리수로 공백이 왼쪽부터 채워진다.<img src = "https://velog.velcdn.com/images/kama_code/post/72aadc14-d6a4-4c18-b318-91c872e0c1d4/image.PNG" width = "80%" height = "30%">  

</li>
</ul>
<p>[2번 문제]</p>
<ul>
<li>자동형변환과 printf를 융합한 문제<img src = "https://velog.velcdn.com/images/kama_code/post/e6c9cd11-4da0-4d1a-8b45-3ba760eacfa1/image.PNG" width = "90%" height = "30%"> 

</li>
</ul>
<p>[3번 문제]</p>
<ul>
<li>강제형변환과 printf를 융합한 문제<img src = "https://velog.velcdn.com/images/kama_code/post/97f6fba3-2f9a-45e9-ad0f-ab4c690ceb4e/image.PNG" width = "90%" height = "30%"> 

</li>
</ul>
<h2 id="★-원리-이해-☆">★ 원리 이해 ☆</h2>
<p>byte : 0000 0000 
short : 0000 0000 0000 0000 
이런 식으로 공간이 있다.
byte형의 값을 short형으로 넣을 때는 short형이 공간이 더 크므로 </p>
<ul>
<li>자동형변환하여 들어간다</li>
</ul>
<p>하지만, short형의 값을 byte로 넣을 때는 0000 0000을 자르고 넣어야 들어가진다.</p>
<ul>
<li>그래서 강제형변환이라고 하며 그 과정에서 데이터 손실이 있을 수 있다.</li>
</ul>
<p>ex) 3번 문제 : double형인 3.14를 더 작은 int로 강제형변환하니까 
자연스럽게 0.14라는 데이터 손실이 발생됨.</p>
<h4 id="형변환은-엄청-중요하다-지금은-자료형-가지고-형변환을-하지만">형변환은 엄청 중요하다. 지금은 자료형 가지고 형변환을 하지만</h4>
<h4 id="나중에는-클래스-메소드도-형변환-비스무리한-것을-한다">나중에는 클래스 메소드도 형변환 비스무리한 것을 한다.</h4>
<h4 id="꼭-이해하고-넘어가자-파이팅-💖">꼭 이해하고 넘어가자! 파이팅! 💖</h4>
]]></description>
        </item>
    </channel>
</rss>