AI·빅데이터 융합 경영학 Study Note

Do it 자바! 완전 정복 4장 제어문과 제어 키워드, 5장 참고 자료 필기 본문

C·Java·Python

Do it 자바! 완전 정복 4장 제어문과 제어 키워드, 5장 참고 자료 필기

SubjectOwner 2023. 2. 20. 16:32

변수의 범위 표현

수학식에서 70 <= a < 80과 같이 표현하던 걸 자바 코드에서는 반드시 각각을 분리하고 논리연산자로 연결해줘야 한다. 즉, 70 <= a < 80을 a>= 70 && a < 80 으로 바꿔 작성해야 한다.

 

for문에서 조건식이 생략됐을 때 컴파일러는 자동으로 true 입력(무한 루프)

 

 

배열

2가지 특징: 생성할 때 크기를 지정해야 함, 한 번 크기를 지정하면 변경할 수 없음.

 

 

배열 선언 및 초기화 하기

https://ifuwanna.tistory.com/231

 

[Java] 배열(Array) 선언 및 초기화 하기

| 배열(Array) 이란? 배열(Array)이란 선형 자료구조(Data Structure)중 하나로, 동일한 타입의 연관된 데이터를 메모리에 연속적으로 저장하여 하나의 변수에 묶어서 관리하기 위한 자료 구조입니다. 가

ifuwanna.tistory.com

배열(Array) 이란?
배열(Array)이란 선형 자료구조(Data Structure)중 하나로, 동일한 타입의 연관된 데이터를 메모리에 연속적으로 저장하여 하나의 변수에 묶어서 관리하기 위한 자료 구조입니다.  가장 기본적인 자료구조인 만큼 C,Java,Python등 거의 모든 언어에 구현되어 있습니다.
 
 배열의 길이는 최초 선언한 값으로 고정되며 위와 같이 인덱스(Index)를 통해 데이터에 접근 할 수 있습니다.
 
배열(Array) 선언 및 초기화
배열을 선언할때  참조변수만 먼저 선언하여 크기 및 값을 이후에 초기화 하는 것도 가능하고 최초 선언시 부터 배열의 크기 및 값을 할당해 주는 것도 가능합니다. 아래는 여러가지 방법으로 배열을 선언하고 초기화 하는 예제입니다.

 

//크기 할당 & 초기화 없이 배열 참조변수만 선언
int[] arr;
int arr[];

// 선언과 동시에 배열 크기 할당
int[] arr = new int[5];
String[] arr = new String[5]; 

// 기존 배열의 참조 변수에 초기화 할당하기
int[] arr;
arr = new int[5]; //5의 크기를 가지고 초기값 0으로 채워진 배열 생성

// 선언과 동시에 배열의 크기 지정 및 값 초기화
int[] arr = {1,2,3,4,5}; 
int[] arr = new int[]  {1,3,5,2,4};    
int[] odds = {1,3,5,7,9};  
String[] weeks = {"월","화","수","목","금","토","일"};

// 2차원 배열 선언
int[][] arr = new int[4][3];   //3의 크기의 배열을 4개 가질 수 있는 2차원 배열 할당  
int[][] arr9 = { {2, 5, 3}, {4, 4, 1}, {1, 7, 3}, {3, 4, 5}};
//arr[0] >> {2, 5, 3};
//arr[1] >> {4, 4, 1};
//arr[2] >> {1, 7, 3};
//arr[3] >> {3, 4, 5};
 
 참고로 기본타입(Primitive type)의 배열인 경우 초기값을 가지고 있는 반면에(int = 0) 참조타입(Reference type)의 배열을 선언했을 경우 배열내 엘리먼트의 초기값이 null임을 주의하셔야 합니다.

 

// 객체(Class) 배열 선언
Student[] StudentArr = new Student[5];     //Student Class의 인스턴스 최대 5개 할당할 수 있는 배열
//StudentArr[0] >> null
//StudentArr[1] >> null
//StudentArr[2] >> null
//StudentArr[3] >> null
//StudentArr[4] >> null
 
배열(Array) 출력하기
아래와 같이 index를 통해 배열내 데이터에 접근 할 수 있으며 Index는 0부터 시작합니다.
int[] arr = {1,2,3,4,5};    
for(int i = 0; i < arr.length; i++) {
       System.out.println(arr[i]);
}
for(int number : arr) {
       System.out.println(number);
}
* 결과 
1
2
3
4
5

 

 

 

 

자바의 메모리 구조(이해  못함)

*책 참고하기!!! 그 뒤에 이어지는 내용을 건너뜀(p153~158)*

https://velog.io/@shin_stealer/%EC%9E%90%EB%B0%94%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0

 

자바의 메모리 구조

Java의 메모리 구조에 대해서 공부했던 내용을 정리한 글입니다.개인적으로 공부한 자료라 틀린 부분이 있을 수 있습니다.여기, 같은 기능을 하는 두 개의 프로그램이 있다고 가정해보자1) 메모

velog.io

Java의 메모리 구조에 대해서 공부했던 내용을 정리한 글입니다.
개인적으로 공부한 자료라 틀린 부분이 있을 수 있습니다.

왜? 프로그램의 메모리를 고려해야할까?

여기, 같은 기능을 하는 두 개의 프로그램이 있다고 가정해보자

1) 메모리 설계가 잘 되어 있는 프로그램
2) 그렇지 않은 프로그램

1번 프로그램에 비해 2번 프로그램에서는
속도 저하 현상이나 튕김 현상이 일어날 확률이 크다.

보다 안정적인 프로그램을 개발하려면
메모리 구조를 이해하고 적절하게 사용할 수 있어야 할 것이다.

자바의 프로그램 실행 구조

JVM 의 전체적인 구조

  • Source Code (.java) 파일을 Java Compiler를 통해서 Byte Code(.Class)파일로 변환한다. (컴퓨터가 이해할 수 있는 코드로 변환)
  • Byte Code로 변환된 파일을 JVM의 Class Loader 로 보낸다.
  • Class Loader는 말 그대로 Class 파일을 불러와서 메모리에 저장하는 역할을 한다.
  • Execution Engine 은 Class Loader에 저장된 Byte Code를 명령어 단위로 분류하여 하나씩 실행하게 하는 엔진이다.
  • Garbage Collector 는 사용하지 않거나 필요없는 객체들을 메모리에서 소멸시키는 역할을 한다.
  • Runtime Data Area (Memory Area) 는 JVM이 프로그램을 수행하기위해 운영체제로부터 할당받은 메모리 공간이다.

그렇다면 한 단계 더 들어가서 Runtime Data Area 는 어떻게 생겼을까?

Memory Area 의 구조

차례대로 살펴 보자.

1) Method Area

  • JVM이 실행되면서 생기는 공간이다.
  • Class 정보, 전역변수 정보, Static 변수 정보가 저장되는 공간이다.
  • Runtime Constant Pool 에는 말 그대로 '상수' 정보가 저장되는 공간이다.
  • 모든 스레드에서 정보가 공유된다.

2) Heap

  • new 연산자로 생성된 객체, Array와 같은 동적으로 생성된 데이터가 저장되는 공간
  • Heap에 저장된 데이터는 Garbage Collector 가 처리하지 않는한 소멸되지 않는다.
  • Reference Type 의 데이터가 저장되는 공간
  • 모든 스레드에서 정보가 공유된다.

3) Stack

  • 지역변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간
  • Last In First Out, 나중에 들어온 데이터가 먼저 나간다
  • 만약, 지역변수 이지만 Reference Type일 경우에는 Heap 에 저장된 데이터의 주소값을 Stack 에 저장해서 사용하게 된다.
  • 스레드마다 하나씩 존재한다.

4) PC Register

  • 스레드가 생성되면서 생기는 공간
  • 스레드가 어느 명령어를 처리하고 있는지 그 주소를 등록한다.
  • JVM이 실행하고 있는 현재 위치를 저장하는 역할

5) Native Method Stack

  • Java 가 아닌 다른 언어 (C, C++) 로 구성된 메소드를 실행이 필요할 때 사용되는 공간
 

 

 

* 기본 자료형은 스택 메모리의실제 데이터값을 저장하고 있으므로 기본 자료형 변수를 복사하면 실제 데이터값이 1개 더 복사된다. 이후 복사된다. 이후 복사된 값을 변경해도 원본 값을 영향을 받지 않는다. 참조 자료형은 스택 메모리에 실제 데이터값이 아닌 힙 메모리에 저장된 객체의 위치를 저장하고 있다. 참조 자료형 변수를 복사하면 실제 데이터가 복사되는 것이 아니라 실제 데이터의 위칫값이 복사된다. 따라서 하나의 참조 변수를 이용해 데이터를 수정하면 다른 참조 변수가 가리키는 데이터도 변하게 되는 것이다.

int a = 3;
int b = a;
int b = 7;
System.out.println(a); //3
System.out.println(b); //7

int[] c = new int[] {3, 4, 5};
int[] d = c;
d[0] = 7;
System.out.println(c[0]); //7
System.out.println(d[0]); //7

 

배열의 길이 구하기

배열 참조 변수.length

//예
int[] a = new int[] {3, 4, 5, 6, 7};
System.out.println(a.length); //5

 

 

 

2차원 정방 행렬

 

 

https://velog.io/@1205kjw/5.1.7-2%EC%B0%A8%EC%9B%90-%EC%A0%95%EB%B0%A9-%ED%96%89%EB%A0%AC-%EB%B0%B0%EC%97%B4

 

5.1.7 2차원 정방 행렬 배열 - 1

가로 및 세로 방향의 2차원으로 데이터를 저장하는 배열이 2차원 배열이다. 그중 직사각형의 형태(모든 행의 길이가 같은 배열)를 띤 배열을 '2차원 정방 행렬 배열'이라고 한다. 2차원 배열을 선

velog.io

 

2차원 배열을 선언할 때도 배열을 대괄호([])로 표시한다. 다만 1차원 배열과 다른 점은 2차원이라는 것을 나타내기 위해 2개의 대괄호로 표시한다는 것이다.

🍃2차원 배열의 선언 방법
자료형[][] 변수명 | 자료형 변수명[][] | 자료형[] 변수명[]

int[][] a;     | int a[][];      | int[] a[];
double[][] b;  | double b[][];   | double[] b[];
String[][] c;  | String c[][];   | String[] c[];

2차원 배열의 선언을 보면 차원이 1개씩 늘어날 대마다 대괄호가 1개씩 늘어난다는 것을 알 수 있다. 따라서 3차원 이상의 배열을 선언하는 방법도 쉽게 유추할 수 있을 것이다. 대괄호 안에는 배열의 인덱스가 들어가는데, 2차원 배열은 각 위치 정보가 2개의 인덱스 쌍으로 이뤄져 있다. 배열의 위치 표현은 세로 방향으로 숫자가 늘어나는 행row 번호와 가로 방향으로 숫자가 늘어나는 열 column 번호로 구성돼 있으며 각 방향의 인덱스는 0부터 시작한다. 예를 들어 a[2][1]은 2차원 배열 a의 세번째 행과 두 번째 열을 의미한다.

실습

        int[] array = new int[] {3, 4, 5, 6, 7};
        
        // 배열의 선언 방법 1 - 자료형 뒤에 대괄호 2개 표기
        int [][] array1 = new int [3][4];
        int [][] array2;
        array2 = new int[3][4];
        
        // 배열의 선언 방법 2 - 변수명 뒤에 대괄호 2개 표기 
        int array3[][] = new int[3][4];
        int array4[][];
        array4 = new int [3][4];
        
        // 배열의 선언 방법 3 - 자료형과 변수명 뒤에 각각 하나의 대괄호 표기 
        int[] array5[] = new int[3][4];
        int[] array6[];
        array6 = new int[3][4];
        
        // 다양한 배열 선언 ( 기본 자료형 배열, 참조 자료형 배열)
        boolean[][] array7 = new boolean[3][4];
        int[][] array8 = new int[2][4];
        double[][] array9 = new double[3][5];
        String[][]array10 = new String[2][6]; // 참조 자료형 배열 

2차원 정방 행렬은 객체를 생성하는 데도 4가지 방법이 있다. 각 방법을 이해하는 것보다 더욱 중요한 사실은 '메모리는 2차원 데이터를 바로 저장할 수 없다.'는 것이다. 지금까지 2차원 배열을 공부해놓고 메모리에 2차원을 저장할 수 없다고 하니 이해하기 힘들 것이다. 실제로 메모리는 1차원 형태의 데이터만 저장할 수 있다.
그렇다면 어떻게 2차원 데이터를 저장할까? 그 방법은 2차원 데이터를 1차원 데이터들로 나눠 저장하는 것이다. 다음과 같은 2X3 크기의 2차원 배열을 살펴 보자.


이 배열의 각 행은 1차원 배열이다. 배열의 첫 번째 특징은 동일한 자료형만 묶어 저장할 수 있다는 것이었다. 즉, 각각의 행이 1차원 배열이므로 '2차원 배열은 1차원 배열을 원소로 포함하고 있는 1차원 배열'이라고 생각할 수 있다. 이 개념을 3차원 배열로 확장하면 3차원은 2차원 배열의 객체를 생성하는 방법과 메모리에서의 동작을 이해할 수 있다.
이제 2차원 정방행렬 배열의 4가지 객체 생성 방법을 알아보자.

방법 ① 배열 객체를 생성하고 값 대입하기
첫 번째 방법은 2차원 배열 객체를 선언한 후 각각의 인덱스 위치에 값을 하나씩 대입하는 것이다. 여기서도 배열의 2가지 특징을 모두 만족한다는 것을 알 수 있다. 우선 어떤 자료형을 저장하는지가 선언에 나와 있고 객체를 생성할 때 배열의 길이가 지정돼 있다.

🍊2차원 정방 행렬 배열 객체를 생성하고 값 대입하기
자료형[][] 참조 변수명 = new 자료형 [행의 길이][열의 길이];
참조 변수명[0][0] = 값;
참조 변수명[0][1] = 값;
...
참조 변수명 [행의 길이 -1][열의 길이-1] = 값;

예
int[][]a = new int[2][3];
a[0][0] = 1; a[0][1] = 2; a[0][2] = 3;
a[1][0] = 4; a[1][1] = 5; a[1][2] = 6;

여기서 중요한 점은 메모리를 이해한다는 것이다. 위 예제에서 2차원 배열은 길이가 3인 1차원 배열을 2개 포함하고 있는 1차원 배열로 볼 수 있다. 즉 int[]가 int를 저장하는 1차원 배열인 것 처럼 int[][]는 int[]를 저장하는 1차원 배열로 볼 수 있다는 말이다. 따라서 몇 차원의 배열이든 최종적으로는 1차원 배열로 분할할 수 있으며 이것이 바로 1차원 데이터만 저장할 수 있는 메모리에 다차원 배열을 저장할 수 있는 이유다.
이제 다시 메모리의 구조로 돌아가 다음 예제를 이용해 생성되는 메모리의 구조를 살펴 보자.


2차원 배열의 참조 변수 a는 2개의 원소(1차원 배열)를 포함하고 있는 1차원 배열 이므로 참조 변수가 가리키는 곳으로 가면 2개의 방이 있다. 이 2개의 방에는 서로 다른 2차원 배열의 위칫값이 들어 있다. 이 위칫값들이 가리키는 또 다른 힙 메모리의 공간에 객체의 실제 데이터 값이 들어 있다. 다소 복잡해 보이지만, 앞의 예제에서 메모리 구조를 자세히 살펴보면 이해할 수 있을 것이다.

메모리의 저장 구조를 이해해야 2차원 배열의 length 속성값을 알 수 있다. '배열 참조 변수.length'는 배열의 길이를 나타낸다고 했다. 다시 말해서 배열의 가리키는 곳으로 가서 방의 개수를 알아오는 것이 '배열 참조 변수.length'의 명령어다. 그렇다면 앞의 예제에서 a.length는 얼마인가? 참조 변수 a가 가리키는 곳으로 가면 2칸의 공간이 있다. 즉 a.length = 2인 것이다. 반면 a[0].length는 a가 가리키는 곳의 방 개수를 의미하므로 a[0].length = 3이 된다. 이와 같은 방식으로 a[1].length = 3이 된다는 것을 알 수 있다.

🍊2차원 배열의 길이 가져오기

System.out.println(a.length); //2
System.out.println(a[0].length); //3
System.out.println(a[1].length); //3