레이블이 CAST연산인 게시물을 표시합니다. 모든 게시물 표시
레이블이 CAST연산인 게시물을 표시합니다. 모든 게시물 표시

2013년 8월 9일 금요일

[오라클자바커뮤니티, 자바닷넷강좌]Object Oriented 객체 지향 이란?(이론)

-------------------
객체 지향 패러다임
------------------- 

오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  


 
S/W개발을 기능별로 나누는 것이 아니라 객체 단위로 분리하는 것. 객체지향 기법은 data(객체)를 중심으로 system을 바라보고 이를 system 개발에 적용하겠다는 것

객체란 데이터와 그 데이터를 처리하는 여러 개의 기능들을 하나의 단위로 묶은 것으로, 외부에 블랙박스 형태로 보인다. 즉 입력과 출력 부분만이 노출이 되고 내부적인 처리 과정은 완전히 밀폐되어 있으며, 외부에서 알 필요도 없는 것

소프트웨어 공학과 프로그래밍 언어에 관한 이론 중에서 객체지향적 분석(Object-Oriented Analysis)이나 객체지향적 설계(Object-Oriented Design) 그리고 객체지향 프로그래밍 언어(Objected-Oriented Language)와 같이 객체지향에 관련된 모든 것을 통틀어 말한다

기존의 프로시저 기반의 구조적 프로그래밍(C나 Pascal과 같은 명령형 패러다임)에서는 프로그램 내에서 일어나는 모든 변화와 동작, 사건 등을 프로그래머가 직접 기술하는 형태로 프로그램을 기술했지만 객체지향 프로그래밍에서는 똑똑한 객체에게 자신이 원하는 일을 해달라는 메시지를 전달하는 형태로 프로그램을 기술한다

기존 시스템들은 절차 중심적으로 개발되어진 경우가 많아서 유지 보수 단계에서 많은 어려움을 겪고 있는 반면, 객체 지향 패러다임은 재사용성, 확장성 등의 특성을 내포하고 있어 유지 보수 단계를 용이하게 해 준다.

객체들 사이의 인터페이스를 위해 사건(또는 메시지)들을 주고받는데 기존의 방법보다 더 실행 시간을 요할 수 있다. 깊은 클래스 계층 구조가 있는 경우와 system 작동 중 객체에 대한 동적 할당과 제어시 성능에 대한 문제가 제기될 수도 있다.

객체지향 기법은 data보다는 성능을 중요시하며, 많은 계산을 요하는 system에서는 적합지 않을 수 있다. 실시간 반응을 해야하는 system의 경우 객체지향 기법을 적용하는 것이 이를 통해 얻을 수 있는 이점보다 성능 등에 대한 부담이 높아져 허용되는 한계(예: 반응시간) 를 넘을 수도 있다. 군사용 미사일 제어 system이나 병원의 환자 상태 관리 system 등이 그 예가 될 수 있다.

컴포넌트가 21세기 정보기술(IT) 산업의 지각변동을 몰고 올 새로운 패러다임으로 급부상하고 있다.

SW를 이제까지처럼 계획, 설계, 분석, 구현, 테스트하는 순차적인 개발과정으로 보는 것이 아니라 레고블록이나 자동차 부품처럼 조립하는 개념으로 간주하며 컴포넌트 SW는 레고블록을 쌓는 것처럼 일단 표준화된 프레임워크와 규칙을 기반으로 만들어진 기능별 SW를 필요한대로 조립하면 원하는 SW를 만들 수 있다. 개발이나 유지보수에도 특별한 노력이 요구되지 않으며 표준화, 규격화를 지향하기 때문에 SW 품질도 눈에 띄게 좋아진다.

현재 국내 신생업체들을 중심으로 자바 컴포넌트 기술을 이용해 상용 애플리케이션을 개발하는 사례가 늘고 있으며 특히 전사적자원관리(ERP) 시스템에서부터 개발툴, XML 솔루션, 검색엔진, 통신용 SW, 인터넷 구축툴, 언어처리 모듈, 지식관리(KM), 고객관리(CRM) 등의 분야에 이르기까지 다양한 분야에서 개발이 진행되고 있다.

컴포넌트의 특장점은 인터넷이라는 환경의 부상으로 더욱 강력한 위치를 차지하게 됐다. 인터넷은 모든 업무를 빠르게 변화시키고 있으며 표준화할 것을 요구하고 있으며 이러한 업무를 지원하는 SW 및 정보시스템도 표준에 기반해 빠른 변화를 수용해야만 하는데 이러한 요구에 가장 부합하는 것이 바로 컴포넌트 개념이다.

Object : 시스템의 관점에서 본다면 어떤 상태(state)를 나타내는 데이터의 구조와 동작을 수행하는 연산(operation)으로 이루어진 프로그램의 한 요소이다. 여기서의 연산을 객체지향에선 메소드(method)라고 한다. 이렇게 객체의 상태는 데이터에 의해 결정되고 동작은 메소드에 의해 결정된다.

Message : 홀로 존재하는 객체는 아무런 의미가 없다. 대부분의 객체는 무언가를 실행하기 위해서 다른 객체를 필요로 한다. 이러한 상호 작용은 메시지를 통해 이루어진다.

Class : 모든 객체는 반드시 클래스를 통해서만 정의될 수 있다. 클래스는 객체의 타입을 정의하는 템플릿(template)으로서, 여러 객체의 공통적인 속성(attribute)과 메소드(method)를 가지고 있는 클래스가 먼저 정의되면, 이 클래스를 통해서 다시 객체가 정의되는 것이다.한 클래스에 속하는 각각의 객체를 그 클래스의 인스턴스(instance)라고 한다.


클래스(Class)
어떤 종류의 모든 객체들에 대해 일반적으로 적용할수 있는 변수와 메소드를 정의하고 있는 설계도 또는 프로토타입 이다.
사용자 정의 자료형, 객체의 자료형
Field라는 변수와 오퍼레이션을 가하는 method 로 이루어짐
클래스의 이름은 대문자로 시작, 다음 단어의 시작은 대문자

객체(Object)
클래스의 인스턴스는 new 수식에 의해 만들어지며 이것이 객체이다.
타입이 클래스인 변수
이름은 소문자로 시작, 다음 단어의 시작은 대문자


•추상 데이타 타입(ADT;abstract data type)
–클래스를 이용하여 표현

•상속(inheritance)
–동적 바인딩(dynamic binding) cf) Static binding
–한 클래스를 확장하여 새로운 클래스를 만드는 것을 말한다. 이렇게 새로 만들어지는 클래스를 하위클래스(SubClass)라고 부른다. 그리고 원래의 클래스는 상위클래스(SuperClass)라고 부른다.
–자바의 모든 클래스는 상속의 대상이 되는 상위클래스(SuperClass)가 반드시 하나 존재한다
–프로그램의 재사용성과 확장성을 높인다.
–하위 클래스는 상속된 필드와 메쏘드 중에 private으로 선언된 것이 아닌 것에만 접근할 수 있다.



객체지향의 핵심 내용

연관(Association)
객체 또는 클래스가 다른 객체 또는 클래스와 ‘어떤 의미의’ 관계를 가질 수 있다.

집합연관(Aggregation)
순수 연관(Association)은 두 동료 클래스, 객체간의 구조적 관계
하나의 객체가 다른 객체들의 조합에 의해 만들어 짐
전체/부분 관계를 모델링 하는 경우 한 클래스는 더 큰 것을(“전체”) 대표하고 그것은 더 작은 것들(“부분”)로 이루어져 있다. Ex)회사와 부서의 관계
전체”와 “부분”의 개념적 관계(“whole-part of”)
Component는 집합체와는 별개로 독립적으로 존재 할 수 있다.(nonexclusive ownership )


복합연관(Composition)
단순한 집합연관은 전적으로 개념적이며 “전체” 와 “부분”을 구분 하는 것 이상의 어떤 것도 수행하지 않는다.
일종의 집합연관으로 전체는 강력한 소유권을 가지며  부분/전체는 동시적 일생을 산다.(“cascading delete”)
(Window : Frame, 책상 : 서랍, 책상 : 다리)
전체는 부분에 대한 책임을 진다. 바꿔 말하면 전체는 부분을 생성시키고 소멸시킨다.
“부분”은 어느 시점에 하나의 “전체”에 속한다.
Component는 집합체와는 별개로 독립적으로 존재 할 수 없다.(exclusive ownership )
전체의 다중성은 0 또는 1(0..1), 부분의 경우는  어느것이 와도 관계 없다(0..*)



상속과 Composition
상속과 컴포지션은 동전의 양면과 같이 유사하게 서로에게 관련이 있다.
상속은 마치 양파가 여러 껍질로 이루어진 것과 같이 계층화된 객체
컴포지션은 여러 재료(객체)가 한데 뭉쳐서 만들어진 죽
컴포지션은 개체들간의 'has a' 관계, 상속은 ‘is a’관계
상속과 컴포지션은 상호 배타적이지 않으며 개발자는 이 둘을 같이 사용한다.


다형성
•다형성(polymorphism)
–상속을 받은 것을 그대로 사용하지 않고 입맛에 맞게 바꾸어 줄 수 있도록 하는 것
–다형성을 위해 자바에서는 메소드 overriding 과 메소드 overloading을 제공 한다.
–상속계층 상에서 어떤 객체의 어느 메소드를 호출할 것인지를 결정하는 객체의 능력을 다형성 이라 한다.
–사인곡선을 그리는 함수가 있다고 할 때 사용자는 파라미터로 radian이나 degree값을 넣게 되지만 둘 다 처리할 수 있다. 이것은 sine(int degrees)나 sine(float Radians)와 같이 동일 이름의 함수가 다른 파라미터로 두 번 선언되었기 때문이다.


다형성(polymorphism)
Overloading : 동일한 함수의 이름 사용 가능, 같은 클래스 내에 같은 이름의 생성자나 메소드를 사용하는 행위,매개변수의 개수와 타입이 달라야 한다

Overriding : 상위 클래스에서 정의된 함수를 하위 클래스에서 재 정의, 기존 클래스의 메소드 구현 부분만 약간 변화시켜 새로운 클래스를 생성할 수 있다. 매개변수의 개수와 타입이 같아야 한다.
 
상위 클래스로부터 메소드를 상속받을 때, 서브클래스 내에 같은 이름의 메소드가 있는 경우에 Signature가 다르면 중복(overloading)이 되고 Signature가 같으면 재정의(overriding)가 된다.

Template : 타입을 인자로 하여 새로운 타입을 생성



캡슐화(encapsulation)
객체는 자신이 수행하는 모든 행동과 속성을 다른 객체와 외부 세계에는 보이지 않는다
객체 자신의 Operation을 수행하고 결과를 내놓지만 그 Operation의 동작 원리는 숨기는 것이다.
높은 모듈성과 정보은닉을 제공



추상클래스
추상클래스는 어떠한 클래스를 만들기 위해 미리 정의해 둔 클래스의 틀을 의미한다. 앞에서 작성한 Employee(직원)클래스와 직원의 하위 클래스를 예로 든다면 직원이라는 클래스는 프로그래머(Programmer), 디자이너(Designer), 프로그램팀장(ProgrammerChief)등을 만들기 위해 작성된 클래스라고 할 수 있다. 사실 직원이라는 클래스는 실제 회사의 프로그램을 개발한다고 했을 때 사용해서는 안되는 클래스라고 할 수 있다. 왜냐하면 A라는 회사에 직원 중 어느 부서에 해당되지 않고 자기 마음대로 회사를 출근하고 퇴근하는 직원은 존재하지 않을 것이기 때문이다. 하지만 Employee 라는 클래스가 존재하는 이상 일반 사용자에게 메뉴얼을 작성해 “Employee 클래스는 다른 특정직원 클래스를 만들기 위한 클래스입니다.”라고 하기 전에는 Employee의 본래의미를 모르고 Employee 의 객체를 생성하여 사용할 수 있다. 물론 이 것은 원래 개발을 한 개발자의 의도와는 상관이 없는 잘못된 사용이지만 이를 막을 수 없는 것이다. 즉 다음과 같은 소스 코딩을 막을 수 없다.
        Employee s1 = new Employee("홍길동", “12345");     
        s1.gotoTheOffice();

만약 Employee 클래스는 사용하기 보다는 다른 클래스에 상속되여 새로운 직원 클래스를 만드는 것이 바람직하다는 의미를 소스 코드에 부여한다면 개발자의 Employee 클래스 개발 의도를 사용자가 쉽게 알 수 있게 될 것이다. 이 때 사용되는 키워드가 abstract 키워드이다. 이 키워드가 클래스에 붙으면 이 클래스는 추상클래스라는 의미이다.


앞서 작성한 Emplopyee 클래스에는 없지만 이를 상속받은 모든 클래스에서 정의하고 재정의하여 사용하고 있는 startJob 이라는 메소드를 Employee에서 추상메소드로 선언하여 정의할 수 있다
       
상속의 개념으로만 본다면 이러한 추상클래스는 굳이 만들 필요가 없다. 추상클래스가 아니더라도 위와 같은 상속과 메소드의 재정의는 얼마든지 가능하기 때문이다. 하지만 수퍼타입(super type)을 이용한 다형성(Polymorphism)의 측면에서 추상클래스(Abstract Class)는 유용하게 쓰일 수 있다.
       
A라는 직원이 회사에 입사했는데 처음에는 디자인팀에 있다가 얼마 후 프로그램개발팀로 소속을 옮기게 되었다. 그러다가 경력을 쌓아 프로그램개발팀장으로 까지 진급하게 되었다. 이렇게 한 사람의 직원은 시간에 따라 때로는 상황에 따라 여러가지 모습으로, 여러가지 업무를 담당하게 된다. 바로 이런 것을 가능하도록 객체를 설계하는 것이 바로 다형성의 구현이다. 즉 실생활의 회사 직원처럼 상황과 시간에 따라 여러가지 모습을 지니는 다형성을 구현할 수 있게 되는 것이다. 모든 직원의 하위클래스들을 수퍼 타입(상위클래스)로 형변환하면 가능하다.

클래스는 필드로 기본자료형, 클래스 등이 올 수 있지만 인터페이스는 int, double 등의 기본 자료형만이 필드로 사용될 수 있다. 또한 각 필드는 반드시 초기화가 되어야 한다. 초기화가 되어야 하는 이유는 인터페이스의 필드는 암시적으로 final과 static이 설정되어 있기 때문이다.

        int maxSmall = 5  à static final int maxSmall = 5;

인터페이스는 메소드를 선언만 하고 구현하지는 않는다. 그리고 인터페이스의 모든 메소드는 접근지정이 기본적으로 public으로 설정된다. 그리고 모든 메소드는 추상메소드이다. 즉 아래의 void driveSmallCar();라는 선언은 암시적으로 설정되는 public과 abstract 키워드를 추가하면 다음과. 같이 선언되어 있는 것과 같다.

                public abstract void driveSmallCar();

인터페이스
추상메소드로 이루어진 클래스라 할 수있다.
Interface와 구현(implementation)의 분리
다중상속의 일부 기능 지원(한가지 인터페이스로 여러 구현을 실행할 수 있다)
인터페이스의 모든 메소드는 자동적으로 public abstract이다
인터페이스의 모든 변수는 자동적으로 public static final이다.
객체의 Instance를 생성할 수 없음
메소드의 구현을 갖지 않으며, 몸체부분은 세미콜론으로 대체된다.
클래스가 인터페이스를 구현하게 되면 인터페이스 내에 정의된 상수는 상속된 것 처럼 직접 사용할 수 있다.


인터페이스와 추상 클래스
추상메소드를 가지고 있고 이를 상속받거나 구현하는 클래스는 이 추상 메소드를 재정의하고 구현해야 한다는 점, 그리고 다형성을 구현하는 방법이라는 점, 메소드들이 동적으로 바인딩 된다는 점들은 비슷하다.
       
차이점
- 인터페이스는 서로 연관성이 없는 클래스들에 의해 구현될 수 있고 따라서 수평적인 구현이 가능하지만 추상클래스의 경우 단일 상속 개념 하에 수직적인 구조로 상속을 해야만 한다.

- 인터페이스에서는 메소드를 선언만 할 수 있으며 구현할 수 없다. 그리고 이 구현은 인터페이스를 구현하도록 설정된 클래스에서 가능하다. 하지만 추상클래스의 경우에는 추상 클래스 내부에서 메소드의 선언과 구현이 모두 가능하며 또한 이를 상속 받은 클래스에서도 재정의가 가능하다.

[오라클자밭커뮤니티자바닷넷교육]C#연산자(Operators)

이번 강좌에서는 C#에서 사용 되어지는 연산자에 대해 알아 보도록 하겠습니다.

아래는 C#의 연산자 목록 입니다.

오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  





구분 연산자
기본 연산자 (x), ., f(x), a[x], x++, x--, new, typeof, sizeof, checked, unchecked
단항 연산자 +, -, !, ~, ++x, --x
산술 연산자 +, -, *, /, %
쉬프트 연산자 <><, >>
비교 연산자 <, >, <=, >=, is
비트 연산자 &, ^, |
논리 연산자 &&, ||
조건 연산자 ?:
할당 연산자 =, *=, /=, %=, +=, -=, <><=, >>=, &=, ^=, |=
연산자 이름 의미
(x) 괄호 연산의 우선순위 명시
x.y 클래스의 메소드나 속성
f() 메소드괄호 메소드의 인자를 괄호안에 넣는다
a[x] 대괄호 배열이나 인덱서의 인덱스
checked 형변환시 오버플로우를 체크
unchecked 형변환시 오버플로우 체크 않음
typeof() 객체에 대한 정보를 얻음 ( 리플렉션참고 )
sizeof() 객체의 크기를 얻음

산술연산자( Mathematical operators)
Operator Description
= Assignment operator
+= a+=b is equivalent to a = a + b
-= a-=b is equivalent to a = a – b
*= a*=b is equivalent to a = a * b
/= a/=b is equivalent to a = a / b
%= a%=b is equivalent to a = a % b
<><= > a<><=b is equivalent to a = a <>< b
>>= a>>=b is equivalent to a = a >> b
&= a&=b is equivalent to a = a & b
^= a^=b is equivalent to a = a ^ b
|= a|=b is equivalent to a = a | b

관계 연산자(Relational operators)
Operator Description
== Equals
!= Not equal to
< > Less than
<= Less than or equal to
> Greater than
>= Greater than or equal to
예)if (x == 2.0 && y != 4.0) { // do some stuff }

논리연산자(Logical Operators)
Operator Description
& Bitwise AND
| Bitwise OR
^ Bitwise exclusive OR
&& Logical AND
|| Logical OR
! Not
?: Ternary
&& 는 AND, || 는 OR l ^ 는 XOR, ! 는 NOT 의 의미
하나짜리는 비트연산자로서 l & 는 AND, | 는 OR l ^ 는 XOR, ~ 는 NOT 의 의미 입니다.
예) a = b
if (b
[참고하세요]
X &&Y 의 경우 X 가 false 이면 더 이상 Y 를 계산하지 않아도 false 임을 아니까 false 로 결정된다 . 결국 X가 true 일때만 Y 를 계산 하는 겁니다.
X || Y 의 경우 X가 true 이면 더 이상 Y 를 계산하지 않고 true로 결정 합니다. 또한 X 가 false 인 경우에만 Y 를 계산 합니다.
X|Y 나 X &Y 의 경우 X 값에 관계없이 B와 같이 계산 한 후에 true, false를 결정 합니다.
할당연산자( Assignment operators )
Operator Description
= Assignment operator
+= a+=b is equivalent to a = a + b
-= a-=b is equivalent to a = a – b
*= a*=b is equivalent to a = a * b
/= a/=b is equivalent to a = a / b
%= a%=b is equivalent to a = a % b
<><= a<><=b is equivalent to a = a <>< b
>>= a>>=b is equivalent to a = a >> b
&= a&=b is equivalent to a = a & b
^= a^=b is equivalent to a = a ^ b
|= a|=b is equivalent to a = a | b
x <>< 4 --> 왼쪽으로 4 bit shift 1bit shift 마다 값이 2 배씩 증가
x >> 4 --> 오른쪽으로 4 bit shift 1bit shift 마다 값이 1/2 배씩 감소
[아래의 예제를 따라 해 보세요]
using System;
public class Bitoper
{
public static void Main(string[] args)
{
int i = 16;
int j = 64;
int k;
k = i & j; //i와 j를 비트 연산
i = i >>3; //i를 3비트 우쉬프트
j = i<><3; //i를 3비트 좌쉬프트
Console.WriteLine("k={0}, i={1}, j={2}", k,i,j);
Console.ReadLine();
}
}
[결과]
k=0, i=2, j=16

객체 연산자( Object operators )
Operator Description
() Type cast operator.
[] Accesses an element of an array or collection, or is the indexer operator.
typeof Returns type of object or if the argument is a primitive the primitive type of the argument is returned.
sizeof Struct size retrieval.
. Member access.
is Object comparison
as Performs object downcast.
new Calls a constructor. For a reference type, a new object is allocated on the heap. For a value type, the fields of the value type are initialized to their default values.
is operator - determine if an object derives from another class (다른 클래스로 부터 파생 되었는지 확인하는 연산자, 파생되었다는 이야기는 하위클래스라는 이야기임.. 이부분은 객체 지향을 공부 하신후 다시 확인 바랍니다.)
if ( a is bird ) b = (bird) a; //safe
else Console.WriteLine("Not a Bird");
as operator - object “downcasts” (두개의 Reference-Type을 casting 하는 것처럼 형병환을 합니다. 변환이 되면 변환 된것을 넘겨주고 변환이 안되면 null을 돌려 줍니다. 이 부분 역시 객체 지향을 공부 하신후 다시 확인 바랍니다.)
Bird b = a as Bird; //a를 Bird로 변환을 시도하여 변환이 되면 변환된것을 b에 돌려주고 아니면 null을 돌린다.
if ( b == null ) Console.WriteLine("Not a Bird");
sizeof 연산자
주어진 데이터 형식의 크기를 byte 단위로 돌려 줍니다.
제약사항 --> sizeof 연산이 가능한 형식은 값 형식인 경우int, float, enum, struct등이 있습니다.

일반연산자( Miscellaneous operators )
Operator Description
checked Arithmetic checking turned on
unchecked Arithmetic checking turned off
어렵지 않습니다. 다음 예를 이해하도록 하죠~
checked {
int number = int.MaxValue;
Console.WriteLine(++number);
}
위예제에서는 Overflow 체크를 한다는 이야기 입니다. 즉 OverfloException이 발생 합니다. 물론 컴파일은 됩니다. 런타임중 예외가 발생한다는 이야기 입니다.
unchecked {
int number = int.MaxValue;
Console.WriteLine(++number);
}
위의 예제는 오버플로우 체크를 하지 않겠다는 의미 이므로 정수형의 최대갑에다 1을 더하니까 2의 보수 표현에 의해 -값으로 바뀌게 됩니다. 



[OracleJava Community, 오라클자바커뮤니티닷넷교육].NET Framework CTS

이번 강좌에서는 C#에서의 변수에 대해 알아 보자구요~ 크게 두가지 정도로 구분 합니다. 실제 그값을 가지고 있는 Value-Type , 가지고 있는것이 값이 아니고 무언가를 참조하는(포인터 변수처럼) 변수인 Reference-Type 두가지로 구분 합니다. 먼저 그러한 데이터 타입을 제공하는 닷넷 프레임웍의 CTS(Common Type System) 에 대해 알아 보도록 하겠습니다.



오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  




----------------------------
CTS(Common Type System
----------------------------

• CTS supports object-oriented and Procedural languages.
• CTS supports both value and reference types

좀더 알아보면 CTS 는 닷넷 프레임워크에서 동작하는 모든 프로그래밍 언어(C#, VB.Net, J#)들이 쪽같은 데이터형식을 사용하도록 해주는 것입니다.
(System.Int32라는 클래스는 CTS에서 제공하는 int 형입니다. 이것은 닷넷에서의 어떠한 개발언어에서도 사용이 가능 합니다.)
모든 데이터형식들은 기본적으로 객체에서 파생되었으며 Value type 은 객체 형식을 포장 (sealing) 해 놓은 개념 입니다.


-----------------------------
Value-Type, Reference-Type
-----------------------------

Value-Type
CTS 에서는 value type 과 reference type 을 지원하는데 Value type 변수들은 데이터를 직접 가지고 있습니다 .예를들어 int i=10 이라고 쓰면 i 변수에는 10 이 직접 들어 있는 것입니다. int j=i 라고 하면 i 의 값이 j에 복사되어 들어 가는 것입니다.(다아시는거죠^^), 자바에서의 기본 자료형과 같은 겁니다. Value-Type은 Built-in Type과 User-Defined Type 두가지가 있습니다. int, long, float, double 등은 Built-in Type 이고 struct, enum등은 User-Defined Type 입니다.

Reference-Type
데이터를 직접 저장하는 것이 아니라 레퍼런스(참조값)을 저장 합니다.(Store references to their data) 그러므로 두개의 레퍼런스형 변수는 같은 데이터(오브젝트)를 지칭하는 것이 가능 합니다.( Two reference variables can reference same object) 물론 같은 것을 서로 쳐다 볼수 있으므로 한쪽에서 변경을 하면 다른쪽은 스스로 변경을 안했어도 나중에 값을 꺼내 보면 당연히 바뀌어져 있겠죠^^;(Operations on one can affect another)

-------------------------------
Built-in Data Type
-------------------------------
정수형
예약어구조체형식크기 (Bit)범위
sbyteSystem.Sbyte8-128~127
byteSystem.Byte80~255
shortSystem.Int1616-32,768~32,767
ushortSystem.UInt16160~65,535
intSystem.Int3232-2,147,483,648 ~2,147,483,647
uintSysten.UInt32320~4,294,967,295
longSystem.Int6464-(2^63) ~ 2^63-1
ulongSystem.UInt64640~ 2^64-1

실수형, 기타
예약어구조체형식크기 (Bit)범위
실수형
floatSystem.Single321.5x10^-46 ~3.4x10^38 
doubleSystem.Double645.0x10^-324 ~1.7x10^308
decimalSystem.Decimal1281.0x10^-28 ~7.9x10^28 
기타
charSystem.UInt1616유니코드 1 자
boolSystem.Int3210 또는 1

Boolean 
boolean type 이 가질 수 있는 값은 true 와 false 입니다. 예 ) bool b = true --> true 는 1 과는 다르며 , 마찬가지로 false 는 0 과는 다릅니다. (C 에서는 TRUE, FALSE 를 #define 을 통해 정의하여 사용 했었습니다.. 정수를 암묵적으로 boolean 형으로 사용한 것이죠.), true 와 false 로 산술 연산을 할 수 없으며 오로지 논리 연산자를 가진 수식에 대해서만 사용가능 합니다.

변수 선언 하는 방법
int itemCount;
int itemCount , employeNumber; ( Possible to declare Multiple variables in one)
int employeeNumber; employeeNumber = 23;
int employeeNumber= 23;
또한 Charater형은 다음과 같이 선언 합니다. char middleInitial= ‘J'; C#은 유니코드를 사용하며 char형은 한 문자를 저장하는데 사용 합니다.
Itemcount = Itemcount + 40; --> ItemCount += 40; --> 이건 다아시죠...

연산자(Operator)
구분연산자
기본 연산자(x), ., f(x), a[x], x++, x--, new, typeof, sizeof, checked, unchecked
단항 연산자+, -, !, ~, ++x, --x
산술 연산자+, -, *, /, %
쉬프트 연산자<><, >>
비교 연산자<, >, <=, >=, is
비트 연산자&, ^, |
논리 연산자&&, ||
조건 연산자?:
할당 연산자=, *=, /=, %=, +=, -=, <><=, >>=, &=, ^=, |=

[isOperator 예제] is연산자는 런타임시 주어진 타입과 객체가 서로 호환이 되는지를 검사하는 연산자 입니다. 또한 as 연산자는 Type을 변환하는데 변환이 되면 변환 시키고 변환이 안되면 NULL을 돌려 줍니다...(참고하세요~)
//is 연산자 예제
using System;
class isOperator {
static void Main() {
//C#은 모든 타입을 객체로 처리한다.
//System.Int32의 BaseType은 System.ValueType이다.
//System.Object > System.ValueType > System.Int32
int i=0;
object o;
Console.WriteLine("i is int? {0}", i is int);
Console.WriteLine("i is long? {0}", i is long);
if (i is object) {
o = i;
Console.WriteLine("o의 Base Type은 " + o.GetType().BaseType);
}
}
}

---------------------------------------------
모든 Object(객체)들이 가지는 메소드
---------------------------------------------
객체 지향 프로그래밍을 하는것은 객체를 많이 다른다는 이야기 입니다. 이번에는 참고로 모든 객체들이 가지고 있는 기본적인 메소드가 어떤것이 있는지 필요한것만 보도록 하겠습니다. 닷넷에서는 System.Object가 모든 객체의 최상위 클래스 입니다. (물론 자바에선 java.lang.Object 입니다.)
메소드명설명
bool Equals()같은 객체인지 비교, 동일한 메모리 공간을 차지해야...
int GetHashCode()해쉬값을 얻음
Type GetType()Type 에 관한 정보(형식 정보)를 돌려 줍니다.
string ToString()객체를 대표하는 문자열 반환, 일반적으로 문자열로 변환한다고 보면 됩니다.

2013년 8월 8일 목요일

[오라클교육,자바교육,오라클자바커뮤니티]JAVA AWT 배치관리자(Layout Manager)

-----------------------------
배치관리자(Layout Manager)
-----------------------------

오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  



Component가 컨테이너에 배열되는 방식을 결정 합니다.
모든 컨테이너는 기본 Layout Manager를 가집니다.
Container는 다른 Component를 포함할 수 있는 최소의 클래스이고 java.awt.container 클래스를 상속해야 합니다.
Container를 상속하지 않은 일반 Component에는 Layout Manager가 등록될 수 없습니다.
Frame, Window, Panel등은 Layout Manager를 설정할 수 있으며 이렇게 설정된 Layout Manager는 화면의 크기가 바뀌거나, Component가 추가 되거나 제거 되었을 경우에 호출 됩니다.(이경우 즉시 다시 배치하지 않으며 Layout을 다시 그릴 필요가 있다는것을 표시한 후 validate함수가 호출되거나 화면이 다시 그려지는 경우에 다시 배치 작업을 수행 합니다. 따라서 Layout Manager를 설치후 즉시 효과를 볼려면 validate를 호출해야 합니다. Invalidate 함수는 특정 Component가 화면에 다시 배치해야 된다고 표시하는 것 입니다.
Layout Manager를 이용하는 경우에 수동으로 Component를 배치하는것이 소용 없습니다. 화면에 표시 될때 Layout Manager가 다시 위치, 크기등을 결정하기 때문 입니다. 수동으로 Layout을 설정하는 경우엔 위치, 크기등을 정해 주어야 하며 그렇지 않은 경우엔 초기 위치, 쿠기등이 정해지지 않으며 보통 화면에 나타나지 않습니다.
Layout Manager를 이용할 경우 크기지정이 유효한 경우는 Window, Frame등과 같은 최상위 Container 입니다.

수동으로 Component 배치하기
주로 소량의 정보를 보이거나 간단한 사용자 입력을 받는 Container에 사용 됩니다.
컨테이너에 설정해야 하는것들…
- 컨테이너의 크기를 고정 시킵니다.(Frame의 경우 setResizable)
- 컨테이너의 Layout Manager를 null로 한다. setLatout을 이용하며 Frame, Panel과 같은 기본 Layout Manager를 가지기 때문에 반드시 이과정을 수행해야 합니다.
- 컨테이너의 크기를 지정 합니다. (자식 컴포넌트의 크기, 위치를 수동으로 주는 경우 상의 컨테이너의 크기도 수동으로 지정해야 합니다. setSize, setBounds 등이용)

[예제]
import java.awt.*;
public class LayoutNull {
public static void main(String[] args) {
Button btn1, btn2, btn3;
Frame myWindow = new Frame("Null Layout");
myWindow.setResizable(false);
myWindow.setLayout(null);
myWindow.setSize(300, 300);
btn1 = new Button("버튼1"); btn1.setBounds(40,50,50,20);
btn2 = new Button("버튼2"); btn2.setBounds(100,50,50,20);
btn3 = new Button("버튼3"); btn3.setBounds(160,50,50,20);
myWindow.add(btn1); myWindow.add(btn2); myWindow.add(btn3);
myWindow.setVisible(true);
}
}

[결과]


인터페이스 java.awt.LayoutManager
컨테이너를 배치하는 클래스의 인터페이스를 정의 합니다.
addLayoutComponent(String, Component) : 지정된 이름을 가진 지정된 컴포넌트를 배치에 추가
layoutContainer(Container) : 지정된 패널에 컨테이너를 배치
minimumLayoutSize(Container) : 지정된 상위 컨테이너에서 컴포넌트를 받은 지정된 패널의 최소 크기를 계산
preferredLayoutSize(Container) : 지정된 상위 컨테이너에서 컴포넌트를 받은 지정된 패널의 환경설정된 크기를 계산
removeLayoutComponent(Component) : 배치에서 지정된 컴포넌트를 제거
LayoutManager2를 구현하는 java.awt의 클래스 - BorderLayout, CardLayout, GridBagLayout, GridLayout, FlowLayout

인터페이스 java.awt.LayoutManager2
LayoutManager2 인터페이스는 LayoutManager 인터페이스를 확장하여 배치에 컴포넌트를 추가하는 방식 및 위치를 지정하는 제약 조건 객체에 따라 배치를 명시적으로 처리 합니다.
addLayoutComponent(Component, Object) : 지정된 제약 조건 객체를 사용하여 지정된 컴포넌트를 배치에 추가 합니다.
getLayoutAlignmentX(Container) : x 축 정렬을 리턴 합니다.
getLayoutAlignmentY(Container) : y 축 정렬을 리턴 합니다.
invalidateLayout(Container) : 배치 관리 프로그램이 버려야 할 정보를 캐시에 넣은 경우 그 사실을 나타내고 배치를 무효화 합니다.
maximumLayoutSize(Container) : 컴포넌트의 최대 크기를 리턴 합니다.
LayoutManager2를 구현하는 java.awt의 클래스 - BorderLayout, CardLayout, GridBagLayout

FlowLayout
컴포넌트를 컨테이너에 연속된 행으로 위치 시킨다. 각 행에 많은 컴포넌트를 채우고 행이 다차면 다음으로 넘어간다. 주로 버튼등을 배열하기 위한 것
컴포넘트의 기본 위치는 행의 한가운데 입니다.
다음과 같은 행의 기본위치를 지정할수 있는 상수가 있습니다.
FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER,
[예제]
import java.awt.*;
class FlowLayoutTest extends Frame {
public FlowLayoutTest() {
setLayout(new FlowLayout());
add(new Button("Button1"));
add(new Button("Button2"));
add(new MyButton("새로운 버튼"));
Panel p = new Panel();
p.add(new Button("Panel Button1"));
p.add(new Button("Panel Button2"));
add(p);
}
public static void main(String[] args) {
Frame f1 = new FlowLayoutTest();
f1.setTitle("Flow Layout Test : default");
f1.setBounds(0, 0, 200, 300);
f1.setVisible(true);
Frame f2 = new FlowLayoutTest();
//((FlowLayout)f2.getLayout()).setAlignment(FlowLayout.LEFT);
FlowLayout flow = new FlowLayout(FlowLayout.LEFT);
flow.setVgap(50);
f2.setLayout(flow);
f2.setTitle("Flow Layout Test : left");
f2.setBounds(200, 0, 200, 300);
f2.setVisible(true);
}
}
class MyButton extends Button {
public MyButton(String text) {
super(text);
}
public Dimension getPreferredSize() {
return new Dimension(super.getPreferredSize().width+30, super.getPreferredSize().height+30);
}
}

GridLayout
각 격자끼리의 width, height는 동일 합니다.
GridLay() : 행이 하나인 GridLayout을 만듭니다.
GridLayout(int row, int col) : 주어진 행과 열의 GridLayout을 만듭니다.
GridLayout(int row, int col, int hgap, int vgap)

[예제]
import java.awt.*;
class GridLayoutTest extends Frame {
public GridLayoutTest(String t, LayoutManager m, int x, int y) {
setTitle("GridLAyout Test " + t);
setLayout(m);
add(new Button("Button1"));
add(new Button("Button2"));
add(new Button("Button3"));
add(new Button("Button4"));
add(new Button("Button5"));
add(new Button("Button6"));
add(new Button("Button7"));
setBounds(x, y, 300, 300);
setVisible(true);
}
public static void main(String[] args) {
new GridLayoutTest("디폴트", new GridLayout(), 0, 0);
new GridLayoutTest("2, 0", new GridLayout(2, 0), 300, 0);
new GridLayoutTest("0, 2", new GridLayout(0, 2), 0, 300);
new GridLayoutTest("3, 3", new GridLayout(3, 3), 300, 300);
}
}

GridBagLayout
Layout Manager중에서 가장 복잡하며, 보통 하나의 GridBagLayout을 사용하여 모든 종류의 폼을 구성할 수 있습니다.
융통성있는 배치 관리 프로그램으로 동일 크기의 컴포넌트를 요구하지 않으면서 컴포넌트를 수직 및 수평으로 정렬 합니다.
각 컴포넌트가 하나 이상의 셀을 차지하는 표시 영역이라 부르는 셀의 사각형 격자를 동적으로 유지 관리 합니다.
GridBagLayout으로 관리하는 각 컴포넌트는 표시 영역에서 컴포넌트 배치 방식을 지정하는 GridBagConstraints의 인스턴와 관련 됩니다
GridBagLayout을 효율적으로 사용하려면 해당 컴포넌트와 관련된 GridBagConstraints 객체를 하나 이상 조정해야 합니다. 그렇게 함으로서 컴포넌트를 원하는 크기와 위치로 배치합니다.
실제 GridBagLayout을 사용하는것 보다 여러 개의 컨테이너와 Layout Manager를 계층적으로 사용하는것이 훨씬 효율적 입니다.
GridBagConstraints
- gridx, gridy : 해당 컴포넌트가 들어가게될 격자의 x번째, y번째 값, 가장 왼쪽 셀의 주소는 gridx=0, gridy=0 입니다.
- gridwidth, gridheight : 해당 열에 존재할수 있는 최대 컴포넌트의 개수, int값 사용, GridBagConstraints.RELATIVE는 컴포넌트들이 이어져서 들어갈수 있게 해주며,GridBagConstraints.REMAINDER는 마지막 자리에 위치해서 더 이상 컴포넌트가 들어갈수 없게 합니다.
- fill : 컴포넌트를 채울때 특정 방향으로 컴포넌트를 늘여 격자를 채울수 있게 합니다. GridBagConstraints.BOTH, GridBagConstraints.HORIZONTAL, GridBagConstraints.VERTICAL등이 있다.
- ipadx, ipady : 컴포넌트가 가지는 내부적 간격, int값 사용 합니다.
- insets : 컴포넌트와 격자와의 외부적인 간격, java.awt.inset 객체가 사용 됩니다.
- anchor : 격자내에서 컴포넌트가 위치하게 되는 격자내의 절대적인 위치, GridBagConstraints.CENTER(기본값), GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST, GridBagConstraints.EAST, GridBagConstraints.SOUTHEAST, GridBagConstraints.SOUTH, GridBagConstraints.SOUTHWEST, GridBagConstraints.NORTHWEST등이 있습니다.
- weightx, weighty : 컴포넌트가 차지할수 있는 가로와 세로의 영역비율, double 값이 사용 됩니다.

[예제]
import java.awt.*;
public class GridBagLayoutTest extends Frame{
public GridBagLayoutTest(String t) {
super(t);
GridBagLayout gbag = new GridBagLayout();
GridBagConstraints con = new GridBagConstraints();
setLayout(gbag);
con.fill=GridBagConstraints.BOTH;
add(new Button("버튼1"), con);
add(new Button("버튼2"), con);
con.gridwidth = GridBagConstraints.REMAINDER;
add(new Button("버튼3"), con);
add(new Button("버튼4"), con);

con.gridwidth = GridBagConstraints.RELATIVE;
add(new Button("버튼5"), con);
con.gridwidth = GridBagConstraints.REMAINDER;
add(new Button("버튼6"), con);
con.gridwidth = 1;
con.gridheight = 2;
add(new Button("버튼7"), con);
con.gridwidth = GridBagConstraints.REMAINDER;
con.gridheight = 1;
add(new Button("버튼8"), con);
add(new Button("버튼9"), con);
}
public static void main(String[] args) {
Frame f = new GridBagLayoutTest("GridBagLayout");
f.setSize(300, 200);
f.setVisible(true);
}
}

CardLayout
여러화면을 겹쳐 두었다가 특정한 화면만 보이도록 할 경우 사용 합니다.
여러 장의 카드가 있으나 보이는 카드는 하나만 있다는 개념에서 나온 이름 입니다
first(), last(), next(), previous() 등의 도구를 사용하여 카드 간에 순차적으로 이동할 수도 있습니다.
CardLayout() : 간격 크기가 제로(0)인 새로운 카드를 작성 합니다.
CardLayout(int, int) : 지정된 수평 간격 및 수직 간격으로 새로운 카드 배치를 작성 합니다.

[예제] //닫기 기능 추가
import java.awt.*;
import java.awt.event.*;
public class CardLayoutTest1 extends Frame {
public static void main(String[] args) {
Frame f = new Frame("CardLayoutTest");

final Panel tabs = new Panel();

tabs.add(new Button("<><"));>
tabs.add(new Button("<"));
tabs.add(new Button("Options"));
tabs.add(new Button("Settings"));
tabs.add(new Button("Preferences"));
tabs.add(new Button(">"));
tabs.add(new Button(">>"));
f.add(tabs, "North");

final CardLayout layout = new CardLayout();
final Panel cards = new Panel(layout);
cards.add(new CardPanel("Options"), "Options");
cards.add(new CardPanel("Settings"), "Settings");
cards.add(new CardPanel("Preferences"), "Preferences");
f.add(cards, "Center");


ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
String cmd = ev.getActionCommand();
if (cmd.equals("<><")) layout.first(cards);
else if (cmd.equals("<")) layout.previous(cards);>
else if (cmd.equals(">")) layout.next(cards);
else if (cmd.equals(">>")) layout.last(cards);
else layout.show(cards, cmd);
}
};

for(int i=0; i
((Button)tabs.getComponent(i)).addActionListener(al);
}
f.setSize(400, 300);
f.setVisible(true);
f.addWindowListener(new WindowListenerProcessing() );
}
}

class CardPanel extends Panel {
CardPanel(String name) {
setLayout(new BorderLayout());
add(new Label("CardPanel : " + name, Label.CENTER),"Center");
Panel p = new Panel();
add(p, "South");
Button btn = new Button("Close");
ActionListener a1 = new ActionListener() {
public void actionPerformed(ActionEvent ev) {
String cmd = ev.getActionCommand();
if (cmd.equals("Close")) {
System.exit(0);
}
}
};
btn.addActionListener(a1);
p.add(btn);
}
}
class WindowListenerProcessing extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}



2013년 8월 5일 월요일

(자바스윈, 오라클자바교육, ORACLEJAVA EDU)JAVA Swing이란

이번 강좌에서는 전강좌에 이어 스윙에 대해 살펴 보도록 하겠습니다.



오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 

 www.onjprogramming.co.kr




컴포넌트와 컨테이너

Container로 부터 파생된 클래스는 다른 Component를 담을수 있으며, 컨테이너라고 부릅니다. 컨테이너는 다른 컨테이너를 포함할수도 있습니다(Window및 그하위 클래스는 예외) JFrame객체는 Application용 메인 윈도우를 나타내며, Window 객체는 그렇지않습니다. 윈도우를 만들기위해서는 항상 JFrame이 필요 합니다. 스윙의 독립 윈도우 컨테이너들은 AWT가 제공해주지 못하는 능력을 제공하기 위해 JFrame에 이미 JRootPane이라는것을 만들어 두었는데 여기에 프로그래머가 만든 컴포넌트는 JRootPane이 관리하고 있는 contantPane이라는것에 넣도록 하고 있습니다.. JFrame, JApplet, JWindow, JDialog등은 JComponent를 상속하지 않으므로 스윙의 능력을 직접 쓸수 없는 대신 JComponent를 상속받은 JRootPane을 미리 넣어 두는것 입니다. 그렇게 함으로서 독립적인 윈도우로 표시되는 컨테이너도 스윙의 기능을 사용할수 있으며 그렇게 하기위해서는 프로그래머가 만든 컴포넌트를 contentPane에 넣는 것 입니다.

JRootPane
- AWT의 경우 Frame에 직접 add를 사용하여 컴포넌트를 추가하였으나 JFrame의 경우엔 getContentPane()을 이용하여 contentPane을 얻은후 거기에 컴포넌트를 추가 합니다.
- JFrame, JApplet, JDialog, JWindow등은 RootPaneContainer 인터페이스를 구현하고 있으며 getXXXPane() 함수등으로 pane(창)을 얻은후 작업을 합니다. 이 인터페이스에는 setXXXPane메소드도 존재 합니다.
- glasspane(투명창) : 기본적으로 보여지지 않게 설정되었으며 보여지게 한다면 어떤 컴포넌트 등의 위에 그림을 그릴 수 있다. 또한 마우스 이벤트등을 가로채 반응을 안하게 할수있습니다.-
- layeredPane(다중창) : contentPane과 JMenuBar(생략가능)등을 담으며 다층레이어로 이루어져 팜업메뉴, ToolTip과 같은 컴포넌트가 contentPane위에 오도록 보장 합니다. 즉 서로다른 레이어를 가지는 컴포넌트를 담을수 있습니다.
- contentPane(내용창) : 루트창의 가시적인컴포넌트들(메뉴창 제외)을 담은 개체
- JMenuBar(메뉴바) : 컨테이너의 메뉴를 담습니다.
- JRootPane 개체는 직계 부속 컴포넌트를 가질 수 없으므로 JRootPane 에 컴포넌트를 직접 부착 할 수 없고 , 그에 따라 다음 표현은 틀린 것이다 . rootPane.add(child); 그 대신 JRootPane 의 contentPane 을 구해 여기에 컴포넌트를 부착 합니다 . rootPane.getContentPane().add(child);

 



(Java Framework, 자바교육,스트럿츠교육)Java Struts View

Struts에서의 VIEW 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 
 www.onjprogramming.co.kr 


Struts Framework에서 VIEW의 역할은 대부분 JSP가 수행 하며 커스텀태그,HTML,JSP의 조합으로 VIEW 를 만들어 낼 수 있습니다.

JSP기술은 개발자가 JSP안의 스크립틀릿에 비즈니스 로직을 마음대로 추가 할 수 있으므로 유지보스를 어렵게 하며 개발자가 JSP문법 뿐 아니라 커스텀태그의 사용법까지 알고 있어야 하는 단점이 있습니다. 또한 변경 후 다시 시작하는 경우 JSP 페이지를 다시 컴파일 해야 합니다.

Struts에서 사용 가능한 태그라이브러리는 HTML, Bean, Logic, Template, Nested, Tiles 6가지가 있습니다. 각 태그라이브러리는 서로 다른 역할을 하며 독립적으로 사용 가능 합니다. 또한 사용자가 새로운 커스텀 태그를 만들어 사용하는 것도 가능 합니다.

이전 로그인 예제(3)에서 사용자가 main.jsp에 접근 할 때 인증을 한 사용자인지의 여부를 검사하는 것을 커스텀 태그를 이용하여 만들어 봤습니다.

스트럿츠에서 제공하는 태그 라이브러리를 사용 하려면 web.xml에 등록해야 하는데 아래는 web.xml 파일의 내용 입니다.

<!-- Struts Tag Library Descriptors -->
        <taglib>
            <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
            <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
        </taglib>
        <taglib>
            <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
            <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
        </taglib>
        <taglib>
            <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
            <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
        </taglib>

다음으로 해야 할 일은 JSP 페이지에서 taglib 지시자를 추가 하는 것입니다.

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>


다음은 스트럿츠에서 제공 하는 커스텀 태그를 이용한 login.jsp 입니다.

<%@ page language="java" %>
<%@ page pageEncoding="euc-kr" %>
<!-- 최초 사용자가 접속하게 되는 페이지 입니다. -->
<!-- 아래는 import와 동일한 기능을 하는 태그로 태그 확장을 사용 할 수 있도록 합니다 -->
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/app.tld" prefix="login" %>

<!-- 인증이 안된 사용자는 login.jsp로 보내 버립니다. -->
<login:IsLogin/>

<html>
<head>
    <title><bean:message key="main.title" /></title>
    <html:base/>
</head>       
        <body>               
            <h3>반갑습니다.<bean:write name="user" property="id"/>님!</h3>                                       
                <ul>                       
                        <li>                           
                                <html:link forward="logoff">로그아웃</html:link>
                        </li>                       
                </ul>
        <body>
</html> 

JAVA Struts Model

Struts의 Model 


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의) 
 www.onjprogramming.co.kr 


스트럿츠에서 모델은 Business Logic을 처리하는 부분과 처리된 결과를 저장 하기 위한 부분으로 나누어 볼 수 있는데 처리된 결과를 저장 하는 빈은 Value Object 또는 DTO라고 부르고 있습니다.

Value Object로 볼 수 있는 DTO(Data Transfer Object)는 대부분 비즈니스 객체를 원격지 뷰에 제공 하는데 사용 합니다.

DTO는 원격 객체의 비즈니스 로직을 표현하지만 비즈니스 로직 안에 있을 필요는 없습니다. 앞의 로그인 예제에서 UserInfoVO.java가 DTO의 역할을 한다고 할 수 있습니다.

DTO를 이용하는 것은 분산 환경에선 거의 필수 이며 네트웍 부하를 줄일 수 있으며 스트럿츠에서 DTO를 사용하는 것은 비즈니스 객체와 프리젠테이션을 분리하며 유지 보수를 용이 하게 합니다.

이전의 로그인 예제를 다시 돌아가 보면 LoginAction에서는 실제 로그인을 처리하는 과정은 포함되어 있지 않습니다. Action 클래스는 Controller의 일부라고 이전에 이야기 했습니다.

Action 클래스에서는 인증 처리를 LoginDAO.java에 위임을 했는데 이렇게 분리 하는 경우 인증 모듈에 변경이 가해 지더라도 Action 클래스에는 영향을 끼치지 않는 것 입니다.

아래 소스 코드를 보도록 하죠…( LoginAction.java)

package login2;

import org.apache.struts.action.Action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;

import login2.LoginForm;
import login2.Constants;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionServlet;

/**
 * @author 이종철
 */
public class LoginAction extends Action {
               
        public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {
                String id = ((LoginForm)form).getId();
                String pwd = ((LoginForm)form).getPwd();
               
                //Model을 이용하기 이용하여 인증부분의 처리를 합니다.
                LoginDAO loginDAO = new LoginDAO();
                UserInfoVO userinfo = loginDAO.authUser(id, pwd);
               
                //에러 내용을 담을 ActionErrors 객체를 생성
                ActionErrors errors = new ActionErrors();
               
                if (userinfo==null) {
                        //인증 실패                       
                        errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.login.invalid"));                       
                }
                else {
                        //사용자 아이디와 비밀번호가 틀릴경우 비밀번호가 틀리다는 에러 메세지 출력
                        if ( !id.equals(userinfo.getPwd()) ) {
                              errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("error.login.invalid"));
                        }
                }
               
                //로그인 과정에서 에러가 있을 경우 Action클래스의 saveErrors 메소드를 이용해  에러를 저장하고
                //이전의 로그인 페이지로 돌려 보내면 login.jsp의 <html:errors/> 태그에 의해 오류가 출력 돔
                //mapping의 getInputForward()에서 반환하게 되는 정보는 struts-config.xml의 action태그의
                //input 속성에  정의된 페이지로 이동하게 됩니다.
                if (!errors.isEmpty()) {
                    saveErrors(request, errors);
                  return (mapping.getInputForward());
                }       
                               
                //인증 성공한 경우 세션에 LoginInfoVO(로그인한 사용자 정보를 담은 객체)저장
                HttpSession session = request.getSession();
                session.setAttribute(Constants.USER_KEY, userinfo);
               
                //로그를 남기자.
                StringBuffer buf = new StringBuffer("LoginAction : User --> ");
                buf.append(id + "logged in session");
                servlet.log(buf.toString());
                               
                return (mapping.findForward(Constants.SUCCESS));                       
               
        }

       
}

LoginDAO loginDAO = new LoginDAO();
UserInfoVO userinfo = loginDAO.authUser(id, pwd);
이 부분을 보면 LoginDAO의 authUser라는 메소드가 인증을 수행 함을 알 수 있는데…
실행 후 결과를 리턴 하는 부분을 보면 USerInfoVO라는 DTO(Data Transfer Object)를 리턴함을 알 수 있습니다.

LoginDAO는 비즈니스 로직을 수행하는데(인증처리), 이 처리가 정상적으로 된 경우 사용자 정보(UserInfoVO)를 어디엔가 저장 해 두고 (ID와 PWD이외의 정보가 DB에서 읽혀져서 포함 될 수 있습니다.) 나중에 VIEW에서도 꺼내 볼 수 있는데 이때 UserInfoVO 빈이 DTO or Value Object가 됨을 알 수 있습니다.

이 USerInfoVO는 LoginAction에서 인증 결과가 성공 이었음을 확인 후 session에 setAttribute로 저장 됩니다.

//인증이 성공한 경우 세션에 UserInfoVO(로그인한 사용자 정보를 담은 객체)저장
HttpSession session = request.getSession();
session.setAttribute(Constants.USER_KEY, userinfo);



아래는 LoginDAO.java 파일의 내용 입니다.

package login2;

public class LoginDAO {
       
        public UserInfoVO authUser(String id, String pwd) {
                /**
                * 이부분은 실제 DB에서 ID와 PASWORD로 인증을 해야 하는 부분 입니다.
                * 예제를 간략히 하기 위해 이부분의 처리는 생략 했으며 ID가 "jclee", Password가 "jclee" 인 경우엔
                * 인증을 허용 합니다.
                */
               
                if ( id.equals("jclee")&& pwd.equals("jclee")) {
                        //ID:jclee, PASSWORD:jclee인 경우 인증이 성공, 사용자의 정보(아이디, 패스워드)를 저장 합니다.
                        return new UserInfoVO(id, pwd);
                } else {
                        return null;
                }               
        }
}


아래는 DTO인 UserInfoVO.java 입니다.

package login2;
/**
 * 로그인이 정상적으로 이루어진 경우 사용자의 정보 등을 저장 하는 빈
 * 본 예제에서는 ID와 PASSWORD를 저장 합니다.
 */
public class UserInfoVO {
        private String id = null;
        private String pwd = null;
       
        //LoginDAO에서 인증이 성공인 경우 아래의 생성자를 불러 값을 setting 합니다.
        public UserInfoVO(String id, String pwd){
                this.id = id;
                this.pwd = pwd;
        }
       
        public  String getId() {
                return id;
        }

        public  String getPwd() {
                return pwd;
        }
}


다음은 VIEW쪽에서 세션에 저장 되어 있는 UserInfoVO 빈을 이용하는 예 입니다.
<body>               
            <h3>반갑습니다.<bean:write name="user" property="id"/>님!</h3>       
                <ul>                       
                        <li>                           
                                <html:link forward="logoff">로그아웃</html:link>
                        </li>                       
                </ul>
        <body> 

2013년 8월 1일 목요일

(JAVA CASTING, CAST)자바 형변환 예제(CastingTest.java)

class CastingTest {
  public static void main(String[] args) {
  //i = (int)l l이 int형의 범위를 넘어선다면 오류, integer형의 범위가 넘는값은 int로 Casting 안된다.
  // integer형의 범위는 -2147483648 ~ 2147483647
  long l=123456789;
  int i=(int)l;
  System.out.println("i --> " + i);
  //작은데 큰것을 넣을때는 명시적으로 형변환을 해야한다.
  //i = l;  integer은 4바이트, long형은 8바이트 이므로 에러...

  boolean bool =true;
  //boolean형의 경우 int형으로 명시적으로 형변환 불가
  //boolean형은 같은 자료형 이외에 다른 자료형으로의 변환이 금지된 자료형이다
  //i = (int)bool; 


  //int형을 boolean 형으로의 형변환은 명시적으로 불가
  //bool = (boolean)i;

  i = 65535;
  byte b = (byte)i; //65535 가 -1로 바뀜
  System.out.println("b --> " + b);

  //왼쪽이 작으니까 명시적 형변환 필요, 협소화
  double d = 3.1313139313;
  float f = (float)d;
  System.out.println("f --> " + f);

    //왼쪽이 크니까 컴파일러에 의한 묵시적인 형변환, 광역화
    f = i;
    System.out.println("i --> " + i);       
  }
}