본문 바로가기
Backend

05월 28일 화 | OOP 09 - JAVA의 Method (재귀함수, 메소드오버로딩)과 JVM구조

by 구라미 2019. 5. 28.

8. 자바의 메소드

재귀적 함수호출

재귀적 함수호출은 자신의 함수를 호출하는 것이다.

내가 나를 불러내는 것. 프로그래밍할 시 정말정말 많이 쓰이는 기능이다.

예시) 시계 - 시간이라는 것은 

 

package oop0524;

public class Test01_Method {
	
	public static void test(){ //함수를 정의한 부분
		test();	//내가 나를 불렀음, 재귀적 호출	
	}//test() end
	

	public static void main(String[] args) {
		//재귀적 함수 호출
		//-> 자신이 자신의 함수를 호출
		

	}//main end
}//class end

메소드 문법 잘 숙지하기

▶ 풀이

test함수안에서 test();을 선언하였다.

함수안에 함수명(); 이런 식으로 자신의 함수를 자신이 다시 호출할 수 있다.

이를 재귀함수라고 한다.

 

이런 식으로 사용한다.

package oop0524;

public class Test01_Method {
	
	public static void test(){ //함수를 정의한 부분
		test();	//내가 나를 불렀음, 재귀적 호출	
	}//test() end
	
	public static long fact(int a){
		if(a==0){
			return 1;
		}
		else{
			return a*fact(a-1); //내가 다를 다시 불러서 이용했다.
		}
	}//fact() end
	

	public static void main(String[] args) {
		//재귀적 함수 호출
		//-> 자신이 자신의 함수를 호출
		
		long result = fact(3); //result변수의 반환값이 있다. 자료형존재
		System.out.println(result);
		

	}//main end
}//class end

a=3 if(3==0)

  else return 3*fact(3-1)

                     a =2 if(2==0)

                           else return 2*fact(2-1)

                                     a=1 1 if(1==0)

                                           else return 1*fact(1-1)

                                                 a=0 if(0==0) 1

a값이 계속 달라지고 있다.

그 다음 *연산을 반복한 후 if문조건을 만족할때 1 return하고 종료.

▶ 풀이

fact라는 자료형 long을 리턴하는 함수를 선언하고 매개변수를 정수 a로 받는다.

만일 a값이 0과 같다면 1을 리턴하고,

그 외는 a값과 fact(a-1)을 곱한 값을 다시 리턴한다. 여기서 fact함수안에서 fact함수를 다시 호출한 형태가 된다.

곱셈의 반복이 진행될 수록 값이 엄청 커질 수 있으므로 long으로 해주었다.

 

 

 

자바 클래스(.class) 실행순서

 

재귀함수는 이렇게 자신이 자신을 호출할 수 있는 함수라고 했다.

이런 식으로 main 함수를 부를 수도 있지 않을까. 함수니까 그러나.. 다른 함수와 다르게

사용자가 임의의 호출 불가능하다.

-> 클래스가 실행될 때.

-> 자바가상머신 (Java Virtual Machine)

-> 호출한다.

 

자바가상머신/

학습모듈에 있는 걸 전부 수업하지는 않음.

 

main()함수 호출 후 .class 실행

---------------------------------------------------

JVM(이란 가상머신이 상주) -> Javaw.exe

 

Java는 OS를 가리지 않는다. 플랫폼이 독립되어있다.

메모리안에 JVM을 설치하고 -> 실행

 

 

컴퓨터를 실행할때 운영체제(OS)가 제일 먼저 불러짐.

OS가 메모리에 상주하게 되면 컴퓨터로 여러가지 일을 수행할 수 있다.

보조기억장치에 있는 걸 RAM으로 불러와서 작업한 후 보조기억장치에 다시 기억.

 

main()함수

자바가상머신/

public static void main(String[] args)

이클립스에서도 테스트할 수 있지만 DOS로 테스트해보기.

 

Plus 클래스틀 만들어서 DOS로 실행해보았다.

 

copy - 복사

del - 삭제

rename - 이름수정

type Plus.java - 메모장수정..?

 

자바는 다른 것을 끌어다 쓴다. 

그래서 환경변수를 설정해줘야한다.

 

환경변수 설정하기

  - 환경변수 설정하지 않으면 컴파일 안됨.
  - 내컴퓨터->속성->고급 시스템 설정->설정변경
            -> 고급-> 환경변수-> 시스템변수 ->

  ① JAVA_HOME 환경변수 C:\Program Files\Java\jdk1.8.0_161

JAVA_HOME  - DOS변수

 

  ② Path 편집 (삭제 절대 안됨)    
     마지막 문장 뒤에 ; 추가 -> ;%JAVA_HOME%\bin

  ③ CLASSPATH 환경변수 (콘솔창에서 자바클래스를 직접 실행할 경우 추가)
     .;%JAVA_HOME%\lib\tools.jar;

  ④ 자바버전확인 : 시작-> cmd -> java  -version

 

*환경변수 설정하기 찾아서 해보기.

* ; (세미콜론)으로 구분.

언제 어디서나 자바를 인식시키기 위해 경로잡는 것이다.

초기 환경설정 때 경로설정하는 것 매우매우매우 중요.

 

자바설치경로 c드라이브 root경로로 해놓는 게 좋다.

클래스 이름 정할때 예약어스러운 것들은 피하기.

Plus 클래스명에 문제가 있었어서 MainTest로 변경하였다.

public class MainTest {

   public static void main(String[] args) {

	System.out.println("main()함수에 값 전달 연습");
        
        for(int idx=0; idx<args.length; idx++){
        System.out.println(args[idx]);
        }   

   }//main end
}//class end

idx는 1차원배열의 갯수만큼 증가반복.

 

CMD에 MainTest 클래스에 SEOUL JEJU BUSAN을 쳐주고 실행했더니

값이 들어와서 For문이 실행되었다. 

이 값은 어떤 값이든 들어갈 때 대부분 String값으로 들어간다.

다른 값을 넣어주었을 때도 동일하게 적용이 된다.

String 값으로 들어가므로 위의 5 4 3은 "5" "4" "3"과 같다.

대부분의 언어에서 핸드폰번호,우편번호 등이 숫자처럼 생겼지만 String형으로 관리한다.

-> 그렇게 해야 관리하기 쉽기 때문에.

 

 

메소드 오버로딩

메소드 오버로딩은 함수명의 중복정의이다.

 

package oop0524;

public class Test02_OverLoading {
	
	public static void print(int a){
		System.out.println(a);
		
	}//print end
	
	public static void print(int a, int b){ //동일한 이름의 함수가 선언되었지만 오류가 아니다.
		
	}//print end

	public static void main(String[] args) {		
		
		
		
	}//main end
}//class end

함수명 print가 두번 선언되었지만 오류가 나지 않았다.

단, 무언가 두 함수가 다름을 알 수 있는 것이 있어야한다.

위와 같은 경우는 매개변수의 갯수가 달랐다. 

그래서 함수 print를 각각 다른 함수로 인식한다.

자바를 배우면서 구조화된 시스템을 많이 마주하게 될 것이다.

자동으로 세팅이 다 되어져있다는 것.

 

함수명을 같이 써도 오류가 생기지 않으려면 (다른 함수로 인식되게 하려면)

1) 매개변수의 갯수가 다를 때

2) 매개변수의 자료형이 다를 때

 

package oop0524;

public class Test02_OverLoading {
	
	//1번
	public static void print(int a){
		System.out.println(a);
		
	}//print end
	
	//2번
	public static void print(int a, int b){ //동일한 이름의 함수가 선언되었지만 오류가 아니다.
		System.out.println(a);
		System.out.println(b);
	}//print end
	
	//3번
	public static void print(double a){
		System.out.println(a);
		
	}//print end
	
	//4번
	public static void print(double a, double b){
		System.out.println(a);
		System.out.println(b);
		
	}//print end
	
	//5번
	public static int print(int a){ //오류발생
		
	}//print end	

	public static void main(String[] args) {		
		print(3);  //1번
		print(2,4);  //2번
		print(5.6);  //3번
		print(7.2,8.3);  //4번	
		
	}//main end
}//class end

*함수의 리턴형은 오버로딩의 대상이 아니다.

그러므로 함수의 리턴형을 다르게 한다고 함수명 중복이 용인되는 것이 아님.

 

api에서 오버로딩은 어디서부터 어디까지 사용할 수 있는지 알려줌.

		System.out.println(Math.abs(3));  //int
		System.out.println(Math.abs(5L));  //long
		System.out.println(Math.abs(1.2f));//float
		System.out.println(Math.abs(4.6d));//double

 

 


 

Sort 정렬

특정한 키를 기준으로 순서대로 재배치하는 것을 sort 정렬이라고 한다.

 

정렬의 유형

1. 오름차순 ascending ASC

예) 1,2,3,4... 또는 ㄱㄴㄷㄹㅁ.... 1->10 , 알파벳이라면 대->소 (알파벳 아스키코드값이 대문자가 더 작기 때문에)

 

2. 내림차순 descending DESC 

예) 5,4,3,2,1... 또는  ㅎ->ㄱ

 

* DB에서 가져올때는  DB에서 자료를 정렬해서 자바로 가져온다.

그렇지 않으면 아주 골치아파짐.

 

9 7 5 3 1 -> 1 3 5 7 9

a a+1

if (  > )  {tmp=a, a=b, b=tmp}

 

정렬의 방법

1. 삽입정렬 (insertion sort)

각 숫자를 적절한 위치에 삽입하는 방법으로 문제해결하는 알고리즘.

기본적으로 '정렬이 되어있다고 가정'한다는 점에서 특정경우에 따라 굉장히 빠른 속도 자랑.

삽입정렬의 시간 복잡도는 O(N^2)

 

 

2. 선택정렬 (selection sort)

가장 작은 것을 선택해서 제일 앞으로 보내는 알고리즘

가장 원시적이고 기초적인 방법

앞부분 부터 정렬된다.

선택정렬의 시간 복잡도는 O(N^2)

 

9 7 5 3 1 -> 1 3 5 7 9

 

9 7 5 3 1

7 9 5 3 1

5 9 7 3 1

3 9 7 5 1

1 9 7 5 3 

----------- 1회전 완

1 7 9 5 3

1 5 9 7 3

1 3 9 7 5

----------- 2회전 완

1 3 7 9 5

1 3 5 9 7

----------- 3회전 완

1 3 5 7 9

----------- 4회전 완 //4회전 만에 오름차순 정렬되었다.

n-1 단계만에 sort가 되었다.

 

사각형안이 기준값

 

 

3. 버블정렬 (bubble sort)

뒤부터 차례차례 정렬되기 시작한다.

 

9 7 5 3 1 -> 1 3 5 7 9

 

9 7 5 3 1

7 9 5 3 1

7 5 9 3 1

7 5 3 9 1

7 5 3 1 9

----------- 1회전 완

5 7 3 1 9

5 3 7 1 9

5 3 1 7 9

----------- 2회전 완

3 5 1 7 9

3 1 5 7 9

----------- 3회전 완

1 3 5 7 9

----------- 4회전 완 // 정렬완료

 

//정렬 알고리즘
		
int[] su = {9,7,5,3,1};
int tmp;
		
//연습문제 1) selection sort 알고리즘을 이용해서
//오름차순 정렬 후 출력하시오.
System.out.print("선택정렬 오름차순은: ");
		
for(int a =0; a<su.length-1; a++){ //-1 들어가야함
	for(int b=a+1; b<su.length; b++){ //자기자신과 비교할 필요가 없기 때문에 a+1 부터.
		if(su[a]>su[b]){ //크기 비교해서 
			tmp = su[b]; //tmp변수에 작은 값을 넣기
			su[b] = su[a]; //작은 값 있던 위치에 큰 값을 넣기
			su[a] = tmp; //큰 값 있던 위치에 아까 임시로 tmp에 넣었던 작은 값을 넣기				
		}//if end
	}//for end
}//for end
		
for(int a = 0; a<su.length; a++){
	System.out.print(su[a]+" ");
}
System.out.println();
System.out.println("------------------------------");
		
//연습문제 2) bubble sort 알고리즘을 이용해서
//내림차순 정렬 후 출력하시오.
System.out.print("버블정렬 내림차순은: ");
		
for(int a =0; a<su.length-1; a++){ //뒤 부터 정렬이기 때문에?
	for(int b=a+1; b<su.length; b++){ //자기자신과 비교할 필요가 없기 때문에 a+1 부터.
		if(su[a]<su[b]){ //b는 a+1이니까 a가 b(a+1)보다 작으면 뒤로
			tmp = su[a]; //작은 값이 뒤로 밀리는. swap
			su[a] = su[b];
			su[b] =tmp;					
		}//if end
			
		}//for end
	}//for end
		
for(int a = 0; a<su.length; a++){
	System.out.print(su[a]+" ");
}
        
        
//결과값
//	선택정렬 오름차순은: 1 3 5 7 9 
//	------------------------------
//	버블정렬 내림차순은: 9 7 5 3 1 

부등호의 위치에 따라 정렬방향이 달라진다.

 

 

■  선생님 답안  

//연습문제 1) selection sort 알고리즘을 이용해서
//내림차순 정렬 후 출력하시오.
System.out.print("선택정렬 오름차순은: ");
for(int a=0; a<su.length-1; a++){
    for(int b=a+1; b<su.length; b++){
        if(su[a]>su[b]) {   //오름차순
           int tmp=su[a];
           su[a]=su[b];
           su[b]=tmp;
         }//swap
      }
   }//for end
        
for(int idx=0; idx<su.length; idx++){
    System.out.print(su[idx]+" ");
}//for end
        
System.out.println();    

//결과값
//1 3 5 7 9


//연습문제 2) bubble sort 알고리즘을 이용해서
//내림차순 정렬 후 출력하시오.
System.out.print("버블정렬 내림차순은: ");
		
		
for(int a = 3; a>=0; a--){ 
	for(int b=0; b<=a; b++){ //회전수 감소, 역삼각형 만들기 참고.
    	if(su[b] < su[b+1]){ //값 두개 비교, 만약 앞의 값이 뒤의 값보다 크다면,
        	tmp = su[b+1]; //큰 값(su[b+1])을 tmp변수에 대입
            su[b+1]=su[b]; //su[b+1]위치에 작은값(su[b])을 대입 
            su[b]=tmp;  //작은 값 위치에 tmp에 있던 값 대입
		}//swap
	}//for end
}//for end
				
for(int a = 0; a<su.length; a++){
	System.out.print(su[a]+" ");
}

//결과값
//9 7 5 3 1

▶ 풀이

1) 선택정렬로 오름차순 정렬

정렬은 기준값과 그 다음차례 오는 값들을 비교하면서 순서를 정리하는 과정이다.

su라는 배열의 9 7 5 3 1을 오름차순 (작은것 -> 큰것) 으로 정렬해야한다.

1. for문을 작성해

기준이 될 순번이 될 정수 a를 0으로 선언하고 (기준은 총 갯수 -1) a의 범위는 su.length-1, 1씩 증가한다.

2. 그 안의 for문은 기준과 비교할 값의 순번이 늘어나는 문장인데 b번째의 값은

a번째의 값과 비교해야(그래서 a의 다음값부터)하므로 b=a+1으로 초기값을 정해준다. 

범위는 <su.length; 로 끝까지 정해주고 1씩 증가한다.

3. if 조건문을 만들어주는데

3-1. 배열su의 a번째값과 b번째값과 비교해서 a번째 값이 크다면

3-2. swap을 위해 만든 변수 tmp에 작은 값인 b번째 값을 담아준다.

3-3. b번째 값(그릇)에 아까 비교해서 큰 값이 a번째 값을 넣어준다 <- 큰 값이 뒤로 밀린 것이다.

3-4. 큰 값이 있던 a번째 값(그릇)에 변수 tmp의 값을 넣어준다 <- 작은 값이 앞으로 온 것이다.

4. 위 조건을 배열의 갯수(길이) 만큼 반복한다.

5. for문으로 정렬된 배열의 원소들을 순서대로 출력한다.

 

2) 버블정렬로 내림차순 정렬

버블정렬은 양옆의 값들을 비교하며 정렬하는 것이다.

*회전수 감소, 역삼각형 만들기를 참고

1. for문의 a의 값을 3 (0 1 2 3 4인 배열이다 기준값인 a가 마지막 번호-1이므로 그래서 3이됨 )으로 정해주고

범위는 a는 0과 같거나 크다. a는 1씩 감소한다. (내림차순 만들어주기)

2. 그 안의 for문 b의 값은 0으로 b의 범위는 a와 같거나 작다. b는 1씩 증가한다. <- 이게 기준값

3. if 조건문을 만들어주는데

3-1. b번째 값과 b+1번째(기준 값의 다음 차례값)을 비교해서 b+1가 b보다 크다면

3-2. swap을 위해 만든 변수 tmp에 큰 값인 b+1번째 값을 담아준다.

3-3. b+1번째 값에 b의 값을 담아준다.

3-4. b의 값에 tmp의 값을 담아준다.

4. 위 조건을 배열의 갯수(길이) 만큼 반복한다.

5. for문으로 정렬된 배열의 원소들을 순서대로 출력한다.

 

 

 

sort 함수도 있음.

함수명이 같은데 여러개 있다 -> 오버로딩

매개변수와 자료형이 다르면 오버로딩이 가능하다.

import로 경로를 연결하는 것이다.

사용하고자 하는 클래스의 패키지 선언하는 것인데

import는 Ctrl + Space로 불러오면 자동 코딩된다.

 

package oop0528; //.java 파일에서 한번만 선언한다.

import java.util.*; //*자리에는 사용하고자 하는 클래스의 패키지 선언
import java.io.*;
import java.sql.*;

Arrays 클래스를 이용하여 오름차순 정렬하기.

//Arrays클래스를 이용해서 오름차순 정렬하기.
Arrays.sort(su); //ascending sort
		
for(int a = 0; a<su.length; a++){
	System.out.print(su[a]+" ");
}

 

지난 주 과제 중

문제4) 로또 추첨기 1~45사이 중에서 서로 겹치지 않게 번호 출력하기.

 

등수

if( 자신 <  ) { rank+1}  // 등수 알고리즘 옆에 있는 애가 나보다 크면 나는 등수가 +1만큼 밀려난다.

 

정렬 오름차순

if( 자신 > ) { swap } //내가 옆에 있는 애보다 크면 자리 바꾸기.

 

로또번호

if( 자신 ==  ) { random() 다시 발생 } //값이 같을 때 다시 하기.

 

로또번호의 비교

3

3 5 (3과 5비교 //1번) 1

3 5 7 (3과 7비교 //1번, 5와 7비교 //2번) 2

3 5 7 9 (3과 9비교 //1번, 5와 9비교//2번, 7과 9비교//3번) 3

3 5 7 9 11 (3과 11비교 //1번, 5와 11비교//2번, 7과 11비교//3번 9와 11비교 //4번) 4

3 5 7 9 11 13 (3과 13비교 //1번, 5와 13비교//2번, 7과 13비교//3번 9와 13비교 //4번 11과 13비교 //5번) 5

....

총 숫자가 6개라면 6 - 1번 비교하게 된다.

총 수 = n , 비교 횟수 = n-1

회전수 증가 / 삼각형만들기와 형식이 비슷하다.

 

a=0 b=0 0<0

a=1 b=0 0<1

        if(lotto[1] == lotto[0])

 

a=2 b=0 0<2

        if(lotto[2] == lotto[0])
                 1   ==   3    

        if(lotto[2] == lotto[1])

                 3   ==   5    

 

a=3 b=0 0<1

        if(lotto[3] == lotto[0])

                 5   ==   3    

        if(lotto[3] == lotto[1])

                 5   ==   5    <- 값이 같기 때문에 break를 거는 것.

        if(lotto[3] == lotto[2])

                 5   ==   7    

3번째 요소를 다시 돌리기.

 

break로 안에 있는 것 빠져나오는 것.

1보 후퇴했다가 다시 실행

 

■  선생님 답안  

// 문제 4)
// 로또 추첨기 1-45 / 배열로 받아와서 겹치면 다시
		
int lotto[] = new int[6];
int size = lotto.length;
		
for(int i=0; i<size; i++){
	lotto[i]=(int)((Math.random()*45)+1);
	for(int j=0; j<i; j++){
		if(lotto[i]==lotto[j]){
			i--;
			break;
		}//if end
	}//for end
}//for end
		
		
Arrays.sort(lotto); //ascending sort
	
for(int i=0; i<size; i++){
	System.out.print(lotto[i]+" ");
}

랜덤값이 나왔을 때 그전에 나온 값과 같은 값이면 그 회차는 무효로 하고 다시 뽑는 것이다.

 

지난 주 과제 중

문제7) 10진수를 2진수로 변환하기.

지폐갯수 구하는 것과 비슷한 과정

// 문제 7) 10진수값을 2진수값으로 변환 후 // 출력하시오. 
int num = 5;  
int[] binary = new int[8];
int count = 0;
//1101 for문으로 2를 계속 나누어서 몫이 있으면 1, 없으면 0 그리고 나머지
		
while(true){  //무한 loop
	binary[count] = num%2;
	count++;
	num = num/2;
			
	if(num==1){
		binary[count]=num;
		break;
	}
}//while end
		
for(int i=count; i>=0; i--){
	System.out.print(binary[i]);
}

Interger 클래스를 활용한 수의 변환

//Integer 클래스를 활용한 수의 변환
System.out.println(Integer.toBinaryString(15));
System.out.println(Integer.toOctalString(15));
System.out.println(Integer.toHexString(15));

//결과값
//1111
//17
//f

 

 

4. 힙 정렬

5. 퀵 정렬

6. 쉘 정렬

 

 

 

 

댓글