[ITWILL : WEB]마진과 패딩, 인라인과 블록 차이

ITWILL학원 : 10강 WEB(HTML, CSS) BY 김영희

1. margin 마진

  • 테두리기준 바깥여백
  • margin왼쪽값과 오른쪽값이 서로 같으면 요소는 항상 중앙에 온다.
    • 따라서 margin의 좌우값을 auto를 지정
  • margin : 위 오른 아래 왼

2. padding 패딩

  • 테두기리준 안쪽여백
  • padding : 위 오른 아래 왼

3. margin과 padding 차이

https://uxengineer.com/padding-vs-margin/

4. inline과 block 차이

  • 인라인요소(한줄에 나란히 오는 요소, 줄바꿈이 없는 요소) :
    • 상하 margin과 height와 width 아예 적용 안됨
    • 좌우 margin가능
    • img태그와 input태그는 예외

https://dev.to/devansvd/did-you-know-html-elements-had-an-element-named-element-2al7

[ITWILL : JSP]Javabean 9 : 게시판만들기(글삭제하기)

ITWILL학원 : 30강 JSP기초 BY 정규태강사

1. 글삭제하기기능구현 순서

  1. deleteForm.jsp 작성
  2. deletePro.jsp 작성
  3. BoardDAO.java에서 bdao.deleteBoard(bno, pw)메서드 생성
  4. 기존의 boardList.jsp에 id가 있을 경우 추가
  5. 기존의 content.jsp 로그인상태에 따라 다르게 보이는 버튼 추가

2. deleteForm.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%
//1. 한글처리
request.setCharacterEncoding("UTF-8");

//2. 파라미터저장
int bno = Integer.parseInt(request.getParameter("bno"));
String pageNum = request.getParameter("pageNum");

%>
<fieldset>
<legend>게시글 삭제</legend>
<form action="deletePro.jsp?pageNum=<%=pageNum%>" method="post">
<input type="hidden" name="bno" value="<%=bno%>">
비밀번호 : <input type="password" name="pw"><br>
<input type="submit" value="글삭제하기" class="btn">
<input type="button" value="뒤로가기" class="btn" onclick="history.back()">
</form>
</fieldset>

3. deletePro.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<%
//1. 한글처리
request.setCharacterEncoding("UTF-8");
//2. 파라미터저장(액션태그사용 & pageNum은 파라미터로)
int bno = Integer.parseInt(request.getParameter("bno"));
String pageNum = request.getParameter("pageNum");
String pw = request.getParameter("pw");
//3. DAO생성
BoardDAO bdao = new BoardDAO();
//4. 정보수정메서드 updateBoard(bb)
// -> 결과를 정수형 데이터로 리턴 (1=>정상처리, 0=>비번오류, -1=>해당글없음)
int result = bdao.deleteBoard(bno, pw);
if(result == 1){
%>
<script type="text/javascript">
alert("정상적으로 글 삭제되었습니다");
location.href="boardList.jsp";
</script>
<%
}else if(result == 0){
%>
<script type="text/javascript">
alert("비밀번호 오류");
history.back();
</script>
<%
}else{
%>
<script type="text/javascript">
alert("존재하지않는 게시글입니다");
history.back();
</script>
<%
}
%>

3. BoardDAO.java에서 bdao.deleteBoard(bno, pw)메서드 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public int deleteBoard(int bno, String pw){
int result = -1;

try {
getCon();
sql="select pw from itwill_board where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
rs = pstmt.executeQuery();
if(rs.next()){
if(pw.equals(rs.getString("pw"))){
sql="delete from itwill_board where bno=?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, bno);
pstmt.executeUpdate();
System.out.println("글삭제 성공");
result = 1;
}else{
result = 0;
System.out.println("글삭제 중 비번오류");
}
}else{
result = -1;
System.out.println("글삭제 중 select오류");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
closeDB();
}
return result;
}//deleteBoard()닫음

4. 기존의 main.jsp에 게시판바로가기 버튼 추가

글삭제의 경우 아무나 할 수 없어야한다.
따라서 로그인한 사람만이 글을 쓰고 글을 삭제할 수 있도록 구현해보자.
이전에 구현했던 main.jsp에 게시판글바로볼 수 있는 버튼을 추가하고 location.href='../board/boardList.jsp을 연결해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%//1.한글처리, 파라미터 
request.setCharacterEncoding("UTF-8");
String id = (String) session.getAttribute("id");//object를 string으로 다운캐스팅
String name = request.getParameter("name");
//1-1. id없이는 진입불가, id없는 경우 로그인페이지로 이동
if(id == null){
response.sendRedirect("loginForm.jsp");
}
%>
<h2><%=id %>님 환영합니다.</h2>
<%=name %><br>

<input type="button" value="ITWILL게시판가기" class="btn" onclick="location.href='../board/boardList.jsp'">
<input type="button" value="회원정보조회" class="btn" onclick="location.href='memberinfo.jsp'">
<input type="button" value="회원정보수정" class="btn" onclick="location.href='updateForm.jsp'">
<input type="button" value="로그아웃" class="btn" onclick="location.href='logout.jsp'">
<input type="button" value="회원탈퇴" class="btn" onclick="location.href='deleteForm.jsp'">

<!-- 관리자일때만 메뉴확인가능 -->
<% if(id != null){
if(id.equals("admin")){ %>
<input type="button" value="회원전체목록(관리자용)" class="btn" onclick="location.href='memberList.jsp'">
<%
}
}
%>

5. 기존의 boardList.jsp에 id가 있을 경우 추가

  • id가 없을 경우 : 로그인버튼만 표시
  • id가 있을 경우 : 로그아웃, 글쓰기버튼 표시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<fieldset>
<legend>땡땡게시판</legend>
<div id="contents">
게시판 총 글의 수 : <%=cnt%>
<%
if(id == null){
%>
<input class="btn" type="button" value="로그인" onclick="location.href='../member/main.jsp'">
<%
}else if( id != null){
%>
<input class="btn" type="button" value="로그아웃" onclick="location.href='../member/logout.jsp'">
<input class="btn" type="button" value="글쓰기" onclick="location.href='writeForm.jsp'">
<%
}
%>
<br>
<table>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
<th>IP</th>
</tr>
<%//반복문
//ArrayList는 가변배열이므로 length가 없고 size가 존재한다.
//size()메서드는 배열의 요소의 갯수를 리턴
for(int i=0;i<boardList.size(); i++){
//ArrayList 한칸의 정보 ->BoardBean 객체 하나로 이동
BoardBean bb = (BoardBean) boardList.get(i);
%>
<tr>
<td><%=bb.getBno()%></td>
<td><a href="content.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>"><%=bb.getSubject()%></a></td>
<td><%=bb.getName()%></td>
<td><%=bb.getReadcount()%></td>
<td><%=bb.getDate()%></td>
<td><%=bb.getIp()%></td>
</tr>
<%
}
%>
</table>
</div>
</fieldset>

6. 기존의 content.jsp 로그인상태에 따라 다르게 보이는 버튼 추가

  • 아이디가 있을 경우
    • 로그아웃버튼, 글쓰기버튼이 보임
    • 글 수정 및 삭제, 답글쓰기 버튼 보임
  • 아이디가 없을 경우
    • 로그인버튼만 보임. 로그아웃,글쓰기버튼 안보임
    • 글 수정 및 삭제, 답글쓰기버튼 안보임
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<fieldset>
<legend>글 내용 보기</legend>
<table border="solid,1px">
<tr>
<th>글번호</th>
<td><%=bno%></td>
<th>조회수</th>
<td><%=bb.getReadcount()%></td>
</tr>
<tr>
<th>작성자</th>
<td><%=bb.getName()%></td>
<th>작성일</th>
<td><%=bb.getDate()%></td>
</tr>
<tr>
<th>제목</th>
<td colspan="3"><%=bb.getSubject()%></td>
</tr>
<tr>
<th>첨부파일</th>
<td colspan="3"><%=bb.getFile()%></td>
</tr>
<tr>
<th>내용</th>
<td colspan="3" height="300px"><%=bb.getContent()%></td>
</tr>
<tr>
<td colspan="4" style="text-align:center">

<% //현재페이지에 로그인 정보가 없거나 글쓴이 이름과 아이디가 다를 경우 수정,삭제버튼을 숨긴다
//1.세션값 가져오기
String id = (String) session.getAttribute("id");//objectstring으로 다운캐스팅
//2. 아이디가 존재하면서 이름과 아이디가 같은 경우
if( id != null && id.equals(bb.getName())){
%>
<input type="button" value="글수정" class="btn" onclick="location.href='updateForm.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>'">
<input type="button" value="글삭제" class="btn" onclick="location.href='deleteForm.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>'">
<input type="button" value="답글쓰기" class="btn" onclick="location.href='reWriteForm.jsp?bno=<%=bb.getBno()%>&re_ref=<%=bb.getRe_ref() %>&re_lev=<%=bb.getRe_lev()%>&re_seq=<%=bb.getRe_seq()%>'">
<%
}
%>
<input type="button" value="목록으로" class="btn"
onclick="location.href='boardList.jsp?pageNum=<%=pageNum%>'">
<!-- location.href='boardList.jsp만 하면 5페이지보고있다가 다시 1페이지로 돌아가버린다
이때 historyback하면 조회수가 올라가지않는다.
따라서 pageNum을 가져와서 사용하면된다
-->
</td>
</tr>
</table>
</fieldset>

[ITWILL : JSP]Javabean 10 : 게시판만들기(답글쓰기)

ITWILL학원 : 30강 JSP기초 BY 정규태강사

1. 답글처리구현 순서

  • 일반글 = 답글이 아닌 글.
  • num : 일반글+답글 둘 다 작성할때마다 계속 증가된 값으로 사용(순차적)
  • re_ref : 답글의 그룹번호(일반글번호와 동일), 답글을 다는 원글의 그룹번호를 사용
  • re_lev (level) : 답글의 레벨값 (깊이), 원글을 기준으로한다 ex)한번내려가면1 두번내려가면 2
  • re_seq (sequence) : 답글의 순서, 원글에 답글이 몇개인지하는 순서대로 카운트.

글목록 예시

  • 일반글은 ref만 num값과 동일하게 초기화
  • 답글은 lev, seq는 0으로 초기화

만약 여기서 3번글의 답글 1개를 추가한다면?
6 / 답급3-1 / 3 / 1 / 1

만약 여기서 3번글의 답글 1개를 추가한다면?
6 / 답글3-1 / 3 / 1 / 1

만약 여기서 3번글의 답글 1개를 또 추가한다면?
7 / 답글3-2 / 3 / 1 / 2

만약 여기서 3번답글인 3-1에 답글 1개를 추가한다면?
8 / 답글3-1-1 / 3 / 2 / 3

만약 여기서 4번밑에 답글을 단다면?
9 / 답글4-1 / 4 / 1 / 1

만약 여기서 일반글 작성한다면?
10 / 일반글 / 10 / 0 / 0

만약 여기서 답글4-1에 답글을 단다면?
11 / 답글4-1-1 / 4 / 2 / 2

2. reWriteForm.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<%
//한글처리
request.setCharacterEncoding("UTF-8");

//전달한 데이터 저장 (bno,re_ref, re_lev, &re_seq)
int bno = Integer.parseInt(request.getParameter("bno"));
int re_ref = Integer.parseInt(request.getParameter("re_ref"));
int re_lev = Integer.parseInt(request.getParameter("re_lev"));
int re_seq = Integer.parseInt(request.getParameter("re_seq"));

//어떻게 가져갈 것인가? 폼태그안에 담아갈까? 주소창에 GET방식으로 가져갈까?
//bean의 멤버변수에 있는 변수는 폼태그안에 담아가면된다. =>hidden 인풋태그
%>
<fieldset>
<legend>게시판 답글쓰기</legend>
<form action="reWritePro.jsp" method="post" name="fr">
<input type="hidden" name="bno" value="<%=bno%>">
<input type="hidden" name="re_ref" value="<%=re_ref%>">
<input type="hidden" name="re_lev" value="<%=re_lev%>">
<input type="hidden" name="re_seq" value="<%=re_seq%>">
글쓴이 : <input type="text" name="name" required><br>
비밀번호 : <input type="password" name="pw" required><br>
제목 : <input type="text" name="subject" maxlength="15" value="[답글] " required><br>
내용 : <br>
<textarea rows="10" cols="35" name="content" placeholder="여기에 답글을 작성해주세요" required></textarea><br>
<input type="submit" value="답글등록" class="btn">
<button type="reset" class="btn">초기화</button>
<input type="button" value="목록으로" class="btn" onclick="location.href='boardList.jsp'">
</form>
</fieldset>

3. reWritePro.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%
// 한글 처리
request.setCharacterEncoding("UTF-8");
// 액션태그 사용 파라미터값 저장
// useBean,setProperty
%>
<jsp:useBean id="bb" class="com.itwillbs.board.BoardBean"/>
<jsp:setProperty property="*" name="bb"/>
<%
System.out.println(bb);
// ip 정보 저장
bb.setIp(request.getRemoteAddr());

// BoardDAO 객체 생성 - reInsertBoard(객체)
BoardDAO bdao = new BoardDAO();
bdao.reInsertBoard(bb);

// 페이지 이동(글 목록)
response.sendRedirect("boardList.jsp");
%>

4. BoardDAO.java에서 reInsertBoard(BoardBean bb)메서드 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public void reInsertBoard(BoardBean bb){
//1.지역변수생성
int num = 0;
//2. 디비연결
try {
getCon();
//sql(게시판의 글번호 중 최댓값 계산) & pstmt
//2-1. 답글번호 계산
sql = "select max(bno) from itwill_board";
pstmt = con.prepareStatement(sql);
// 실행
rs = pstmt.executeQuery();
// 데이터 처리
if(rs.next()){
num = rs.getInt(1)+1;
}
System.out.println(" 답글 번호 : "+num);

//2-2. 답글 순서 재배치
//re_ref(같은 그룹기준)으로 re_seq값이 기존의 값보다 큰 값이 있을경우 seq값을 1증가시킴
sql = "update itwill_board set re_seq=re_seq+1 "
+ "where re_ref=? and re_seq>?";
pstmt = con.prepareStatement(sql);

pstmt.setInt(1, bb.getRe_ref());
pstmt.setInt(2, bb.getRe_seq());

pstmt.executeUpdate();

//2-3. 답글 추가 동작
sql="insert into itwill_board "
+ "values(?,?,?,?,?"
+ ",?,?,?,?,now()"
+ ",?,?)";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, num);//bno는 가지고있는게 아니라 계산해서 만든것이므로 num사용
pstmt.setString(2, bb.getName());
pstmt.setString(3, bb.getPw());
pstmt.setString(4, bb.getSubject());
pstmt.setString(5, bb.getContent());
pstmt.setInt(6, bb.getReadcount());
pstmt.setInt(7, bb.getRe_ref()); //기존 원글의 그룹번호와 동일
pstmt.setInt(8, bb.getRe_lev()+1); // 기존의 값 + 1
pstmt.setInt(9, bb.getRe_seq()+1); // 기존의 값 + 1
pstmt.setString(10, bb.getFile());
pstmt.setString(11, bb.getIp());

//3. 실행
pstmt.executeUpdate();
System.out.println("답글쓰기 성공");
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB();
}
} //reInsertBoard닫음

5. BoardList.jsp에서 답글 들여쓰기 추가 구현

이미지와 조건문을 통해 구현

  • img src=”level.gif” width=”<%=wid%>” height=”15”
  • img src=”re.gif”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<fieldset>
<legend>땡땡게시판</legend>
<div id="contents">
게시판 총 글의 수 : <%=cnt%> 개
<%
if(id == null){
%>
<input class="btn" type="button" value="로그인" onclick="location.href='../member/main.jsp'">
<%
}else if( id != null){
%>
<input class="btn" type="button" value="로그아웃" onclick="location.href='../member/logout.jsp'">
<input class="btn" type="button" value="글쓰기" onclick="location.href='writeForm.jsp'">
<%
}
%>
<br>
<table>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
<th>IP</th>
</tr>
<%//반복문
//ArrayList는 가변배열이므로 length가 없고 size가 존재한다.
//size()메서드는 배열의 요소의 갯수를 리턴
for(int i=0;i<boardList.size(); i++){
//ArrayList 한칸의 정보 ->BoardBean 객체 하나로 이동
BoardBean bb = (BoardBean) boardList.get(i);
%>
<tr>
<td><%=bb.getBno()%></td>
<td>
<%
//답글일때만 이미지넣기
//변수 wid를 이용하여 들여쓰기 처리
int wid = 0;
if(bb.getRe_lev() > 0){
wid= 10 * bb.getRe_lev(); //레벨값의 10을 곱한 값만큼 이미지 가로길이를 길게해줌
%>
<img src="level.gif" width="<%=wid%>" height="15">
<img src="re.gif">
<% } %>
<a href="content.jsp?bno=<%=bb.getBno()%>&pageNum=<%=pageNum%>"><%=bb.getSubject()%></a></td>
<td><%=bb.getName()%></td>
<td><%=bb.getReadcount()%></td>
<td><%=bb.getDate()%></td>
<td><%=bb.getIp()%></td>
</tr>
<%
}
%>
</table>
</div>
</fieldset>

[ITWILL : JAVA]로깅, 디버깅

ITWILL학원 : 20강 JAVA BY 윤미영강사

1. 로깅(Logging)

  • 로깅 : 사용자의 요청사항을 출력하는 것 이외에 애플리케이션에서 발생하는 사건들을 기록하는 것.

참고링크 : java.util.Logging.Logger의 메서드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SimpleLoggingFile {

private final static Logger logger = Logger.getLogger(SimpleLoggingFile.class.getName());

public static void main(String[] args) throws SecurityException, IOException {
FileHandler fHandler = new FileHandler("mylog_%g.log");
logger.addHandler(fHandler);
logger.log(Level.INFO, "INTO LOG");
logger.info("메서드 타입 인포 로그");
logger.warning("메서드 타입 경고 로그");
logger.severe("메서드 타입 시비어 로그");
}

}

//출력값
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
정보: INTO LOG
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
정보: 메서드 타입 인포 로그
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
경고: 메서드 타입 경고 로그
723, 2020 11:11:40 오전 ch9.SimpleLoggingFile main
심각: 메서드 타입 시비어 로그
  • 더불어 mylog_0.log파일이 생성되었다.

  • 출력된 로그는 콘솔과 함께 파일에도 기록된다.

  • 실무에서는 logging패키지의 클래스보다 주로 logback과 같은 별도의 로깅 프레임워크들을 사용함.

2. 디버깅

  • 리커시브방법 : 함수가 자기 자신을 계속 호출하는 구조 = 재귀함수

  • break point : 프로그램 동작 중 디버깅을 위해서 동작을 멈추는 지점

    • 중단점을 지정해 놓으면 그 전까지 프로그램이 동작하다가 브레이크포인트에서 사용자의 다음동작을 기다린다.
    • step into를 하면 변수뷰창에서 valables가 어떻게 변화하는지 알수있다.

[ITWILL : JAVA]내부클래스

ITWILL학원 : 20강 JAVA BY 윤미영강사

1. 내부클래스(p363)

  • 클래스가 서로 밀접한 관련이 있을때 객체생성없이 사용하기 용이하다
  • 주로 이미 만들어진 내부클래스라이브러리를 사용.
  • 공통점 : static 변수는 가질 수 없지만, final static 변수는 가질 수 있다.
    • 만약 상수가 아닌 변수형태로 선언이 되어있다면 그건 앞에 final이 생략되어진 것임.
    • 변수를 사용하고싶다면 차라리 외부클래스의 멤버변수로 선언하는 것이 낫다.
  • 내부클래스의 종류 4가지 :

https://github.com/burberry-check/java-basic/wiki/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4,-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4

2. 인스턴스 내부클래스

  • 내부클래스를 외부클래스의 멤버변수 선언위치에 선언하는 것.

  • 인스턴스내부클래스는 외부클래스의 멤버변수를 자신의 멤버변수처럼 불러와서 쓸 수 있다.

  • 단독으로 사용하기도한다.

  • 내부클래스의 메서드 사용하는 방법 :

    1. 외부클래스 객체생성 : 외부클래스명 A = new 외부클래스명();
    2. 내부클래스 객체생성 : 내부클래스명 B = A.new 내부클래스명();
    3. 내부클래스의 메서드 사용 : B.method();
    • 이러한 것을 단독사용이라고 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class InstanceInner {
private int outerMember = 1;

private void outerMethod(){
Inner inner = new Inner();
inner.innnerMember = 11;
inner.innerMethod();
}

class Inner{
int innnerMember = 10;
//static int staticMember = 10; staitc멤버변수 선언 불가. 만약 상수가 아닌 변수형태로 선언이 되어있다면 그건 앞에 static이 생략되어진 것임.
static final int finalStaticMember = 20; //단 static final형태는 선언할 수 있다.

private void innerMethod(){
System.out.printf("out : %d, inner %d%n", outerMember, innnerMember);
}
}

//내부클래스 메서드 사용은 어떻게 할까?
public static void main(String[] args) {
InstanceInner ilt = new InstanceInner(); //1.외부클래스객체생성
Inner inner = ilt.new Inner(); //2.내부클래스객채생성
inner.innerMethod(); //3.내부클래스의 메서드사용

}
}

3. 지역클래스(local class)

  • 내부클래스가 외부클래스의 메서드안에서 정의되어지는 것.
  • 지역클래스는 단독으로 사용하지않고 내부에서 객체생성 후 호출해서 사용.
    • 단독사용의 의미 : 직접 메서드를 불러와서사용,
    • 지역클래스인 경우 메서드를 호출하는 순간 객채생성하고 바로 사용할 수 있게해야한다. 즉 단독사용처럼 직접 클래스이름을 불러 사용하는 것이 아니라 지역클래스가 속한 외부클래스메서드를 부르면서 그 속에 있는 클래스가 자동으로 사용되게끔 하는 것이다.
1
2
3
4
5
6
7
8
9
10
class OuterClass(){
...
public methodA(){ //멤버메서드
class InnerClass(){ //로컬클래스
...
}
}
}

//객체생성 후 호출해서 주로 사용

4. 익명클래스(p373)

  • 인터페이스를 구현할 목적으로 사용.
  • 실무에서 자주 사용.
  • 익명클래스의 override는 인터페이스 규칙에 의해 public을 붙여줘야한다
  • 익명클래스를 어떨때 사용할까?
    • 독립적인 클래스 사용 : 인터페이스를 구현한 클래스를 여러번 사용할때 용이.Intf a는 언제어디서나 불러서 사용가능
    • 익명클래스 사용 : 인터페이스를 구현한 클래스를 딱 한번 사용할때 용이. 익명클래스는 Intf b에서만 사용가능. 이름이 없기때문에 불러서 사용할 수 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
interface Intf{
void methodInf();
}

class A implements Intf{
@Override
public void methodInf() {
System.out.println("인터페이스 메서드 오버라이딩");
}
}

public class test {

public static void main(String[] args){

//기본적인 interface구현(독립적인 클래스사용)
Intf a = new A();
a.methodInf();

//익명클래스를 이용한 interface구현
Intf b = new Intf(){
@Override
public void methodInf() {
System.out.println("익명클래스로 인터페이스 메서드 오버라이딩");
}
};
b.methodInf();
}
}

5. 내부클래스 예시

다양한 내부클래스를 생성한 뒤 main메서드로 호출해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
interface InfoPrintable{
public void printInfo();
}

public class VariousInnerClassTest {

//멤버메서드(매개변수가 인터페이스)
public void useInnerClass(InfoPrintable inner){
inner.printInfo();
}

//멤버메서드
public void useSpeakerTest(){

//로컬 내부클래스생성(메서드안에 선언한 내부클래스=로컬클래스)
class EngSpeaker implements InfoPrintable{
@Override
public void printInfo() {
System.out.println("로컬 내부 클래스");
}
}//EngSpeaker닫음

//멤버메서드사용하여 클래스 부르기
//1. 익명의 내부클래스 생성
useInnerClass(new InfoPrintable(){
@Override
public void printInfo() {
System.out.println("익명의 내부클래스");
}
});

//2. 로컬내부클래스부르기
useInnerClass(new EngSpeaker());

//3. 인스턴스내부클래스부르기
useInnerClass(new InstanceInnerClass());

//4. 걍 밖에있는클래스
useInnerClass(new SomeClass());

}//useSpeakerTest메서드닫음

//인스턴스 내부클래스(외부클래스의 멤버에 생성)
class InstanceInnerClass implements InfoPrintable{
@Override
public void printInfo() {
System.out.println("인스턴스 내부클래스 사용");
}

}//InstanceInnerClass닫음


//만든 내부클래스를 main메서드로 호출해보자
public static void main(String[] args){

VariousInnerClassTest vt = new VariousInnerClassTest();
vt.useSpeakerTest();

}

}//VariousInnerClassTest닫음

//걍 다른 클래스인데 인터페이스구현
class SomeClass implements InfoPrintable{

@Override
public void printInfo() {
System.out.println("걍 상관없는 일반 클래스");
}

}

[JAVA]예외처리기법3가지 및 Error와 Exception 차이

1. 오류 Error

  • 발생하면 복구하거나 되돌릴 수 없는 심각한 상황.
  • 발생상황 예시 : 메모리부족, 메서드끼리 호출을 무한반복등등.
  • 처리방법 : 오류를 발생하는 요인을 찾아서 업애는 디버깅.
  • 예방법 : 코드 짜임새있게 짜기.
    즉, 프로그램을 잘 짜는 것만이 대안이기때문에 예외처리와 무관하다.

2. 예외 Exception

  • 오류와 비교하면 심각도가 낮으며 프로그램의 정상적인 흐름을 방해하는 상황.
  • 발생상황 예시 : 네트워크 연결 끊기는 상황, 해당 파일을 읽지 못하는 상황등등.
  • 예외처리란 : 예외가 발생했을때 비정상적인 종료를 막고 계속해서 사용할 수 있도록 처리하는 것
  • 예외처리 라이브러리 = 최상위 클래스 = Throwable

https://deftkang.tistory.com/44

  • RuntiomeException = unchecked Exception : 중간에 throws 할 필요없다
  • 그 외 예외 = checked Exception

3. 예외 처리 기법

3-1. try catch finally구문

  • 단축키 : ctrl + space
  • try catch finally :
    • finally블록은 무조건 실행. 예외 발생 여부와 상관없이 반드시 실행되어야하는 내용을 작성.
    • 심지어 return문을 만날때에도 먼저 finally 블록을 실행 후 메서드가 리턴된다.
    • finally 주요 목적 : try블록에서 사용한 시스템 자원(System Resource)의 반납처리.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class TryCatchFinallyFlow {

public static void main(String[] args) {

int num = new Random().nextInt(2);
try{
System.out.println("코드1 : "+ num);
int i = 1/num;
System.out.println("랜덤숫자 1일경우 예외없음");
return;
} catch (ArithmeticException e){
System.out.println("랜덤숫자0일경우 예외처리완료");
} finally {
System.out.println("코드4 : 파이널리 항상 실행");
}
System.out.println("코드5");
}

}
//랜덤숫자가 1일경우 출력값 - return때문에 코드5출력되지않음
코드1 : 1
랜덤숫자 1일경우 예외없음
코드4 : 파이널리 항상 실행

//랜덤숫자가 0일경우 출력값
코드1 : 0
랜덤숫자0일경우 예외처리완료
코드4 : 파이널리 항상 실행
코드5

3-2. Exception 객체 정보 활용

참고링크 : Throwable 메서드

  1. getMessage()사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SimpleException {
public static void main(String[] args) {
int[] intArr = {10};
try {
System.out.println(intArr[2]);
} catch (Exception e) {
System.out.println("예외발생 - 배열확인필요 : "+ e.getMessage());
}
System.out.println("프로그램을 종료합니다.");
}
}

//출력값
예외발생 - 배열확인필요 : 2
프로그램을 종료합니다.
  1. printStackTrace()사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SimpleException {
public static void main(String[] args) {
int[] intArr = {10};
try {
System.out.println(intArr[2]);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("프로그램을 종료합니다.");
}
}
//출력값
java.lang.ArrayIndexOutOfBoundsException: 2
프로그램을 종료합니다.
at ch9.SimpleException.main(SimpleException.java:8)

3-3. try with resources 구문

  • try catch finally 코드가 길다.
  • 따라서 java 7버전에서 새롭게 추가된 기능이 try with resources구문이다.
1
2
3
4
5
try (리소스타입1 res1 = 초기화; 리소스타입2 res2 = 초기화; ...){
//예외 발생 코드
}catch(Exception e){
//예외 처리 코드
}

4. throws 키워드를 통한 예외처리 위임

예외 처리의 두번째방법은 throws 키워드를 통한 위임 또는 전달이다.

  1. throws 키워드
  • throws는 메서드에서 처리해야 할 하나 이상의 예외를 메서드를 호출한 곳으로 던져버린다.
  • 이러한 위임은 처리와는 다름.
  • 첫번째 방법이었던 try catch 에서 catch블록은 예외를 처리해서 없애 버림
  • BUT 위임은 예외를 없애지 못하고 그냥 호출한 곳으로 예외를 전달만 함.
  • 예외를 전달받은 메서드는 다시 예외 처리 책임이 발생함.
  1. throws를 왜 사용할까?
  • 항상 try catch로 처리하는 것은 좋지않다
  • WHY? 특히 API나 다른 모듈에서 사용되는 기능을 제공하는 경우 예외를 전달해서 그 예외에 대해 적절히 대응할 수 있는 코드를 작성할 수 있게 해줄 필요가 있기때문이다.
  • 예 : 어떤 프로그램을 install할때

5. 사용자 정의 예외

  • 예외가 unchecked exception계열이면 중간에 throws절차가 필요없다. (ex : runtiomeException)
  • 고급스러운 코딩이 가능하다.

6. throw와 throws 차이

둘 다 Exception을 발생시키지만 큰 차이가 있다.

  • throws : 예외를 위임하는 예약어
  • throw : 억지로 예외를 발생시키는 예약어, 즉 사용자 정의에 의한 exception = 인위적인 exception이다.
    • 생성자에 exception을 넣으면 예외 문구로 출력된다.
1
throw = new throw("나만의 예외메세지");