본문 바로가기
Language/Java

공부내용 정리 Java :: 기초 V

by Cs.Woo 2021. 6. 14.

1. 반복문

 반복문(loop, iteration)은 어떠한 명령으 반복적으로 수행할 수 있도록 마련된 기능이다. 반복문은 반복문의 조건절이 참일때 반복하고 거짓이면 반복을 멈추는 기능을 갖고있다. 

 본 장에서는 반복문과 관련된 학습을 정리하였다.

 

1-1) 문법

 반복문의 문법에는 여러가지가 존재하는데 각기 문법은 서로 대체 가능하기 때문에 상황에 맞추어 선택하여 사용하면 된다 

 

i ) while문

 while문은 while문의 조건절에 언제까지 반복을 해야하는지에 대하여 명시하여야 한다. 프로그램은 while문의 조건에 명시되어있는 조건까지 반복을 계속 실행할 것이며 그것이 불분명하거나, 혹은 계속적으로 반복하도록 구성되어있다면 - 종료할 수 있는 조건이 없다면- 무한적으로 반복하게 된다.

 while문의 문법은 다음과 같다.

 

while ( Condition ) {

	Command 
    
    }
    

 

 while문의 조건(Condition) 이 참이라면, while문의 중괄호( { } )안에 있는 명령(Command)를 계속 반복하여 실행하는 것이다.  이때 주의해야할 점은 조건절을 계속 true로 맞추어 놓는다면 무한적으로 반복되는 상태(무한루프)이다. while의 조건절을 의도하고자 하는 대로 제대로 제어하여 사용하는 연습을 하여야 한다.

 

int i = 0;

while(i<10){    

    System.out.println("Command "+i);
    
    i++;
}

 

 상기의 예제처럼 while문을 종료시킬 수 있는 장치를 마련하여야 한다.

 

ii ) for문

for문은 while문과 같이 조건이 만족할때까지 반복하는 반복문이다. for문은 while문에서 반복적으로 사용되는 요소를 한 곳에다가 몰아넣고 사용할 수 있도록 개편한 문법이라고 볼 수 있다.

 

int i = 0;

while(i<10){    

    System.out.println("Command "+i);
    
    i++;
}

 

 상기의 while문은 반복이 끝나는 시점을 정하기 위해서 while문 밖에 i라는 변수를 선언하여 초기화 하였고(i = 0)

그 다음 단계로서 while이 언제까지 반복해야 하는지(i <10)를 결정하였고 마지막으로 명령이 반복될때 마다 횟수를 세어주는 (i++)장치까지 마련하여 사용하였다.

 

 이러한 형식으로 while문을 사용할 때의 문제점은 상기 3개의 장치의 거리가 멀어지거나, 혹은 while문의 반복범위를 변경할때, 오류가 발생할 가능성이 높다 라는 점이다.

 

 따라서 이러한 점을 개선하여 나온 문법이 for문이다. for문은 상기 3개의 장치를 조건문에 삽입하여 사용할 수 있도록 설계되었다. 다음과 같다. 

 

for ( 초기화 ; 종료조건 ; 반복실행 ) {
	명령
}

 

 for문의 조건절에는 while문에서와 같이 초기화(i=0)와 종료조건(i<10), 반복실행(i++)의 3가지 장치를 명기하여 반복의 범위를 지정하고 해당 반복의 범위동안 명령을 반복시킬 수 있도록 설계되어있다.

 

public class ForDemo {
 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println("Command " + i);
        }
 
    }

 

 상기와 같이 작성한다면 while문의 예제와 같은 결과를 얻을 수 있는 것이다. while문과 비교했을때 유지 보수 혹은 변경과 관리가 더욱 편리해졌다고 할 수 있다. 

 초기화와 종료조건 반복실행이 모두 필요한 반복문일 경우에는 for문이 더 적합할 수 있으나 그렇지 않은 반복문에는 while이 사용될 수 있다. 따라서 적절한 상황에 알맞게 사용하는 것이 가장 좋다.

 

int i = 0;
int max = 10;

while(i<max){
    System.out.println("coding everybody"+i);
    i++;
}

 

 cf) 프로그래밍에서는 가변적인것과 고정적인 것을 분리해 내는 것이 중요하다. 상기의 예제에서도 max대신 10 이라는 정수를 while문에 직접 삽입하여도 결과는 똑같고 문제도 없다. 즉 같은 것이다. 

 그렇다면 무슨 이유로 분리하여 쓰는 것일까? 예제에서 가변적인 부분은 int max=10; 이다. 그 외의 나머지 부분 - 변수 i 부터 while문 까지- 고정적인 부분이다. 

 따라서 예제의 반복범위를 확장하거나 축소하고자 한다면, 가변적인 부분을 따로 분리하였기 때문에 가변적인 부분의 값만 바꿔주면 나머지 고정적인 부분이 따라서 바뀌게 될 수 있다.

 이렇게 되면 향후 코드가 많아지고 구조가 복잡해졌을 때, 가변적인 부분만 따로 분리하여 놓았다면, 가변적인 부분의 값만 바꾸면 훨씬 쉽게 코드를 유지/보수 할 수 있게 되는 것이다.

 

1-2) break, continue

 반복문을 조금 더 정밀하게 제어하는 방법이 있다. 바로 break와 continue를 이용하는 방법이다. 여태까지 우리가 학습한 내용으로는 반복문의 전체적인 조건을 설정하여 반복의 범위를 설정하고 그 반복문 자체를 종료시켜서 제어하는 방법만 숙지하고 있었다.

 그러나 반복문 전체를 종료하지 않고, 특정한 조건 혹은 시점에서 종료하고 나머지 부분은 다시 반복시킬 수 있도록, 더욱 정교하게 반복문을 다룰 수 있다면 반복문의 효용성이 더욱 제고될 것이다.

 break와 continue는 그러한 정교한 반복문의 제어에 사용되는 키워드이다. 내용은 다음과 같다.

 i ) break

 break는 순환되고 있는 반복문 안에서 특정 조건이 되었을때, 순환이 다 끝나지 않았음에도 불구하고 종료시킬 수 있는 키워드 이다.

 

public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
        
            if (i == 5) {
            
                break;
                
                }
                
            System.out.println("Count " + i);
            
        }

 

 상기의 예제를 실행한다면, Count의 숫자가 4까지만 출력되고 나머지는 출력되지 않는것을 확인할 수 있다. 순환하고있는 for문 안에서 i가 5가 되었을 때 break를 한다는 조건을 추가하였기 때문에 순환이 중간에 끊겼기 때문이다.

 즉 break는 특정한 조건에서 반복문 자체를 중간에 멈추고자 할때 사용하는 키워드이다.

 

 ii ) continue

 continue는 반복문이 순환을 하고 있을 때, 특정한 조건에서는 반복하지 않고 나머지 부분을 반복할 때 사용하는 키워드이다.

 

    public static void main(String[] args) {
    
        for (int i = 0; i < 10; i++) {
        
            if (i == 5) {
            
                continue;
                
                }
                
            System.out.println("Count " + i);
            
        }

 

 상기의 예제를 실행한다면 5를 제외한 나머지 Count가 출력된다는 것을 확인할 수 있다. 즉 i가 5와 같을 때 조건이 만족했으므로 그 조건은 실행하지 않고(건너 뛰고) 나머지 부분을 다시 실행하여 출력하는 구조로 되어있는 것이다.

 break와 달리 continue는 반복문 전체를 종료시키지 않고 특정 조건에서 한번 만 멈추었다가 다시 실행할 수 있도록 반복문을 제어하는 키워드이다.

 

1-3) 반복문의 중첩

 반복문은 조건문처럼 중첩하여 사용할 수 있다. 가령 0부터 99까지 숫자를 출력하고자할 때 한개의 반복문을 사용하여 출력할 수 있지만, 10의자리수, 1의자리수를 나누어 반복문을 작성하고 그 두개의 반복문을 사용한다면 보다 효율적으로 출력을 할 수 있게 되는 것이다.

 필자도 반복문을 중첩하여 사용할 때, 의도한대로의 결과가 나오지 않아서 고민을 많이 하였다. 그러나  충분한 연습을 한다면 효율적인 반복문을 작성할 수 있게 될 것이다. 내용은 다음과 같다.

 

public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
        
            for (int j = 0; j < 10; j++) {
            
                System.out.println(i + "" + j);
                
            }         
           
        }
 
    }

 

  상기의 예제를 실행하면 00부터 99까지의 수가 출력되는 것을 확인할 수 있다. 십의자리수를 표현할 반복문과 일의 자리수를 표현할 반복문을 중첩하여 사용하였기 때문에 그러한 결과를 얻은 것인데, 구조는 이러하다.

 

 첫번 째 반복문 (변수 i를 사용한 반복문)에서 i는 0으로 초기화 되어있고 i가 0인 상태로 for문의 안에있는 구절이 실행이 된다. 

 첫번 째 for문 안에는 다시 변수 j를 내포한 for반복문이 있다. 이 때 상위의 반복문과는 별개로 두번째 반복문이 존재함으로 두번째 반복문의 내용이 실행되어야 다음 명령으로 넘어갈 수 있다.

 따라서 두번 째 반복문에서 0으로 초기화된 j는 조건이 만족하는 (10미만의 숫자 9)범위까지 반복하여 조건절을 수행하게 되는데, 조건은 i와 j에 공백을 더한후 두개의 값을 출력하는 것이다.

 이렇게 된다면 i는 0인 상태로 j가 0부터 9까지 반복함으로 00, 01, 02, 03, ... 09까지 출력이 되는것이다. 09까지 출력을 하고나면 j는 10이 됨으로 두번째 반복문에서 조건이 false인 상태가 된다. 따라서 이 때 명령이 두번 째 반복문(loop)을빠져나오게 되고, 다시 첫 번쨰 반복문으로 간다.

이때 i는 0이었으므로 아직 반복문이 종료되지 않았고, 다시 i가 1인 상태로 두번째 반복문에 도달하고, 명령이 빠져나온 상태로 다시 두번째 명령에 진입한것이므로 j는 0으로 초기화된 상태로 다시 반복문이 시작되게 된다.

 따라서 i가 1인상태의 두번째 반복문은 10, 11, 12, 13, ... 19가 되고 이러한 현상이 첫번째 반복문의 i가 9가 될때까지 반복되게  된다.

 

 상기와 같은 논리로 되어있는 중첩된 반복문이다. 반복문의 중첩은 코딩을 처음 접하는 이들에게는 비교적 복잡한 내용이 될 수도 있다. 필자도 개인적으로 반복문 중첩에대한 이해도가 그다지 높지 않았다. 그러나 실제로 여러가지 예제를 작성해보고, 프로그램을 나름대로 만들어본다면, 이러한 어려움이 해소될 것이라고 생각한다.

 

2. 배열(Array)

 배열은 연관된 정보를 서로 묶어서 사용할 수 있도록 설계해 놓은 기능이다. 자바 역시 타 언어와 마찬가지로 배열을 보유하고 있고 다음과 같은 특징과 형식을 갖고있다.

 

2-1) 배열의 개념

 배열은 연관된 데이터를 모아서 관리하기 위하여 사용하는 데이터 타입중 하나이다. 변수가 하나의 데이터를 저장하기 위한 것이라면 배열은 여러 개의 데이터를 저장하기 위하여 사용하는 것이다.

 

2-2) 배열의 생성 및 제어

 

    public static void main(String[] args) {
 
        데이터 타입[] 배열명 = { "요소1", "요소2", "요소3", "요소4" };
 
    }

 

 자바에서 배열을 생성하기 위해서는 상기와 같은 규칙으로 생성해야 한다. 우선 배열에 들어갈 데이터 타입을 표기하고, 배열이라는 것을 나타내기 위하여 []를 뒤에 표시한다. 그리고 배열의 이름을 적고 중괄호 안에 배열에 포함될 요소를 입력해주면 된다 예제는 다음과 같다.

 

    public static void main(String[] args) {
 
        String[] myArray = { "요소1", "요소2", "요소3", "요소4" };
 
    }

 

 myArray라는 배열은 문자열이 포함될 배열이기 때문에 앞에 String이라고 표기한다. 그리고 배열에 들어갈 요소로서 문자열을 입력하여 포함시켜주면 배열이 생성되는 것이다.

 

 연관된 데이터를 저장할 수 있는 배열을 생성했으면 그러한 데이터를 꺼내서 사용할 수 있도록 장치가 마련되어있어야 한다. 배열을 생성하였으면 제어를 할 수 있어야 되는 것인데 배열의 제어 방법은 다음과 같다.

 

    public static void main(String[] args) {
        String[] classGroup = { "요소1", "요소2", "요소3", "요소4" };
        System.out.println(classGroup[0]);  // 요소1
        System.out.println(classGroup[1]);  // 요소2
        System.out.println(classGroup[2]);  // 요소3
        System.out.println(classGroup[3]);  // 요소4
 
    }

 

 상기의 예제와 같이 배열명[번호]를 사용하면 해당되는 번호에 있는 요소를 불러와 사용할 수 있게 된다. 그렇다면 번호는 어디서 온 것이며 어떠한 구조를 갖고있는 것일까?

 배열에서의 요소의 번호는 색인(index)라고 한다. index는 배열을 생성하고 요소를 추가할 때 프로그램 내부적으로 부여하는 번호로서 배열에서는 색인번호를 사용자 임의대로 변경할 수 없다.

 또한 컴퓨터는 숫자를 0부터 기산함으로 인덱스의 제일 처음 번호는 0이된다. 따라서 예제와 같이 첫번 쨰 요소의 인덱스 값은 0이되는것이다.

 

 배열을 생성하는 또다른 방법에는 배열의 객체를 생성하여 생성된 객체에 요소를 추가하는 방법이 있다. 이는 아직 객체를 학습하지 않았기 객체와 관련된 내용은 후일에 다시 다루도록 한다. 다음과 같다.

 

 

    public static void main(String[] args) {
        String[] myArray = new String[4];
        
        myArray[0] = "요소1";
        myArray[1] = "요소2";
        myArray[2] = "요소3";
        myArray[3] = "요소4";
 
    }

 

 생성 방법은 상기와 같다. 이전 배열의 생성방법과 마찬가지로, 배열의 데이터 타입을 명기해주고, 배열명을 표시한다음에 포함될 요소의갯수를 표시한 배열 객체를 생성하면 되는 것이다(new String[4]) 이렇게 된다면 요소를 4개 포함할 수 있도록 메모리를 할당받은 객체가 생성이되고, 각 인덱스값에 해당하는 요소들을 빠르게 추가할 수 있게 되는 것이다.

 객체를 생성하고 요소를 추가할 때에는 배열명[인덱스] = 요소; 의 statement를 사용하여 추가하면 된다.

 

 상기와 같이 객체를 통하여 배열을 생성하였을 때, 생성된 배열이 몇개의 요소를 포함할 수 있는지를 알기위한 메소드로는 length가 있다. 다음과 같다.

 

    public static void main(String[] args) {
        String[] myArray = new String[4];
        
        myArray[0] = "요소1";
        System.out.println(myArray.length);  // 4
        myArray[1] = "요소2";
        System.out.println(myArray.length);  // 4
        myArray[2] = "요소3";
        System.out.println(myArray.length);  // 4
        myArray[3] = "요소4";
        System.out.println(myArray.length);  // 4
 
    }

 

 length는 배열의 메소드이기 때문에 배열명에 직접적으로 사용하면 된다. 사용은 상기 예제처럼 하며, 결과로는 배열이 최대로 수용할 수 있는 수인 4가 출력되게 된다.

 

2-3) 반복문을 활용한 배열의 사용

 배열 안의 요소들을 하나씩 꺼내어 사용하는 방법에 대하여 알아보았다. 그러나 그러한 형식으로 배열의 값을 꺼내어 사용하고 제어한다면 하나의 변수의 값을 저장하여 사용하는 것과 다를게 없다. 따라서 배열에 값을 저장하고 그것들을 효율적으로 사용하는 방법에 대하여 학습을 하여야 한다.

 

    public static void main(String[] args) {
 
        String[] myArray = { "요소1", "요소2", "요소3" };
        for (int i = 0; i < myArray.length; i++) {
            String element = myArray[i];
            System.out.println(elment + "(이)가 호출되었습니다.");
        }
 
    }

 

 예제의 코드를 실행하면 요소1 부터 요소3이 호출되었다는 내용을 출력받는다. 생성한 배열의 요소들을 반복문으로 하나씩 꺼내어 저장한 뒤 문자열의 덧셈연산으로서 모든 내용을 호출하는 구조로 되어있다. 

이런식으로 반복문과 배열을 같이 사용한다면, 배열을 더욱 효율적으로 사용할 수 있도록 되는 것이다.

 

 상기의 예제 역시 불편한 부분이 눈에 들어온다. 요소를 하나씩 꺼내서 사용하기 위하여 for문을 사용하였는데, for문으로 요소를 꺼내서 지역변수에 할당하고, 할당된 지역변수를 호출하여 연산한 후 그 내용을 출력하는 모든 절차를 전부 표기해야되는 불편함이 존재하는 것이다.

 

 자바에서는 그러한 불편함을 최소화하고 배열-반복문의 효용성을 더욱 극대화하기 위하여 for-each라는 구문을 만들어 사용할수 있도록 하였다.

 

    public static void main(String[] args) {
        String[] myArray = { "요소1", "요소2", "요소3" };
        for (String element : myArray) {
            System.out.println(element + "이 사용 되었습니다.");
        }
    }

 

 이전의 예제와 같은 결과를 도출하는 예제이다. 내부의 구조 역시 동일하게 작동하지만 for each라는 구문으로 줄여서 사용할 수 있도록 되어있는것이다. 로직은 다음과 같다.

 

 문자열을 할당받는 배열 myArray를 생성하고, 요소1, 요소2, 요소3을 할당한다.
 그 후 for문을 사용하는데 for문의 조건으로 문자열을 할당받을 지역변수 element를 선언하고 그 뒤에 값을 꺼내올 배열을 콜론( : ) 뒤에 명시해주면 된다. ( String element : myArray)
 이렇게 되면 문자열이 포함되어있는 배열 myArray에서 문자열 요소를 하나씩 꺼내서 지역변수 element에 할당하고 for문 이하의 명령에 실행을 한다.
실행이 끝나면 myArray에 다음 요소를 꺼내서 반복을 실행하고, myArray의 마지막 요소까지 반복한 후 요소가 없다면 반복을 종료하는 형식으로 설계되어 있다.

 

 for-each 구문을 사용하면 이전의 예제보다 간단히 큰 효율을 내서 배열과 반복문을 사용할 수 있게 되는 것이다.