반응형
SMALL
1. 복습
- primitive : 숫자 1개
- reference : 주소, 대입연산만 가능.
- new Scanner()
- new Random()
- new String()
- new는 Heap이라는 공간에 할당되며, reference는 new의 리턴값이다.
- new 리턴값은 할당된 공간의 참조값
- 참조타입 = new ~~~()
- 배열 : 동일 데이터 타입을 요소로 가지고 연속적으로 저장되어 운영됨.
- 한번 할당되면 크기 고정
- 연속적으로 저장 = 인덱스(번호)
- int[] 변수명;
- 참조값을 저장할 수 있는 4byte가 잡힘.
- 값을 지정을 안했기 때문에 어떤 값이 들어가는지 알 수 없다.
- 타입(int, long, double, String)에 상관없이 배열은 항상 4byte이다.
- 배열의 크기 : 요소를 몇개 가지는 배열인가? (byte 크기가 절.대. 아님!)
- int[] 변수명 = {1, 2, 3};
- 원래는 정식적으로 int[] 변수명 = new int[] {1,2,3}; 이 맞음.
- 하지만 이미 선언된 타입을 보고 컴파일러가 타입을 추론할 수 있기 때문에 대입할 때 생략이 가능함.
- 그리고 new역시 당연히 선언을 하고있기 때문에 생략이 가능함.
- 이처럼 컴파일러가 추론할 수 있는 것들은 생략이 가능한데, 이것을 타입추론이라고 함.
- int[] 변수명 = new int[] {1,2,3}; // 하드코딩
- int[] numbers = new int[100];
- new int[]; 의 대괄호 안에는 개수를 넣어줌.
- int[] numbers = new int[100]; 해석
- heap이라는 공간 안에 int 100개가 들어갈 수 있고, 0으로 자동초기화가 됨.
- int 타입 = 0, double = 0.0, char = NULL, boolean = false, 참조 = null 로 초기화.
- numbers [0], numbers [1], numbers [2] ...
- 0부터 시작하는 이유는, 시작주소이기 때문.
- 시작주소(numbers) + 1개 요소크기 * 인덱스 = offset
2. 본수업
- 많은 양의 데이터를 다루는 기술 2가지 : 배열과 컬렉션 비교
- 배열(Array)
- 배열은 언제 사용하면 좋을까?
- 데이터들의 타입이 동일한 경우
- 데이터들이 3개 이상인 경우
- 데이터들의 수가 정해져 있는 경우
- 사용하면 안좋은 경우
- 타입들이 다양한 경우
- 수가 변경이 있는 경우
- Collection 계열의 class를 사용
- ArrayList(80%)
- HashMap, Set
- int[] num = new int[3];
- int만 넣겠다는 의미, 같은 타입만 넣을 수 있다.
- 고정된 크기를 가진다. (크기 변경 불가능)
- 배열은 많은 양의 데이터를 다루기 위한 특수한 부품
- String[] names = {"홍", "송", "정", "박", "장"};
- 6개 + length 총 7개를 RAM에 할당
- 이 때 배열에 의해 차례대로 names[0], names[1], names[2], names[3], names[4]의 인덱스 값을 갖는다.
- for (int i = 0; i < names.length; i++) { System.out.println(names[i]); }
- for (String s : names) { System.out.println(s); }
- for each는 names의 주소 5개를 한번에 변수 s로 불러온다.
- advanced for문이라고도 불린다.
- for( in 배열 )
- index를 줌.
- for( of 배열 )
- 값을 줌.
- for each(advanced for)문과 동일하다.
- String[] names = {"홍", "송", "정", "박", "장"};
- 배열의 초기값은 자동으로 들어가있다. (자동초기화)
- int[] s = new int[4];
- int s[] = new int[4]; 와 동일
- 정수는 0, 실수는 0.0, 문자는 NULL, 문자열(참조형)은 null, boolean은 false로 초기화
- 배열.length에서 length는 상수이다. 이미 결정된 값이기 때문에 우리가 임의로 바꿀 수 없다.
- java.lang.ArrayIndexOutOfBoundsException: Index 1000 out of bounds for length 1000 at java_study.chapter05.ArrayEx2.main(ArrayEx2.java:20)
- 잘못된 인덱스 값을 사용했을 때 나오는 에러. (대표적인 에러임.)
- int[] s = new int[4];
- 배열을 만드는 방법 2가지
- 선택기준 : 배열에 넢을 값이 생성시점에서
- 정해지지 않은 경우 : int[] x = new int[10];
- 정해진 경우 : int[] x = {1, 2, 3};
- 선택기준 : 배열에 넢을 값이 생성시점에서
- 배열을 사용하는 경우 (조건 3가지)
- 많은 데이터 양
- 같은 타입의 데이터
- 고정된 크기 : 이게 항상 문제가 됨. 치명적인 단점.
- 크기 조절 불가능
- 다른 타입의 데이터들을 넣을 수는 있으나, 형변환 등을 해야함으로 선호하지 않음.
- 제너릭을 사용한 컬렉션 선호
- 장점 : 속도
- 자료구조 (data structure) : 2개 이상의 여러 데이터를 다룰 때, 그 데이터를 어떤 구조로 운영할 것인지를 뜻함.
- System.out.println(num); // 참조값, 주소확인
- System.out.println(num[0]); // 인덱스 값 확인.
- 에러인 상황, 에러가 아닌 상황
- 배열은 언제 사용하면 좋을까?
int[] arr = { 1, 2, 3, 4 }; // new int[] 생략
//(1) 에러
arr={10,11,12}; // 이거는 당연히 안된다. 왜냐하면 타입선언도 없고, [] 배열인지 표시도 안해줬기 때문에 당연히 에러가 남.
//(2) 정상
arr = new int[] { 10, 11, 12 }; // 에러 아님.
int[] arr2 = new int[] { 5, 6, 7, 8 }; // 정식 문법
- for-each문 : 무조건 순서대로 하나씩 꺼내옴.
- 배열명[배열명.length-1]; : 마지막 요소 인덱스
- 참조형(reference) 배열
- String[] names = new String[2];
- names = new String[] {"a", "b"};
- 참조형이기 때문에, 값을 초기화 시킬때도 반드시 new String[]을 써줘야 함.
- 주소 2개를 저장할 수 있는 배열이 됨.
- 기본(primitive) 배열
- int[] numbers = new int[2]; // heap에 int 2개의 공간이 잡힘.
- numbers[0] = 10;
- 값을 2개 저장할 수 있는 배열
- stack 영역
- 상수 영역
- heap 영역
객체의 필요성을 위해서 한 코딩.. (아직 객체에 대해서 배우지 않음. 배열까지만 배움.)
package java_study.chapter05;
public class ArrayEx4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 친구 이름
String[] names = { "홍길동", "김길동", "박길동", "송길동", "정길동" }; // 선언문에서만 가능한 표현
for (int i = 0; i < names.length; i++) {
System.out.println(names[i] + " ");
}
System.out.println();
// 우리 가족 5명의 나이를 넣어보세요. 전체 출력
int[] ages = { 50, 40, 30, 20, 10 };
for (int i = 0; i < ages.length; i++) {
System.out.println(ages[i] + " ");
}
System.out.println();
// 친구들의 발 사이즈를 넣어보세요. 전체 출력
int[] shoes = { 134, 235, 245, 255, 300 };
for (int i = 0; i < shoes.length; i++) {
System.out.println(shoes[i] + " ");
}
System.out.println();
// 친구들의 성별을 넣어보세요. 전체 출력
char[] gender = { '남', '여', '남', '남', '여' };
for (int i = 0; i < gender.length; i++) {
System.out.println(gender[i] + " ");
}
for (int i = 0; i < 5; i++) {
System.out.println(i + " " + names[i] + " " + ages[i] + " " + shoes[i] + " " + gender[i]);
}
}
}
나는 하단에 저렇게 추가를 해줬는데,
강사님은 이렇게 코딩하심.
그거나 그거나..
- 참조형에 대한 이야기
- CPU(피코세컨드의 가장 빠른 속도) - (Process) - Main Memory(그나마 CPU의 속도를 따라갈 수 있음.) - Loading(자동차에 짐을 싣는다.) (Loader : Loading을 실행하는 것들. 운영체제에 있음.) - HPP - Program - OS
- Process : 운영체제가 관리를 한다 는 의미.
- 코드파트 (컴파일 결과를 의미하며, 명령어 순서가 고정됨. 크기와 내용도 고정됨.) - 데이터파트 (항상 상황에 따라서 변함.)
- stack 영역
- stack : 쌓다.
- 원통인데 위쪽에만 구멍이 뚫려있다.
- 넣을때도 위에서만 넣을 수 있으며, 꺼낼때도 위에서만 꺼낼 수 있다.
- 맨 밑에 있는 것은 가장 처음에(오래전에) 들어간 것. 맨 위에 있는 것은 가장 나중에(최근에) 들어간 것.
- 그래서 스택의 성격을 Last In First Out 이라고 함. (LIFO)
- 자료구조에서 많이 쓰임.
- main() 에 할당된 변수 : 지역변수
- 함수호출에서 stack을 쓸 때 속도가 아주 중요하다.
- 초기화 하는 것은 시간을 잡아먹는 행위이기 때문에 지역변수에서는 초기화를 안해준다.
- 쓰레기 값 : 뭔지 모른다.
- 왜? 초기화를 안하니까 다음 스택에 이전에 저장된 값이 그대로 남아있어서.
- 함수가 끝나면 지워지거나 사라지는 것이 아니라, top의 위치만 바뀌는 것이다.
- 그것에 지워진거나 마찬가지이다. 왜냐하면 접근을 못하므로. 하지만 이전에 쓰였던 값이 그대로 남아있어서 쓰레기 값이라고 부른다.
- 이렇게 된 이유는, 아주 빠르게 stack을 운영해야 하기 때문에 쓰레기 값을 초기화하는 과정이 없기 때문이다.
- main의 지역변수 args
- 그 하단에 str, str2
- 이것을 한꺼번에 통칭하는 것 : stack frame
- 코드영역, 리터럴 상수영역 = 읽기 전용
- 자바(JAVA)에서는 메소드 영역이라고 부른다.
- 그 이유는 99%정도 메서드가 다 채우는 영역이여서이다.
- 지역변수는 Stack에서 운영함.
- 아랫단에는 Stack이, 윗단에는 Heap이 운영함.
- stack과 heap의 차이
- 리터럴(상수)이 2개지만, 동일한 데이터일 경우(new로 생성하지 않고, 값을 넣음.) 한번만 유지한다.
- https://madplay.github.io/post/java-string-literal-vs-string-object
String str = new String("Hello"); //1번 주소
str = new String("World"); //2번 주소
String str2 = new String("World"); //3번주소
// 2개는 내용은 같지만, 주소가 다름.
str == str2; //false
str = str2; //값 복사 X, 참조값 복사 O
//str과 str2 모두 3번주소, 1번과 2번주소는 쓰레기값이 됨.
str = null; //아무것도 참조하지 않는다.
// 3번주소는 str2에서 참조중이므로 쓰레기값이 아님.
- 이전에 사용했던 데이터(쓰레기)를 다시 가져오는 방법 : Java VM(Virtual Machine)에서 G.C.(Garbage Collector)를 통해 회수함. -> 그때 사라짐. (다음 메모리를 할당할 수 있다.)
- life time, access scope
- 규칙이 정해져 잇음. (규칙 : 언제 생성되고 언제 사라지는가?)
- 언제 생기는가? : new 호출할때.
- heap에 할당되는 변수 : 동적(Dynamic)할당 (개발자 맘대로)
- stack에 할당되는 변수 : 정적할당 (이미 정해져있음. 못바꿈.)
- 동적할당의 의미 : 생성과 소멸의 시점이 정해져있지 않다.
- 자바는 Java VM 때문에 메모리 관리가 매우 쉽다. : 메모리를 잘못 쓸 일이 낮음.
- 하지만, C나 C++에서는 메모리를 직접 해제해줘야 하기 때문에 메모리를 잘못 쓸 염려가 있음.
- str = str2; 와 같은 상황은 함수 호출 시, 매개변수로 값을 넘겼을 때 자주 일어나는 현상이다.
- call by reference라고 함. : 원본에 영향을 줌.
- call by value, call by reference를 잘 비교하는 것이 중요하다.
- 리터럴(값) : 메소드영역에 저장
- 리터럴은 int a = 100; 이라고 했을때, 말 그대로 오른쪽에 저장되는 값을 의미하는 것.
- 객체 : heap에 저장
- 객체는 변수, 데이터 구조, 함수, 메서드가 될 수 있으며, 식별자가 참조하는 메모리의 값이다.
- 가비지컬랙터에서 메모리가 할당이 됐는지 안됐는지를 아는 방법 : 참조 카운트를 통해서.
- 메소드 정의 및 호출
- 규칙이 정해져 잇음. (규칙 : 언제 생성되고 언제 사라지는가?)
- 여러 개의 메소드가 포함된 클래스
class LuxuryHelloJava {
//메인 메서드 = 엔트리 포인트
// void : 이부분에 리턴 타입 값이 들어감. 그러나, 리턴값이 없으므로 void로 표시.
public static void main(String args[]) {
printCharacter('*', 30);
System.out.println("Hello, Java");
printCharacter('-', 30);
}
// void : 이부분에 리턴 타입 값이 들어감. 그러나, 리턴값이 없으므로 void로 표시.
static void printCharacter(char ch, int num) {
for(int cnt = 0; cnt < num; cnt++) {
System.out.print(ch);
}
System.out.println();
}
}
- 메소드를 사용하면 좋은 이유 : 코드 재사용에 용이하다. (코드 중복을 줄일 수 있다.)
package java_study.chapter05;
public class StartTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//점점 커지는 별의 수
for (int i = 1; i <= 5; i++) {
printStars('*', i);
}
//점점 작아지는 별의 수
for (int i = 5; i > 0; i--) {
printStars('*', i);
}
// for (int i = 5; i > 0; i--) {
// System.out.println("몇번?*");
// }
}
static void printStars(char ch, int num) {
for (int j = 0; j < num; j++) {
System.out.print(ch);
}
System.out.println();
}
}
- 결과를 리턴하는 메서드
- 리턴 값(return value) : 메소드가 호출한 쪽으로 넘겨주는 메소드의 실행 결과
- 리턴 값을 리턴하는 메소드 호출문의 형식
- 타입 변수 = 메소드이름(파라미터1, 파라미터2, 파라미터3);
- 변수 : 메소드의 리턴 값을 대입할 변수의 이름
- 파라미터
- 메소드 타입이랑 변수 타입이 일치해야 함.
- paramter변수 = 지역변수임.
- 파라미터는 주소값이 복사됨.
- primitive → reference 혹은 reference → primitive 로 데이터 이동이 전.혀. 안됨.
- Call By Value
package java_study.chapter05;
public class CallByValueEx {
public static void main(String[] args) {
// primitive 타입
int x = 100;
int y = 200;
swap(x, y);
System.out.printf("변경 전 - x: %d, y : %d\n", x, y);
System.out.println(System.identityHashCode(x));
System.out.println(System.identityHashCode(y));
}
static void swap(int x, int y) {
int temp;
temp = x;
x = y;
y = temp;
System.out.printf("변경 후 - x: %d, y : %d\n", x, y);
System.out.println(System.identityHashCode(x));
System.out.println(System.identityHashCode(y));
}
}
- Call By Reference
package java_study.chapter05;
public class CallByReferenceEx {
public static void main(String[] args) {
// reference 타입
int[] data = { 100, 200 };
System.out.printf("변경 전 : %d, %d\n", data[0], data[1]);
swap(data);
System.out.printf("원본 변경 후 : %d, %d\n", data[0], data[1]);
}
// 배열의 첫번째, 두번째 엘리먼트 교환
static void swap(int[] data) {
int temp;
temp = data[0];
data[0] = data[1];
data[1] = temp;
System.out.printf("변경 후 : %d, %d\n", data[0], data[1]);
}
}
- 바꾸고자 하는 단어를 한꺼번에 바꾸는 법 : 해당 단어를 드래그 후 Refactor 메뉴 -> Rename
- 또는 alt + shift + enter
- 맥은 option + command + R
반응형
LIST
'멀티캠퍼스 > Spring' 카테고리의 다른 글
20230809 (수) (0) | 2023.08.09 |
---|---|
20230808 (화) (0) | 2023.08.08 |
20230807 (월) (0) | 2023.08.07 |
20230731 (월) (0) | 2023.08.04 |
20230801 (화) (0) | 2023.08.01 |