메서드 - 문장들을 묶어놓은것

값(입력)을 받아 처리하고 결과를 반환(출력)  - 코드의 중복을 줄이고, 코드의 관리가 쉽다, 코드 재사용 가능, 가독성 향상

 

메서드와 함수는 비슷한 개념이라고 보면 되는데 주요 차이점은

메서드 - 클래스 내부에 존재

함수 - 클래스 내부, 외부에 존재

 

메서드 - 선언부와 구현부로 구분되며 이를 합하여 메서드영역 이라고 칭한다.

int add(int a, int b)	//선언부
{			//구현부 시작
	int result = a+b;
    return result; 
}			//구현부 끝

호출스택 (call stack) - 메서드 수행에 필요한 메모리가 제공되는 공간

메서드가 호출되면 호출스택에 메모리가 할당되며 사용이 종료된경우 해제된다 (GC와 같은 원리)

 

스택- LIFO(후입선출)의 원리로 

 

public static void main(String args[]){
	   
        System.out.println("test");
}

상단의 코드를 실행시 하단의 순서에따라 스택이 push되고 pop 되는구조다.

스택구조의 원리를 참고해서 설명하자면

① - 초기상태

② - main이 실행된 상태

③ - main은 대기, println은 실행상태

④ - println이 사용이 끝나 Pop(메모리 반환)되어 바로 밑에 있는 main이 다시 실행

⑤ - 프로그램 종료 

메서드는 맨위의 1개만 실행중이며 나머지는 대기중이다.

 


static메서드, 인스턴스 메서드

 

IV -> Instance Variable(인스턴스변수)

IM -> Instance Method (인스턴스 메서드)

LV -> Local Variable(지역변수)

CV -> Class Variable(클래스변수) 

 

 

인스턴스 메서드

 

인스턴스맴버 (IV,IM) 관련 작업을 하는 메서드

인스턴스 생성후 "참조변수.메서드 이름()"으로 호출

메서드 내에서 인스턴수 변수 (IV)사용가능 -> 객체가 있기 때문에 사용가능?

 

 

static 메서드 (클래스 메서드)

 

객체생성없이 "클래스이름.메서드이름()"으로 호출

인스턴스멤버와 관련없는 작업을 하는 메서드

메서드 내에서 인스턴스 변수(IV) 사용불가 -> 객체가 없기 때문에 사용불가?

 

두 메서드의 차이점은 하단의 코드를 확인하길 바란다.

//메서드 정의
class MyMath2 {
	long a,b;		//인스턴스변수 (구분을 위하여 하단의 설명에선 a,b를 aa,bb로 지칭한다.)

	long add() {		//인스턴스 메서드 -> (I)
    	return a+b;		
    }

	static long add(long a, long b){	// 클래스메서드 (static메서드) -> (J)
    	return a+b;
    }

}

 

메서드 정의 코드에서 (I)와 (J)의 차이점은 매개변수가 들어간것, 앞쪽에 static이 붙은것 2가지 차이인데 상세하게 설명하자면

 

(I)는 파라미터를 없이 a+b를 계산하는데 여기서 a,b는 인스턴스 변수인 aa,bb를 의미한다. (IM는 IV,CV 둘다 사용가능)

(J)는 파라미터(지역변수)를 받고 (a와 aa 다른변수이다.) 호출할시 파라미터가 주어지지 않으면 오류를 출력하게 된다.

(static메서드는 CV만 사용가능 -> IV를 사용하기 위해선 객체가 필요한데 static은 객체가 없으니 사용불가능) 

//메서드 호출
class MyMath2Test2
public static void main (String args[]){

    system.out.println(MyMath2.add(200L,100L)};		//클래스메서드 호출 (J)호출 -> 편의상 P로 칭함
							//클래스이름(Mymath2).메서드이름(add)
                            
    MyMath2 mm = new MyMath2();				//인스턴스 생성 (I) 호출 -> 편의상 K로 칭함
    mm.a = 250L;
    mm.b = 100L;
    system.out.println(mm.add())};			//인스턴스 메서드 호출
							//참조변수(mm).메서드이름(add)
}

메서드 호출 방식에도 차이점을 확인할수 있다.

 

(J)호출과 (I)호출에선 파라미터가 다르게 출력됨을 확인할수 있는데

(P)는 (J)를 호출 : 호출과 동시에 매개변수만 넣으면 실행되는것 (객체의 생성이 없다! -> IV를 사용하지 않을때 사용한다)

(K)는 (I)를 호출한다 : 인스턴스(객체) 생성 -> 기존 메서드의 값 삽입 -> println 실행

 

여기서 의문이 생기는점은 static은 어느 기준으로 붙이면 되는건지 궁금한것인데

1. 클래스변수(공통속성)으로 사용되는 경우에 붙인다.

2. IV를 사용하지 않는 메서드에 static을 붙인다 (상단의 "//메서드정의" 코드 참조)

 

추가로 덧붙이자면 IM(인스턴스메서드)에서 다른 static메서드,IM호출이 가능하지만, static 메서드는 다른 static메서드 호출이 되지만 IM는 호출불가하다 (IV는 객체가 필요하기 때문!)

 

 

 

'JAVA' 카테고리의 다른 글

오버로딩  (0) 2023.02.02
매개변수  (0) 2023.01.31
클래스 변수,인스턴스 변수  (0) 2023.01.30
인터페이스란?  (0) 2023.01.13
지수와 가수  (0) 2023.01.13

클래스 변수 (Class Value) - 각 객체별로 공통적인 속성 (객체 생성없이 사용가능)

인스턴스 변수 (Instance Value) - 각 객체로 공통적이지 않은 속성 

 

한가지 예시로 설명하자면 포커카드의 상대방이 내 카드크기만 보고 카드값을 를 알수 없어야 하기에 동일사이즈 (CV)로 제작되고 카드값(IV)은 각자 다르게 제작된다(스페이드3,다이아9 등)

////////
//코드1
////////
class CardTest{
public static void main(String args[]){
	     Card c1 = new Card();
        c1.kind = "Heart";
        c1.number = 7;

        Card c2 = new Card();
        c2.kind = "Dia";
        c2.number = 5;

        System.out.println("c1은"+c1.kind+c1.number+"이며, 처음 크기는"+c1.width+","+c1.height+"");
        System.out.println("c2은"+c2.kind+c2.number+"이며, 처음 크기는"+c2.width+","+c2.height+"");
        c1.width = 300;
        c1.height = 350;

        System.out.println("c1은"+c1.kind+c1.number+"이며, 바꾼 크기는"+c1.width+","+c1.height+"");
        System.out.println("c2은"+c2.kind+c2.number+"이며, 바꾼 크기는"+c2.width+","+c2.height+"");
    }
}  
////////
//코드2
////////

class Card {
   String kind;	//무늬,IV
   int number;	//숫자,IV
   
   static int width = 100;	//폭,CV
   static int height = 250;	//높이,CV  
}

코드2에서 card를 선언후 코드1에서 호출하는 형태의 코드를 작성하였는데 해당 코드를 실행시켯을 경우 하단과 같은 결과가 나타나게 된다.

이것은 CV와 IV의 생성시점이 다르기 때문에 나타나는 문제인데 객체 생성시마다 IV는 계속 생기는데(신규 메모리를 할당받는데) CV는 초기 메모리에 선언된이후 처음 메모리에 계속 참조되는 형식으로 진행되기 때문에 같은 값이 출력되는 것이다.

순서를 말하자면

1.처음 시작시 Card클래스의 인스턴스가 생성되기 위해 Card클래스(CV)가 메모리에 로드되는데 이때 width와 height가 메모리에 초기화된다.

2.Card인스턴스 생성후 맴버변수인 kind와 number은 초기화가 되고 코드1에서 값을넣은 주소(IV)가 참조변수 c1에 저장이된다.

3.Card클래스는 기존 메모리에 로드되어 있으므로 Card클래스를 신규 생성하는게 아닌 기존의 있는 Card 클래스를 재사용 하기 때문에 코드1에서 값을 넣은 주소(IV)가 참조변수는 c2에 저장된다. 

 

'JAVA' 카테고리의 다른 글

매개변수  (0) 2023.01.31
메서드  (0) 2023.01.30
인터페이스란?  (0) 2023.01.13
지수와 가수  (0) 2023.01.13
JPA란 무엇인가  (0) 2022.12.23

인터페이스란 객체간 사용방법을 정의한 타입을 인터페이스라고 한다.(추상메서드의 집합)

인터페이스는 단일객체가 아닌 여러 객체들과 사용이 가능하기에 (한번 선언해두면 필요할때마다 가져와서 사용할수 있기 때문에) 코드의 수정이 필요할경우 사용하는 객체 (파라미터)만 변경하면 다른 값이 반환시키는것(코드의 종속성을 낮추는것)이 주요 목적이다.

 

또한 인터페이스가 추상메서드만 갖게 된 이유는 기존 메서드와의 충돌로 인하여 이를 없애고자 추상메서드만 갖도록 정한것이다. 


인터페이스의 다형성 

//다형성예시 코드
//추상메서드
abstract class Unit{	
    int x, y;
    abstract void move (int x, int y);
    void stop() {System.out.println("멈춤")};
}

//인터페이스 선언
interface Fightable{	
    void move(int x, int y);	//public abstract 생략(추상메서드)
    void attack(Fightable f);	//public abstract 생략(추상메서드)
}

//인터페이스 구현(오버라이딩) 
class Fighter extnes Unit implments fightable{
    //오버라이딩 규칙 : 조상보다 접근제어자가 낮으면 안된다.
    //인터페이스 선언 코드의 접근제어자는 public이다
    
    pbulic void move(int x, int y) {
    	System.out.println(x+","+y+"위치로 이동");
    }
    pbulic void attack(Fightable f) {
    	System.out.println(f+"를 공격");	
    } 	
}

//메인함수
public class FighterTest{
	public static void main(String[] args){
    	Fighter f= new Fighter();
        f.move(100,200);
        f.attack(new Fighter());
    }
}

다형성 코드에서 주목해서 볼것은 Fightable(인터페이스)가 Fighter(자손객체) 를 참조해서 받는모습을 볼수있는데 이것은 상속과 다형성을 설명하면서 이야기하겠다.

이전에 배운 상속은 부모클래스가 자식클래스에게 맴버를 물려주는것을 상속이라고 하고있는데 (A)같은 경우는 매개변수 타입이 인터페이스인경우 이것을 구현한 클래스(자손클래스)의 인스턴스만 사용이 가능하다.(사용 가능한 메서드는 move와attack 2개이고 stop은 사용 불가능하다. -> 부모님이 주신 유산을 받은 자식도, 물려준 부모도 쓸수 있되 자식이 산건 못쓴다고 생각하면 된다.)

 

//부모의 자손참조
Unit u = new Fighter();		//조상클래스의 자손객체참조	
Fightable f = new Fighter();	//인터페이스의 자손객체참조   (A)

//단, f는 상단의 Fightable의 메서드만 사용이 가능하다.
//즉,f.move(100,200); OR f.attack(new Fighter()); 2개는가능 f.stop();는 불가능

다형성은 자식객체가 부모객체로 자동변환(Casting)이 가능하다는 특징이 있는데 인터페이스에서 이러한 예시를 보여주는것이 (A)이다.

하단의 주석처리를 해놨듯이 부모클래스는 자식클래스에서 구현된것만 사용가능하다.

조금더 알기쉽게 설명하자면 포유류(부모) / 박쥐,고래(자식)으로 생각하고 하단의 사진을 보길 바란다.

포유류인 고래는 헤엄을 칠수 있고 박쥐는 날수 있다.(부모클래스를 자식클래스에게 상속)

박쥐는 포유류이며 날수있다 하지만 헤엄은 못친다.(자식클래스를 부모클래스로 변환)

고래는 포유류이며 헤엄칠수 있다. 하지만 날수는 없다. (자식클래스를 부모클래스로 변환)

이런식으로 이해할수 있다.

 

//(B)
Fightable method(){
	....//구현내용
    Fighter f = new Fighter();	//여기서부터
    return f;			//여기까지 한줄로 줄여 쓰면 return new Fighter(); 이다.
}

(B)는 메서드 반환타입이 인터페이스면 반환받는 변수의 타입도 인터페이스이어야 한다.

이것은 인터페이스의 구현한 객체를 반환해야한다 -> 인터페이스가 아닌 추상메서드, 객체등을 반환할수 없기 떄문이다.

(A)에서 나타나 있듯이 메서드의 반환타입이 인터페이스면 반환받는 변수도 인터페이스이어야 한다.

여기서도 자식객체(retutn f)가 부모객체(Fightable)로 자동변환(Casting)이 되기 때문에 해당코드를 실행해도 문제없는 모습을 확인할수 있다.


인터페이스 선언맴버

//인터페이스 선언 방법
//interface 인터페이스 이름

interface PlayingCard{
    //상수필드 : 타입 상수명 = 값;
    public static final int SPADE = 5;	
    final int DIAMOND = 3;				//public static final int로 자동 치환
    static int HEART = 2;				//public static final int로 자동 치환
    int CLOVER = 1;					//public static final int로 자동 치환
    
    //추상메서드 : 타입 메소드명(매개변수,..);
    public abstract String getCardNumber();
    String getCardKind();				//public abstract String getCardkind로 자동 치환

    //디폴트 메서드 : default 리턴타입 메소드명 (매개변수,..) {...내용...}
    default void setCard(boolean gameplay){
    	if(gameplay){
        System.out.println("게임 시작");
        } else {
        System.out.println("게임 종료");
        }    
    }
    
    //정적메서드 : static 타입 메소드명(매개변수) {..내용..};
    static void changeSatge(){
    	System.out.println("스테이지 변경");
    }
}

상단은 인터페이스의 예시인데 인터페이스의 선언에서 허용되는건 다음과 같다.

1.상수필드 - 상단에 기술한대로 인터페이스는 데이터를 저장할수 없고 추상 메서드의 집합이므로 추상메서드의 규칙에 반하지 않는 값이 고정된 상수는 사용이 가능하다 

2.추상메서드 - 메서드인데 내용( {..내용..} ) 이 없는 메서드 (내용은 구현단계에서 오버라이드로 구현한다)

3.디폴트메서드 - 기존 인터페이스를 확장하여 새로운 기능을 추가하기 위한 목적이다. (실행내용을 작성한것)

4.정적메서드 - 객체가 없어도 인터페이스 호출이 가능하다 

(인터페이스 내부의 필드는 자동적으로 public static final이 접두로 붙는다 -> 그래야 추상메서드의 목적인 다른메서드에서 참조가 가능하니까)


추상클래스와 인터페이스 차이점

추상클래스 - 일반 클래스 인데 추상메서드를 갖고있는것 (일부 미완성)

인터페이스 - 추상메서드만 갖고있는것 (완전 미완성 - 구현된게 없음)

 

만일 하단의 코드처럼 추상클래스의 attack 메서드가 미구현된 경우 (인터페이스에서 일부만 구현하는 경우) 추상클래스로 인식이 되며 앞쪽에 abstract를 붙여준다.

//인터페이스 예시
interface Play_Unit{
	void move(int x, int y);	
	void attack(string m);	//public abstract 생략됨
}


//추상클래스 예시)	(B)
abstract class Play_Unit2 implements Play_Unit{
    public void move(int x, int y){
        System.out.println("캐릭터가"+x+"위치에서"+y+"위치로 이동합니다");}	//구현됨
    public void attack(string m);	//미구현됨

}


//인터페이스 구현
//class 클래스명 implements 인터페이스 이름{..}

class Unit implements Play_Unit{
	public void move(int x, int y){
    	System.out.println("캐릭터가"+x+"위치에서"+y+"위치로 이동합니다");	//구현완료
    }
    
	public void attack(string m){
    	System.out.println("캐릭터가+m+"를 공격합니다.");	//구현완료
    }

}

인터페이스의 특징

1. 인터페이스는 다중 상속이 가능하다. (extends 는 동일한 메서드가 있을경우 이전에 설명한 충돌의 우려 때문에 다중상속 불가 -> ambiguous 에러)

2. 여러개의 인터페이스를 상속받은 인터페이스를 클래스에 적용할 땐 모든 메서드를 구현해 줘야한다.

3. 추상메서드와 상수로만 이뤄진다(코드의 종속성을 낮추기 위함, 접근제어자는 public이 붙으며 상수처럼 값이 명확하거나 메서드가 추상적이어야 타객체에서 접근할때 문제가 없다)

4. 생성자 사용 불가(객체가 아니기 때문이다)

5. 인터페이스의 조상은 인터페이스만 가능하다


인터페이스 구현

인터페이스에 구현된 추상메서드를 완성하는것으로 클래스 뒤쪽에 implements 인터페이스명을 붙인다

또한 기존 인터페이스선언에 있던걸 구현하는건 오버라이드기능을 활용하는 것이다.

//인터페이스 구현
//class 클래스명 implements 인터페이스 이름{..}

class Unit implements Play_Unit{
	public void move(int x, int y){
    	System.out.println("캐릭터가"+x+"위치에서"+y+"위치로 이동합니다");	//구현완료
    }
    
	public void attack(string m){
    	System.out.println("캐릭터가+m+"를 공격합니다.");	//구현완료
    }

}

 

 

여담..

기존의 인터페이스는 추상메서드만 가질수 있지만 디폴트 메서드가 생김으로써 메서드간 충돌할 우려가 생긴것인데 이것은 크게 인터페이스간 충돌, 디폴트메서드와 조상클래스 메서드간 충돌로 나뉘는데

인터페이스간 충돌 > 인터페이스 구현 클래스에서 디폴트 메서드 오버라이딩

조상클래스와 충돌 -> 조상클래스 메서드 상속, 디폴트메서드 무시됨

2가지의 이유로 사용하여도 문제가 없다고 한다.

'JAVA' 카테고리의 다른 글

메서드  (0) 2023.01.30
클래스 변수,인스턴스 변수  (0) 2023.01.30
지수와 가수  (0) 2023.01.13
JPA란 무엇인가  (0) 2022.12.23
3항 연산자에 관하여  (0) 2022.12.22

실수의 형태는 float, double으로 2가지 형태가 있는데 

float는 4byte

double는 8byte를 갖는다

 

그렇지만 int형 도 4byte인데 float과 int형이 같은 메모리 크기를 갖는건 무언가 이상하다.

그이유인 지수와 가수에 대하여 알아보자 

상단의 사진은 IEEE가 제공하는 부동소수점 방식의 형태인데 가수부와 지수부의 크기가 다른것을확인할수 있다

이러한 이유는 

float형은 4byte -> 32bit이며 (7자리)

double형은 8byte -> 64bit를 (15자리)갖는데 이것은 표현하는 자릿수의 차이이며

이를 설명하기 위한 코드는 아래와같다

//코드1

int a = 1;
float b = 1.1f;		(float은 뒤에 f붙이기)
double c = 1.1;

//자리수 테스트

float testFloat = 0.1234567890123456789f;
double testDouble = 0.1234567890123456789;

System.out.println(testFloat);
System.out.println(testDouble);

실행결과 (사진1)


코드1과 사진1을 참조하면 뒤의 자릿수가 2배차이나는것 확인할수 있고 뒤의 숫자는 자릿수를 넘어간 관계로 자동적으로 반올림 된것을 확인할수 있다.

조금더 자세하게 설며하면 하단의 사진을 참조하면 된다.

부동 소수점 방식은 부호는+(0) 또는 1(-)으로 제일 앞쪽에 , 지수, 가수로 나뉘는데

가수 - 곱하는수 (2)

지수 - 제곱하는 부분을 뜻하며

float은 128~126 (256 = 2^8)으로 총 구현 가능한 숫자는 128+126+0 총 255 이며 여기에 bias(127)을 추가하여 총 256이 나오는것이다.

1024,-1022(총 구현가능한 숫자는 1024+1022+0으로 총 2047개이며 1024 = 2^10) 여기서도 bias(1023)을 추가하여 2048이 되는것이다.

 

여기서 의문을 가질것은 지수부분과 가수부분의 비트가 23,52로 측정된 이유가 궁금할것이다.

이것은 소수점 표현방식의 차이로 나타나는 숫자이다.


실수의 표현방식은 고정소수점, 부동소수점 방식이 있는데 float형을 기준으로 설명하자면 아래와 같다.

 

고정소수점

float의 경우 32bit를 부호 (1bit), 정수(15bit),소수(16bit)로 구분하는 방식인데 이는 정밀한 값을 표현할수 없다는 단점이 있다 (정수가 20bit로 넘어가거나 소수가 20bit로 넘어가는 경우 정확한 값이 출력할수 없다.)

 

부동소수점

고정소수점의 정확한 값을 표현하지 못한다는 문제점을 보완한 방식으로 모든 2진수 숫자를 1.xxx의 형태로 출력하는 것으로 현재 가장 보편적으로 사용된다.

32bit를 부호(1bit), 소수점이  움직일 위치 - 지수부(8bit), 소수점이 움직인 결과에서 소수점 뒤로 오는 부분을 채워넣는것(23bit)

 

double형의 경우 지수부에 11bit를 할당해 더 많은 양(소수점이 움직일수 있는 범위가 커짐)을 저장할수 있게된것이다.

 

 

bias

IEEE에선 지수에 해당하는 숫자 + bias(127)을 더한 숫자가 2진수로 바뀌어 들어가는데

bias를 쓰는 이유는 지수가 음수일수도 있기 때문에 들어가는것이다.

float의 경우 -126~128인데 두 숫자의 중간값인 127을 할당했고

double의 경우 - -1022~1024인데 두 숫자의 중간값이 1023을 할당한것이다.

 

 

'JAVA' 카테고리의 다른 글

클래스 변수,인스턴스 변수  (0) 2023.01.30
인터페이스란?  (0) 2023.01.13
JPA란 무엇인가  (0) 2022.12.23
3항 연산자에 관하여  (0) 2022.12.22
라이브러리와 프레임워크  (0) 2022.12.20

객체 지향 프로그래밍 (Object Oriented Programing) 이란?

프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법

 

- 장점

코드 재사용이 용이

남이 만든 클래스를 가져와서 이용할 수 있고 상속을 통해 확장해서 사용할 수 있다.

유지보수가 쉬움

절차 지향 프로그래밍에서는 코드를 수정해야할 때 일일이 찾아 수정해야하는 반면 객체 지향 프로그래밍에서는 수정해야 할 부분이 클래스 내부에 멤버 변수혹은 메서드로 존재하기 때문에 해당 부분만 수정하면 된다. 

대형 프로젝트에 적합

클래스 단위로 모듈화시켜서 개발할 수 있으므로 대형 프로젝트처럼 여러 명, 여러 회사에서 프로젝트를 개발할 때 업무 분담하기 쉽다.

 

- 단점

처리 속도가 상대적으로 느림

객체가 많으면 용량이 커질 수 있음

설계시 많은 시간과 노력이 필요

 

OOP의 4가지 특징

1. 캡슐화

2. 추상화

3. 다형성

4. 상속

 

오버라이딩 : 부모클래스의 메서드와 같은 이름, 매개변수를 재정의 하는것.

오버로딩 : 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출할 수 있게 하는 것.


1. 캡슐화

원래의 목적은 객체의 속성(data fields)과 행위(methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다.

즉, 사용하려는 메서드에 접근제어자를 활용하여 기존의 데이터에 손상이 가지 않도록(접근 못하도록) 하는것으로 주요목적은

1. 메서드를 통한 간접접근이 가능하도록 하는것

2. 내부적으로만 사용되는 부분을 감추기 위하여 사용

이것을 조금더 상세하게 설명하자면 

//접근 가능 코드
public class Time{
	public int hour = 12;		//0~23
	public int minute = 35;		//0~60
	public int second = 27;		//0~60
    //출력시 12:35:27
}

public class TimeTest{
	Time t = new Time(); 		//생성
	t.hour = 50;			//Time 맴버변수에 직접 접근
	System.out.println(t.hour);	//출력시 50:35:27이 출력된다...
	}
}

한가지 예시로 실시간 반영 서비스를 위한 코드를 작성하고 있다고 가정했을때 public으로 구현된 hour에 직접 접근하여 50을 넣는다면 코드상으론 문제가 없지만 실제 서비스를 구현한다고 했을때 사용자는 이로인해 여러 애로사항이 발생할것이다

 

여기서 발생하는 문제점은

문제점1. 접근제어자가 public이라 데이터의 원형이 바뀔 우려가 있다.

문제점2. 시간,분,초가 기준범위를 넘어선 값이 입력될 우려가 있다(현재시간 50시입니다..)

//수정한 코드

public class Time2{				//접근제어자 변경으로 문제점1 해결
	private int hour = 12;			//0~23
	private int minute = 35;		//0~60
	private int second = 27;		//0~60
    //출력시 12:35:27

    public int getHour() {return hour;}		//다른 메서드에서 호출은 가능해야 하기 때문에 public으로 선언
    public void setHour() (int hour) {		//조건문을 활용해 문제점 2 해결
	if (hour < 0 || hour >23) return;	
        this.hour = hour;
	}
}

public class TimeTest {
	public static void main(String[] args){
    	Time t - new Time();
        t.setHour (21);
        System.out.println(t.getHour));
	}	
}

이것이 캡슐화가 진행되도록 수정된 코드이다.

 

문제점1은 public에서 private로 접근제어자를 변경하여 데이터의 원형을 참조할수 없도록 하였다 

문제점2는 조건문을 활용하여 정해진 범위만 들어가도록 하였다

추가로 hour은 private로 선언하여 외부에선 접근이 불가능 한데 이를 활용하기 위하여 public을 사용하여 외부의 다른 클래스에서 사용이 가능하도록 하였다.

 

객체의 속성과 행위를 하나로 묶고 -> 시간과 관련된 객체, 행위(유효한지 확인)를 한곳에("Time2"메서드) 묶고

실체 구현 내용 일부를 외부에 감추어 은닉한다 -> private를 활용하여 외부에서 접근할수 없고 참조하는 형식으로만 진행된다.

 

접근제어자

public - 외부 클래스가 자유롭게 사용가능

protected - 같은 패키지, 자식클래스(상속)만 사용가능

default - 같은 패키지에 소속된 클래스만 사용가능

private - 외부에서 사용 불가(캡슐화!)

 


2. 추상화(Abstraciton)

공통된 속성, 기능을 묶어 이름을 붙이는것

 

좀더 자세히 설명하기 위해 코드를 작성하기로 하자

//추상클래스
abstract class Player{		//(A)
    abstract void Unit_attack (Sting Unitname);	//공격
    abstract void Unit_Idle();			//대기
    abstract void Unit_Run(Sting Unitname);	//후퇴
    
}

상단의 코드는 3개의 메서드가 있지만 어떠한 기능을 하는것이 아닌 그저 선언만 되있는 반쪽짜리 메서드이다.

선언만 해놨기에 작동하지는 않고 그저 사람이 어떤기능을 하겠거니 하고 추측할수 있는 추상화된 메서드를 작성한것일 뿐이다. (이하 추상메서드) 라고 칭한다.

그리고 이것을 실제로 사용하는 코드를 작성하였다.

public class Main extends Player{
	
    public static void main(String[] args){
    	String Player_name = "marine";
    	Main main = new Main();    
    	main.Unit_attack("Zergling");
    	main.Unit_Idle();
        main.Unit_Run("Zergling");
    }

    @Override
    void Unit_attack (Sting Unitname){	//공격
    System.out.println(Player_name+"이 "+ Unitname + "을 공격합니다"); 
    }
    
    @Override
    void Unit_Idle(){			//대기
    System.out.println(Player_name+"이 대기중입니다"); 
    }
    
    @Override
    void Unit_Run(Sting Unitname){	//후퇴
    System.out.println(Player_name+"이 "+ Unitname + " 에게서 달아납니다."); 
    
    }

상단의 코드는 추상메서드의 선언에 지나지 않은것을 Override하여 구체화한 코드이다.

공통된 속성, 기능을 묶어(플레이어가 갖고있는 기본적인 기능)이름을 붙이는것

 

추상화를 사용하는 이유가 무엇이냐?

설계자가 특정 메서드를 각 클래스 별로 재 구현을 원하지만 부모 클래스에서 일반 메서드로 구현하면 자식 클래스에서 구현을 하지 않는 경우가 발생할 수 있다. 이런 메서드를 추상 메서드로 선언하면 자식 클래스는 재구현을 강요받는다.

조금더 상세히 설명하자면 마린과 탱크가 있다고 가정을 해보자. 2개의 유닛은 기본적인 기능(A)외에 추가적인 기능(ex:스팀팩, 시즈모드) 등이 있을때 해당 기능을 넣지 않고 개발해버린다면 큰 오류이다. (시즈모드 못하는 탱크...)

이것을 추상메서드로 선언해놓고 구체화를 진행할경우 구체화된 메서드에서 빠진부분이 없는지 컴퓨터가 점검해주는것 + Override를 통해 부가기능을 추가하는것이 장점이다.


3. 상속(Inheritance)

 

부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 추가로 작성하여 사용하면 되는것이다.

하단의 코드를 참조하길 바란다.

//부모클래스
class Tv{
    boolean power;
    boolean now_touch;
    
}

class Phone{
    boolean power;
    boolean now_touch;
}

class nintendo{
    boolean power;
    boolean now_touch;

}

간단한 예시로 TV, 핸드폰, 닌텐도 3기기 모두 공통적으로 power,touch 맴버를 선언하였다.

상단의 코드는 3개밖에 안되지만 예를들어 스타 유닛마다 체력,공격력,방어력을 저장할 변수를 만든다고 생각해봐라..... 굉장히 번거로운 작업일것이다.

이러한 문제점을 없애주는 기능이 상속이다.

쉽게 말해서 공통적으로 사용되는것을 만들어놓고(부모클래스) 필요할때마다 가져와서(상속해서) 사용하는것

//자식클래스 상속 예시
//class 자식클래스 extends 부모클래스{...}

//총 맴버는 power,now_touch,Tv_Channel 3개
class Tv_attribute extends Tv{		
    int Tv_Channel;
}

//총 맴버는 power,now_touch,app_name 3개
class Phone_attribute extends Phone{	
    string app_name;
}

//총 맴버는 power,now_touch,game_name 3개
class Nintendo_attribute extends Nintendo{	
    string game_name;
}

//총 맴버는 power,now_touch,game_name,stage_level 4개
class Nintendo_play_gmae extends Nintendo_attribute{	
    int stage_level;

}

상속의 특징

1. 자식클래스는 부모의 생성자, 초기화 블럭을 제외한 모든 맴버를 상속받는다. (부모가 아닌 부부모의 맴버도 상속이 된다)

2. 자바에서는 다중상속이 불가능 하다.(extends Nintendo,Phone 등은 불가능하다 -> 이것은 자바의 일반클래스가 부모 클래스를 1개만 가져야 하기 때문인데 클래스가 아닌 인터페이스를 이용한다면 다중 상속이 가능하긴 하다)

3. 접근제어자가 private을 갖는 필드나 메소드는 상속이 불가하고, 패키지가 다를 경우 접근제어자가 default인 경우도 상속이 불가하다.(접근제어자에 대한 내용은 별도 포스팅 예정)

4. 접근제한을 더 강하게 오버라이딩 할수없다.

5. 부모의 메서드와 동일한 시그너처(동일한 리턴타입, 동일한 메소드이름, 동일한 매개변수 리스트)를 가져야한다.

6. 상속으로 부모클래스의 메서드를 오버라이딩 해버린경우 부모클래스의 메서드는 숨겨지고 오버라이딩된 자식메서드만 사용되며 부모클래스의 메서드를 호출하려면 super키워드로 호출할수 있다..(만일 그렇지 않으면 ambiguous 오류 발생)

 


4. 다형성(polymorphism)

여러가지 형태를가질수 있는 능력 -> 가장 범용적인 예시로 오버로딩, 오버라이딩, 함수형 인터페이스 3가지 종류이다.

다형성을 한줄로 요약하자면 "조상타입 참조변수로 자손타입 객체를 다루는것"이다.

 

하단의 예시를 참조하길 바란다.

//다형성 설명용 코드
class Controller {	//인스턴스 5개 (power,channel,power(),channelUp(),channelDown())
    boolean power;
    int channel;

    void power()	{ power =!power;}
    void channelUp()	{ ++channel;	}
    void channelDown()  { --channel;	}

}

class SmartTv extends Controller{	//부모(Controller)가 자식(smarTv)
    String text;			//인스턴스 2개 (text,caption())
    void caption() {...}

}

// 기존 생성자를 활용한 코드
// 앞뒤의 타입이 일치함을 확인할수 있다.
Controller TvController = new Controller();
SmartTv STV = new SmartTv();	//(A)

//타입의 불일치 - 다형성 (B)
Controller TvController2 = new SmartTv();

 

Controller 타입(참조타입) TvController 변수는 Controller객체를 생성자로 받고

SmartTv 타입(참조타입) STV변수는 SmartTv생성자로 받고있다.

 

다형성이 적용된 코드(B)를 확인하면

Controller타입 TvController2 변수에 SmartTv를 생성자로 받고있는것이다.

두 코드의 차이점은 타입이 불일치 한다는것을 확인할 수 있는데 이것을 조금더 자세히 설명해보겠다.

 

상단에서 다형성이란 조상타입참조변수(Controller)가 자손타입 객체를 다루는것(SmartTv, TvController)이라고 설명을 해놨는데 일단 타입이 일치할때(A)와 일치하지 않을경우(B)의 차이부터 알아보자

 

(A)는 동일한 타입을 생성하기에(SmartTv-SmartTv) (A)가 사용가능한 맴버의 숫자는 7개이다. (Controller + SmartTv)

(B)의 타입이 다르기 때문에 맴버는 7개이나 사용가능한 맴버는 5개이다. (Controller)

 

그러면 제약이 더 많은것 같은데 다형성의 장점이 무엇이냐?

1. 유지보수가 쉽다. (상단 코드의 예시로 Controller만 건드리면 자식클래스도 모두 변경되기 때문이다.)

2. 느슨한 결합 (클래스간 의존성이 줄어들며 확장성이 늘어나고 결합도가 낮아 안정성이 높아진다. -> 참조타입이 달라도 사용이 가능하기 때문)

3. 재사용성 증가 (한번 선언해두면 필요할때마다 호출해서 사용이 가능하기때문 참조타입이 달라도 된다!)

 

조건

자손타입 참조변수로 조상타입 객체를 가리킬순 없다. (업캐스팅만 가능하다)

한가지 예시를 들면 갤럭시10(이하 "10v")에서 20(이하 "20v")으로 넘어갈때 터치기능 외에 스와이프 기능이 추가되었다 가정을해보자

그리고 10v에서 작성된 프로그램 (A)는 터치기능만 있으면 작동이 되지만

20v에서 작성된 프로그램이(B)는 터치기능과 스와이프가 필수로 필요하다고 가정을 했을때

10v에서 사용하던(A)는 20v에선 사용이 가능하다. -> 20v도 터치기능은 내장되있기 때문이다!

그러나 20v에서 사용하던(B)는 10v에선 사용이 불가능하다. -> 스와이프 기능이 없기 때문이다!

class phone10V{
	boolean touch;	//터치기능
}

class phone20V extends phone10V{
	boolean swape;	//스와이프기능
}


phone10V A = new phone20v();	//가능 - A는 터치만 있으면 사용가능
phone20V B = new phone10v();	//불가능 -	B는 스와이프까지 있어야 사용가능

'CS' 카테고리의 다른 글

프로세서, 프로세스  (0) 2023.03.21
주소 바인딩  (0) 2023.03.18
제네릭(Generic)  (0) 2023.03.14
객체 지향 프로그래밍 (OOP) - 2 (5대원칙)  (0) 2023.03.02
스택트레이스(Stack Trace)  (0) 2023.02.26

JPA (Java persistence API)

스프링 PSA에 의해서 (POJO를 사용하며 특정기술 사용을 위한) 표준 인터페이스를 정해두었는데 JPA의 자바의 ORM 기술의 EE표준중 1가지이다

JAP는 인터페이스이면서 동시에(라이브러리가 아님!) 구현체이므로 사용키 위해선 ORM 프레임워크를 선택해야한다

 

ORM (Object-Relation Mapping/객체-관계 매핑)

애플리케이션 Class와 RDB의 테이블을 연결해준다는뜻 으로 어플리케이션의 객체를 RDB(관계형 데이터베이스) 테이블에 자동으로 영속화 해주는 것이라고 보면 된다.

ORM은 DB테이블을 자바객체로 매핑하여 SQL을 자동으로 생상하지만 MAPPER는 SQL을 직접 명시해줘야한다

ORM - RDB(관계형 DB)의 관계를 Object에 반영하는것이 목적

Mapper - 단순 필드를 매핑시키는게 목적

 

DB 데이터 <- mapping -> Objcet필드  // 객체를 통한 간접적 DB데이터 

객체와 DB데이터의 자동매핑 (메서드를 통한 데이터 조작, 객체간 관계를 바탕으로 SQL 자동생성)

Persistant API라고 칭할수 있다.

 

장점

  • 객체와 테이블 자체를 매핑해서 패러다임의 불일치를 개발자대신 해결해준다.
  • SQL이 아닌 메소드로 DB를 조작해 개발자는 객체모델만을 이용해 비즈니스 로직구성에 집중 가능
  • 내부적으론 쿼리를 생성해서 DB를 조작하나 이것은 JPA가 해주는영역이다.
  • 매핑하는 정보는 Class로 명시되어 ERD(개체-관계모델)를 보는의존도를 낮고 유지보수, 리팩토링에 유리
  • MySQL DB를 사용하다 PostgreSQL로 변환시 기존DB를 PostgreSQL에 저장된 쿼리를 새로 짜야하는데 ORM은 자동으로 쿼리를 생성해주기에 부담이 적다.
  • JPA는 네이티브 SQL 기능을 제공해주는데 관계매핑, 성능에대한 우려가 있을때 SQL을 직접 작성해 사용가능

단점

  • 프로젝트 규모가 크고 복잡하여 설계가 잘못되는경우 속도저하 및 일관성을 무너뜨리는문제
  • 복잡하고 무거운 쿼리는 속도를 위해 별도의 튜닝이 필수적이기에 불가피하게 SQL을 사용해야 할수도 있따
  • 어렵고 비싸다...

개체관계모델 - (ERD)


패러다임의 불일치

객체나 DB간 불일치 하는것을 "패러다임의 불일치" 라고한다.

 

객체지향 VS 관계형DB

관계형DB와 객체지향은 갖고있는 사상이 다르다

객체지향 - 추상화, 캡슐화, 정보은닉, 상속, 다향성등 시스템 복잡성을 제어하는 다양한 장치 제공 (개발하기쉽게)

관계형 DB - 데이터 정규화를 통한 저장 (저장이 깔끔하게)

 

JPA는 애플리케이션과 JDBC 사이에서 동작하는데 JPA 내부에선 JDBC API를 사용하여 SQL을 호출하여 DB와 통신한다.

개발자가 ORM 프레임 워크에 저장하면 적절한 Insert SQL을 생성하여 DB생성하고 저장, 검색을 활용하면 적절한 SELECT SQL을 생성하여 객체에 매핑 및 전달

 

 

기존 EJB에서 제공되던 엔티티 빈을 대체하는 기술

객체를 통해 쿼리작성이 가능한 JPQL(Java Persistence Query Language)를 지원한다

JPA는 성능 향상을 위해 즉시로딩, 지연로딩등 몇가지 기법을 제공한다

 

#JAVA 표준은 Java SE(J2SE), Java EE(J2EE), JAVA ME(J2ME)가 있다? //다른페이지에 작성예정

 

 

자바컬렉션

 

JPA 1 - 2006년 -> 초기버전, 복합기 연관관계 기능부족

JPA 2 - 2009년 -> 대부분의 ORM 기능 포함, JAP Criteria가 추가

JPA 2.1 2013년 -> 스토어드 프로시저 접근, 컨버터, 엔티티 그래프 기능 추가

 

빌드그레이들 파일에서 확인후 인텔리제이에선 

 

spring이 자동으로 적용해준다....

JDBC

 

SQL Mapper

JDBC는 SQL로 DB에 직접 접근할수 있도록자바에서 제공하는 API이며 Mybatis, jdbcTemplate이 그 예시다.

 

SQL<-Mapping-> Object 필드

JDBC 예시

 

 

 

TABLE - SQL용어로 DB에 들어가는 값을 구분해주는 KEY가 되는것이라 생각하면 된다.

 

//SQL 생성문
CREATE TABLE emp_table
(   emp_id      NUMBER           NOT NULL,			// DB에 보낼때 id는 emp_id에 기입
    emp_name    VARCHAR2(100)    NOT NULL,			// DB에 보낼때 이름은 emp_name에 기입
    gender      VARCHAR2(10)         NULL,			// DB에 보낼때 성별은 gender에 기입
    age         NUMBER               NULL,			// DB에 보낼때 나이는 age에
    hire_date   DATE                 NULL,			// DB에 보낼때 생년월일은 hire_date에 기입
    etc         VARCHAR2(300)        NULL,			// DB에 보낼때 기타 내용은 etc에 기입
    PRIMARY KEY (emp_id)                  );
    
//SQL 값 기입    
    INSERT INTO 	emp_table (emp_id, emp_name, gender, age, hire_date)
     	 VALUES 	(1, '홍길동', '남성', 33, '2018-01-01');
    INSERT INTO 	emp_table (emp_id, emp_name, gender, age, hire_date)
         VALUES 	(2, '김유신', '남성', 44, '2018-02-01');
    INSERT INTO 	emp_table (emp_id, emp_name, gender, age, hire_date)
         VALUES 	(3, '강감찬', '남성', 55, '2018-03-01');
    INSERT INTO 	emp_table (emp_id, emp_name, gender, age, hire_date)
         VALUES 	(4, '신사임당', '여성', 66, '2018-04-01');
    COMMIT;
    
    
    
    //JPA 사용 예시

동작사진

 

JPA는 애플리케이션과 JDBC 사이에서 동작한다

개발자가 JPA를 사용시 JPA 내부에선 JBCD API를 사용해 SQL을 호출하여 DB와 통신한다

즉, 개발자도 직접JDBC API를 호출하는게 아닌 JPA에 요청하면 여기에 내장된 JDBC API가 혼자 작동하는것

MemberDao에서 객체를 저장하고 싶을경우

 

개발자 : JPA에 Member 객체를 넘긴다 (개발자의 행동은 여기서 끝난다)

JPA : Member 엔티티 분석 -> INSERT SQL (삽입용)을 생성한다 -> JDBC API를 사용하여 SQL을 DB에 넣는다

  • 엔티티에 필드 추가시 등록,수정,조회 관련 코드 모두 변경하는데 이것을 JPA가 모두 진행
  • JPA는 수정메소드를 제공하지 않고 매핑된 데이터(테이블 데이터)를 조회하여 값을변경후 커밋하면 DB서버에 UPDATE문을 전송하여 혼자 UPDATE를 실행한다.

Member 조회기

개발자 : Member의 pk값을 JPA에 넘긴다

JPA : 엔티티의 매핑정보 기반 적절한 SELECT SQL을 생성 -> JDBC API를 사용해 SQL을 DB에 요청 -> DB로부터 결과를 받아 결과(ResultSet)를 모두매핑한다

쿼리가 JPA를 만들어주기에 Object와 RDB간 패러다임 불일치를 해결할수 있다.

 

 

객체와 관계형DB의 차이점

 

1. 상속관계

JAP는 객체의 참조로 연관관계 저장가능 -> 

객체상속관계 : 부모가 값이 바뀌면 자식도 바뀌나 반대의경우는 그렇지 않다?

객체상속 관계에선 extnds, implements로 상속관계를 맺고 부모<->자식의 캐스팅(형변환)도 자유롭다 

  • 상속 받은 객체 (Album, Movie, Book)을 DB에 저장하려면 객체분해를 통해  Album객체를 Item과 분리해야하며 Item Table에 1개, Album 테이블에 2개의 쿼리를 작성해야한다.
  • Album 객체를 DB에서 조회하러면 ITEM과 ALBUM을 조인해 가져온뒤 조회한 필드를 각각 맞는 객체(ITEM, ALBUM)에 매핑시켜 가져와야한다.

(쿼리 - DB에 데이터를 요청하는것)

 

JPA와 상속 관계 비교사진

2. 연관관계

객체는 참조를 사용하며 테이블은 외래키를 사용한다.

Member와 Team간 참조가 가능한가?

객체관게 : Member은 member.getTeam()의 형태로 참조가능, 반대의 경우는 참조불가

테이블관계 : 쌍방간 참조할 키(FK?)가 있기에 양측 참조가 가능

 

//외래키 - SQL 글에서 작성예정


 

 

RDB 

 

ORM이란?

Object-Relational Mapping

자바의 객체와 관계형DB를 맵핑하는 것으로 DB의 특정테이블이 자바의 객체로 맴핑되어 SQL을 일일이 작성하지 않고 객체로 구현할 수 있도록 하는 프레임워크이다.

 

객체와 관계형 dB를 매핑한다는 뜻

ORM 프레임워크를 사용하면 객체를마치 자바 컬렉션에 저장하듯 저장하고 이에대해 ORM 프레임워크가 적절한 SQL을 생성해서 DB에 객체를 저장해준다

 

Hibernate

에서 가장 자주사용되는 프레임워크

Hibernate기반으로 만들어진게 ORM기술표준이 JPA다

JPA는 ORM기술표준이 구현한게 Hibernate 이므로 JPA를 사용하려면 Hibernate를 사용하면 된다.


DDL (Data Definition Language) - 객체생성,변경,삭제 명령어로 schema, domain, table, view, index를 정의,변경,삭

ㄴ>종류 = create(생성), alter(변경,수정), drop(삭제), rename(재정의)

DML (Data Manipulation Language) - 데이터 조작어 (제어 명령어)  

ㄴ>종류 = select(선택), insert(삽입), update(변경,수정), delete(삭제)

DCL (Data Control Language) - 객체 권한 부여 데이터의 보안, 무결성, 데이터 회복, 병행 수행 제어 등을 정의하는 데 사용하는 언어입니다. DB 관리자의 DB 관리목적

종류 = commit, rollback, grant, revoke

 

DELETE, DROP, TRUNCATE 차이점

DELETE - 데이터는 지워지나 용량은 줄지 않는다 - 테이블 남기기 (되돌리기 가능) 

TRUNCATE - 용량이 줄고 인덱스등이 삭제되며 테이블만 잔존한다 - 테이블도 날리기 (되돌리기X)  

DROP - 테이블 전체, 공간, 객체 삭제 - 전부삭제 (되돌리기X)

DB 관련 내용은 블로그내 다른글을 참조해주세요


사용하는 이유

1.JPA를 사용하면 자바 컬렉션에 저장하듯이 JPA 에게도 저장할 객체를 전달하면 된다.

코드의 간소화, 가독성 및 수정 용이

MySQL등 DB 벤더에따라 조금씩 다른SQL 문법때문에 애플리케이션이 DB에 종속되나 JPA는 직접 쿼리작성을 안해서 DB벤더에 독립적 개발이 가능하다.

CRUD 형태

  • 저장: jpa.persist(member)
  • 조회: Member member = jpa.find(memberId)
  • 수정: member.setName("변경할 이름")
  • 삭제: jpa.remove(member)

DDL문도 자동으로 생성해주기에 DB 설계 중심을 객체설계 중심으로 변경이 가능

 

 

2. 필드를 1개만 추가해도 SQL과 JDBC코드를 전부 수행해야했지만 JPA는 이를 대신 처리해주기에 개발자가 보다 maintenance(유지보수)  해야하는 코드가 줄어든다

 

객체와 관계형 DB를 매핑한다는 뜻이다.

 

3.패러다임의 불일치 해결

JAP는 연관객체 사용 시점에 SQL에 전달가능, 같은 트랜잭션 내에서 조회할때 동일성도 보장하기에 다양한 패러다임의 불일치를 해결한다.

 

4.성능

애플리케이션과 DB사이엔 성능 최적화 기회를 제공한다.

같은 트랜잭션 안에서는 같은엔티티를 반환하기 떄문에 DB와의 통신 횟수를 줄일수 있다.

또한 트랜잭션을 커밋하기전까지 메모리에 쌓고 한번에 SQL에 송신한다.

 

5. 데이터 접근 추상화와 벤더 독립성

RDB는 동일기능이라도 벤더마다 사용법이 달라 처음의 DB에 종속되고 변경이 어렵다

JPA는 DB 사이에서 추상화된 데이터 접근을 제공키에 종속이 되지 않도록한다.

DB가 변경되더라도 JAP에게 알려주면 변경이 가능하다.

 

6.JPA가 제공하는 API를 사용하면 객체를 DB에 저장하고 관리할때 개발자가 직접 SQL을 작성하지 않아도 된다.

JPA가 개발자 대신 적절한 SQL을 생성해서 DB에 전달 및 객체를 자동으로 매핑해준다

JPA는 내부적으로 JDBC API를 사용하는데 개발자가 직접 JDBC API를 활용하면

 

7. SQL 중심적인 개발에서 객체 중심으로 개발

 

SQL을 직접 다룰때의 문제점

1.생산성 저하

ㄴ> 100개의 테이블이 존재하면 100개의 CRUD를 일일이 작성해야한다. 그렇지만

CRUD - Create(생성), Read(읽기), Update(갱신), Delete(삭제)를 앞글자를 따서 만든 단어

(SQL은 작성, JDBC API로 SQl실행, 결과를 객체로 매핑)

 

2.SQL 의존적 개발

테이블에 1개의 칼럼을 추가하려면?

모든 SQL의 변경이 필요,

DDL 관련 모든 쿼리와 메소드의 변경필요

버그 발생시 직업 DAO를 열어 SQL을 확인해얗나다

ㄴ> 논리적인 계층 분할이 어렵다

 

3.패러다임의 불일치

하단참조

4. 객체 그래프 탐색

객체는 자유롭게 그래프 탐색이 가능해야하나 SQL을 이용해 조회한경우 초기 SQL에 따라 탐색범위가 저장되기에 제약이 발생한다 -> 이것때문에 DAO를 직접 열어서 SQL을 확인해야 탐색이 가능하다

(Member객체 에서 그래프를 통해 Category 까지 접근이 가능해야한다)

탐색예시

 

비교 - DB는 기본키의 값으로 구분하나 객체는 동일설비교(주소 비교 "=="), 동등성 비교(값 비교 "equlas()" ) 2가지가 있다

SQL을 통하여 기본키가 같은 객체를 불러와 매핑하면 동일성을 비교할때 false가 출려괴는데같은 로우지만 다른 인스턴스로비교하기 때문이다.

 

 

ORM 프레임워크 - 객체와 테이블의 매핑만 진행하면 대신 해결해준다객체는 객체끼리 알아서 생성하고 DB는DB끼리 맞도록 설계가 가능해진다.

 

지연로딩 - 객체가 실제로 사용될때 로딩하는 전략?

값이 필요한 시점에 JPA가 Team에 대한 SELECT쿼리를 날린다.

Member 및 Team 객체 각각 따로 조회하기에 네트워크를 2번타는데 Member를 사용시 TEAM도 필요하면 즉시 사용한다.

 

즉시로딩 - JOIN SQL로 한번에 연관된 객체까지 미리 조회하는 전략

Join을 통하여 연관객체 모두를 전부 가져온다

 

 

 

객체를영구보관하는 저장소 종류

RDB - 가장 많이쓰이는것

NoSQL - 2안으로 자주 채택

File - 객체 100만개를 Serialize(직렬화)하여 정렬하고 

 

 

 

쿼리의 불일치

비즈니스 로직

JDBC Template

CRUD 쿼리에 TEL을 하나씩 다 추가해줘야한다?

UPDTAE MEMBER SET ...TEL = ?

벤더독립성

 

동일성(identical)과 동등성(Equivalent)

동일한 오브젝트 - 같은 레퍼런스를 바라보고 있는 객체라는말 (1개의 오브젝트이다) // "=="

동등한 오브젝트 - 같은 내용을 담고 있는 객체인지? // "equals" 

 

 

 

 

참고사이트

https://girawhale.tistory.com/119

https://velog.io/@adam2/JPA%EB%8A%94-%EB%8F%84%EB%8D%B0%EC%B2%B4-%EB%AD%98%EA%B9%8C-orm-%EC%98%81%EC%86%8D%EC%84%B1-hibernate-spring-data-jpa

https://kim-oriental.tistory.com/20

https://velog.io/@jwkim/JPA-JPA%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

https://gmlwjd9405.github.io/2019/08/04/what-is-jpa.html

https://wikidocs.net/4021

https://velog.io/@ek1816/SQL-%EA%B8%B0%EC%B4%88-1

https://catsbi.oopy.io/0a48ff61-ee46-4909-b5b4-d5f63937195f

'JAVA' 카테고리의 다른 글

클래스 변수,인스턴스 변수  (0) 2023.01.30
인터페이스란?  (0) 2023.01.13
지수와 가수  (0) 2023.01.13
3항 연산자에 관하여  (0) 2022.12.22
라이브러리와 프레임워크  (0) 2022.12.20

코딩을 하는도중 조건부 로직을 설계하려고 할때 if문을 자주 사용하나 이것이 길어질경우 가독성이 떨어져 버그를 찾기위해 코드를 다시 열어보더라도 내가 한게 맞는지 싶을정도로 헷갈리는게 많습니다.

여기 페이지에선 이러한 문제를 줄이기 위하여 3항 연산자라는 개념에 대해 설명하려고 합니다.


3항연산자

2개 이상 변수를 비교할때 if-else의 대체로 쓸수 있는 연산자로

기본 형태는 : "(조건) ? true : false;" 이다.

//3항 연산자 기본형태

String cc = (5>4) ? "Answer" : "no";	// 5>4인경우? 맞으면 Answer, 틀리면no
int b = (5 > 4) ? 5 : 0;				// 5>4인경우? 맞으면 5, 틀리면0

System.out.println(b);
System.out.println(cc);

if(5>4){
	System.out.println("정답입니다");
}
else{
	System.out.println("틀렸습니다");
}

 

왜쓰는가?

3항연산자와 if-else의 가장큰 차이점은 표현식(3항 연산자)과 명령문(if-else)의 차이이다.

  • 표현식(expression)은 항상 어떠한 값을 계산하며 단일 값으로 평가되는 코드이다
  • 표현식이 모여서 명령문(statement)을 만드며 명령문은 하나의 실행 단위로 존재한다.

표현식은 값을 계산하지만, 명령문은 결과값을 어떤 변수에 할당 및 함수의 인수로 넘겨주는것은 할수없습니다.

그렇지만 대부분의 경우 if 문은 명령문 그 이상 동작을 수행합니다. 이들은 부수효과를 발생시키고 변수를 변경합니다. 부수효과의 영향과 가변적인 공유변수를 다루는 제어 흐름을 완전히 파악하지 못한다면 if 문이 작동하는 모든 그림을 볼 수 없습니다.

 

장점

  • 삼항 연산자는 임시 변수를 필요로하지 않으므로 단기기억력의 부하가 줄어 듭니다.
  • 삼항식은 신호 대 잡음비가 더 좋습니다. - 버그가 날시 원인을 찾기 쉽다
  • if문은 부수작용과 변이를 권장하지만, 삼항연산자는 순수한 코드를 권장합니다.
  • if보다 연산이 빠르다 - 과거보다 처리속도가 빨라져 if를 사용해도 되지만 프로그램 성능이 중요시 된다면 삼항 연산자를 쓸것

 

단점

  • 브레이크 포인트를 만들수 없다
  • 조건에 따른 결과를 쉽게 이해하기엔 어렵다 - IF는 문제발생시 시험용객체를넣어 어디가 문제인지 확인이 가능하지만 3항연산자는불가능하다 (0 또는 1만 나오기떄문)
// 함수적이지 않은함수 예시
// b가 0인경우 에러가 발생한다.
public static int div(int a, int b) {		
  return a / b;
}


// 변경한 함수
public static int div(int a, int b) {
  return (int) (a / (float) b);
}

 

부수효과

부수 효과는 함수 내의 실행으로 인해 함수 외부가 영향을 받는 것을 의미한다. 함수의 매개 변수의 값이 변경되어, 이로 인해 함수를 사용하는 코드에 영향을 주거나, 함수의 외부 세계인 데이터베이스, 파일 시스템, 네트워크로 데이터 이동이 함수 실행 중에는 발생하지 않아야 함수형 코드가 된다.

 

https://jinwooe.wordpress.com/2017/12/21/%EB%B6%80%EC%88%98-%ED%9A%A8%EA%B3%BC-side-effect-%EC%B0%B8%EC%A1%B0-%ED%88%AC%EB%AA%85%EC%84%B1-referential-transparency/

https://yceffort.kr/2022/02/think-about-ternary-operator

https://tpgns.github.io/2018/04/24/nested-ternaries-are-great/#fnref1

'JAVA' 카테고리의 다른 글

클래스 변수,인스턴스 변수  (0) 2023.01.30
인터페이스란?  (0) 2023.01.13
지수와 가수  (0) 2023.01.13
JPA란 무엇인가  (0) 2022.12.23
라이브러리와 프레임워크  (0) 2022.12.20

공통점 - 누군가가 이미 작성한 코드를 가져와 사용하는것

차이점 - 누가 누구를 컨트롤하는가가 2개를 가르는요소

 

라이브러리

코딩중 내가 필요할때마다 가져와서 사용하는것

Java -> Import, C -> <.h>, 파이썬 -> 패키지

 

Java기준 

리스트 선언시 String [] 의 형태로 선언이 가능하지만 메모리 공간의 효율을 위해 ArrayList를 사용하려는데 이럴때 사용하는게 라이브러리를 import 하는것

 

import java.util.ArrayList;

 

프레임워크

특정 운영체제에서 응용 프로그램 표준구조를 구현하는 클래스와 라이브러리 모음

즉, 프레임워크에서 정의한 규칙에 따라 코드를 작성해야하는것 (diango)

'JAVA' 카테고리의 다른 글

클래스 변수,인스턴스 변수  (0) 2023.01.30
인터페이스란?  (0) 2023.01.13
지수와 가수  (0) 2023.01.13
JPA란 무엇인가  (0) 2022.12.23
3항 연산자에 관하여  (0) 2022.12.22

+ Recent posts