주의할 점
나는 여기에다 책을 만드는 것이 아니다. 그러므로 모든 정보를 적을 필요도 없고, 다만 내가 공부한 내용을 누군가에게 설명한다고 생각하고 스스로 정리하면 된다. 체계만 잡히면 된다. 그래서 이곳은 순전히 메모장이니 완벽하게 정돈하려 하지 말고, 내 머리 속에 있는 걸 잘 풀어주기만 하고 여러번 읽어주기만 하면 목적은 달성한 것이다. 책 만드는게 아니란 걸 기억하자.
뭐든지 프로그램 Syntax를 공부할 때는
(1) 역사적배경(문제-해결책) (2) 개념의 구조-종류 (3) Syntax - 작동원리
이 3가지를 유념해라. 이 중 Syntax는 아래의 4가지 포인트를 내가 바로바로 입밖으로 뱉을 수 있게 정리를 해야한다.
1. 선언(생성) 2. 변경 3. 사라짐 4. 참조
이걸 공부하고, 각각의 node에 2가지 포인트를 정리해라. 문법을 공부한 다음에는 메모리 스택에 어떻게 올라가며 작동원리가 어떤지를 공부해라.
1995년에 나온 자바는 변수를 선언할 때 일반적인 기본 타입을 여러개로 정리해두었다. 옛날에는 메모리가 적었다는 것을 명심해라. 메모리를 효율적으로 세세하게 관리하려고 이렇게 시작한 것이다.
JVM은 크게 3가지 영역으로 메모리를 나눈다.
Method Area : 클래스 변수 저장메모리(1) /
Stack(2) /
Heap(3)
포인트는 Stack은 계산을 위한 메모장이고, 호출스택은 LIFO라는 것임
(1) Method Area
코드는 모두 Method Area에 호출된다. 아직은 이를 기초수준에서 공부할 능력은 안된다.
(2) Stack (실질적인 계산을 하는 메모장)
이제 Stack부분에서 인스턴스에 실행을 할 때 메모장처럼 a는 10이고, b는 20이라고 저장이 됨.
(3) HEAP (Stack에 주소값을 담은 친구들의 original 값이 모여있는 곳)
매우 중요하다. HEAP은 중복되는 value는 저장하지 않는다. 참조변수는 stack 안에서 주소값만 저장할 뿐이다.
Java든 뭐든지 간에...Memory management is crucial key to let performance of your program leaped. The reaon of problem is "Compiler never knows precisly when to free the memory associated with an object.
The bug is known as "Memory leak". In java, they automatically oversee and track of orphaned objects and returning the memroy they use to a pool of free memory. That is how we call as garbage collection.Aliasing - Alias means Reference in CS.
Java에서 자주 생기는 버그 (Introduction p.353)
- Changing the state of an object impacts all the code involving aliased variables referencing that objects.
In Java, there is only one way to create a reference(new) and only one way to change a reference address (with an assignment statement).
Reference in "Programming in Java by R.Sediwick"
Remember a datatype is a set of values and a set of operations defined on those values.
참고사항 1과 2가 시사하는 바는 무엇인가? 메모리는 양수와 음수가 절반씩 나눠먹는다.
참고사항1
음수와 양수는 바이너리로 어떻게 정의될까?
10은 00000...001010;
-10은 11111...110101 인데 여기에 1을 더 한다.
1을 더하는 이유는 0의 존재 때문임.
-10은 11111...110110;임.
참고사항2
추가적으로 이진법은 어떻게 표현하는가?
int a = 0B0101;
0B라는 operator가 붙으면 뒤를 이진법으로 표현하겠다는 뜻.
자바는 클래스로 이뤄져있어. 자바에서 public static void main 안에서 코드가 짜이고, 그 코드가 저장되어 바이너리코드로 저장된다.아무리 위에 public static 코드 위에 뭔가를 써도 특별하게 달라지는 것은 없다.
명명규칙 총정리(내가 자주 놓치는)
클래스는 반드시 대문자로 시작한다. 클래스 안에는 반드시 하나의 public 메소드가 있어야한다.
변수는 반드시 소문자로 시작한다.
Variables consists of two types : primitive type and reference type.
즉, 변수는 둘 중 하나다. 원초 변수와 주소값 변수
The most important difference between a reference type and a primitive type is that you can use reference type variables to invoke the methos that implement data type operations. so called instance methods.
중요한 점....!
Java는 data를 담을 그릇인 variable의 type을 모두 지정해줘야한다...어? data값 지정 안해줘도 되던데?
이건 컴파일러가 자동으로 넣어준 경우로 생략이 가능한 경우여서 그렇다.
예를 들어, int a = 1 +2 ; 로 1과 2는 다 data type이 안보이지만, 사실은 int a = int 1 + int 2;이다.
그래서 매우 중요한 개념이다.
JAVA는 등호(=)를 중심으로 양 옆을 같은 Type으로 통일시키고자 하는 원칙이 있다.
생략이 가능한 경우에는 컴파일러가 자동으로 통일시키고,
생략이 안되는 경우에는 에러를 출력한다.
(1) STRING 클래스는 한번 선언되면, heap에 저장된 값은 수정변경이 안된다. 이건 모든 참조변수가 그러하다. 그저 주소값만 변할 뿐이다.
정확하게는 8가지이지만 그러면 내 머리 속에 그걸 직관적으로 이애할 수가 없다. 크게 4가지다.
정수 / 실수 / 논리값 / 문자
정수의 기본값은 Int이다. 하지만, 실질적으론 long을 쓸 것이다. 왜냐면, Int는 너무 데이터값이 적기 때문이지. 자매품으로 short, byte가 있지만 안쓴다고 보면 된다.
실수의 기본값은 Double이다. float도 쓰긴 하지만, 실질적으로 기본값인 Double을 쓸 것이다.
논리값은 Boolean.
문자는 char.
큰 데이터 타입은 작은 데이터 타입으로 들어갈 수 없다.
큰 형님이 비좁은 작은 형님 집으로 들어갈 수는 없는 것이다.
작은 데이터 타입은 큰 데이터 타입과 만나면 큰 데이터가 된다.
논외로 지필시험에서 물어볼 수 있는 내용 중 하나는, byte와 short도 잘 안쓰이지만, 결국은 정수Integer Family이다. Integer끼리는 서로 아무리 더해도 integer이다. long만 빼고...
long a = 10;
if I need to initialize it, every variables need to be declared to zero(0).
Type transformation
int a = 10;
long b = (long)(a) 처럼 앞에 (long)(변수)이렇게 바꿔주면 됨.
In a nutshell, a String value is an indexed sequence of car values.
참조변수는 다양한 API가 많다. 그런데 주소값이 있는 참조변수에 접근할 땐 그 accessor가 .(콤마)이다. 대신 이 .(콤마)는 힙에 있는 메모리를 직접 건드릴 수 없으므로 힙의 메모리를 참조하여 copy한 후 변형한다. 즉 다시 말해, heap에 A(주소 #1001)가 있었는데 B(#1002)로 바꾸었다면, Stack엔 주소만 (#1001 --> #1002)로 바뀐 것이지만, heap내에도 A와 B는 그대로 있다. 이 B에 접근하기 위한 accessor가 .(콤마)이다.
강행규정에 대한 다양한 사례
내가 만약 정수를 string으로 바꾸고 싶다면...?
int a1 = 10;
String n2 = a1 + "";
하지만, 조금 더 세련된 API를 쓰고 싶다면,
String n2 = String.valueof(a1);
이라고, API를 쓸도 있다. 하지만....여기선 .전자 때문에 소개했다.
강행규정에 대한 다양한사례2
String s1 = "10";
int a1 = 10;
int s2 = Integer.parseInt(s1);
//이건 s1이란 String을 정수로 변환해주는 것임. API이다
System.out.println(s2 + 10);
//--->20이란 값이 나온다.
참조변수를 다시 재분류하자면, 접근자 / 제어자 / 생성자 / 연산자로 나뉜다.
the value sof String are sequences of characters. 즉, 문자들의 집합으로 본다.
new
new, followed by class name; followed by the construcotr's arguments, enclosed in parentheses and sperated by commas.
EX) String s = new String("abc");
하지만, 짧게 String s = "abc"; 이렇게 하는 것도 허용한다. 대부분 짧게 쓰지만, 전자가 원칙이란 걸 기억해.
invoking method concat.
Split() methods
-->참고로 배열만큼 for문과 친한 경우가 없다. for문과 달고 산다고 생각하면 된다
궁금한 점....int 안의 값이 변하면, 얘도 주소값만 변하고 계속 heap 메모리 안의 메모리가 추가가 되는 걸까?
Answer : 그렇다. 이 친구도 마찬가지로 배열 안의 데이터 값을 변경하면, 힙 메모리 안의 데이터가 새로 생기는 거고, 남은 데이터는 garbage로 남고 stack 메모리 안에선 주소값만 바뀌는 것이다.
그래서, in textbook, an array of objects is an array of references, not the objects themselves.
배열은 생성과 동시에 자동적으로 기본값(null)으로 초기화되므로, 배열을 사용하기 전 따로 촉화 해줄 필요가 없다. 참고로, boolean을 제외한 모든 primitive type은 0으로 초기화되고, boolean은 true가 아닌 false.나머지 reference type은 null값임.
int arr[] = new arr[3]; (ok) - 가장 많이 쓰는 경우.
or
int []arr = new int[3]; (ok)
or
int arr[] = {10, 20, 30}; (ok) -드문 경우.
not
int arr = new int[3]; (never)
not
int arr = {10, 20, 30, 40}; (never)
not
int arr = {10, 20, a}; (never)
배열은 생성과 동시에 자동적으로 기본값(0)으로 초기화되므로, 배열을 사용하기 전 따로 촉화 해줄 필요가 없다.
arr.length
주의할 점은 length라는 accessor는 배열 등 object에만 가능하다. Primitive type에는 불가능한 accessor라는 것을 명심하자.
These days, computer engineer prefer more easier way to conventional way.
It is very straightforward like below.
(1)
//arr 안에 있는 int값을 하나씩 하나씩 꺼낼 수 있는 방법.
//최근에는 for(int i = 1....)이것보다 더 많이 쓴다.
//다만 단점은 이 경우에는 각 data값에 일련번호를 달기가 어렵다는 단점이 있다
System.out.println("Type2");
for(int data:arr) {
System.out.printf("%d \t", data);
}
(2) Conventional way
for(int i = 0; i < arr.length ; i++) {
arr [i] = r.nextInt(9) + 1 ;
//참고로 nextInt(x) 안에 있는 x에 99를 넣으면 0~99까지
// 999를 넣으면 0~999까지
}
이런 방식도 가능하다. 아래의 경우엔 모든 원소를 sum 내리는 것이지.
for(int a : arr) {
sum += a;
}
(3)
System.out.println(Arrays.toString(arr));
Arrays.toString(배열이름) 메소드를 사요하면 가능하다. 단, import 값이 들어와야하니...에러가 나면 import 단축키를 눌러주자.
System.out.println(Arrays.toString(arr));
최단거리 문제에 자주 나온다. for문을 사용해야하는 건 명확하지만, depth가 2개 이상. 고려해야할 용인이 2개 이상인 경우 시험에 많이 나오는 것이 이 경우이다.
Matrix의 경우에는 해당 CS 내용을 이해하는 게 매우매우매우 중요하다. 물론, 실무적으로 많이 쓰이진 않는다.
한줄로 핵심만 정리하자면, 모든 Matrix는 (1)주소값 배열- 사진의 주황색 배열 과 (2)값 배열 - 사진의 초록색 배열이 존재한다.
주황색 배열은 배열의 배열을 품은 케이스이다.
For example)
2차원 배열의 경우엔, 1차원 주소값배열(함수로 치면 x값)이 있고, 각 배열은 x=0일 때 (0,0) (0,1) (0,2)....(0,n)을 지칭한다.
3차원 배열의 경우엔, 2차원 주소값배열(함수로 치면 x,y값)이 있고, 각 배열은 x=0,y=0일 때 (0,0,0) (0,0,1) (0,0,2) ....(0,0,n)을 지칭한다.
메모리 구조는 배열 안에 배열이 들어가있는 구조이다. 배열 안에 주소값이 들어있는 구조이다. 아래의 사진에서 보면, Heap Memory 안에 있는 주황색 Array 안에 주소값이 있고, 초록색 Array가 value값이 있는 구조이다.
흔히 생각하기엔 단순하게 5*5 2차원 행렬이 있다고 한다면, 각각의 행의 값을 지정하는 array가 따로 있고, 그 array는 번지수(주소값)을 저장하는 array가 따로 있는 셈이다. 2번째 칠판에 판서된 내용을 고려해보면 이는 좀 더 명확하게 이해할 수 있다.
int arr[][] = new int[5][5];
Random r = new Random();
for (int i = 0 ; i < arr.length ; i++) {
for(int j = 0 ; j < arr[i].length; j++) {
arr[i][j] = r.nextInt(9) +1 ;
}
}
참고 주석2


심화된 내용----> String이 배열 안에 있으면 어떻게 될까?
사진과 같지만, 사진의 내용도 같은 원리이다. 주소값 배열 안에 주소값이 들어가는 것이다.
사진1

사진2

int arr[ ] [ ] = new int [ ] [ ];
배열은 for문을 달고 산다는 걸 기억해라.
(1) Modern way
for(int a[] : arr) { // arr에 있는 주소값 배열 (사진으로 치면 주황색)
for(int data : a) {
System.out.printf("%d\t", data);
}
System.out.println("");
}
(2) Conventional way
for(int k = 0 ; k < arr.length ; k++) {
for(int m = 0 ; m < arr[k].length ; m++) {
System.out.printf("%d\t", arr[k][m]);
}
System.out.println("");
}
매우 중요하다. HEAP은 중복되는 value는 저장하지 않는다. 참조변수는 stack 안에서 주소값만 저장할 뿐이다.
String str1 = "abc";
String str2 = "abc";
System.out.printf("%d %4.2f %s", a, d, str1);
System.out.printf("%d\t%10.2f\t%s\n", a, d, str1);
if(str1 == str2) {
System.out.println("TRUE");
}
if(str1.equals(str2)) {
System.out.println("TRUE");
}
// 매우 중요함....!!!!!!!!! 주소값이 다르기 때문에 false가 나오는 것임.
String str3 = new String("abc");
if(str1 == str3) {
System.out.println("TRUE");
}else {
System.out.println("FALSE");
}
Matrix n차원 배열
package array;
import java.util.Random;
public class P114 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[][] = new int[5][5];
Random r = new Random();
for (int i = 0 ; i < arr.length ; i++) {
for(int j = 0 ; j < arr[i].length; j++) {
arr[i][j] = r.nextInt(9) +1 ;
}
}
for(int k = 0 ; k < arr.length ; k++) {
for(int m = 0 ; m < arr[k].length ; m++) {
System.out.printf("%d\t", arr[k][m]);
}
System.out.println("");
}
}
}