자료형과 메모리

- 기본자료형 && 지역변수 -> 스택에 저장됨, 자동으로 초기값이 설정되지 않음.
- 기본자료형 && 멤버변수/정적변수 -> 아직 안함
- 참조형 -> 값은 힙메모리에 저장됨
- 기본자료형이라도 참조형이면 자료형에 따라 자동 초기화
- 클래스들도 필드들이 자동 초기화됨

 

new 연산자

- String 클래스를 제외한 클래스, 배열, 인터페이스는 필수적으로 new 연산자 사용함
- 힙에 새로운 공간을 형성하라는 표시

 

참조형

- 클래스, 배열, 인터페이스, 열거타입(잘 쓰지 않음)
- 값이 힙메모리에 저장됨, 그 값이 저장된 영역의 시작주소를 스택메모리에서 가짐
- 힙메모리 : 동적으로 계속 공간을 늘릴 수 있는 특징

 

메모리 영역

- 스택 메모리 영역
- 힙 메모리 영역
- 메소드 메모리 영역

 

참조형

+ 인터페이스(자료구조)
- 대표적인게 List

 

배열 정리

- 동일한 자료형만 저장가능한 정적인 자료구조
- 정적 자료구조 = 크기가 딱 정해져 있음. new int[3] 하면 딱 3개만 생성
- 배열이름.length 속성 : 배열의 크기 = 배열 방의 개수 

 

배열 매개변수 예시1
- 메소드의 매개변수가 기본자료형이 아니라 참조형 중 배열일때

 

public static void main(String[] args) {

		int[] scores; // 여기 int[] scores ; 는 아직 주소를 가지지 않은 상태

		scores = new int[] { 83, 90, 87 };

		// int[] scores = new int[] {83,90,87}

		int sum1 = 0;
		for (int i = 0; i < 3; i++) {
			sum1 += scores[i];
		}
		System.out.println("총합 : " + sum1);

		// add 메소드를 호출해서, 리턴된 총합을 sum2에 저장
		int sum2 = add(new int[] { 83, 90, 87 });
		System.out.println("총합 : " + sum2);

	} // main() end

	// 사용자 정의 메소드 : 합을 구해주는 메소드 : 배열을 매개변수로
	public static int add(int[] scores) {
		int sum = 0;
		for (int i = 0; i < scores.length; i++) {
			sum += scores[i];
		}
		return sum;
	}

- int[] scores 는 주솟값을 가지지 못한 형태다
- 메소드의 매개변수가 참조형 중 배열이다.
- 이땐 배열의 주솟값을 전달해야함
- Call by Reference 방식으로 호출해야한다.
- 이 int 형 배열의 주솟값을 전달하자
- 매개변수자리에 클래스, 배열, 인터페이스 다 올 수 있다.

 

배열 매개변수 주의(위 예제의 부분)

 

	public static int add(int[] scores) {
		int sum = 0;
		for (int i = 0; i < scores.length; i++) {
			sum += scores[i];
		}
		return sum;
	}


	public static void main(String[] args) {

		int[] scores; // 여기 int[] scores ; 는 아직 주소를 가지지 않은 상태
	}

- main의 int[] scores 는 주솟값을 가지지 못한 형태다
- new 연산자를 써야만 새로운 공간을 힙메모리에 할당받는데 아직 안썼으므로
아직 주솟값이 없는 상태
- add함수로 전달하는 건 주솟값을 전달해야함 = Call by Reference

 

	public static void main(String[] args) {
		int sum2 = add(new int[] { 83, 90, 87 });
	}

- 이 경우엔 리턴받는게 없으니 이 공간은 재사용을 못한다
- 이렇게 해서 new를 써서 add 메소드로 주솟값을 전달함
- 힙 메모리 상에 있는 "같은 자료형 "(여기선 int형) 배열의 주솟값을 전달해야함
- new를 쓸때마다 새 공간이므로 이 sum2가 가리키는 new의 공간이랑 맨 위에 scores 이 가리키는 공간은 다른 주소이다
- 힙메모리상에 불필요하게 공간을 사용하는건 Garbage Collector 프로그램이 주소를 전달한 뒤 자동으로 지워버림 = 재사용 불가

 

+ 값 전달하는거보다 주솟값을 전달하는게 처리가 빠르다
+ C언어에선 이걸 포인터로 전달함

 

참조형인 매개변수 정리
- 주솟값을 할당받기 위해선 반드시 new 연산자가 있어야함
- String s= "자바" 가 가능하므로 String s 가 매개변수로 올때만 예외적으로 바로 check("자바") 로 호출 가능
- 또는 String s = new String("파이썬") 도 가능하므로 check(new String("파이썬") 으로 호출해도 된다.
- 다른 참조형 변수는 99% new를 써야함

메소드 정리
- 메소드 앞에는 return 자료형이 반드시 와야함
- 정적메소드이기 때문에 클래스명.add 또는 같은 클래스 내에선 .add 로 생략하고도 쓸수있다
- 정적메소드 아니면 객체를 생성후 호출해야한다.

배열 초기화 정리
- int뿐아니라 정수형 배열들은 다 0 으로 초기화 됨(char제외)
- 실수는 float 는 0.0f double 은 0.0
- 클래스/인터페이스/배열은 null로 초기화
* null : 주솟값이 없다는 의미


확장 for문 = 향상된 for문
- 순차적인 자료구조인 배열, 리스트같은 곳의 원소를 끄집어낼때 사용함
- 배열에 있는 값을 원소값이 더이상 없을떄까지 하나씩 왼쪽의 변수로 옮김
- 간결하기때문에 자주 씀

 

for( 타입 변수 : 순차적인 자료구조(배열,컬렉션)) {
             실행문 ;
}

* 타입변수 : 전달 받을 값 
* 컬렉션 = 자료구조(여기선 순차적인 자료구조를 의미), 대표적인게 리스트

 

확장 for문 예제

		int[] score = { 95, 71, 84, 93, 87 };


		// 확장 for문
		int sum1 = 0;
		for(int s : score) {
			sum1 += s;
		}

- 값을 받는 변수 s 도 배열의 자료형과 같은 int 형으로 받아야함
- score 배열에 들은 원소(값)들을 왼쪽의 s변수에 하나씩 전달, 이걸 원소값이 없을때까지 반복한다
- 전달된 값을 sum1 변수에 누적 

+ 순차적인 자료구조 :List, Vector
+ stack은 순차적인 자료구조 아님 다른 방식

 

main 메소드의 매개변수

- public static void main(String[] args){}
- JVM에서 여태껏 main 실행할때 아무 값 전달하지 않았음
- 하지만 전달 할 수도 있다.
- 전달시 args[0]에 첫번째 값이, args[1]에 두번째 값이 들어감
- String 자료형이므로 숫자를 적어도 문자로 처리됨

 

main 메소드의 매개변수 활용

package p2022_06_27;

public class ArrayEx07 {

	// 절대값을 구해주는 메소드
	static int abs(int data) {
		if (data < 0)
			data = -data;
		return data;
	}

	public static void main(String[] args) {

	// args[0] = "-10", args[1] = "-20"
		System.out.println("args[0] : " + args[0]);
		System.out.println("args[1] : " + args[1]);
	// args[0] = "-10" ---> -10 : 형변환(int로)
		int num = Integer.parseInt(args[0]);
		System.out.println("절대값 : " + abs(num));
	}

}

- 이 코드를 그냥 실행시 오류
- main 메소드 통해서 값을 전달할땐 그냥 실행시 오류가 생김
- 실행시키는 방법이 다름 ! (자주 쓰는건 아니지만 알아두기)

 

이클립스로 실행법
1. RUN 초록 화살표 버튼 마우스 대고 있으면  Run Configuration  메뉴 잇다
2. 두번째 탭인 arguments 선택
3. 위칸 program arguments 에서 -10 -20 을 입력(뛰어쓰기로 args[0] args[1] 값 구분)

- args[0]에 -10, args[1]에 -20 이 전달됨
- (-10)을 써도 String[] 이 매개변수이므로 문자인 "-10" 인것임
+이클립스가 아닌 콘솔창 자바 가상머신에서 실행시

java ArrayEx07 -10 -20

- 이렇게 실행함


의미 설명

1. java : 자바 가상머신 JVM
2. ArrayEx07 :ArrayEx07.class 란 바이트 코드를 실행함
3. -10 -20 이렇게 구분해서 입력

 

- args[0]에 -10, args[1]에 -20 이 전달됨
- (-10)을 써도 String[] 이 매개변수이므로 문자인 "-10" 인것임

 

자료형 변환

- 형변환된 값을 abs 메소드에 전달해야하는데 abs는 매개변수가 int 형이므로 그래서 문자를 숫자로 일단 변경하고 메소드 호출해야함.
-이걸 절대값 구할때는 args[]에 들은 데이터는 String은 문자열 이므로 int 로 바꿔야함
- "-10"을 숫자 -10 으로 바꿀땐 

int num = Integer.parseInt(args[0]); // 자주씀 외우기

- 자바의 3가지 자료형 변환 중 두번째 자료형 변환 방법임

 

Wrapper 클래스 (자료형 변환 원리)

- 기본자료형마다 Wrapper 클래스가 있다 .
- Integer 는 int 의 wrapper 클래스임
- 그래서 Integer.parseInt("20") 을 사용해서 문자 20을 숫자 20으로 변환
- Wrapper 클래스를 쓰면 기본자료형과 참조형 사이의 자료형 변환이 가능하다 (ex) string <-> int)
- 모두 java.lang 패키지안에 있어서 import 필요없다
-  Wrapper 클래스 쓰면 다른 자료형으로 쉽게 변환 가능

 

Wrapper Class

- boolean 은 Boolean
- byte 는 Byte
- char 은 Character
- int는 Integer

 

Wrapper 클래스를 이용한 변환 방법 2가지
1.

 int num = Integer.parseInt("20")


- pasreInt는 정적메소드라서 따로 객체 생성없이 클래스명. 으로 호출 parse() 안에는 String 자료형
2. 

Integer in01 = new Integer("20");
int num01 - int01.intValue();


- 언박싱

wrapper클래스의 주요 2가지 기능
1. String -> int (이게 거의 대부분임)
2. int -> String ex) String s - String.valueOf(20);

Integer 클래스 구조 (api 문서)
java.lang.Object
java.lang.Number
java.lang.Integer
- 최상위 클래스 = 슈퍼클래스는 Object
- 부모 클래스는 Number
- 상속 관계가 이미 다 형성되어있다.


1. Integer 의 필드(변수, 상수 의 개념)
- MAX_VALUE 쓰면 int형 변수가 가질 수 있는 최대값을 구해줌(정적필드) 약 +21억
- MIN_VALUE 스면 int형 변수가 가질 수 있는 최솟값을 구해줌


2. Integer 의 생성자
- 2개뿐


3. Integer의 메소드
- 메소드 중 pasreInt 는 2개가 있다 = 메소드 오버로딩
* 메소드 오버로딩 에서 이름은 같아도 매개변수등 구분이 되어야 잘 사용한것
- parseInt (String s) : 우리가 쓴 메소드 . 타입은 static int다 정적메소드이므로 Integer.parseInt로 사용하고, int 형 변수에 결과를 저장해서 돌려줌 매개변수 안엔 String 형만 들어가야함
- parseInt (String s, int radix) 도 있다.

+ 오라클등의 DB 연동할때 java.lang.Class 클래스 사용


배열을 복사하기
- 여러 방법 있다
1. for문
2. System.arrayCopy() 메소드
3. Arrays 클래스 이용

 

for문으로 배열 복사하기

public class ArrayEx08 {

	public static void main(String[] args) {

	//p167~p168
	//배열 복사 : for문으로 배열 복사
		
		int[] oldArray = {10,20,30}; //원본 배열
		int[] newArray = new int[5]; //새로운 배열
		
		for (int i = 0; i < oldArray.length; i++) {
			newArray[i] = oldArray[i]; //배열 복사
		}
		
		//복사된 배열 출력
		for(int i : newArray) {
			System.out.print(i + "\t");
		}
	}

}

- newArray는 배열이므로 0으로 다 초기화 된 상태
- oldArray -> newArray 로 복사할때 for문돌아가면서 10이 newArray[0] 으로 20이 newArra[1]으로 30이 newArray[2]로 복사됨
- 한줄 엔터키를 안쓰고 그냥 띄우기나 \t를 쓸때는 println이 아니라 print인점 주의

 

위 예제 그림

2차원 배열 정의방법 2가지

1.

int[][] score = new int[5][3];

- 메모리상에 값 저장위한 기억공간만 생성하고 그 값이 아직 뭔지 모를때 사용
- 2차원배열은 [][]처럼 2개임, [][]가 score 뒤에 가도 됨
- new란 연산자를 쓰는 형식
- 왼쪽, 오른쪽 자료형 같은걸로 맞추기
- 첫번째 괄호에 들어가는건 행의 수 (가로방향)
- 두번째 괄호에 들어가는건 열의 수 (세로방향)
- 4바이트짜리 기억공간을 행 5, 열 3으로 15개 생성하라는 뜻. 5행 3열짜리 기억공간 생성 

 

그림

2.

int[][] score = {{0,0,0},{0,0,0},{0,0,0}};

- 값이 고정되어있을때 쓰는 방식

 

예시

 

int [][] score = { { 85,  60,  70},      //0 행
	            { 90,  95,  80},       //1 행
	            { 75,  80, 100},       //2 행
                    { 80,  70,  95},       //3 행
	            {100,  65,  80} };     //4 행

- 0행 0열에 85, 4행 2열에 80이 들어감

 

2차원 배열 인덱스
- 행 = row = 가로번호
- 열 = colume = 세로번호
- 행 번호는 가로번호 의미
- 배열에 인덱스는 0번부터니까

배열 인덱스 예시

score[0][0] = 85; //0행0열에 85점을 할당하라
score[4][2] = 80; //4행2열에 80점을 할당하라

 

2차원 배열 입력/출력

 

public class Arr04 {

  public static void main(String[] args) {
   
    int [][]score = { { 85,  60,  70},   //0 행 = 1번학생
			{ 90,  95,  80},   //1 행 = 2번학생
			{ 75,  80, 100},   //2 행 = 3번학생  
                        { 80,  70,  95},   //3 행 = 4번학생
			{100,  65,  80}    //4 행 = 5번학생
					};
    int [] subject = new int[3]; //과목총점 저장할 1차원 배열
    int [] student = new int[5]; //학생의 총점 저장
        //    subject[0]=0, student[0]=0;
    int  r, c;  
	    
    System.out.println("각 과목별 총점구하기 "); //열방향으로 다 합쳐야
    for(c = 0; c < 3 ; c++){ // 과목         
      for(r = 0; r < 5 ; r++){ //학생      
        subject[c] += score[r][c];   
      }//subject[c]=subject[c]+score[r][c];
      System.out.println(subject[c]);  
    }

    System.out.println("학생별 총점구하기");
    for(r = 0; r < 5 ; r++){    //학생      
      for(c = 0; c < 3 ; c++){  //과목    
        student[r] += score[r][c];  
      }//student[r]=student[r]+score[r][c];
      System.out.println(student[r]);
    }

  }//main() end
}// class end

- 행 열을 따로 처리해야하므로 중첩 for문을 쓴다
- 행번호는 0~4이기 때문에 for문으로 0부터 시작해서 <5까지 즉 4까지 함, == 학생수는 5명
- 그 학생 당 과목 성적을 위해서 안쪽 for문으로 0부터 2까지 3번 돌림 == 과목수 3개(국영수)
- 행과 열이 만나는 곳의 점수를 출력하면 score[row][col]
- 더 빨리 바뀌는 부분이 for문의 안쪽에 와야함 나중에 움직이는 부분이 바깥쪽에
- 과목 총점 구하기는 [0][0] [1][0] [2][0] ... 을 더해야하고 ->과목은 열이기 때문에 for문 안쪽에 r 가 와야함
- 학생별 총점 구하기는 [0][0] [0][1] [0][2] ... 를 더해야함 -> 학생은 행이기 때문에 for문 안쪽에 c가 와야함
- int [] subject = new int [3] 이나 int [] student = new int[5]; 는 자동초기화 0 이므로 sum = 0 같은
번거로운일 할 필요 X

 


객체지향언어

 

클래스
- 클래스도 자료형이다
- 배열과 메모리상 처리는 거의 비슷함

String 클래스
- 클래스 중에서 쉽게 이해할 수 있는 String 클래스로 예시들어서 설명
- 클래스 중 사용빈도 가장 높음

String 클래스와 메모리
- String 클래스로 String 객체를 만든다
- 객체를 만들면 배열과 마찬가지로 문자열 " " 들은 모두 힙메모리상에 저장됨(참조형이 가지는 공통적인 특징)
- 그 메모리의 시작주소값을 변수가 스택에서 가지고 있다

 

String name;
name = "신용권"

- 그냥 이름을 저장하는것같아 보이지만 "신용권"은 힙의 공간에 저장, 그 주소를 가진 name은 스택에서 주소를 가지고 있다.

 

String 클래스와 메모리2
- String 클래스의 경우에는 문자를 바로 할당해도 되고 new 연산자를 사용해도 된다
- 이 두가지 되는건 String 밖에 없다
- 보통의 클래스는 new 연산자를 써서만 객체 만들어야함
- 하지만 new 연산 썼을때와 쓰지 않았을때 메모리에 차이가 있다.

String name1 = "신용권";
String name2 = "신용권";

- new 연산자를 쓰지 않고 만들면 처음 한번은 "신용권"을 저장한 기억공간을 힙메모리에 만듬
- 두번째의 경우에는 새로운 공간 만들지 않고 이미 "신용권"이 저장된 공간의 주솟값을 리턴받음
- name1 == name2 주솟값이 같다

 

String name1 = new String("신용권");
String name2 = new String("신용권");

- new 연산자를 쓰면 매번 새로운 공간을 힙메모리에 생성하라는 명시적인 표시
- new 연산자를 2번 썼기 때문에 새로운 공간이 2번 만들어짐
- 그림을 보면 힙 메모리상에 공간이 따로 따로 만들어짐
- name1 != name2 주소가 다르다

 

참조형의 비교

- 참조형들은 비교대상이 2개다
- name1 == name2 처럼 비교연산자로 주솟값을 비교
- equals() 란 메소드로 값들끼리 비교

 

주솟값 비교 예시

		String str1 = "자바";
		String str2 = "자바";

		if (str1 == str2) { //비교연산자(==)로 참조하는 주소를 비교
			System.out.println("같은 주소"); //같은 주소
		} else {
			System.out.println("다른 주소");
		}



		String str3 = new String("자바");
		String str4 = new String("자바");
		
		if (str3 == str4) { //비교연산자(==)로 참조하는 주소를 비교
			System.out.println("같은 주소"); //같은 주소
		} else {
			System.out.println("다른 주소");
		}

- 비교연산자(==)로 참조하는 주소를 비교

 

그림

값 비교 예시

		if(str1.equals(str2)){ // 참조하는 값(데이터)을 비교
			System.out.println("같은 값"); //같은 값
		}else {
			System.out.println("다른 값");
		}

- 값비교 equals() 메소드를 사용
- 같으면 true를 반환

 

참조형의 비교 정리

- 비교연산자(==) : 참조하는 주소를 비교
- equals() : 참조하는 값(데이터)을 비교

 

+ 메소드를 찾는 법
ex) equals() 메소드를 어디서 찾아야할까
1. 1차적으로 api에서 equals() 메소드가 어디 붙어있는지 보자 -> String
2. String클래스 찾아야
3. String클래스 안에 없으면 그거 조상들 클래스를 찾아야
- String의 경우엔 부모가 java.lang.Object가 최상위 클래스 , 자기 부모 클래스 임. 
- String 안에 없더라도 조상이 그 메소드를 가지고 있으면 상속 받아 string 객체에서도사용할 수 있다.
- 만약 String클래스도 String의 부모클래스에도 equals()없다면 그건 없는 것임.

+ 클래스 구조
- 필드 1개 있고 생성자있다
- 생성자 : 객체를 생성할때 자동으로 호출되는 메서드, 클래스와 같은 이름이다.

 

String 클래스 구조 생성자
- 우리는 매개변수가 String으로 된 생성자를 호출해왔었음 String(String original) 을 써왔던것

 

String str3 = new String("자바")

- 에서 오른쪽은 String은 생성자를 호출하는 것임
- 생성자는 없으면 못씀 제공되는것만 쓸 수 있다

 

String 클래스 구조 메소드
- String 클래스 안 메소드 많다(기능 많다 )
- equals() 메소드의 리턴타입은 boolean, 값이 같으면 true, 다르면 false를 리턴해줌
- 그래서 이 메소드 자체를 if문 안에 넣었던 것

 

Object 클래스와 equals()

- equals() 메소드의 매개변수는 Object
- 자바의 가장 최상위 클래스가 Object임 = 슈퍼클래스= 최상위 부모 클래스
- 패키지가 엄청 많지만 그게 뭐든지 가장 위는 Object 
- 즉, Object 는 모든 클래스의 최상위 부모, 조상
- equals() 메소드 매개변수가 equals(Object anObject) 
- 값을 비교할때 Object의 자식들은 다 equals 안에 들어갈 수 있다. 모든 클래스 다 들어갈 수 있다.
- 즉, equals() 괄호 안에 int, boolean, String등 다 들어갈 수 있다
- String뿐만 아니라 Object의 자식들은 모두 비교 equals로 비교가능, 즉 모든 자료형 다 비교 가능

 

예시1

		boolean b = "자바".equals("파이썬");
		if(b) {
			System.out.println("같은 값");
		}else {
			System.out.println("다른 값");
		}

- 가능함
- 3번째 자료형형변환 방법, 레퍼런스 관련이 있다

 

예시2

		if(new Integer(30).equals(30)){
			System.out.println("같은 값");
		}else {
			System.out.println("다른 값");			
		}

- int형끼리 비교도 가능하다.
- int, double, boolean 등 모든 걸 equals 로 비교 가능
- wrapper 클래스 , 오토박싱,오토언박싱 등의 개념 앞으로 공부하는것과 연관

 

객체배열
- 객체의 주소를 참조하는(저장하는) 배열
- C++은 많이 쓰지만 String은 많이 쓰진 않음 객체배열보다 성능 좋은 list등이 있기 때문에

 

ex) String객체를 3개 저장하기 위한 배열 = 객체배열

		String[] strArray = new String[3]; // 객체배열
		strArray[0] = "Java";
		strArray[1] = "Java";
		strArray[2] = new String("Java");

- 이렇게 객체 생성시시에 2가지 방법 써서 가능
- 0번방, 1번방 가리키는 "Java"는 같은 곳임
- 0번방, 2번방 가리키는 "Java"는 서로 다른 곳음

		System.out.println(strArray[0] == strArray[1]); //주소값을 비교, true
		System.out.println(strArray[0] == strArray[2]); //주소값을 비교, false
		System.out.println(strArray[0].equals(strArray[2])); //값을 비교, true

 

사용자 정의 클래스
- String 클래스와 비슷한 방식으로 메모리상 처리가 됨

객체 지향 프로그래밍(OOP)
- 부품 객체를 먼저 만들고 이것들을 하나씩 조립해 완성된 프로그램을 만드는 기법

객체
- 물리적으로 존재하는 모든게 객체가 될 수 있다 ex) 자동차, 사람, 책
- 추상적인 것도 객체가 될 수 있다 ex) 회사, 날짜
- 현실세계에선 사람이란 객체가 있을때 사람에 대한 속성이 있다 ex)나이, 이름 => 속성
- 사람이란 객체가 있을때 있는 동작 ex) 달린다, 걷는다 => 메소드

객체 모델링
- 자바같은 객체지향언어에선 객체 모델링이란 작업을 수행한다
- 사람이란 객체의 속성을 표현할때는 '필드'라는걸가지고 속성을 나타남
- 메소드 바깥쪽에 쓰는 변수 = 멤버변수 = 필드 변수 = 객체의 속성 나타냄
- 메소드를 가지고 객체의 동작을 표현함

현실세계의 자동차 객체
- 필드를 가지고 객체의 속성에 대한 것들을 표현
- 속성 : 색상, 속도 -> '필드' 로 표현함, 필드는 쉽게 말하면 멤버변수임
- 필드는 메소드 바깥쪽에 정의되는 변수로서 멤버변수라고 불린다. 자바에선 필드라고 불림
- 동작 : 메소드를 가지고 표현. 달린다 멈춘다 등의 동작을 메소드로 표현

객체 지향 프로그래밍이 가지는 특징
1. 캡슐화
- 한개의 클래스가 만들어져 있을때 외부클래스에서 접근하지 못하도록 캡슐로 보호를 한다.
- 캡슐화위해선 접근제어자로 접근을 허용을 하기도하고 허용을 하지않기도 한다.
ex) private 써서 외부로부터 접근 막음 = 캡슐화로 안전하게 안의 정보를 보호함

2. 상속
- api에서 제공되는 클래스는 이미 상속관계 정의 다 된 상태임.
- 상속을 함으로서 중복적인 코드를 많이 줄일 수 있다
- 또 유지보수를 편리하게 해주는 기능을 제공하기때문에 상속을 많이 사용함.

ex) 부모 클래스가 있고 자식 클래스가 있을떄
- 클래스 = 필드, 메소드, 생성자 로 구성
- 상속이 되는건 2가지 뿐! 필드와 메소드만 상속이 되고! 생성자는 상속되지 않음!

3. 다형성(Polymorphism)
- 부모로부터 상속받은 것들을 다양한 형태로 바꿔서 쓴다는 것

객체와 클래스
- 설계도 역할을 하는게 클래스다
- 현실세계 : 설계도 -> 객체  를 만들어냄 (ex)설계도로 자동차를만들어냄)
- 자바 : 클래스 -> 객체. 설계도역할하는게 클래스, 클래스 가지고 객체를 무한히 많이 만들어 낼수 있다.

클래스 이름
- 하나이상의 문자로 이루어져야
- 변수명과 마찬가지로 첫번째 글자는 숫자올수없다 ex) Car 3Car (x)
- $나 _ 외의 특수문자 사용불가
- 자바 키워드는 사용할 수 없다
- 변수명,함수명,클래스명등은 한글명으로 클래스 명 쓰는건 바람직하지 않다. 웹으로 가면 여러 문제 발생!

클래스와 소스파일
- 이클립스에서 클래스를 만들면 소스파일이 생성됨 클래스이름.java 가 생성됨
- 이걸 javac.exe가 컴파일 해줘서 클래스이름.class 생성됨
- 앞으로는 한개의 .java 파일에 클래스가 여러개가 들어가는 소스파일 .java 을 만들것
- 소스 파일 당 public class 는 1개만 사용가능함! 이 public 을 가진 클래스와 파일명을 일치시켜야함
- 클래스명과 파일명이 일치되어야하는데 단, 이때 메인메소드를 가진 클래스명과 파일명을 일치 시켜야함
- 컴파일이 되면 파일 안의 여러개 클래스가 각각 따로 따로 .class 파일들로 만들어짐(클래스 수만큼)

객체 생성

new 클래스();

- 클래스와 동일한 이름의 생성자를 호출하라는 코드
- 생성된 객체는 힙메모리상에 객체가 생성됨
- new 연산자는 객체를 생성후 객체 생성 주솟값을 리턴하므로, 왼쪽의 변수가 그 주솟값을 갖고있게됨

 

객체 생성 방법 2가지

1.

클래스 변수;
변수 = new 클래스();

2.

클래스 변수 = new 클래스();

- 한줄

 

클래스 구성 멤버와 역할
- 필드 : 변수기때문에 메모리상의 값을 저장하는 역할
- 생성자 : 객체가 생성시 호출되며 필드값을 초기화하는 역할
- 메소드 : 객체의 동작적인 걸 표현하는 역할

사용자 정의 클래스
- api 에 있는 클래스를 모방하여 생성
- 메소드 바깥쪽에 사용되는 변수 = 필드 = 멤버변수, 변수기때문에 값을 저장함, 속성을 표현
- 생성자는 클래스명과 동일한 이름으로 만들어야함. 객체가 생성될때 생성자가 호출되며
필드값을 초기화시키는게 생성자의 역할
- 메소드는 객체에 대한 동작을 나타냄, ex) public void static main

 

정리
메인 메소드 안의 변수 = 지역변수 = 스택메모리 = 메소드종료시 삭제
메소드 밖의 변수 = 멤버변수 = 필드 = 전역변수 = 힙 메모리 = 초기화

 

사용자정의 클래스 만들기 예시

 

public class Animal {
//Animal 은 사용자 정의 클래스(자료형)

	
	int age; //자바에선 멤버변수, 필드(field) 라고 한다. C에선 전역변수라고 부른다.
		// : 메소드 바깥쪽에 정의되는 변수
	
	public static void main(String[] args) {

	}

}

- age는 메소드 바깥에 있고, 이 클래스 전역에 사용 가능
- 멤버변수= 필드 = 전역변수 는 메모리 중 힙메모리 상에 저장됨!
- 클래스도 참조형이기 때문에 int age; 는 힙메모리상의 공간을 할당받고 초기화 0 으로 자동초기화됨

 

* JAVA구조 : 클래스 내에 메소드가 있다

 

생성자
- 멤버 함수 중 하나
- 반드시 클래스명과 동일한 이름으로 생성해야함.
- () 괄호가 반드시 있어야한다.
- 생성자명앞에는 접근제어자만 올 수 있다.

기본생성자(default constructor)
- 생성자 중 매개변수가 없는 생성자

 

	int age; 
	public Animal() {
		System.out.println("생성자 호출 성공");
	}

 

사용자 정의 클래스와 클래스의 구조 3가지

 

public class Animal {
//Animal 은 사용자 정의 클래스(자료형)

	
	int age; //필드
	public Animal() { //생성자
		System.out.println("생성자 호출 성공");
	} 
	
	public static void main(String[] args) {  //메소드
		
		int a = 10;

	}

}

- 필드, 생성자, 메소드가 다 있는형태
- 생성자는 주로 객체생성과 동시에 필드값의 초기화를 설정하기 위한 용도로 객체가 생성될때 호출되면서 실행
+ a는 지역변수, stack 메모리 영역에 저장, 이 메소드 안에서만 사용가능
+ 지역변수와 멤버변수는 스택과 힙 이라는 다른 공간에 저장되는것 뿐만 아니라 메모리상에 저장되는 영역과 할당되는 시점이 다름

 

	public static void main(String[] args) {

		int a = 10; //지역변수
		String str = new String("자바");
		Animal a1 = new Animal();
	}

+ 이 main메소드는 Animal 클래스 내부임. Animal 클래스 내부에 Animal 클래스로 객체 만들어도 된다.

 

그림

필드 접근

    Animal     a1         =   new       Animal();
// 클래스 레퍼런스변수 연산자 생성자호출

- 이렇게 객체를 생성시 4바이트짜리 Animal 클래스의 '필드'를 저장하기 위한 기억공간을 힙에 생성함
- 그 필드는 age (=0 , 자동초기화) 이다. 그 주솟값을 a1이 가지고 있는 상태
- a1이 age가 저장된 힙메모리상의 시작주솟값을 가지고 있다.
- 이 a1으로 접근해야지만 이 age에 접근가능하다!

 

System.out.println(age); // 불가능
System.out.println(a1.age); // 로 해야함

- 반드시 a1이 가진 주소 이용해서 a1.age로 접근해야함!
- 객체 생성될때마다 새로운 age만들어지므로 어느 영역에 있는 age인지 알 수 없기 떄문이다

- age의 값을 수정하고 싶을때도  a1.age로 접근해서 수정해야한다

		a1.age = 5;
		System.out.println(a1.age); //5가 출력됨

 

생성자 호출

- 오른쪽의 Animal() 은 생성자를 호출하라는 코드임

	public Animal() {
		System.out.println("생성자 호출 성공");
	}

- 출력이 됨

 

생성자를 안쓴다면?
- 기본으로 알아서 생성해줌 

 

객체 생성2

ex) 이번에는 Animal 클래스로 다시 new 연산자로 다시 객체 생성해보자

		Animal a2 = new Animal();
		System.out.println(a2.age);

- 이러면 힙메모리상에 새로운 공간이 또 생성됨!

- 그림 참고

 

그림

- a1이 가진 주소와 a2가 가진 주소를 비교해보자

		if (a1 == a2) {
			System.out.println("같은 주소");
		} else {
			System.out.println("다른 주소");
		}
출력 : 다른 주소

- new로 힙메모리에 새로운 공간을 만들었기 때문이다

 과제
2022.06.27 / Hw2

구구단(2~9단)의 연산 결과를 2차원 배열에 저장하고,
 배열에 저장된 결과를 이용해서 구구단을 출력하는 
프로그램을 작성하세요?

 

 

의도

2차원 배열의 이해

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220627/Hw2.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_27;

public class Hw2 {

	public static void main(String[] args) {

//	    2. 구구단(2~9단)의 연산 결과를 2차원 배열에 저장하고,
//	       배열에 저장된 결과를 이용해서 구구단을 출력하는 
//	       프로그램을 작성하세요?

		int[][] gugudan = new int[8][9];

		// 저장하기
		int r, c;
		for (r = 0; r < 8; r++) {
			for (c = 0; c < 9; c++) {
				gugudan[r][c] = (r+2)*(c+1);
			}
		}
		
		//출력하기
		for (r = 0; r < 8; r++) {
			for (c = 0; c < 9; c++) {
				System.out.print(gugudan[r][c] + "\t"); 
			}
			System.out.println();
		}

	}

}

 

출력

 과제
2022.06.27 / Hw1

2차원 배열을 이용해서 5명 학생들의 국어,영어,수학        
점수를 저장 했을때, 과목별 총점과 학생별 총점을 
 출력하는 프로그램을 작성하세요?
(단, 과목명(국어,영어,수학), 학생번호를 출력 하세요) 

 

 

의도

2차원 배열 익히기

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220627/Hw1.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

 

package p2022_06_27;

public class Hw1 {

	public static void main(String[] args) {

//	과제 1. 2차원 배열을 이용해서 5명 학생들의 국어,영어,수학        
//	       점수를 저장 했을때, 과목별 총점과 학생별 총점을 
//	       출력하는 프로그램을 작성하세요?
//	    (단, 과목명(국어,영어,수학), 학생번호를 출력 하세요) 

		int[][] score = { { 85, 60, 70 }, // 0 행 = 1번학생
				{ 90, 95, 80 }, // 1 행 = 2번학생
				{ 75, 80, 100 }, // 2 행 = 3번학생
				{ 80, 70, 95 }, // 3 행 = 4번학생
				{ 100, 65, 80 } // 4 행 = 5번학생
		};
		int[] subject = new int[3]; // 과목총점 저장할 1차원 배열
		int[] student = new int[5]; // 학생의 총점 저장
		// subject[0]=0, student[0]=0;
		
		//과목명
		String[] subjectName = {"국어","영어","수학"};
		
		int r, c;

		System.out.println("각 과목별 총점구하기 "); // 열방향으로 다 합쳐야
		for (c = 0; c < 3; c++) { // 과목
			System.out.print(subjectName[c] + " ");
			
			for (r = 0; r < 5; r++) { // 학생
				subject[c] += score[r][c];
			} // subject[c]=subject[c]+score[r][c];
			System.out.println(subject[c]);
		}

		System.out.println("학생별 총점구하기");
		for (r = 0; r < 5; r++) { // 학생
			System.out.print( r+1 + "번 학생 : "); //학생명
			for (c = 0; c < 3; c++) { // 과목
				student[r] += score[r][c];
			} // student[r]=student[r]+score[r][c];
			System.out.println(student[r]);
		}
	}

}

 

 

출력

 

등장 배경

전통적 프로세스 :

- 같은 OS, CPU 등의 환경이여아 프로그램이 돌아간다, 사실상 동일기계여야 돌아감
- 마이크로 소프트웨어 PC 세데에선 OS, 환경들이 동일했으므로 같은 환경이어서 동작했었다

 

But 웹의 등장 이후 :

- 모든 소프트웨어는 웹에서 서비스 하게 되었다.

- VM 은 같은 OS여도 보조 앱들이나 라이브러리 디펜던시가 다를 수도 있다.

- VM은 비교적 무거움

 

Image vs Container

- Image : 조리법(레시피), Container는 만들어진 요리, 실제 사용되는 프로세스
- Stopped Container : 만들어서 냉장고에 보관한 요리

 

세상의 모든 SW는 Containerized 되어 제공된다.

- Container 배포 = SW 배포
- Container 테스팅 = SW 테스팅
- Containerized된 어플리케이션 앱 = 프로세스

- 그 앱이 실행되는데 필요한 환경, OS, 커널, 비표준 라이브러리 등의 환경(Helper Process)까지 장착하여 한 패키지로 되어 어디서나 실행할 수 있도록 만들어짐

- Container Engine : 컨테이너를 동작시키기 위한 OS 수준에서 Virtualize 를 해준다.

 

Docker Hub

- Container 이미지들을 모아둔 Github 같은 저장소이다. 하지만 최근 대부분 Github 사용

 

VM vs Container

- VM : OS가 다같이 들어있으므로 과도한 메모리 점유, 느린 부팅시간, 여러 VM 실행시 성능 저하, Portability 제한, VM 사이 데이터 공유 불가능, 낮은 효율

- Container : 낮은 메모리 점유, (각 app은 미니멀하게 dependancy만 가지고 있다), 빠른 부팅 시간, 훨씬 많은 수의 container 실행 가능, platform에 좌우되지 않음, 여러 Container끼리 데이터 공유 가능, 높은 효율

 

Container

- App 과 App 실행에 필요한 모든 Dependency 를 묶은 Package

- 지정된 OS 위에서는 Container가 실행될 수 있도록 container engine을 기계에 장착 = 이건 OS level에서의 virtualization 을 app에 제공하는 것.

 

Container의 일생

- Docker Hub 에서 pull/push 로 Image를 가져옴, 이건 환경을 만드는데 필요한 템플릿(코드,시스템,OS 다 포함됨) 이다.

- 또한 Docker File 이라는 텍스트 파일에 이미지 생성 명령과 규정을 적어두고 BUILD(코드+환경까지 같이 컴파일) 해서 Image를 만들수도 있다.

- 이 Image를 RUN 시켜서 Container 를 만듬, 이건 이미지의 instance 라고 볼 수 있음

- Container는 STOP과 DELETE 하면 사라짐

 

Docker 설치 및 기본 명령

sudo apt-get install docker.io
docker run hello-world

- hello-world 라는 dockerhub의 기본 이미지를 가져와서 run하는것. 실제로는 pull 후 run 해야하지만 이건 맛보기

sudo usermod -aG docker $USER

- docker란 그룹에 나를(ubuntu) add 해란 뜻-> sudo 쓸 필요 없다.

cat /ect/group

- add 됐는지 확인 가능

 

Docker 기본 명령 (ubuntu 사용 예시)

docker pull ubuntu // ubuntu 커널 가져오기
docker images //현재 가져온 이미지 확인하기, 이미지 사이즈 확인 가능

 

#RUN(이미지로부터 컨테이너 만듬)

docker run -it -d ubuntu // 여기선 우분투를 RUN

= interactive 하게 우분투 커널을 detached 모드로 RUN 실행만 시키겠다, OS를 demo로 만들어서 동작시켜라

-> terminal 하게 bash shell에서 쓸수있도록, 즉 현재 ubuntu 기계에서 ubuntu OS 를 쓰도록 해준다.

docker ps

= 현재 process 들의 상태를 알려준다.

 

#EXEC(그 컨테이너 실행)

docker exec -it <container id> <prorm in the container>

-  <ps로 확인한 컨테이너이름> bash 로 작성했었다.

-> </ps로 확인한 컨테이너이름>이후 우분투 OS root로, 즉 컨테이너 안으로 들어옴

exit

- 그 우분투 OS 에서 나가기

 

#STOP

docker stop <container id>
docker kill <container id>
docker ps -a //모두 확인

#REMOVE

docker rm-f <container id> //컨테이너 프로세스를 제거
docker rmi-f <image id> //이미지를 제거

 

Containerized Web Service 실습
docker exec -it <container id> bash 이후, 즉 EXEC 이후

1. apache2 설치

apt-get update
apt-get install -y apache2

2. vim 설치 후 /var/www 에서 html 문서 작성하기

cd /var/www
apt get install -y vim
vim 1.html // 작성함

3. 우분투 root에서 빠져나옴

exit

4. 은 laker99/firstweb 처럼 내가 웹 서비스 컨테이너를 이미지로 만든것임

docker commit <container id> <new image name>

5. 이미지 및 프로세스 확인

docker images // image size 확인가능
docker ps // 실행중인 프로세스 확인 가능

6. #WEBSERVICE CONTAINER 실행

6-1. 이 이미지를 81번 포트로 포트포워딩 함. (디폴트는 TCP80)

6-2. EC2의 security inbound rule 에서 TCP 81 열기 브라우저는 IP:81

docker run -it -p 81:80 -d laker99/firstweb
docker ps
docker exec -it <container id> bash //docker ps 에서 확인한 container id 를 적기

7. #CONTAINER 속에서

Service apache2 status //상태확인
Service apache2 start //시작
Exit

 

Dockerfile

= Docker image를 만들기 위해 내리는 순차적인 command들을 모아둔 text 파일

- docker command 들을 입력하여 container 를 수동으로 생성하는 대신에 Dockerfile 안의 Docker build command를 사용해서 container 생성

 

기존 vs Dockerfile

기존: image -> RUN -> container -> EXEC -> inside the container -> do jobs -> exit -> COMMIT -> save a new image

Dockerfile 이용 : Dockerfile -> BUILD -> Docker Image -> RUN -> Docker container

 

Dockerfile 기본 구문

FROM : base image 지정, 기본적으론 OS ex)ubuntu
RUN : base image 위에 추가 SW 계층 설치, image 생성 시점에 사용할 명령어 지정
ADD : ADD <source> <컨테이너내 목적지> 로 파일들을 복사함. COPY와 다른점은 source로 url 을 사용가능
CMD : container 안에서 실행하려 하는 command, container 실행 시 실행되는 명령어를 지정한다.
ENTRYPOINT : CMD 와 유사
ENV : container에서 사용할 Environment 환경 변수를 지정

 

예시

docker run -it ubuntu bash // docker 구문

- entrypoint는 /bin/sh -c (Docker 는 /bin/sh-c를 디폴트 entrypoint )

- image는 ubuntu

- command는 bash

Dockerfile 예시 

- 반드시 vim Dockerfile 라는 이름으로 해야함

FROM ubuntu ##이 커널을 쓸테니 dockerhub에서 ubuntu 이미지를 가져와라

ENV DEBIAN_FRONTEND noninteractive
ENV DEBCONF_NONINTERACTIVE_SEEN true
## 이걸 쓰면 이미지 만들때 Timezone설정하라는 등 뭐 안나옴. interactive 모드 끄는것

RUN apt-get update ## docker image만드는데 필요한 명령어니까 RUN 작동
RUN apt-get install -y apache2

ADD . /var/www/htm
## 현재 디렉토리, 즉 커널 디렉토리의 모든 파일을 모두 다 특정 디렉토리 (html)로 카피(add)하란 명령어임

ENTRYPOINT apache2ctl -D FOREGROUND
## FOREGROUND 의미 : 이게 없으면 Entrypoint에 지정되어있는 apache2ctl을 호출하고 그냥 끝난 후 container process stop되어 아무일도 안벌어짐
## ENTRYPOINT는 반드시 한줄만 있으며 container를 run 시킨 후 해당 container에 entry 하는것 == 위에 bash해서 그 안에서 Service apache2 start 와 같다

ENV env_var_name <변수 이름>

- 이렇게 dockerfile 작성후 이 dockerfile 로 빌드하자

 

BUILD

docker build . -t <image name>
ex) docker build . -t laker99/test

1.

- docker file로부터 이미지 만들기 ex) laker99/test

- .는 현재 디렉토리의 (dockerfile)의미, t는 태그를 의미, image name은 만들 이미지 이름

docker run -it -p <host port #:container port#> -d <image>
ex) docker run -it -p 81:80 -d laker99/test
docker run -it -p <port #:port #> -v <local dir : mounting point dir in container> -d <image>
ex) docker run -it -p 81:80 -v ~/dockerfile:/var/www/html -d laker99/test

= 호스트기계의 디렉토리(~/dockerfile)를 컨테이너의 디렉토리(/var/www/html)에 마운트 시킨것이다.

= volume 쓰면 실행 이후 즉 kill 하지 않은 돌고 있는 상태에서 html 파일을 고칠수있다. 파일내용 업데이트 시 그대로 반영

 

* Docker에서 “마운트"는 컨테이너 외부에있는 데이터를 컨테이너에서 사용할 수 있는 상태가 될 것을 의미한다.

 

Docker-compose

- 다수의 docker container들을 규정하고 실행하고 관리하는 automation 도구 (서로 연동법등 규정)

- 여태까지 했던 것들은 단일 container를 만드는 것이었다.
- but 요즘 웹서비스는 한덩어리 프로그램이 아님. 여러개가 돌아감.

 

Monolithic App vs Microservices

Monolithic App : 비현실, 비효율, 낮은 생산성, 하나의 앱 vs
Microservices : 각 단일 서비스가 서로 느슨하게 결합, 그 사이에서는 HTTP 통신 프로토콜을 이용해서 데이터 교환(REST-API JSON)

 

* 여러개의 프로세스들 = 개별적인 container들 이 모여서 하나의 서비스

- 그래서 다수의 컨테이너를 만들어야함 -> docker compose 사용

 

Docker-compose 를 우분투에 깔아보자

mkdir test;
cd test;
vim docker-compose.yml

- docker compose 사용위해선 이 .yml 포멧의 텍스트파일 사용해아함. 이게 2개이상이 한 디렉토리에 있어선 안된다.

 

version: '3.9' //compose file version
service:
    hello-world: // 컨테이너 하나
        image: hello-world:latest // 가장 최신걸로 이미지인 hello-world를 가져와라

- 키는 version, ' ' 으로 value 와 key 구분
- service의 value는 또다른 key-vaule 짝
- hello-world 의 value는 또다른 key-value 짝
- image의 value는 hello-world:latest

 

.yml 파일 작성 후

docker-compose up -d // .yml을 실행해라, 지금은 연습이니 container 하나만 docker ps

.yml 실행하기

 

예시. wordpress 를 만들어보자

- 여기선 1개 host기계에서 2개 컨테이너를 실행할 것이지만 실제로는 2개 host에서 함

version: "3.9"
service:
    db: //라는 컨테이너임
        image: mysql:5.7
        volumes: //DB 서비스가 사용하는 volume을 create 함.
          - db_data:/var/lib/mysql // name volume 이다. db-data는 volume이름을 작명한 것이고 docker가 이걸 알아서 volume을 만듬
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: somewordpress
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: wordpress // MYSQL에 필요한 것들을 environment 변수로 작성해줌
    wordpress: //wordpress 컨테이너
        depends_on: -db // db란 이름의 서비스에 depend한다는 의미, 즉 위에 있는 db의 결과를 사용한다. db:가 wordpress: 보다 위에 써져있어야만 함
        image: wordpress:latest // 가져와
        volumes:
          - wordpress_data:/var/www/html //name volume이다. wordpress_data를 여기 /var/www/html에 마운트 시키란 의미
        ports: - "8000:80" //8000번으로 포트포워딩 시키기
        restart: always
        environment:
          WORDPRESS_DB_HOST: db
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: wordpress
          WORDPRESS_DB_NAME: wordpress
volumes: //named volumes
  data_base: {}
  wordpress_data: {}

이 .yml 파일 작성 후 그 디렉토리에서 docker-compose up -d 하면 됨

 

Docker Volume 

 

메모리 구조

- container의 가상파일시스템(var/lib/mysql) 이 있고 그 바깥에 host machine의 host의 file system 이 있다.

 

Docker Volume 배경

Container에는 그 안 자체의 메모리앱이 있다., 모두 in 메모리 os리소스이다.

Container를 만든 의도는 메모리상에서만 실행되면 되는 app들을 위해 만들어진것이다.

하지만 persistant한 storage에 OS를 write/read file 서비스 하는 container를 만들어야 할때를 위해 docker volume을 만든 것.

-> 호스트 기계의 on-disk persistent filesystem을 컨테이너의 in-memory virtual filesystem에 mount 하여, 컨테이너가 종료되어도 데이터가 사라지지 않고 호스트 기계의 파일 시스템에 저장되어 다시 동일 컨테이너가 시작되어 과거 데이터를 사용할 수 있도록 제공된 기능.

- DB를 사용하는 컨테이너의 경우에는 필수적

 

Docker Volume의 세가지 타입

1. Host volume

docker run -v /home/mount/data:/var/lib/mysql/data 

- : 의 앞에서 : 뒤로 마운트, 호스트 기계의 파일 시스템 디렉토리가 앞,

- 이게 호스트 볼륩 방식으로 마운트 시키기인데 실제론 사용안함

- 이유: 내 마음대로 원하는 호스트기계 파일 디렉토리 만드는거라 다른 사람들은 경로를 모른다.

 

2. Anonymous volume

docker run -v /var/lib/mysql/data

- 호스트 기계의 볼륨을 지정안했음

- docker가 호스트 기계의 정해진 경로에 폴더를 생성하는데 random hash하여 경로 이름을 달리함.

- yml 설치 이후 이 디렉토리에 호스트 볼륨 자동으로 만들어줌

- 이름 필요없을때 사용

 

3. named volume

docker run -v name:/var/lib/mysql/data

- docker가 생성하게 하되 생성된 볼륨에 이름을 붙여서 여러 컨테이너가 이름을 통해 공유할수있도록함.

 

 

컨테이너 간 통신

- 독립된 OS 가진 다른 컨테이너끼리는 같은 기기더라도 네트워크 통해 통신해야하는데 이때 내부 private network에서 rest-api (json)형식으로 통신한다.

 

+ docker swarm 또는 전통적인 분산환경에서의 동일한 종류의 서비스 제공은 서로 다른 호스트에 같은 서비스를 제공하는것, 외부로부터의 서비스 요구를 여러 호스트에 나누어 할당하는 reverse proxy 이용

 

*curl : 컴과 컴 사이에서 데이터를 주고받는 어플리케이션, 그 사이에서 프로토콜의 지정없이 귀찮은 작업을 다 해줌 확인가능

'CS지식 > 개발 상식' 카테고리의 다른 글

프론트엔드의 상태 관리  (1) 2023.05.17
DOM 과 Virtual DOM, 그리고 React (리액트)  (0) 2023.05.17

자바의 보조 제어문 break

1. switch-case문 빠져나가기 
2. 반복문 빠져나갈때 (while, for, do~while문)

- 주로 무한 루프를 빠져나올 때 break문을 이용함
- 어떤 무한루프에서 조건식을 쓰고 그 조건을 만족하면 빠져나오는게 일반적

 

for 무한루프 돌리는 방법 2가지

1. 초기, 증감, 조건 식 안적기

		for(;;)
		{
			System.out.println("무한출력");
		}

2. 조건 식 안적기

		for (int i = 1;; i++) {
			System.out.println(i + "무한출력");
			if (i == 100)
				break;
		}

break문 주의1

- break 뒤에 다른 내용 있으면 안된다.

while(true)
{
	break;
	System.out.println("출력"); // 오류생김
}

 

break문 주의2

- break문 만나는 순간 그 밑은 아예 안보고 바로 빠져나옴
- break문의 위치를 잘 설정해야함

- 비교해보기(아래 예제2개)

		while(true) {
			
			System.out.println(i+ "무한루프");
			if(i==100) break;
			i++;
			
		}

- 이러면 100번 출력

		while(true) {
			
			System.out.println(i+ "무한루프");
			i++;
			if(i==100) break;
			
		}

- 이러면 99번 출력됨 
* "if"나 "메소드"를 빠져나올땐 break가 아닌 return문을 써야함!!

 

break문 예시

- 1부터 45사이의 난수를 발생 시킬때, 6이 나올때까지 몇번 루프가 돌아가는지 구해보자

package p2022_06_24;

public class Break03 {

	public static void main(String[] args) {

		
		int i = 1;
		while (true) {

			i++;
			int num = (int) (Math.random() * 45) + 1; // 난수발생 : 1~45

			if (num == 6)
				break; // 무한루프를 빠져나옴
		}
		System.out.println("루프횟수 : " + (i - 1)); 
		System.out.println("프로그램 종료");

	}

}

- 루프횟수에서 초기값이 0이 아니라 1이니까 -1 해줌.(한번 루프 돌아도 i값이 2가 되기때문)

 

continue

- 반복문 안"에서만" 사용가능!! (while, do~while, for)
- 다시 반복문으로 돌아가라는 의미
- break문처럼 반복문 가장 위에있으면 오류가 생김
- break문처럼 if문과 함께 쓰임.

		for (int i = 1; i <= 10; i++) {

			if (i == 5)
				continue;
			System.out.println("출력 : " + i);

		}

- i==5일때 출력5는 실행되지 않음
- i==5일때 아래를 실행안하고 i++쪽으로 돌아감, 6이되고 다시 조건식 참이니 출력 : 6이 출력됨

 

메소드 호출

- 여태껏 main 메소드 안에 모든 내용을 다 집어넣었다 이젠 사용자 정의 메소드 만들고 호출해볼것
- 나중에 클래스로 객체 쓸때도 메소드는 계속 쓰므로 중요함.

 

메소드

- 여러가지 코드를 묶어둔 집합체
- 한번 정의된 메소드를 호출 통해서 재사용하기 위해 사용
- 어떤 언어에선 함수 라고 부른다.
- 각 언어마다 메소드 만드는 방법이 꽤 다르다.

 

메소드 호출 방법

- Call by Value
- Call by Reference

 

메소드 의미

접근제어자     공유      자료형     메소드명(매개변수)
public           static         void         check(){

 return   값;
}

 

접근 제어자 종류

-  public
- 생략(default접근제어자)
- private
- protected

 

접근 제어자

- 접근 허용할지 막을지 설정
- 클래스 앞에 도 붙일수 있고, 클래스를 구성하는 3가지 필드(변수), 생성자, 메소드 앞에도 붙일 수 있다
- default : 아무 표시 안하면 default 접근제어자
- public : 모든 접근을 허용한다는 의미로 사용됨, 가장 많이 사용됨

 

static 자리

- 공유를 할경우, 누구나 쉽게 접근할 수 있도록 공유원할때 붙임
- static이 붙은 메소드를 정적메소드라고 불린다.
- 어제 배운 Math 클래스는 정적메소드 밖에 없었다.
+ 아직 클래스-객체 개념 안배웠기떄문에 모두 정적메소드로 해서 공부/실습할것

 

void 자리 = 리턴자료형 자리

- void 대신 기본자료형도 들어갈 수 있고, 참조형인 클래스, 배열, 인터페이스도 여기에 올 수 있다
- void는 값을 돌려주지 않아도 된다는 의미이므로 void 가 왔을땐 마지막의 return이란 구문을 생략 할 수있다
- 자료형이 오면  return 자료형 ; 해서 자료형에 맞는값을 반드시 돌려줘야함
ex) void대신 int란 자료형이 왔을땐 int형 값을 return으로 돌려줘야함.

 

메소드 명 

ex) check()
- 예약어로 설정된 Class If Switch 같은건 메소드 명으로 쓰면안됨
- 메소드 쓸땐 괄호를 반드시 가져야함 . 괄호가 없는 메소드는 거의 없다.
- 괄호만 써도 되고, 메소드가 실행되는 동안 필요한 값이 전달되어야할 땐 변수를 쓴다. 기본자료형, 참조형 다 올 수 있다.

 

메소드 호출/반환

- 기본자료형의 경우 값을 전달한다.
ex) int형이 매개변수로 있다면 int형 값을 전달해서 호출을 해야함
- 클래스가 오면 객체를 전달해야하고, 배열이 오면 배열주소값을 전달해야한다
- void 자리에 클래스, 인터페이스, 배열등의 참조형이 올땐 주소값을 리턴해줘야 한다.

 

main 메소드

-main 메소드는 이름 바꾸지 못함
- public static void check(){}
- 개발자가 호출 할 수 없다 JVM이 해줌

 

사용자 정의 메소드 작성

- 자바는 메소드 안 메소드가 들어가는 중첩메소드 허용안함
- 즉 메인 메소드 안에 메소드가 들어갈 수 없다. (파이썬은 중첩함수 허용)
- 그러므로 메인 메소드 바깥 (위,아래) 에 메소드 작성하기

 

Main 메소드 호출 vs 사용자 정의 메소드 호출

- Main 메소드는 MethodEx01.class란 바이트 코드에서 JVM이 호출해줌. 
- 사용자 정의 메소드는 프로그래머가 직접 호출해줘야함

 

static이 붙은 정적메소드 호출 vs static이 없는 메소드 호출

- static이 붙은 메소드는 그 클래스 . 해서 바로 호출 ex) Math.random()
- static이 없는 메소드는 그 클래스로부터 객체를 생성해서 . 을 해서 메소드를 호출

 

접근 제어자

- 같은 클래스 내에선 접근 제어자가 아무 의미 없다
- protected이든 private이든 public이든 default든 같은 클래스 내에선 다 접근 가능
- 이 클래스,메소드,변수,생성자에 접근을 허용할건지 말건지를 정해둔 것임.
- 아무것도 없어도 default 접근제어자이다

 

return 자료형 적는 자리

- void 가 오든지 자료형이 오든지 둘 중 하난 반드시 와야함
- void면 return구문 생략 가능 또는 return;

 

메소드 호출 방법

- 매개변수가 없는 check() 는 그냥 check(); 라고 호출해주면 됨.

 

메소드 작성 순서
- 자바는 객체지향언어라서 메소드가 적힌 순서가 상관없다
ex) check()가 main() 보다 밑에 있어도 main()에서 check() 호출 가능
- 메소드가 적혀있는 순서가 중요한 언어가 있다.
ex) 파이썬, C

static 메소드 호출
- Math는 정적메소드만 있다. 그래서 Math.random()처럼 사용함
- 원래 static 메소드 호출 시, 클래스명.메소드명() 이 원칙이지만 같은 클래스내에 있는 정적메소드를 호출시엔 클래스명을 생략 가능
ex) MethodEx01.check(); 이지만 같은 클래스 내에선 check(); 만 작성해도 됨.

+ Math메소드의 호출법
- static이 붙은 필드 = 정적 필드 만 있다
- static이 붙은 메소드 = 정적 메소드 만 있다.
- random() 메소드는 static double random() 이다.
- 그러므로 객체 생성하지 않고 Math.random()으로 호출함.

* 클래스 : 필드, 생성자, 메소드가 있다.(api문서)

 

static이 없다면?

MethodEx01 mx = new MethodEx01();
mx.check()

- 이런식으로 객체를 생성하여 호출해야 한다.

 

매개변수가 없을때 vs 매개변수가 없을때 호출

- 매개변수가 없을때 : check(); 으로 호출
- 매개변수가 있을때 : check(ck) ; 로 호출, ck는 int값이어야

	static void check(int a) { //매개변수(parameter) : int a
		System.out.println("전달된 값 : " + a);
	}

- 즉 정수값을 전달해야 함수가 실행될때 매개변수는 스택에 자리가 잡혔다가 메소드 끝나면 지워짐
- check(30); 시 매소드 실행될때 a에게 30을 주게 되고 이 매개변수(파라미터)를 출력
* 매개변수는 지역변수

 

Call by Value

- 이렇게 매개변수가 기본자료형일떈 값을 전달해서 호출하는 것.
- 값 전달에 의한 메소드 호출 방식

Call by Reference
- 매개변수가 참조형 일땐 주소값을 가짐
- 주소값을 전달해서 호출

메소드 "오버로딩"
- 매소드 정의 할때 이름이 똑같음 check(), check(int a)
- 한개 클래스내 동일 이름 클래스 정의할 수 있는 것.
- 하지만 매개변수를 다르게 함으로서 구분이 가능하도록 해야한다. 

지역변수 정리
- 메소드 안에서 사용되는 지역변수 = 매개변수 = 스택에 저장됨 = 메소드 종료시 삭제됨
- 블럭문 안에서 사용되었던 i 같은것도 지역변수

 

메소드 예시

	static void check(int a, double d) {
		double result = a + d;
		System.out.println("전달된 값의 합 : " + result);
	}

- check(10, 10.5); 로 호출 (Call by Value)값을 전달해서 호출함
- 순서에 맞게 자료형에 맞게 전달해야함 int, double 순으로

 

매서드의 매개변수에 참조형이 오는 경우

ex) String 클래스

	static void check(String s) { 

		System.out.println("전달된 값 : " + s);
	}

- main 에서 

check("자바");
check(new String("파이썬"));

- 호출 시 둘 다 잘 출력됨.

- 바로 check("자바") 해서 객체 만들 수도 있고 new 연산자를 써서 String객체를 만들 수도 있다.

 

+ String클래스만 두가지 방법 모두 가능.
1. String s = "자바"
2. String s = new String("파이썬");

static void check(String s) { //String s = "자바"

		System.out.println("전달된 값 : " + s); 
		//String s = new String("파이썬");
}

- 바로 check("자바") 해서 객체 만들 수도 있고 new 연산자를 써서 String객체를 만들 수도 있다.

 

Call by Reference (위 예시 참고)

- Call by Reference = 주솟값 전달에 의한 매서드 호출 방식
- 우리가 볼땐 '자바' '파이썬'을 직접 전달하는거같지만 사실 주솟값을 전달하는것
- 그 데이터가 저장된 영역의 주솟값을 메소드로 전달하는것임
- "자바' "파이썬"데이터는 모두 힙이란 영역에 저장
- 매개변수 s는 스택영역에서 "자바", "파이썬" 의 주솟값을 가지게 됨

 

그림

 

Math 클래스의 리턴자료형

- Math클래스 random() 메소드의 리턴값은 double
- 그 우리는 그것을 int 강제형변환 해서 사용했었다.

 

메소드 예시1

// return문 : 메소드를 호출한곳에 값을 돌려주는 역할을 한다.
static int check01()
{
	System.out.println("출럭");
	return 50; 
	System.out.println("출럭"); //오류발생

}

- 리턴이 void가 아니므로 필수, int형 값만을 돌려줘야한다. 50.5를 리턴할순X

* 리턴구문은 메소드 가장 마지막 줄에 써야한다. 아니면 오류 발생
* 저걸 check()라는 이름을 쓸 수 없다 .  맨 위에서 check()를 썼기때문에 오류 발생
check01로 만들었다.
- Main에서 check01() 로 호출하면 출력은 되지만 리턴으로 돌려받은 값을 받지 않았으므로 그 값을 쓸수 없게됨

 

int result = check01();

- 리턴형이 int이기 떄문에 그 값을 받는 변수도 int여야함

 

값 돌려받는 2가지 방법

1. System.out.println("돌려 받은 값1 : " +  result);
2. System.out.println("돌려 받은 값1 : " +  check01());
- check01()에서 리턴값을 돌려받자마자 바로 출력해도 된다. 변수로 안받아서 출력해도됨

 

메소드 예시2

- 더블형이 리턴일땐

static double check02(int a, double d)
{
	double result = a + d;
	return result;
}

- 이 result도 이 메소드 안의 지역변수다 그래서 이 메소드 말고 다른 메소드에선 사용가능
- main 메소드에서

double result2 = check02(50,3.14);
System.out.println("돌려 받은 값3 : " + result2);
System.out.println("돌려 받은 값4 : " + check02(50,3.14));

 

return

- 메소드를 호출 한 곳으로 값을 돌려줌
- static int check01 에서 int자리에 참조형이 올땐 값이 아니라 주솟값을 돌려줌!

 

메소드 주의

- 클래스 배열 인터페이스도 매개변수 자리, 리턴 자료형자리 들어 갈 수 있다.
- 값을 돌려받을 때는 그 메소드의 리턴 자료형과 일치하는 자료형으로 값을 받아야함.
ex) int i = sc.nextInt();
- public static void main 에서처럼 이 순서 바뀌면 안됨 접근제어자 다음 static 다음 리턴자료형 다음 함수명
- 지역변수는 다른 메서드일땐 이름같아도 충돌 발생하지 않는다

System.out.println(max(n1,n2));
System.out.println(min(n1,n2));

- 가능함
- 원래는 MethodEx03.max(n1,n2)지만 같은 클래스라 생략(max는 static 함수이므로)

 

메모리
- 기본 자료형들은 값을 참조형은 주소를 저장
- 기본 자료형이라 하더라도 항상 스택에만 저장되는게 아님
- 기본 자료형 중 지역변수 만 스택이란 영역에 값이 저장됨
- 멤버,정적 변수는 기본자료형이라도 스택에 저장되지 않음

메모리 예시1
- 참조형 중 클래스 중 String 클래스 예시

String name = "신용권"


- 값인 "신용권"은 힙이란 메모리에 저장되고
- 이 저장된 값의 시작 주소값을 스택 영역에서 가지고 있다


메모리 예시2

String hobby = "독서"


- "독서" 는 힙에 저장 , 그거의 시작 주소값은 참조형 변수가 가지고 있는데 그건 스택에 있다
- (name, 2312415) 이런식으로 (주솟값 : 2312415) 스택에 있는거

 

배열

- 동일한 타입의 데이터를 연속된 공간에 저장하는 정적인 자료구조
- 변수를 확장시킨 개념이 배열 (변수는 1개의 데이터만 저장)
- 변수가 여러개 필요할때 간결하게 쓰기 위해 배열을 쓴다.
- 10개과목 점수 입력받으려면 변수가 10개나 필요함 - > 배열을 쓰면 코드가 늘어나지 않음
- 1가지 자료형 데이터만 저장 가능
- 거의 대분의 언어는 배열을 지원함
- 배열 정의 할때도 반드시 자료형을 적어야함.
- 1차원 배열은 [] 1개 2차원은[][] 2개... 

int[][] score = new int[5][3];


- 배열이름 (변수)쓰고 new를 씀 = 명시적으로 힙메모리상에 새로 공간을 만드는것
- 왼쪽이 int면 오른쪽도 int형으로 해야

 

배열 의미

int score[] = new int[3];

- 힙메모리에 int인 4바이트 연속된 공간을 3개를 생성하란 의미

 

그림

 

배열 기타
+ 우리가 여태껏 봤던 main 메소드의 매개변수는 String 형 1차원 배열
- main(String[] args)
- []는 자료형 뒤에 써도 되고 변수명 뒤에 써도 된다
- String[] args == String ar[] 도 가능하다

new
- 연산자 오퍼레이터
- 힙 메모리상에 배열을 위한 새로운 공간을 만들라는 의미
+ 클래스로 객체 생성할때 쓰는 new도 같은 원리로 힙 메모리 상에 새 공간 만들라는 의미임
- String 클래스만 new를 써도 되고 안써도 되지만 다른 클래스 99%는 new를 꼭 써야만 객체 생성 가능

배열의 초기화
- 배열을 정의 시 힙메모리 상의 연속된 공간은 자동 초기화 된다.
- 자료형에 따라 초기화 되는 값이 다르다
- int 형 배열을 정의하면 힙메모리상의 공간(배열)이 자동으로 0으로 초기화 된다.
- boolean 배열 은 false 로 double 배열 은 0.0 으로 int는 0 으로 초기화 됨
- 또는 원하는 할당값이 있을 때는

score[0] = 80;
score[1] = 90;
score[2] = 100;

 

* 지역변수는 초기화되지 않지만 참조형은 자료형에 따라  초기화 되는 값들이 있다

 

배열을 만드는 2가지 방법
1.

int score[] = new int[3]


2-1.

int[] score = {80,90,100};


2-2. int[] score = new int[]{80,90,100}

int[] score = new int[]{80,90,100}; // 도 가능함

 

 

1. int score[] = new int[3] 방법

- 배열에 어떤 값이 들어가야할지 아직 안정해지거나 모를때
- new가 반드시 들어가야함

2. int[] score = {80,90,100}; 방법
- 값이 정해져있을때 쓰는 방식
- 배열 선언과 동시에 초기화를 할 때 주로 사용

 

int[] s1 = {80,90,100};
int[] s2 = new int[]{80,90,100};
//두가지 형식으로 선언 가능하다

 

- 다른 자료형도 마찬가지

double[] d = {3.14,10.5,42.195}

 

- 같은 자료형만 가능

int[] score = {80,90,100,3.14} // 오류 발생

 

변수->배열->리스트

- 변수를 확장시킨게 배열이고 배열을 확장시킨게 리스트(List)
- 배열은 한가지 자료형만 가능하고 리스트 라는 자료구조를 쓰면 자료형 혼용가능, 동적으로 자료크기 늘릴수도있다

 

char형 배열 / String형 배열

 

char[] c = {'j','a','v','a','안'};
String[] str = {"java", "jsp","oracle"}
String[] str = new String[]{"java", "jsp","oracle"}

- 모두 가능

 

메모리 정리
- 모든 참조형으로 변수 만들땐 거의 다 new를 필수적으로 쓴다 (클래스,배열,인터페이스)
- 힙메모리상에 저장된 값은 초기화 된다!
- 스택 메모리상에 저장된 값은 초기화 되지 않음

 

선언 이후 값 할당

 

score[0] = 80; //0번 방에 80점을 할당
score[1] = 90; //1번 방에 90점을 할당
score[2] = 100; //2번 방에 90점을 할당

 

배열 자동초기화

- int형 배열은 자동초기화 0으로 됨
- double형 배열은 자동 초기화 0.0으로 됨
- char형 배열은 자동으로 초기값 설정이 안됨!
- char 배열은 자동으로 초기화가 되지 않는다.
- boolean 형 배열은 자동초기화 false 로 됨!

 

참조형 배열 예제 : String 배열

- String형 배열은 자동 초기화 null 로 됨 (초기값이 없다는 의미)
* null : 값이 없다 는 의미

배열과 반복문
- 배열을 의미있게 쓰려면 반복문을 써야(ex) 합, 곱 등 구하기

배열의 크기 구하기 : length 속성
- length란 속성 이용해서 배열의 크기 구할 수 있다.
- 메소드가 아니라서 괄호가 없다! 속성이다. 
- 그 배열이름.length 하면 된다

 

배열의 인덱스 주의
+ 배열은 인덱스 번호가 0번 부터 시작함 
- 출력시 for문 쓸때 주로 i=0 해야하는점 주의, 
- <=말고 < 써야하는거도 함께 주의 

 

배열에서의 형변환
- double형 배열 예시

	double[] dd = { 3.14, 10.5, 42.195, 50 }; 

	for (int i = 0; i < dd.length; i++) {
	 	System.out.println(dd[i] + "\t");
	}

- int형 값인 50을 넣으면? 내부적으로  double 로 바뀜(자동형변환)
- 이 반대의 경우는 안됨 double 이 int보다 크므로

- 반대로 int 형 배열에 double 형 자료를 넣어선 안됨

 

크기 구하는 방법 3가지의 비교(중요)

1. 배열크기 구할땐  length 속성
2. 문자열의 길이 구할땐 length() "메소드"
3. list같은 자료구조는 size() "메소드"

 

+ 형변환 항상 주의

double avg = (double)sum / 3; // 또는  sum/3.0
System.out.println("평균 : " + avg);

- sum은 int 형 3도 int형이라 (double)을 안쓰면 소수점 전부 짤려서 나옴.

- 살리려면 (double)을 붙여야함 또는 3.0으로 연산

 

+ 평균을 소수점 2째자리까지 출력하려면

System.out.printf("평균 : %.2f",avg); // 평균 : 86.67

- 실수값일땐 뒤에 f를 써줌, %.2 는 둘째자리까지 출력하란 뜻이고 셋째자리에서 반올림된다.

 

출력형태 정리

 %b : boolean 형식으로 출력 
 %d : 정수 형식으로 출력
 %o : 8진수 정수의 형식으로 출력
 %x / %X :16진수 정수의 형식으로 출력
 %f : 소수점 형식으로 출력
 %c : 문자형식으로 출력 
 %s : 문자열 형식으로 출력
 %n : 줄바꿈 기능
 %e / %E : 지수 표현식의 형식으로 출력

 

복습

char 자료형

- 영문자 1글자는 1바이트
- 한글자 1글자는 2바이트

 

- 하지만 char 안에는 모두 한글자만 가능

char c1 = 'k'
char c2 = '안'

 

참조형

- 기본 자료형과 달리 값 저장 방법이 다르다.

- 값은 힙에 주소는 스택에 저장된다.

 

자바의 구조, api 문서

- jre의 패키지는 비슷한 클래스끼리 묶여져 있다.
- 바이트 코드를 가져와서 import해서 사용하는것이다.
- 바이트 코드 = 기계어
- 그것의 설명서가 api문서

 

필드 : 쉽게 말하면 멤버변수

생성자

- 여기서 제공되는 생성자중 하나를 선택해서 써야함.
- 클래스명과 반드시 동일한 이름으로 되어있고, 메소드라 무조건 괄호가 있는 형태

 

if~else if~else 문

- 가장 먼저 만족한 하나만 실행하고 조건문 나간다.

 

if (score >= 90)
grade = 'A';
else if (score >= 80)
grade = 'B';
else if (score >= 70)
grade = 'C';
else if (score >= 60)
grade = 'D';
else
grade = 'F';

- 가장 먼저 해당하는 것의 문장을 실행하고 if문 전체를 나간다

ex) 90점이면 60점이상이므로 아래 else if 도 만족하지만 첫번째에서 걸리므로 'A'만 출력된다.

 

난수발생 공식

- 난수 = (정수화)(Math.random() * (상한값 - 하한값  + 1)) + 하한값;

 

난수발생 공식 설명

0.0 <= Math.random() < 1.0

- 실수형태의 난수 발생시킴.

* 자세한 설명은 아래에서

 

난수발생 예시

 

// 주사위 번호 뽑기 : 1 ~ 6
		int num = (int) (Math.random() * 6) + 1; // 1~6
		System.out.println("num = " + num);

		if (num == 1) {
			System.out.println("1번");
		} else if (num == 2) {
			System.out.println("2번");
		} else if (num == 3) {
			System.out.println("3번");
		} else if (num == 4) {
			System.out.println("4번");
		} else if (num == 5) {
			System.out.println("5번");
		} else {
			System.out.println("6번");
		}

 

난수 발생 2가지 방법

1. Math 라는 클래스 중 random()이란 '메소드'를 사용. Math.random()
2. Random 이라는 클래스를 import 하고 랜덤 객체를 생성해서 난수 발생

 

// 난수 발생
// 0.0 <= Math.random() < 1.0
//  1         ~            6

 

Math 클래스 (by API 문서)

- java.lang의 클래스이므로 import필요없다.

 

java.lang.Object
java.lang.Math

- Object 클래스가 자기 부모이다(상속관계)

 

1. Math 클래스의 필드 = 멤버변수

* 직접 클래스를 우리가 만들떈 필드를 변수 형태로 만들게 됨.
- E는 자연로그 2.7xx , PI는 파이(원주율) 3.14xx

- static 이 붙은 변수(필드) = 정적 필드
- E는 자료형이 static double
- PI도 자료형이 static double

+ 정적 필드
- 정적 필드 들은 객체를 따로 만들지 않고 클래스명.필드 로 접근해서 바로 해당 필드 값 사용가능
ex) Math.E , Math.PI 하면 값이 나옴

 

		System.out.println("E = " + Math.E); //E값
		System.out.println("PI = " + Math.PI); //PI값
		System.out.println(Math.random()); //난수 발생

 

2. Math 클래스의 생성자

- Math 클래스는 객체를 생성할 필요가 없으므로 (static) 생성자가 없다.

ex) Math m = new Math(); 라는 식으로 사용 불가!
- Math 클래스는 아무 생성자도 제공이 안된다
- 즉, 생성자 자체가 없기때문에 new를 쓰면 오류가 남. 

 

3. Math 클래스의 메소드
- 정적 메소드 = static이 붙은 메소드
- Math는 전부 static이 붙은 정적메소드 뿐이다.
- Math의 메소드도 객체를 생성해서 사용하지 않고 클래스명.메소드 해서 바로 사용함
- Math 메소드 중 random() 메소드가 난수 발생 시켜주는 메소드

 

+ random() 메소드 : 
- Type : static double
- double 형이니 실수값으로 처리됨, 양수로 double 형 값을 리턴한다.
- 0.0 보다 크거나 같고, 1.0 보다 작은 범위의 난수를 리턴 
- double이 return 되므로 정수로 값을 받고 싶으면 (int) 강제 형변환

 

Math.random() 난수 공식의 이해

- 공식 : 난수 = (정수화)(Math.random() * (상한값 - 하한값  + 1)) + 하한값;
ex) int num = (int) (Math.random() * 6) + 1; // 1~6

- 0.0 <= Math.random() < 1.0

 

1. 1.0 미만 이니 1.0 이 포함되지 않는다.
2. Math.random() * 6 을 하면 0.0 <= 난수 < 6 까지 난수발생
- 즉 5.99999..까지 난수가 발생되지 6이 발생될 수 없다.
3. 그래서 +1 을 시키는 것
4. 난수값이 0.0 <= 난수 이므로 0.0 이 나온다면 6을 곱해도 0.0 이다.
- 이걸 int로 형변환하면 0이 된다.
5. 그래서 + 하한값 을 해주는 것

 

예시1
- 1~45사이의 난수 발생

int random;
random = (int) (Math.random() * 45 + 1);
System.out.println("난수 = " + random);


예시2
// 5~70사이의 난수 발생
int r;
r = (int) (Math.random() * 66) + 5;

- 일단 5부터가 아니라 0 부터의 기준으로 생각해야한다
- 그러면 5 ~70까지 몇개의 숫자가 있는지 생각 (70-5+1)
- 그다음 5부터 시작한다 생각해서 5를 더해주면 된다.

 

switch~case문

 

  switch(변수){

	case 값1: 실행될 문장;
		break;
	case 값2: 실행될 문장;
		break; 
	default: 위의 case를 만족하지 않을때
	            실행될 문장;
     }

- case를 빠져나가려면 반드시 break;를 써야한다.
- break;를 안쓰면 밑으로 내려간다.
- 아무것도 만족 안하면 아래의 default값을 실행한다.

 

break

- 반복문, 조건문(switch~case 만)에서 빠져나갈 때 break;
- break문은 현재 위치에서 가장 가까운 switch문 또는 반복문을 벗어나는데 사용된다.
- 주로 if문과 함께 사용되어 특정 조건을 만족하면 반복문을 벗어나도록 한다.

 

switch~case문 사용법

- 그냥 case 값: 이라 적고 그걸 만족하면 그 아래있는 case 가 실행됨

		switch (score/10) {
		case 10 : 
		case 9 : 
			grade = 'A';
			break;
		case 8 :
			grade = 'B';
			break;

+ score/10 == 10일때, case 9의 문장 실행됨, 즉 100점일때 break문이 없기때문에 내려감

 

switch~case문 단점

- 100~90 이런 범위값 처리위해서 위의 예제처럼 나누기하는등의 처리가 필요함

 

 

반복문 : 반복적인 걸 할 때 사용

- for , while, do~while

 

for문

for(초기값,조건식,증감식){
	반복 실행할 문장;
}

- 초기값이 있어야함
- 비교연산자로 조건식을 씀
- 증감연산자로 증감식을 씀
- 조건식을 만족하는 경우에만 안의 식들을 수행함
- 만족안하는 경우엔 수행 안함

 

자바의 if 초기값 설정 2가지 방법

1. 선언하면서 초기화
2. 선언은 위에하고 for문 ()안에서 초기화

- 자바는 두가지 방법 다 가능하다
- C등의 언어는 2번 방법만 가능 

if문 작동원리 예시1

for (int i = 1; i <= 10; i++) { 
	System.out.println(i + "사랑해요.");
}


1. i=1로 설정된다.
2. i<=10을 만족한다
3. 1사랑해요 출력
4. i++해서 i==2가 된다
5. i<=10 만족한다
6. 2사랑해요 출력
7. i++해서 i==3이 된다.
8. ...
9. 10이 되면 <=10 만족하기떄문에
10. 10사랑해요 출력하고
11. i++되어 11이 되면
12. <=10만족하지 않기 때문에 
13. 출력안하고 나가게됨!

 

지역변수
- 지역변수는 초기화가 자동이 안됨. ->  초기화는 필수!
- 선언된 {}안에서만 사용가능
- 스택이란 메모리 영역에 공간을 할당받음
- 메소드가 실행될때 할당받고 종료되면 자동으로 지워진다
+ 멤버변수(클래스 변수, 인스턴스 변수)와 배열의 초기화는 자동(기본값으로)


if문 작동원리 예시2

int sum = 0;
for(int i = 1; i<=3; i++)
{
	sum = sum + i;
}

 

변수값 변화

변수     sum  = sum + i
                        0        1
1차           1
                        1       2
2차           3
                        3        3
3차           6
                              4 (조건 불만족) -> 끝. sum은 6이고 i는 4인 상태로 끝

- 지역변수 이므로 int sum = 0 라고 초기화를 꼭해줘야함
- 덧셈일땐 영향이 없는 0으로 초기화
+ int 형 i 도 for 문안의 지역변수 이기 때문에 for문 안에서만 사용 가능하다.
+ for문 밖에서 i를 사용하면 오류가 생김 


지역변수 정의
1. 메소드 안에서 정의되는 변수 (그 안에서만 사용가능 sum은 메인 메소드의 지역변수
2. 매개 변수
3. 블럭문(조건문, 반복문) 안에서 사용되는 변수 i는 for문 안의 지역변수

* 증감식 영역에서 i++, ++i, i=i+1, i+=1 다 가능함
+ \t는 탭키만큼 간격벌림, print("\t") 라고 하면 된다.

 

while문

while(조건문){
	반복 실행할 문장;
}


- 비교연산자로 조건문을 작성하고 조건이 참일때만 반복수행함.
- 초기값이 조건식에 안맞으면 아예 실행 안됨


while문 주의
- for문은 조건식, 증감식, 초기값 자리가 있지만 while은 조건식 외는 내가 설정해야한다
- 일반적으로, 초기값은 while문 밖 위에
- 일반적으로, 증감식은 보통 while문 맨 밑에 
- 증감식 안쓰면 항상 참이라서 무한루프가 돌아감

do~while문

do{
	반복 실행할 문장;
}while(조건식);


- 조건식이 거짓이라도 최소 1번은 실행됨
- 끝에 세미콜론 기억하기!!

do~while문 예시

int i = 1;
do {
	System.out.println(i + "사랑해요");
	i++;
}while(i<=10);


- i 초기값이 11이어도 11사랑해요 가 출력된다.
- i 가 10일때, 10사랑해요를 마지막으로 i는 11이 되어 조건 불만족하여 빠져나가게된다

do~while문 예제

System.out.println("메세지를 입력하세요?");
System.out.println("프로그램을 종료하려면 q를 입력하세요");

Scanner sc = new Scanner(System.in);
String input;

do {
	System.out.println(">");
	input = sc.nextLine();  //문자로 입력을 받는다.
	System.out.println("입력문자 : " + input);
}while(!input.equals("q"));

System.out.println("프로그램 종료");
sc.close();


- String을 입력받기 위해 .nextLine() 메소드로 입력받는다.
- do while은 최소 1번은 실행하므로 실행 하자마자 >가 출력되며 입력할 수 있음
- 그 뒤 q를 입력시 do while을 더이상 못하고 나간다
- scanner 함수를 안전하게 close()로 닫아주는게 좋다.


+ input.equals("q") 메소드
- 값을 비교할때 사용하는 메소드, 값이 일치하면 true인데 앞에 NOT연산자 !를 붙여서 q일땐 false를 만들어서 반복문을 빠져나오게 한다.

+ nextLine() 메소드
- 문자열을 받을때 nextLine() 사용
- 결과는 String 타입 자료형에 저장한다.
- 뛰어쓰기 있어도 된다. 
- 사용자가 입력한 한 줄을 통째로 받음.

지역변수 정리
- 메소드 안에서 사용되는 지역변수 = 매개변수 = 스택에 저장됨 = 메소드 종료시 삭제됨
- 블럭문 안에서 사용되었던 i 같은것도 지역변수

    과제
2022.06.24 / Hw1

       키보드를 이용해서 정수 5개를 입력 받은후 int형
       배열에 저장한다. 이때 배열에 저장된 값중에서
       최대값과 최소값을 구하는 프로그램을 작성하세요.

 

의도

배열과 for문의 활용

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220624/Hw1.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_24;

import java.util.Scanner;

public class Hw1 {

	public static void main(String[] args) {
//		과제.
//	       키보드를 이용해서 정수 5개를 입력 받은후 int형
//	       배열에 저장한다. 이때 배열에 저장된 값중에서
//	       최대값과 최소값을 구하는 프로그램을 작성하세요?

		int[] numbers = new int[5];
		Scanner sc = new Scanner(System.in);
		int max, min;

		// 키보드로 입력받기
		System.out.println("정수 5개를 입력하세요?");
		for (int i = 0; i < numbers.length; i++) {
			numbers[i] = sc.nextInt();
		}

		max = numbers[0];
		min = numbers[0];

		for (int i = 0; i < numbers.length; i++) {

			if (numbers[i] > max)
				max = numbers[i]; // 최대값 구하기
			if (numbers[i] < min)
				min = numbers[i]; // 최소값 구하기
		}
		
		//출력
		System.out.println("max = " + max);
		System.out.println("min = " + min);

	}

}

오늘은 1학년때 만들었던 별트리가 생각나서

별트리 만들었다.

 

한번쯤은 해봤을 별트리 만들기

 

 

깃허브

https://github.com/kindacool/etc/blob/main/StarTree.java

 

GitHub - kindacool/etc

Contribute to kindacool/etc development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_24;

public class StarTree {

	public static void main(String[] args) {

		final int lineNum = 10;
		for (int i = 1; i <= lineNum; i++) {
			
			for (int j = 1; j <= lineNum - i; j++) {
				System.out.print(" ");
			}
			
			for (int k = 1; k <= 2 * i - 1; k++)
				System.out.print("*");
			System.out.println();
		}

	}
}

 

 

출력

과제

2022.06.23 / Hw2

구구단(2~9단)을 열방향(세로방향)으로 출력하는 프로그램을 작성 하세요?

 

 

의도

중첩 for문의 활용

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220623/Hw2.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_23;

public class Hw2 {

	public static void main(String[] args) {

		/*
		 * 구구단(2~9단)을 열방향(세로방향)으로 출력하는 프로그램을 작성 하세요?
		 */

		for (int i = 0; i <= 9; i++) {

			System.out.println();

			for (int dan = 2; dan <= 9; dan++) {
				if (i == 0) {
					System.out.print(" [" + dan + "단]\t\t");

				} else {
					System.out.print(dan + " * " + i + " = " + dan * i + "\t");
				}
			}

		}

	}

}

 

 

 

출력

예시

 

과제

2022.06.23 / Hw1

키보드를 이용해서 입력한 정수의 팩토리얼을 구하는 프로그램을 작성

 

 

의도

for문의 활용

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220623/Hw1.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

 

코드

package p2022_06_23;

import java.util.Scanner;

public class Hw1 {

	public static void main(String[] args) {

//		키보드를 이용해서 입력한 정수의 팩토리얼을
//		  구하는 프로그램을 작성 하세요?
//			ex) 3! = 3 * 2 * 1
//		        5! = 5 * 4 * 3 * 2 * 1
		int a; 
		int result = 1;
		// 입력받기
		System.out.println("정수를 입력하세요?");
		Scanner sc = new Scanner(System.in);
		a = sc.nextInt();

		// 팩토리얼
		for (int i = a; i >= 1; i--) {
			result *= i;
		}

		// 출력
		System.out.println(a + "! = " + result);

	}

}

 

 

출력

+ Recent posts