out 기본객체를 공부하면서 out.print() 와 out.println() 이 눈에 들어왔다.

조건문을 사용할 경우 스크립트릿 이랑 표현식이랑 복잡하게 열고 닫고 하는 짓을 해야하는데 out.println을 사용해서 간단히 만들 수 있다.



1
2
3
4
5
6
<%if(grade>90){ %>
    <%=gradeA%>
<%}%>
<%else if(grade>80){%>
    <%=gradeB%>
<%}%>
cs

복잡하다..



1
2
3
4
5
6
<%if(grade>90){ 
    out.println(gradeA);
}
else if(grade>80){
    out.println(gradeB);
}%>
cs
깔끔하다 ^*^


자바를 공부하면 알 수 있듯이 개행문자를 넣어주느냐 아니냐에 차이기 때문에 println을 쓰면 줄바꿈이 되겠거니 생각했다.




하 지 만 

줄바꿈이 되지 않았다..


1
2
3
4
5
6
7
<%
    for(int i=0;i<3;i++){
        out.print(i+" = ");
        out.println(i+"입니다.");
    }
 
%>
cs

0 = 0입니다. 1 = 1입니다. 2 = 2입니다.




당연히 될 줄 알았는데 .. 그럼 줄바꿈을 해줄려면 결국 <br>을 넣어야하고 그러면 어차피 스크립트릿을 열고 닫아야 하는거 아닌가.. 라는 생각이 들었다.



일단 저기 println의 개행은 사라진게 아니다.

이렇게 html 소스코드 안에서 개행이 이루어 진 것이다.. 

하지만 원한건 이 개행이 아니었는데..


는 중에 방법을 찾았다.


1
2
3
4
5
6
7
<%
    for(int i=0;i<3;i++){
        out.print(i+" = ");
        out.println(i+"입니다.<br>");
    }
%>
 
cs

이렇게 print("<br>") 을 해주면 된다. 저기 안에 html태그를 넣으면 먹힌다는걸 처음 알았다. 이것 때문에

out.print 들은 웹브라우저 에게 그저 데이터를 넘겨 주는 것이구나 라고 이해가 되었다.


서블릿은 아직 모르지만 jsp도 결국 서블릿으로 변환한 후 실행 된다고 아는데

서블릿은 html태그들을 

out.println("<HTML>");
out.println("<BODY>");
out.println("Hello World!!");
out.println("</BODY>");

out.println("</HTML>");

이렇게 쓴다고 보았다

음 뭔가 이어지는 것 같다. 

'JSP' 카테고리의 다른 글

[JSP] GET방식 POST방식 인코딩 디코딩 방법  (0) 2018.08.09
[JSP] Get방식 Post방식 차이점  (1) 2018.07.26

HTML5의 등장으로 웹표준이 이제 정착해가고 있지만 아직도 HTML4.01이나 XHTML1.0을 사용하는 경우도 있기에 정리를 해본다. 


왜 이러한 타입이 나뉘어져있는지 알려면 약간의 배경지식이 필요하다.


아주 간단히 설명해보면


초기 HTML은 단순 텍스트위주의 표현을 위하였지만 

점차 발전을통해 다양한 요소를 표현하고 디자인적인 태그들도 생겼고

IE에 독주로 ActiveX 사용등 특정 브라우저에서만 볼 수 있는 기술들이 생겨났다.


하지만 점점 다양한 플랫폼 다양한 브라우저 사용이 늘어나면서 웹 표준이 필요하게 되었다.


웹 표준을 만들기 위해 HTML4.01 XHTML의 등장의 과정을 겪고 현재 HTML5가 탄생하였다.

웹 표준은 HTML에서는 구조만 짜고 디자인적인 표현요소는 CSS로 분리하였다.


더 자세히 알고싶으면 http://hyoje420.tistory.com/22 참고!

 


즉 현재 HTML5는 다양한 브라우저에서 다 호환이 되고 HTML과 CSS를 분리하면서 기존 HTML의 디자인태그를 삭제하였다. 

하지만 그 전 버전은 한번에 모든 웹 페이지들이 코드를 바꿀 수 없기 때문에 발전 과정에 있어서 하위호완성의 여지를 남겨 두었다.



1. HTML 4.01


버전  :  HTML 4.01 Strict


선언부  :  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">


설명  :  strict 단어 뜻대로 웹 표준을 엄격하게 지키는 버전center, font를 포함한 14가지 태그를 사용하지 않습니다.



버전 : HTML 4.01 Transitional


선언부  :  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

설명 : 아직까지도 많이 쓰이며 프레임을 제외한 모든 태그 사용이 가능



버전  : HTML 4.01 Frameset


선언부  :  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

설명  :  프레임 관련 태그까지 모두 사용 가능 



2. XHTML1.0 도 마찬가지로 위와 동일하게 나뉘어 진다


버전  :  XHTML 1.0 Strict


선언부  :  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">


설명  :   웹 표준을 엄격히 지키는 버전



버전  :  XHTML 1.0 Transitional


선언부  :  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


설명  :  역시 여전히 쓰이며 기존 웹 페이지와의 호환성을 위해 쓰인다



버전  :  XHTML 1.0 Frameset


선언부  :  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">


설명  : 마찬가지 프레임 관련 태그 사용가능



 

3. HTML5


버전 :  HTML5

선언부  :   <!DOCTYPE HTML>


설명  :  선언부가 매우 간단해졌다. 웹표준을 지키며 디자인을 위한 14개의 태그가 삭제되었다. 대형 웹사이트 들은 대부분 HTML5로 갈아탔다. 


요즈음은 HTML5가 많이 쓰이지만 여전히 4.01과 1.0 버전이 보인다.

HTML5가 나온 세대에 살고 있는 나는 편안하게 웹 표준을 공부하면 되겠다.



참고

http://roydest.tistory.com/entry/DOCTYPE-HTML-%EB%B2%84%EC%A0%84-%EC%84%A0%EC%96%B8


 코딩 과제를 하다가 scan.nextLine()이 분명 있는데 값을 받지 않고 넘어가는 경우가 생겼다.

 알아보니  scan.nextLine() 앞에 있는 nextInt()때문이었다.


 nextInt()는 정수형을 입력 받는 메소드인데 사용자가 입력할 때 ' ex) 10을 치고 엔터를 눌렀다 ' 엔터 앞부분까지만 입력 받는다. ( 이 경우 10까지만)

 즉 개행문자를 제거하지 않아 그 다음 나오는 nextLine()이 개행문자(엔터)를 받게 된다.


간단한 내용이지만 모르면 해맬 수 있어 정리를  해 놓는다.


문제 상황


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;
 
public class Problem {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int num;
        String str;
        System.out.print("num 입력 = "); 
        num = scan.nextInt(); // 10입력
        
        System.out.print("str 입력 = "); 
        str = scan.nextLine();             // 분명 이 줄이 있는데 값을 받지 않고 넘어가 진다.
 
        System.out.println();
        System.out.println("num : " + num);
        System.out.println("str : " + str);
        scan.close();
 
    }
}
 

cs


num 입력 = 10

str 입력 =

 

num : 10

str : 



해결방법



 1. nextInt() 뒤에 nextLine을 추가


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Scanner;
 
public class Problem {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int num;
        String str;
        System.out.print("num 입력 = "); // 10 입력
        num = scan.nextInt();
        scan.nextLine();                // 추가된 nextLine() 개행문자를 받는다. (제거한다)
 
        System.out.print("str 입력 = "); 
        str = scan.nextLine();          // 문제없이 입력을 받는다. hello 입력
 
        System.out.println();
        System.out.println("num : " + num);
        System.out.println("str : " + str);
        scan.close();
 
    }
}
 
cs


num 입력 = 10

str 입력 = hello


num : 10

str : hello



 2. nextLine()을 입력 받아 형변환 하기


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
import java.util.Scanner;
 
public class Problem {
    public static void main(String[] args) {
       Scanner scan = new Scanner(System.in);
       int num = 0;                   // 지역변수라 초기화 필요
       String str;
       System.out.print("num 입력 = "); 
      
       try {
           num = Integer.parseInt(scan.nextLine()); // 형변환을 한다 10입력
       }
       catch(NumberFormatException e) {
           System.out.println("정수를 입력해!");
       }
        
 
        System.out.print("str 입력 = "); 
        str = scan.nextLine();             // hello 입력
 
        System.out.println();
        System.out.println("num : " + num);
        System.out.println("str : " + str);
        scan.close();
 
    }
}
 
 
cs


num 입력 = 10

str 입력 = hello


num : 10

str : hello



 3. 새로운 Scanner 객체 생성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Scanner;
 
public class Problem {
    public static void main(String[] args) {
        Scanner scanI = new Scanner(System.in); // int를 받는 스캐너
        Scanner scanS = new Scanner(System.in); // String을 받는 스캐너
 
        int num;
        String str;
        System.out.print("num 입력 = ");
        num = scanI.nextInt(); 
 
        System.out.print("str 입력 = ");
        str = scanS.nextLine();
 
        System.out.println();
        System.out.println("num : " + num);
        System.out.println("str : " + str);
        scanI.close();
        scanS.close();
    }
}
 
cs


num 입력 = 10

str 입력 = hello


num : 10

str : hello




 간단하게 1번이나 아님 정수형 요청시 예외 값을 처리 할 수 있는 2번방법이 좋아보인다.




참고

http://allg.tistory.com/17

Jsp Php Asp.net 모두 웹 서버 언어이다. 

웹 개발자로써 어떤 언어를 공부하고 사용할 것인지는 중요해 보인다. 그래서 각각의 특징을 알아보았다.



JSP


자바기반 언어이다 

방대한 자바 api 사용가능

자바의 우수한 이식성을 물려받아 윈도우 리눅스등 다양한 플랫폼에서 구동 가능하다

우수한 보안성을 가지고 있다.

우리나라에서 많이 쓰인다.

유지보수가 용이하다


단점

배우기 어렵다

개발이 오래 걸린다

상대적으로 무겁다



php


c언어 기반이다

역사가 길고 오픈소스여서 다양한 정보가 널려있다.

가볍다

리눅스 윈도우에서 다 가능하다.

유연한 언어


단점

서버 과부하시 상대적으로 불안정

상대적으로 보안성이 낮음



asp


vb기반

배우기 쉽다.

개발하기 쉽다.



단점

윈도우플랫폼에 한정된다






라고 흔히들 나와있다. 


그래서 소/중규모에는 php 중/대규모에는 jsp를 많이 쓴다고 한다.


하지만


 php도 보안에 취약하지 않다. 개발하기 나름이다 jsp는 오히려 느리고 불편하다 등등 말이 엄청 많다.


 나는 아직 어떠한 언어도 제대로 공부해본적이 없고 써본적도 없으니 와닿는 느낌이 없다. 그냥 그저 어떠한 언어든 익숙해지고 잘 쓰면 되는구나 라고 생각이 든다. 물론 어느정도 정점에 다다르면 언어탓을 할 수 도 있겠지만..


 그래서 결국어떤 언어를 사용하든 언어는 도구일 뿐이고 더 중요한 것은 개발자의 역량 이라는 결론이 주류인 듯 하다..

 어떤 언어가 낫다 라고 주류가 있는게 아니라 각자가 잘 쓰고 있는 언어를 좋다고 말하는 것 같다..

 그러므로 어떤 회사를 목표로 그 회사가 주로 사용하는 웹언어를 목표로 먼저 공부하는 것이 낫겠다.




html과 jsp를 배우면서 사용자 입력 정보가 필요할 때 쓰는 get과 post를 많이 사용해보았지만 그저 url에 보내는 방식과 패킷 body 안에다가 보내는 방식 이다 정도 밖에 몰랐었다.




다들 기본적인 get과 post에 알거라 생각하고 기본적인 get post에 대한 내용은 생략하고 바로 본론으로 넘어가겠다.


결국 get과 post에 차이는 내가 원래 알고 있었던 url에 보내는가 패킷 body안에 보내는가의 차이에서 다 온다고 생각한다.



 1. 데이터의 크기 

get은 url에 보내므로 url은 길이제한이 있기 때문에 짧은 데이터

post는 길이제한이 없으므로 긴 데이터의 적합


음.. IE에 경우 2083자 제한이 있고 나머지 브라우저는 없다 그래서 이 차이점은 중요하지 않는듯..



 2. 보안

get방식은 url에 키와 값이 모두 노출 되므로 보안에 취약하고

post는 직접 노출이 되지 않아 보안에 유리하다.


이 내용도 썩.. 와닿지 않는다 post는 그처 최~~소한의 보안을 하는 수준인 듯 하다. 어차피 암호화 되지 않는건 마찬가지기 때문에..



 이 다음 부터가 중요하다고 생각한다.

 get은 단어 뜻 그대로 받다,얻어오다 post는 게시하다 

 즉 get은 파라미터로 특정한 정보를 요청하는데 쓰이고 ( 이러한 짓을 해도 다른곳에 영향을 주지않음 예를들어 검색하기 조회하기등등... )
 post는 내가 전달한 키와 값이 다른 곳에 영향을 끼친다 ( 회원정보를 제공해 회원등록이 되고 게시판에 글을 작성하고 ..)



 이렇게 검색창은 get방식을 사용한다. 

 내가 어떤 내용을 검색하고 그것을 공유하고 싶으면 그저 url을 공유하면된다. 남이 같은 url을 입력하면 같은 페이지를 볼 수 있다.  만약 post방식으로 검색을 구현했다면 남에게 공유하려면 어떤 검색어를 쳐서 어떤 경로로 가는걸 다 말해주어야 할 것이다.

 또 내가 어떤 내용을 검색한다고 검색된 내용이 바뀐다던가 같은 영향을 끼치지 않는다. (조회기록은 남겠지만) 





 회원가입 같은 경우는 post방식을 사용한다

 내 개인정보를 입력해서 회원가입을 하는데 이러한 내용을 공유할 필요가 있는가?

 또 회원가입을 하면 내 정보가 db에 올라가고 나는 네이버에 회원이 된다. 이렇게 post방식은 영향을 끼친다.

 만약 get방식 이라면 그url이 남아 중복으로 회원가입이 요청되는 등 에 문제가 생길 것이다.



 내 생각대로 정리하자면 일회성이 필요한 정보들은 post로 남들과 공유하고 반복이 필요한경우 get을 써야 할 것같다.

 아까 말한대로 get은 영향을 끼치지 않으니 반복하고 남이해도 상관이 없지만 post는 영향을 끼치니 말이다.







참고


https://blog.outsider.ne.kr/312

http://uiandwe.tistory.com/1133

'JSP' 카테고리의 다른 글

[JSP] GET방식 POST방식 인코딩 디코딩 방법  (0) 2018.08.09
[JSP] out.println 줄바꿈  (0) 2018.08.07

다형성이란??? 


여러 가지 형태를 가질 수 있는 능력!

자바에선 한 타입의 참조변수여러 타입의 인스턴스를 참조할 수 있는 것!


보통 A a = new A(); 이렇게 참조변수와 인스턴스의 타입이 같은 경우를 흔히 보았을 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package test;
 
public class Poly {
    public static void main(String args[]) {
        
        Human a = new Human();
        Human b = new Programer();
    }
}
 
class Human {
    String name;
    void eat(){
    }
}
 
class Programer extends Human {
    void coading(){
    }
}
 
cs


 

 하지만 위 예제를 보면 Human 타입의 참조변수가 Human의 인스턴스와 Programer의 인스턴스를 참조한다.

한가지 타입의 참조변수로 여러 타입의 인스턴스를 담았다!


다만 아무 타입이 아무 타입의 인스턴스를 참조할 수 있는 것은 아니다


 

 조건

 

 조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있다. 하지만 역은 성립하지 않는다!!

 즉 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 하는 것이다.

 Human b = new Programer(); 의 경우 Programer의 인스턴스를 참조중이라 해도 Human타입의 참조 변수기 때문에 Human이 가지고있는 name과 eat() 멤버만 사용 가능하다 

 즉 참조 변수의 타입에 따라서 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 수가 달라지게 된다!


Programer b = new Human(); 만약 이런식으로 한다면 Programer의 참조변수이므로 coading()을 쓸 수 있지만 Human인스턴스를 참조중이고 Human은 coading()을 가지고 있지 않으므로 문제가 발생한다. 그래서 위에 언급한 조건이 있는 것이다.



 참조변수의 형변환


참조변수도 기본형과 같이 형변환이 가능하다. 다만 상속관계에 있는 클래스사이에서만 가능하다. (간접적인 상속관계 즉 조상의 조상 같은경우도 가능)


byte b = 4;           업캐스팅 형변환 생략

int i = b; 


int i = 30;             다운캐스팅 형변환 생략 불가

byte b = (byte)i;  


 기본형 변수의 형변환이다. 보면 더 작은 자료형인 byte에서 더 큰 int로의 형변환은 생략됨을 볼 수 있다.

 마찬가지로? 자손타입에서 조상타입으로의 형변환은 생략이 가능(업캐스팅) 하지만 반대는(다운캐스팅) 생략이 불가능하다.


내가 이해하기엔 자손클래스가 부모클래스보다 큰? (더 많은 멤버를 가지고 있으니 당연한거 아닌가?)개념이라 처음에 무지 헷갈렸다.


 아까보았던 Human c = new Programer(); 이 예제도  Human c = (Human)new Programer(); 사실 저형변환이 생략된 형태이다.(업캐스팅)


다운캐스팅


1. Programer p = (Programer)new Human();    그럼 이렇게 형변환을 명시해주면 되는 것일까??

답은 아니다! 컴파일은 되지만 런타임 에러가 뜨고만다.


2. Human h = new Programer();

   Programer p = (Programer)h;

 

 이렇게 해주어야 한다. 왜 일까?

형변환은 단순히 참조변수의 타입을 변환해주는 것이지 인스턴스에는 영향을 끼지지 않는다. 무슨말이냐면!

Human이 Programer의 타입으로 바뀐다해도 Human은 coading()을 가지는 것은 아니다.!!!

그래서 결국 참조변수 p가 다룰 수 있는 멤버의 개수가 Human인스턴스보다 더 많아 불가능한 것이다 (계속 같은말..) 


 2.의 경우 첫번째 줄을 보면 h는 Programer의 인스턴스를 참조하지만 Programer의 멤버를 Human이 가지고 있는 멤버만큼만 이용이 가능하다

 Programer인스턴스를 참조하는 h의 정보를 형변환으로 타입을 맞추어 p에 제공하면 Programer의 타입으로 Programer를 참조하는 것이다. 당연히 되고 모든 멤버를 이용가능해 진다.


 처음 이 개념을 공부 했을때 왜 구지 이런 짓을 하지? 라는 생각이 딱 들었다. 방법은 알아도 활용도가 와닿지 않았다.

하지만 다운캐스팅을 활용을하는 예제를 밑에 두었으니 차차 다음내용도 보자!




매개변수의 다형성


동호회를 만들어 클래스로 관리하려한다. Club클래스를 만들고 클럽 멤버로 프로그래머가 올수도 학생이 올수도 있다. 그러면


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
class Human {
    String name;
    void eat(){
    }
}
 
class Programer extends Human {
    void coading(){
    }
}
class Student extends Human{
    void study() {
        
    }
}
 
class Club {
    static int memberNumber=-1;
    String clubName= "java";
    String [] members = new String[10];
    
    void member(Programer p) {
        members[++memberNumber] = p.name;
    }
    void member(Student s) {
        members[++memberNumber] = s.name;
    }
 
}
cs


 이렇게 Club이라는 클래스에 member라는 메소드를 여러번 오버로딩 해주어야 할까?? 여기서는 2개의 상황만 나열했지만  실제로 가입하려는 사람들은 더 다양한 직업을 가졌을 것이다.

 하지만 매개변수의 다형성을 적용해보자. Programer와 Student 모두 공통의 조상인 Human을 가지고 있다.


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
class Human {
    String name;
    void eat(){
    }
}
 
class Programer extends Human {
    void coading(){
    }
}
class Student extends Human{
    void study() {
        
    }
}
 
class Club {
    static int memberNumber=-1;
    String [] members = new String[10];
    String ClubName;
    Club(String a) {
        ClubName=a;
    }
    void member(Human h) {
        members[++memberNumber] = h.name;
    }
    
}
cs

 

 이렇게 하나의 메소드로도 표현할 수 있게 된다. (24번줄)


 멤버의 특성이 이름만 있을까? 위 코드에는 그렇지만 실제로는 나이도있고 성별도있고 등등 더 많을 것이다.

그렇다면 members라는 배열을 객체의 배열로 만들어 하나의 배열에 객체정보를 담으면 되지 않을까?



여러 종류의 객체를 하나의 배열로 다루기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Club {
    static int memberNumber=-1;
    Human [] members = new Human[10];
    String ClubName;
    Club(String a) {
        ClubName=a;
    }
    void member(Human h) {
        members[++memberNumber] = h;
    }
    
    void getMemberInfo(int number) {
        System.out.println("회원이름 :"+ members[number].name);
        System.out.println("회원나이 :"+ members[number].age);
    }
    
}
cs


하나의 배열의 여러 종류의 객체를 담아 더 간단하게 코딩이 가능해진다. (3번줄)


1
2
3
4
5
6
7
8
9
10
11
public class Poly {
    public static void main(String args[]) {
        
        Club A = new Club("java");
        Programer Programer1 = new Programer();
        Student Student1 = new Student();
        A.member(Programer1);
        A.member(Student1);
        
    }
}
cs

이렇게 클럽A의 member배열에 여러종류의 객체가 담긴다. (7,8번줄)



 하지만 위에 코딩에서는 클럽멤버의 수를 정해 10으로 정해놓았다. 물론 동호회 인원을 정해놓고 더 안받는 경우도 있겠지만 그렇지 않는 경우는 어떻게 해야할까?  이 블로그에서 다루진 않았지만 가변배열중에 하나인 Vector 클래스를 사용하면 된다.

Vector클래스는 내부적으로 Object타입의 배열을 가지고 있어서 이배열에 어떤 객체든 추가가 가능하다.


다운캐스팅 예제 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Club {
 
    Vector members = new Vector();
    String ClubName;
    Club(String a) {
        ClubName=a;
    }
    void member(Human h) {
        members.add(h);
    }
    void getMemberInfo(int number) {
        Human h =(Human)members.get(number);
        
        System.out.println("회원이름 :"+ h.name);
        System.out.println("회원나이 :"+ h.age);
    }
    
}
cs


 자 3번줄을 보면 더이상 멤버의 수가 제한되지 않게 members를 Vector로 만들어 주었고 member의 추가도 9번줄 Vector의 메소드인 .add()로 해주었다.

 여기서 알고가야할 점은 Vector의 add() 메소드는 객체를 Object타입의 변수로 저장한다는 것이다. 물론 오늘 배운 핵심인 조상의 참조변수로 자식의 인스턴스를 담을 수 있다. 라는 점을 어긋나지 않아 가능하다 Object는 모든 클래스의 조상이니.. 


 하지만 Object는 name이나 age같은 변수를 가지고 있지 않아 사용할 수 없다.


그래서!


 12줄을 보면 Vector의 있는 정보를 꺼내 Object의 자식중 하나인 Human으로 다운캐스팅 하는 것을 볼 수 있다!!! 그럼다시 Human은 name,age를 가지고 있기 때문에 사용이 가능해진다. 


 이렇게 예제를 통해 다형성, 참조변수의 업캐스팅,다운캐스팅, 매개변수의 다형성, 여러 종류의 객체를 하나의 배열로 다루는 것을 알아보았다.

 나는 이부분을 공부하면서 처음에 이해가 너무 어려웠고 특히 다운캐스팅 같은경우는 왜 저런짓을 하는지 이해가 안갔다. 하지만 이런 예제를 통해 이해가 되어 무리를 해서라도 만들어 보았다.. 


참고

자바의 정석 남궁 성 지음

에러 관계도



이처럼 프로그램 실행 시 발생할 수 있는 예외(Exception)를 대비해 코드를 작성하는 것을 예외처리(Exception handling) 라고 하며 

프로그램의 비정상 종료를 막고 정상적인 실행상태를 유지하는 것이 목적이다!




○ 예외의 종류


자바에서는 에외와 에러를 클래스로 정의 하였다. 역시 Object가 최상위 클래스 이다.

예외클래스 계층도



예외는 그 특징에 따라 크게 2가지로 다시 나뉘어진다.

예외의 두종류


RuntimeException클래스와 아이들 (위 그림에 아랫부분)  //이하 RuntimeException클래스들


RuntimeException클래스와 아이들 제외한 나머지 Exception클래스와 아이들 (위 그림에 윗부분) //이하 Exception클래스들



 RuntimeException클래스들 


-주로 프로그래머의 실수에 의해 발생되는 예외다. (배열의 범위를 벗어남, 정수를0으로나누려함 등등등)

-so 프로그래머의 주의필요

-이런종류의 예외들은 예외처리 없어도 컴파일이 된다. 

-unchecked예외라고 부른다



 Exception클래스들


-주로 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 (입력한 데이터 형식이 잘못됨, 존재하지 않는 파일 이름 입력 등등등)

-이런종류의 예외들은 반드시 예외처리가 필요함 

-checked예외라고 부른다





○ 예외 처리 방법

try catch, method에 선언하기 2가지가있다.


1. try catch 문



-보기와 같이 catch문은 여러번 쓸 수 있다.


try문에서 예외가 발생하면 해당하는 클래스의 인스턴스가 만들어지고 그 인스턴스를 가지고 catch문에 선언된 참조변수의 종류와 instanceof 연산자를 이용해 true인 catch문을 찾는다.


그래서 먼저 나오는 catch문에 예외는 뒤에 나오는 예외보다 자식이어야 한다!

why? 만약 첫 catch문에 가장 부모인 Exception이 있다면 모든 예외가 다잡하기에 밑에 선언된 catch문은 쓸모가 없어지게 된다. 


-catch문 괄호안의 선언된 변수는 그 catch문 안에만 유효하므로 보기의 'e'처럼 반복사용 가능하다.


-try문이나 catch문 안에 또 try catch문 선언이 가능하다.


-if문과 달리,  try와 catch문의 포함된 문장이 하나여도 {}를 생략할 수 없다


-흐름

예외가 있을경우 : try문(예외까지만) -> 해당되는 예외의 catch문 -> finally문

예외가 없을경우 : try문 -> finally문

try문에서 예외가 발생하면 나머지 try문은 실행되지 않으므로 try문을 잘 구성해야 한다.



-printStackTrace() : 예외발생 당시의 스택에 있던 메서드의 정보와 예외 메시지를 출력한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

class Excep {
    public static void main(String args[]){
        System.out.println(1);
        try{
            System.out.println(2);
            System.out.println(0/0);
            System.out.println(3);  //위에서 예외가 발생해서 실행되지 않는다
        }catch(ArithmeticException e){
            System.out.println(4);
e.printStackTrace(); //
        }finally {
            System.out.println(5);
        }
        System.out.println(6);
    }
}

cs

1

2

4

java.lang.ArithmeticException: / by zero

at blog.Excep.main(Excep.java:8)

5

6


다음과 같이 6번줄에 예외가 발생하여 7번줄이 실행되지 않았고 catch문으로 흐름이 이동해 4와 예외 메시지가 출력되었다.


-멀티 catch 블럭

JDK1.7부터 여러 catch문을 | 을 이용해서 하나로 합칠 수 있게 되었다. 합치는 개 수에는 제한이 없다.


1
2
3
4
5
6
7
8
try{
}catch(ExceptionA e){
 
}catch(ExceptionB e){
 
}catch(Exceptionc e){
 
}
cs

1
2
3
4
try{
}catch(ExceptionA | ExceptionB | ExceptionC e){
 
}
cs

예외 종류는 다르지만 처리방법이 같았던 경우 중복 코드가 생겼었지만 위 방법으로 중복을 피할 수 있다.


한 catch문에 부모 자식 관계에 예외를 사용하지 못한다. 의미가 없다 그냥 조상 클래스의 예외만 써주는 거랑 똑같다.


참조변수 e가 어떤 예외클래스를 참조하는지 알 수 없기 때문에 참조변수 e로는 공통 조상 클래스에 멤버만 쓰거나 instanceof 로 확인 후 써야한다.


1
2
3
4
5
6
7
8
9
try{
}catch(ExceptionA | ExceptionB | ExceptionC e){
    if(e instanceof ExceptionA){
        ExceptionA e1 = (ExceptionA)e;
        e1.methodA();
    }else if(e instanceof ExceptionB){
        ......
    }
cs





* 고의로 예외 발생시키기 (throw)

Exception e = new Exception(); 

throw e;


throw new Exception();  아까 말했듯이 반드시 예외처리 필요

throw new RuntimeException();  예외처리 없어도 됨

이렇게 예외처리가 없어서 에러가 뜬다.


예외처리 해주므로 빨간줄 사라짐~


반면 RuntimeException 에러는 예외처리 안해주어도 컴파일 가능! (하지만 실행시 에러가 발생하면 마찬가지로 프로그램 종료됨)




2. 메소드에 예외 선언하기 (예외 던지기)


method () throws Exception1, Exception2 {


}


throws 키워드를 사용하며 역시 , 로 여러 예외를 선언할 수있다. (throw 랑 헷갈리지 말자)



 사실 메소드에 예외를 선언하는건 예외를 처리하는건 아니다. 

저렇게 선언된 메소드에서 에러가 발생하면 그메소드를 호출한 메소드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.


 그렇게 던지고 던져서 만약 main메소드까지 전달되고 main에서도 예외가 처리되지 않으면 프로그램은 종료된다.

이렇게말이다. 저 에러코드로 알수있는 점이 있는데 예외가 발생한 곳은 method1이고 그메소드를 main이 호출했다는 것을 알 수 있다.

 



결국 어디서든 try catch문으로 예외처리가 필요하다

3가지 처리 방법이 있는데




예외가 발생하는곳에서 처리하는경우

 method1 에서 처리

 

 예외가 발생하는 메소드에서 처리를 해버리는 경우다. 이런 경우에는 main은 예외가 발생하는 지도 모르며 그래서 main에 throws가 필요없다.




예외를 받아 처리하는경우

main에서 처리

 

 예외가 발생하는 method1에서는 예외처리를 하지 않으므로 throws를 해주어야한다. (Exception 예외 이므로)




두곳다 처리하는경우



method1에서 처리

main에서 처리


에러가 발생한 method1에서 처리를 해주고 아까배운 throw로 다시 예외를 만들었다. (예외 되던지기)

이미 처리가 끝난다음에 에러가 발생해 method1에서 다시 throws를 해주어야하고 (역시Exception 에러므로) 

이 에러는 main으로 던져진다 

main에서 역시 try catch로 예외처리 해주어야 된다.




참조

http://sjh836.tistory.com/122

http://history1994.tistory.com/10?category=668240

Java의 정석    남궁 성 지음



반복문 사용시 break 와 continue는 유용하게 사용된다.

다만 중첩 반복문 사용시 원하는 반복문으로 한방에 탈출 할 수는 없을까?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Exit {
    public static void main(String[] args) {
 
        int r1 = 0;
        int r2 = 0;
        
        roop : while(true) {    // roop라고 반복문 이름을 주었다  : 키워드로 붙여준다
            r1++;
            System.out.println("첫번째 반복문 "+r1);
            
            while(true) {
                r2++;
                System.out.println("두번째 반복문 "+r2);
                
                if(r2==3)
                    break roop; // roop라는 반복문을 탈출
            }
            
        }
        
    }
}
 
cs


첫번째 반복문 1

두번째 반복문 1

두번째 반복문 2

두번째 반복문 3


적절한 예제가 떠오르지 않았다..... 하여튼 알아두면 된다.




반복문 앞에   name : while , name : for  과 같이  이름을 붙이면


break name; continue name; 과 같이 지정한 반복문을 빠져나가거나 컨티뉴 할 수 있다.


이는 반복문 안에 반복문을 넣었을 때 한번에 빠져 나온다던가 같이 반복문을 요리조리 이동하고 싶을 때 유용하다.

'java' 카테고리의 다른 글

자바[java] nextInt() 다음 nextLine()이 안돼요  (0) 2018.07.30
자바[java] 다형성  (4) 2018.07.12
자바[java] 예외처리  (2) 2018.07.10
자바[java] Call by value Call by reference  (1) 2018.07.04
자바[java] JVM의 메모리구조  (2) 2018.06.25

역시나 기초지식이 전무하기에 간단하게 상위 개념부터 알아보겠다.


 우리는 웹 브라우저에 https://www.tistory.com/skin 과같은 URL을 치면 티스토리 웹 페이지가 화면에 딱 나온다.

 어떤 과정을 거쳐 나오게 되는 걸까?


 간단한 용어 정리


클라이언트 : 네트워크에서 요청하는 쪽 ex) URL을 요청하는 웹 브라우저 또는 그런 브라우저를 돌리는 컴퓨터

서버 : 요청을 받아 알맞은 기능이나 데이터를 제공하는 쪽 ex) 요청을 받아 응답을 하는 웹 서버 또는 서버 프로그램이 실행되는 컴퓨터





 웹 브라우저에 URL을 입력하면 웹 서버라 불리는 프로그램이 웹 브라우저에 웹 페이지를 제공한다. 하지만 웹 브라우저와 웹 서버는 각각 다른 컴퓨터에 위치한다. 예를 들어, 집 PC에서 웹 브라우저에 URL을 요청하면 그 URL을 받을 웹 서버는 다른 컴퓨터에서 실행 되고 있다. 그래서 웹 브라우저가 웹 서버에 연결하려면, 웹 서버가 실행중인 컴퓨터의 IP주소를 알아야 한다.


 IP 주소는 숫자로 구성되어 있고 ex)180.70.134.239 그래서 외우기가 힘들다. 이런 이유로 tistory.com 와 같이 도메인 이름을 사용한다. 하지만 연결하기 위해서는 IP주소가 필요하므로 DNS를 이용한다 DNS는 도메인 이름과 IP주소를 저장하고 있는 데이터 베이스로 웹 브라우저가 URL을 요청할 때 그 도메인에 맞는 IP주소를 제공한다.


 이러한 과정으로 클라이언트가 요청을 하면 그 요청에 맞게 웹 서버가 응답한다.

 처음에  웹 서버에 대해 알아볼 때 어떻게 클라이언트와 웹 서버가 통신을 하는지 궁금해서 알아본 내용이다. 



이제부터 본격적인 주제인 웹 서버와 웹 어플리케이션 서버 (WAS)에 대해 알아보자!


 웹 서버 (Web Server)

 

 클라이언트(웹 브라우저)로 부터 HTTP 방식으로 정적인 자원을(html, css, 이미지 등) 요청 받아  그에 맞는 응답을 제공해주는 프로그램 이다. 또 자체적으로 처리할 수 없는 동적인 자원(JSP, PHP, ASP.net, DB연동 등)을 웹 컨테이너로 넘겨주고 컨테이너에서 처리한 결과를 다시 받아 클라이언트에게 제공해주는 역할을한다.


 대표적으로 Apache, IIS(Internet Information Server), WebtoB 등이 있다.


  *정적/동적 자원의 차이: 전자는 네이버에서 네이버 로고같이 파일이 바뀌기 전까지 같은 내용을 보여주는 것 이고 

실시간 검색순위 같이 시간이나 특정 조건에 따라 응답 데이터가 달라지는 자원을 후자라고 한다.


 컨테이너 (Containner)


 웹 서버가 보낸 JSP, PHP, ASP.net등의 파일을 실행하고 수행 결과를 다시 웹 서버로 보내주는 역할을 한다. 


 대표적으로 자카르타 톰캣, RESIN, 웹로직, 웹투비 등이 있다.


 


 웹 어플리케이션 서버 (Web Application Server)

 

 웹 서버와 웹 컨테이너가 합쳐진 형태.

인터넷 상에서 HTTP를 통해 어플리케이션을 수행해 준다. 동적 서버 콘텐츠를 수행하는 것으로 일반적인 웹 서버와 구별이 되며 주로 데이터베이스 서버와 같이 수행이 된다. 


 대표적으로 톰캣 BEA사의 Web Logic, IBM사의 Web Sphere, T-max사의 Jeus, Redhot사의 JBoss 등이 있다.

  웹 서버와 WAS는 동적 컨텐츠를 직접 수행할 수 있는가? 로 차이점을 둘 수 있겠다.



그럼 WAS 만 쓰면 되지 않는가???? 


 많이 쓰는 아파치 톰캣으로 설명 하겠다.

WAS 에는 웹 서버와 웹 컨테이너가  모두 있어 문제가 없어보인다. 하지만 과거 톰캣5.5 이하때는 WAS 가 단독으로 정적,동적 처리를 하면 부하가 많이 걸려 서버의 부담이 늘어 속도 저하가 있었다. 그래서 대규모의 서버는 톰캣을 단독으로 사용하지 않고 아파치를 앞에 두었다. 

 하지만 5.5버전 이상의 톰캣은 httpd의 native 모듈을 사용하여 정적인 페이지를 처리하는 기능을 제공하기에 완전히 아파치와 동급의 속도를 자랑한다. 그러면 단독으로 써도 되지 않는가????


 답은 아니다.

톰캣은 특성상 java언어만 해석 가능하기 때문에 JSP같은경우 처리를 하지만 PHP는 실행이 불가능하다. 따라서 하나의 서버에서 JSP PHP를 모두 사용하고 싶다면 아파치와 톰캣 모두 사용해야 한다.


++로드밸런싱을 위해서도 같이 사용한다는데 추후 알아볼예정




참고

http://limmmee.tistory.com/4

http://reizeo.tistory.com/entry/%EC%9B%B9%EC%84%9C%EB%B2%84WebServer-%EC%9B%B9%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88WebContainer-%EC%9B%B9%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%84%9C%EB%B2%84Web-Application-Server-%EC%9B%B9%EC%84%9C%EB%B2%84%EC%99%80-%EC%9B%B9%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%9C%EB%B2%84%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90?category=300418

http://jeong-pro.tistory.com/84

http://gap85.tistory.com/entry/WAS-%EC%99%80-%EC%9B%B9%EC%84%9C%EB%B2%84-%EC%9D%98-%EC%B0%A8%EC%9D%B4

http://hyoje420.tistory.com/5




'개념' 카테고리의 다른 글

[Windows10] 윈도우10 hosts파일 수정하기  (0) 2019.01.22
Jsp Php Asp ?  (1) 2018.07.27
TCP 3 Way-Handshake  (0) 2018.06.27
유니코드와 utf-8 utf-16  (3) 2018.06.26
Base64  (0) 2018.06.26

 Call by value, Call by reference ?

 

 위 두 내용은 메소드(함수)에서 인자값을 받을 때 어떤식으로 받아 올 것 인지에 대한 방식이다.

 뜻 그대로 '값에 의한 호출' 그리고 '참조에 의한 호출' 인데 그 내용은 예시를 들어 설명해보겠다.


 

 Call by value


메소드 호출 시에 사용되는 인자의 메모리에 저장되어 있는 값(value)을 복사하여 보낸다.

무슨 뜻이냐면 int a =3 이라는 문구가 있으면 

메소드에서 인자값을 받을 때 a라는 자체에 주소를 받는게 아니라 a의 값인 3을 받아 처리하는 방식이다.


 Call by reference


메소드 호출 시 사용되는 인자 값의 메모리에 저장되어있는 주소(Address)를 복사하여 보낸다.

값이 아니라 인자 그자체에 주소 값을 보낸다. 




결론을 먼저 말하자면 자바는 Call by value  방식으로 인자값을 받는다.





결과 값은 이렇다
비포
안녕잘가
에프터
안녕잘가


 왜 스왑 메소드를 이용해서 서로를 바꿔준 것 같지만 바뀌지 않았을까?? Call by value 방식이기 때문이다. 

스왑 메소드가 받는 두 인자는 인자값에 주소 즉 인자 그자체를 받는 것이 아니라 인자의 값을 복사해서 받는다.

즉 String one 에는 a에 값인 "안녕" 에 값이 (String 은 참조 변수 이므로 "안녕" 에 주소 값이 복사)

마찬가지로 two 에도 b의 주소가아닌 b값에 주소가 복사 되어진다.




 이렇게 메인 메소드의 a, b와 swapS 메소드의 one two는 서로 같은 값을 참조할 뿐 이다.

 이렇게 메소드 내에서는 변화가 이루어 지지만 메소드가 닫히면 swapS에 있던 정보는 다 사라지므로 메인 메소드에 영향을 주지 못한다.

만약 위 코드에 있는 //주석문을 활성화 시키면 바뀐 값을 출력 할 것이다.



 만약 call by Reference 방식 이였으면 메소드내에서 one two가 a, b의 주소값을 받아 곧 a=one b=two 이고 메소드 수행으로 서로값이 바뀌니 메소드 수행을 하고 나서도 a, b가 바뀌어 있을 것이다. 



하지만 이러한 효과를 내는 방법은 있다.





swap() 호출 전 : a = 10, b = 20

swap() 호출 전 : a = 20, b = 10


이렇게 값이 바뀌는 걸 볼 수 있다.


그림으로 보자

 

마찬가지로 one과 two는 값의 주소를(call by value) 복사받아 같은 인스턴스를 참조하는 것 이지만..



이렇게 참조 되어지는 값을 바꾸어 주어 마치 call by reference 가 이루어진 것 처럼 보인다.


비슷한 예로 


1 8
8 1

이렇게 가르키고 있는 공간의 값을 바꾸어 주면 된다.




정리하자면 !!

자바는 !

기본형 타입 변수와 참조형 타입 변수가 있는데 

둘 다! 상관없이 call by value 방식으로 메소드에서 받아진다 !


대신 기본형 타입은 그 값을 복사 해서 주지만

참조형 타입은 값의 래퍼런스(주소)가 저장되는 것이므로 그 값의  래퍼런스가 복사 되어진다 !


즉 값의 래퍼런스가 call by value 방식으로 넘어간다!.


말이 긴데 어찌되었든 call by value 방식이다 자바는..



참조

http://hyoje420.tistory.com/6

http://re-build.tistory.com/3#comment14570096

http://purple-dev.tistory.com/36

https://brunch.co.kr/@kd4/2

https://muckycode.blogspot.com/2017/07/java-paratmeter-call-by-reference-vs.html

http://history1994.tistory.com/8?category=668240

+ Recent posts