JAVA lamda

재귀함수

  • 자신을 정의할 때 자신을 리턴하는 함수

  • 다시(재) 귀한(귀) 하는 함수

  • 실습1

  • 인자로 받은 숫자까지 1식 증가하는 모든 수를 더한 수를 리턴하는 함수를 만든다

    예) 함수(3) = 1 + 2 + 3 = 6

    // 단, 반복문 사용 금지.재귀함수로 풀이한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main {

public static void main(String[] args) {

System.out.println(reFunc(100));

}

static public int reFunc(int num) {

if(num>1) {
num = num + reFunc(num-1);
return num;
}else {
return num;
}
}
}

컬렉션(Collection)

자료 : https://st-lab.tistory.com/240

  • 자바에서 미리 만들어놓은 데이터를 수집하고 관리(추가 ,생성 ,삭제 ,초기화 ,크기 ,리스트)해주는 목적의 클래스와 인터페이스

  • 왜 사용하는가?

    • 일관된 API
    • 프로그래밍의 노력 감소
    • 프로그램 속도 및 품질 향상
  • 선언법
    (중요) 컬렉션종류<데이터타입> 이름 = new 컬렉션종류<데이터타입>();
    예) HashSet<String> set = new HashSet<String>();

[객체 리스트]

  • Set

  • 구현클래스 : HashSet, TreeSet, LinkedHashSet

  • 중학교때 배웠던 “집합”. 순서가 없다. 데이터의 중복을 허용하지 않는다.

  • Hash : 임의의 길이를 갖는 데이터를 고정된 길이의 데이터로 변환(매핑)하는 것

  • 해쉬는 유니크함을 보장하기 때문에 순회할 필요가 없다.

  • 동일한 입력값에 대해서는 동일한 결과값(다이제스트)를 갖는다.

  • 이 다이제스트의 값을 index로 활용한다.

    • 함수 : equals(), hashCode(), removeAll(), contains(값), remove(값) add(), size()
    • 정의예 : HashSet<String> alphabetSet = new HashSet<>();
      for(String spell: alphabet){
      alphabetSet.add(spell);
      }
  • HashSet의 add() = 중복된 값은 추가하지 않는다

  • Set.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import java.util.HashSet;
    // 함수 : equals(), hashCode(), removeAll(), contains(값),
    // remove(값) add(), size()

    public class Set {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    String[] alphabet = {"a", "b", "c", "d", "e", "f", "g", "g", "a"};

    HashSet<String> alphabetSet = new HashSet<>();
    HashSet<String> alphabetSet2 = new HashSet<>();

    for(String spell: alphabet) {
    alphabetSet.add(spell);
    alphabetSet2.add(spell);
    }

    alphabetSet.add("z"); // 중복없이 추가
    alphabetSet.remove("z");

    System.out.println(alphabetSet); // 중복없이 출력
    System.out.println(alphabetSet.contains("h"));
    System.out.println(alphabetSet.size());
    System.out.println(alphabetSet.equals(alphabetSet2));

    }

    }

  • List

  • 구현클래스 : ArrayList, LinkedList, Vector

  • 순서가 있는 데이터의 집합으로 데이터의 중복을 허용

    • 함수 : add(값), addAll(리스트), remove(인덱스), clear(), size()
      get(인덱스), indexOf(값), lastIndexOf(값)
  • 반복문과 결합 : 향상된for문 for(자료형 이름 : 리스트)
    while(iterator.hasNext())

  • 예제)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// ArrayList 선언
ArrayList<Integer> al = new ArrayList<Integer>();

// ArrayList에 데이터 입력
for (int i = 1; i <= 5; i++)
al.add(i);

// 결과 출력
System.out.println(al); //[1, 2, 3, 4, 5]

// **인덱스 제거**하기
al.remove(3);

// **값으로 제거**하기
al.remove(al.indexOf(5));
al.remove(Integer.valueOf(3)); // 값 지우기 : 오버로딩 사용
System.out.println(al);

// 결과 출력
System.out.println(al); //[1, 2, 3, 5]

// 하나씩 가져와서 결과 출력
for (int i = 0; i < al.size(); i++)
System.out.print(al.get(i) + " "); //1 2 3 5

  • Queue
  • 구현클래스 : LinkedList, PriorityQueue
  • Map
  • 구현클래스 : Hashtable, HashMap, TreeMap
  • 키(Key), 값(Value)의 쌍으로 이루어진 데이터의 집합
  • 함수 리스트
    add(), remove(), clear(), size()
    • // 직접 위의 함수들 구현해보는 것도 좋은 공부다
    • private int[] nums, private int current;

String 문자열 클래스

  • 이제야 눈에 보이는 스트링. 원시타입이 아니다 (헷갈리지 않게 조심)
  • 자바에서 컬렉션으로 만들어 놓은 자료구조다
  • charAt(), compareTo(), concat(), indexOf(), trim(), toLowerCase(), toUpperCase(), substring, length(), isEmpty(), contains() 문자의 위치반환 없으면-1, matches(정규식) 등의 함수가 있다
  • 스트링은 값이 달라질 때 새로운 객체를 만들어서 할당받는다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

//자바에서 문자열1에서 문자열2를 포함한 갯수 찾기
```java
public int getCountInclude(String str1, String str2){
boolean include = true;
int count = 0;
include = str1.contains(str2); //포함되었는지 참,거짓 판단
while(include) { //포함되었다면
count++;
int where = str1.indexOf(str2); //시작하는 위치 파악
str1 = str1.substring(where+str2.length());
System.out.println("str1 : "+str1);
//방금 찾은 거를 빼고 남은 문자열을 부모로 업데이트
//substring 함수는 인자가 하나면 해당 위치부터 이후로 끝까지 자르는 함수
include = str1.contains(str2);
}
return count;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

### 제네릭(Generic)

- 뜻 : 포괄적인, 일반적인
- Object 를 만들면 사용(저장, 로드)하기전에 형변환 작업을 해줘야 하는 불편함이 존재한다.
- 범용 컬렉션의 장점과 특화된 클래스의 장점을 모두 겸비한 템플릿.
- Java5에서 추가
- 컬렉션, 람다식, 스트림, NIO(New IO)등에서 널리 사용되므로 제네릭을 이해하지 못하면 API 문서를 정확히 이해할 수 없다.

- 목적
- 자료형을 일반화. 정의시가 아니라 인스턴스 생성시 자료형을 결정하도록 한다.
- 우리가 어떤 자료구조를 만들어서 배포하려고 할때 '여러 데이터타입을 지원하고 싶다.' 그러면 String에 대한 클래스, Integer에 대한 클래스 등등을 하나하나 타입별로 만들어줘야하나? 너무 비효율적이다.

- 제네릭은 이런 문제를 해결해준다.
- 그렇게 강조했던 메소드의 정의와 호출 다시한번 보자. 어떤 이름으로 넘어오든지 정의한 영역내에서는 이 이름으로 쓰겠다는 뜻이었던가?
- 마찬가지로 제너릭이라는 것은 어떤 데이터타입으로 넘어오든지 이 정의한 영역내에는 넘어온 그 데이터타입으로 쓰겠다 라고 하는것이다.
- 즉 데이터형을 정의시 명시하지 않고 호출할때 정할 수 있도록 일반화 한것이다.
- 클래스 내부에서 지정하지 않고 외부에서 지정도록 한 것이다.
- 엄밀히 말하자면 컴파일때 해당 타입으로 캐스팅하는 것이다.

- 사용 예시

```java
import java.util.List;
import java.util.ArrayList;

public class 제네릭 {
// 함수의 정의와 호출이 다르다. 파라미터와 아큐먼트는 다르다


public static void main(String[] args) {

//일반
List list = new ArrayList();
list.add("hello");
String str = (String)list.get(0);
System.out.println(str);

//제네릭사용한 코드 < 데이터 타입>
List<String> list2 = new ArrayList<String>();
list2.add("hello");
String str2 = list2.get(0);
System.out.println(str2);

}


}
1
2
3
4
5
6
7
public class Box<T>{
// 클래스 뒤에 <T> 타입 파라미터를 명시했기 때문에 변수의 타입으로 사용 가능합니다.
private T t;
public T get() { return t; }
public void set(T t){ this.t = t; }
}

  • 특징

  • 보편적(암묵적)으로 매개변수의 타입으로는 아래의 이름을 쓴다.
    : Element
    : Key
    : Number
    : Type
    : Value

  • 특정범위 내로 좁혀서 제한하고 싶다면 extends, super, ? 를 활용한다.

  • 예를 들어서, 이면 T타입의 조상만 가능하고 K로 쓰겠다는 말이다.

  • 문법

  • 정의 : 클래스 또는 인터페이스 이름 뒤에 <타입파라미터>

  • 생략하면 컴파일러가 제네릭 관련 문장에서 자료형의 이름을 추론한다. 이걸 다이아몬드 표시라고 한다.

  • 타입 파라미터로 명시할수 있는 것은 참조타입만 가능하다.

  • 여러 개의 타입변수는 쉼표로 구분하여 명시한다.

  • 사용 : 본문에서 그 이름을 데이터타입처럼 사용하면 된다.

  • 장점

  1. 런타임에 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지함
  2. 반환값에 대한 타입 변환(캐스팅) 및 타입검사에 들어가는 노력 줄어듬
  3. 코드의 재사용성이 높아

람다식(Lamda Expression)

  • 자바8에 함수적 프로그래밍 기법으로 도입됨. 람다가 포함되면서 자바가 완전해졌다고 말하는 이가 있을 정도
  • 익명함수를 생성하기 위한 식
  • y = f(x) 형태를 (타입 매개변수) -> { 실행문 } 으로 정의
    좋든 싫든 자바의 람다식은 선택이 아닌 필수가 되었다
  • 장점 : 1. 코드가 매우 간결해진다
    2. 인스턴스 생성안하고 기능하나만 필요할 때
    3. 컬렉션요소를 매핑해서 쉽게 집계할 수 있다
  • 단점 : 1. 가독성이 안좋아진다

2.함수이름이 없기 때문에 stacktrace보고 디버깅하기 어렵다
3. 이 함수가 있음을 인식하기가 어렵다

  • 결론 : 저런 단점들 때문에 고급개발자는 람다식 쓰지 말라 하는 사람 많다
  • 코드가 3줄안에 끝나고 단 한번만 쓰임을 보장할 수 있고 행동이 명확할 때만 제한적으로 사용
  • 문법 : 인풋데이터 -> 함수본문
    • 예 :1. 줄임이 없는 예
      (String s) -> { System.out.println(s); }

      1. 매개변수가 하나일 때 괄호생략. 본문이 하나일 때 중괄호와 세미콜론 생략
        s -> System.out.println(s)
        (a,b) -> a+b

      2. 제네릭으로 사용한 예
        Calculate<Integer> ci = (a,b) -> a+b;
        System.out.println(ci.cal(4,3));

JAVA thread

상수와 enum

  • final 키워드

  • final에 초기값을 줄 수 있는 경우는 2가지 뿐이다

  • 필드선언 시, 생성자

  • 초기화되지 않은 final 필드가 남아있으면 컴파일 에러

  • 진짜 상수는 static final로 선언. 객체마다 저장할 필요가 없으며 다른값으로 바꿀 수도 없기 때문

  • 명명규칙 : 대문자에 언더바 조합

  • enum은 열거형(Enumeration). 상수의 그룹을 나타낸다.

  • 주목적 : 우리만의 데이터 타입을 가지기 위해서

  • 모든 enum들은 내부적으로 java.lang.Enum 클래스에 의해 상속된다.

  • 만드는 문법 : enum 열거체이름 { 상수1이름, 상수2이름, ... }

    • 예) enum Rainbow { RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET }
  • 사용문법 : 열거체이름.상수이름

    • Rainbow.RED
  • 메소드

  • values() 모든 상수 배열로 반환

    • 예) Rainbow[] arr = Rainbow.**values**();
  • ordinal() 상수 인덱스 반환.

    • 예) int idx = Rainbow.YELLOW.**ordinal**();
  • valueOf() 상수 문자 값 반환

    • 예) Rainbow rb = Rainbow.**valueOf**("GREEN");

실습-enum

  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Main {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    String 요일 = "TUESDAY";
    Test t1 = new Test(Day.valueOf(요일));
    t1.요일평가();
    }
    }
  • Test.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class Test {

    Day day;

    public Test(Day day) {
    this.day = day;
    }

    public void 요일평가() {
    switch(day) {
    case MONDAY:
    System.out.println("월요일은 좋지 않음");
    break;
    case FRIDAY:
    System.out.println("금요일은 좋음");
    break;
    case SATURDAY:
    case SUNDAY:
    System.out.println("주말은 최고지");
    break;
    default:
    System.out.println("평법합니다.");
    break;
    }
    }
    }
  • Day.java

    1
    2
    3
    4
    5
    6
    	// 문법 : enum 이름{값 값 값}
    public enum Day {

    SUNDAY, MONDAY, TUESDAY, WHEDNESDAY, THURSDAY, FRIDAY, SATURDAY

    }

사전지식

  • 프로그램 : 어떤 작업을 위해 실행할 수 있는 파일
  • 프로세스 : 실행되고 있는 프로그램. 실행되기 위해서는 메모리에 올라와야 한다. 프로세스는 운영체제로부터 자원을 할당받는다. 1개의 프로세스는 최소 1개의 스레드를 가지고있다.
    • 예) 크롬을 켜서 유튜브를 보고있는동시에 마우스를 움직이는 동시에 파일은 다운 받아지고 있다.
    • 예) 햄버거를 시키면 그릴에서 고기를 굽고, 음료수는 기계에서, 감자튀김은 튀김기에서.

Thread

  • 쓰레드 : 하나의 프로세스내에서 돌아가는 병행적인 메소드

  • 쓰레드는 프로세스내에서 Stack영역만 따로 할당받고 Code, Data, Heap영역은 공유한다. 즉, 프로세스내의 여러자원들을 공유하면서 실행된다.

  • 모든 자바어플리케이션은 Main Thread가 main()메소드를 실행하면서 시작한다.

    • 멀티 쓰레드의 장점 : 시스템자원의 효율성 증대, 처리량 증가, 응답시간 단축, 통신의 부담 감소
    • 멀티 쓰레드의 단점 : 주의깊은 설계, 까다로운 디버깅, 동기화문제, 하나의 쓰레드가 잘못되어도 프로그램이 멈춤
  • 멀티 프로세스 대신 멀티쓰레드를 사용하는 이유

  • 위에서 말한 쓰레드의 장점.

  • 생성방법 2가지

    1. Thread상속 (java.lang.Thread)
    2. Runnable 인터페이스를 구현
  • 대표적인 메소드

  • sleep, start, join, run 이 있다.

  • 호출시 실행하는 메소드는 start해주지만 쓰레드가 실제 돌아갈때는 오버라이드하는 run이 돌아간다.

  • run을 통해 실행시키면 stack으로 쌓여서 병행처리가 안된다. 해당메소드가 종료되어야 다른 스레드가 실행된다.

  • start를 통해 실행해야 정상적인 병행처리가 된다.

  • 쓰레드를 start하면 바로 실행하는것이 아니라 실행대기상태에 있따가 OS의 스케쥴러가 작성한 스케줄에 의해 순서대로 자기 차례에 실행되는 구조다.

  • 쓰레드의 상태 6가지. getState()를 하면 알 수 있다.

    • NEW
    • RUNNABLE
    • BLOCKED
    • WAITING
    • TIMED_WAITING
    • TERMINATED
  • 쓰레드의 종료

  • 쓰레드는 자신의 run메소드가 모두 실행되면 자동적으로 종료된다.

  • 그런데 run메소드의 끝까지 가기전에 ‘즉시 종료’ 해야한다면 boolean으로 된 플래그를 사용하거나 interrupt()메소드를 이용하는 방법이 있다

  • interrupt() 메소드는 InterruptedException 예외를 발생시키는데, 주의해야할점은 interrupt메소드를 이용하기위해서는 종료시키고 싶은 메소드가 일시정지상태일때 정지된다는것이다.

  • 돌아가고있는 중에서는 정지가 안된다.

실습 - Thread

  • Runnable 인터페이스 사용

  • checkThread.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class checkThread implements Runnable {
    String name;

    public checkThread(String name) {
    this.name = name;
    }

    @Override
    public void run() {
    for(int i=0; i<5; i++) {
    try {
    System.out.println(name);
    Thread.sleep(1000); // 1000 밀리세컨드 == 1초
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    System.out.println(name + "쓰레드 종료");
    }

    }
  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Main {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    Runnable d1 = new checkThread("피카츄"); // 다형성
    Runnable d2 = new checkThread("꼬부기");
    Runnable d3 = new checkThread("파이리");
    Runnable d4 = new checkThread("롱스톤");

    Thread thread1 = new Thread(d1);
    Thread thread2 = new Thread(d2);
    Thread thread3 = new Thread(d3);
    Thread thread4 = new Thread(d4);

    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();

    }
    }
  • 코드 실행시 4개의 쓰레드 순서가 바뀌기도 한다

Untitled

실습 - Thread 타이머

  • 시간을 이용한 프로그래밍

  • < 5판 3선승제 - 컴퓨터와 가위바위보 게임>

  • 이겼다 / 졌다 판단해서 출력

  • 위의 개발에다가 방금 배운 쓰레드로 타이머 만들기 원래는 사용자의 입력을 받을때까지 아무작업 안하고 기다렸는데 멀티쓰레드로 타이머가 돌아가면서 3초 안에 입력 안하면 지게 만들기

  • Thread 클래스 상속하여 사용

  • 정답지

  • GameControl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    import java.util.Scanner;

    public class GameControl {

    public static boolean inputCheck = false; //유저가 입력 했는지

    static int life = 999; //남은목숨. 컴퓨터가 이기면 1감소
    static int totalGameCount = 1; //총 게임진행횟수
    static int win=0; //유저의 승리횟수
    static int draw=0; //비김
    static int lose=0; //유저의 패배횟수

    public static void main(String[] args) {
    GameTimer timer = null;
    GameControl gc = new GameControl();
    String computersChoice = null; //컴퓨터의 선택
    String usersChoice = null; // 유저의 선택

    // 난수를 이용하여 컴퓨터의 가위 바위 보를 정한다.
    String[] data = {"가위", "바위", "보"};

    while(win<3 && lose<3) { //누구 하나라도 해당횟수의 승리를 하게되면 중단
    timer = new GameTimer(totalGameCount); //게임진행횟수를 인자로줌. 매번 새로운 타이머 생성
    timer.start();
    usersChoice = gc.choiceRSP(); //유저입력 true로 바꾸는 작업도 안에서 한다.
    computersChoice = data[(int) (Math.random()*3)]; //0.000001~2.9999999니까 0,1,2
    System.out.println("\n"+gc.judge(usersChoice,computersChoice));
    gc.showScore();
    totalGameCount++;
    }
    gc.printGameOver();

    }

    //유저에게 가위바위보중 하나를 입력받도록 한다.
    public String choiceRSP() {
    System.out.println("\n****가위, 바위, 보 중 무엇을 내겠습니까?****");
    Scanner sc = new Scanner(System.in);
    String result = sc.nextLine();
    if(!result.equals("가위") && !result.equals("바위") && !result.equals("보")) {
    System.out.println("가위바위보 중에 하나를 입력해주세요.");
    }else {
    inputCheck = true; // 정상적인 가위바위보를 냈을때 입력이 완료로 변경
    }
    return result;
    }

    //결과 판단하기
    public String judge(String usersChoice, String computersChoice) {
    System.out.printf("당신은 %s를 내고 컴퓨터는 %s를 냈습니다.", usersChoice, computersChoice);
    inputCheck = false; //이것이 핵심이였음!!!!!!!!!!!!
    if( usersChoice.equals(computersChoice) ){
    draw++;
    return "비김";
    }else if( (usersChoice.equals("가위") && computersChoice.equals("보"))
    || (usersChoice.equals("바위") && computersChoice.equals("가위"))
    || (usersChoice.equals("보") && computersChoice.equals("바위")) ){
    win++;
    return "승리";
    }else{
    life--;
    lose++;
    return "패배";
    }
    }

    public void showScore() {
    System.out.printf("총%s판(%d승 %d무 %d패)\n", totalGameCount, win, draw, lose);
    }

    public void printGameOver() {
    System.out.println("게임이 끝났습니다.");
    if(win>lose) {
    System.out.println("당신이 이겼습니다.");
    }else {
    System.out.println("컴퓨터가 이겼습니다.");
    }
    }
    }
  • GameTimer.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    public class GameTimer extends Thread{
    int gameCount=0;
    public GameTimer(int now) { //몇번째 게임에 만들어진 타이머인가
    super();
    this.gameCount = now;
    }

    @Override
    public void run() {
    for(int i=5; i>=1; i--){
    /* 여러번 경기를 할때 어려움이 발생하는 지점
    * inputCheck를 true로 하면 다음 타이머 작동안하고,
    * false로 하면 이전것이 살아있어서 남아있는 초를 출력하게 된다.
    * 타이머는 5초를 셀 뿐이다. 타이머의 제어는 타이머의 외부에서 일어나도록 하자. 객체지향적으로
    */

    if(GameControl.inputCheck==true || gameCount!=GameControl.totalGameCount){
    //유저가 입력했거나 타이머가 자동한게임회차와 본게임의 회차가 다르면
    return; //run함수를 나가버리면 쓰레드는 자신이 가지고있는 자원을 정상적으로 반납하며 종료된다.
    }
    try {
    System.out.println(i); //타임 출력
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    //System.exit(0); //타이머가 끝났다고 시스템이 끝나면안되지.
    System.out.println(this.getName()+" 시간초과");
    }
    }
  • 나의 풀이

  • 단, GameTimer는 그대로 사용

  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    import java.util.Random;
    import java.util.Scanner;
    import java.util.Timer;
    import java.util.TimerTask;

    public class Main {
    public static boolean inputCheck = false;
    static int totalGameCount = 1;
    static int win=0;
    static int lose=0;
    static int draw=0;
    static int select=10;
    static int count=0;
    static int rand=0;

    public static void main(String[] args) {
    // TODO Auto-generated method stub
    GameTimer timer = null;
    Main gc = new Main();
    System.out.println("게임을 시작합니다.");
    Random random = new Random();

    while(win<3 && lose<3) {

    timer = new GameTimer(totalGameCount); //게임진행횟수를 인자로줌. 매번 새로운 타이머 생성
    timer.start();
    select = gc.choiceRSP(); //유저입력 true로 바꾸는 작업도 안에서 한다.
    rand =random.nextInt(3)+1;
    gc.judge(select, rand);

    totalGameCount++;
    }

    matchResult();
    }

    public int choiceRSP() {
    System.out.printf("1. 가위 \n2. 바위\n3. 보\n");
    System.out.printf("선택지 중에서 하나를 선택해주세요 : ");
    Scanner scanner = new Scanner(System.in);
    select = scanner.nextInt();
    return select;
    }

    public void judge(int select, int a) {

    inputCheck = false; //이것이 핵심이였음!!!!!!!!!!!!
    String pc="";
    String me="";
    String[] arr = {"scissor", "rock", "paper"};
    me = arr[select-1];
    pc = arr[a-1];
    System.out.println("==============");
    System.out.println("나 : " + me);
    System.out.println("컴퓨터 : " + pc);

    switch(select-1) {
    case 0:
    if(pc==arr[1]) {
    System.out.println("결과 : 패배");
    lose++;
    }else if(pc==arr[2]) {
    System.out.printf("결과 : 승리!!! > %d승\n", ++win);
    }else {
    System.out.println("결과 : 무승부");
    }
    break;
    case 1:
    if(pc==arr[0]) {
    System.out.printf("결과 : 승리!!! > %d승\n", ++win);
    }else if(pc==arr[2]) {
    System.out.println("결과 : 패배");
    lose++;
    }else {
    System.out.println("결과 : 무승부");
    }
    break;
    case 2:
    if(pc==arr[0]) {
    System.out.println("결과 : 패배");
    lose++;
    }else if(pc==arr[1]) {
    System.out.printf("결과 : 승리!!! > %d승\n", ++win);
    }else {
    System.out.println("결과 : 무승부");
    }
    break;
    default:
    break;
    }
    System.out.println("==============");
    }

    static public void matchResult() {
    System.out.println("==============");
    System.out.println("==============");
    System.out.printf("최종 전적 : %d승 / %d패\n", win, lose);
    }
    }
  • GameTimer.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    public class GameTimer extends Thread{
    int gameCount=0;


    public GameTimer(int now) { //몇번째 게임에 만들어진 타이머인가
    super();
    this.gameCount = now;
    }

    @Override
    public void run() {
    for(int i=5; i>=1; i--){
    /* 여러번 경기를 할때 어려움이 발생하는 지점
    * inputCheck를 true로 하면 다음 타이머 작동안하고,
    * false로 하면 이전것이 살아있어서 남아있는 초를 출력하게 된다.
    * 타이머는 5초를 셀 뿐이다. 타이머의 제어는 타이머의 외부에서 일어나도록 하자. 객체지향적으로
    */

    if(Main.inputCheck==true || gameCount!=Main.totalGameCount){
    //유저가 입력했거나 타이머가 자동한게임회차와 본게임의 회차가 다르면
    return; //run함수를 나가버리면 쓰레드는 자신이 가지고있는 자원을 정상적으로 반납하며 종료된다.
    }
    try {
    System.out.println(i); //타임 출력
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    //System.exit(0); //타이머가 끝났다고 시스템이 끝나면안되지.
    System.out.println(this.getName()+" 시간초과");
    }
    }

JAVA runnable_file

Java 실행파일 생성, 사용

자바 실행파일 생성 & 사용

  • 프로젝트 우클릭 → export → 검색 : runnable

Untitled

  • 다음 그림에서 Runnable Jar file 클릭

Untitled

  • 해당 경로로 가서 Shift + 우클릭 → 현재 위치에서 powerShell 열기

ls명령어로 파일 확인

  • 다음과 같이 Main 을 지정해준다.
  • Browse → 원하는 경로 설정 → 파일 저장

Untitled

  • Browse → 원하는 경로 설정 → 파일 저장
  • 이름 지정하고 파일 저장

Untitled

  • 파일 탐색기에서 해당 경로로 이동
  • 공백에서 Shift + 우클릭 → 여기에 PowerShell 창 열기

Untitled

  • java -jar + ‘찾을 파일 앞글자’ + Tab
  • Enter → 자바 파일 실행
  • 정삭적으로 실행되었다.

Untitled

JAVA exception

학습목표

(클래스, 인스턴스, 오버로드, 함수정의, 함수호출, 데이터타입)

  • 에러 : 개발자가 처리할 수 없는 심각한 영역의 문제. 반드시 프로그램이 종료되는 문제

    • 문법에러 : 컴파일 전에 걸러지는 에러
  • 예외 : 개발자가 프로그램을 죽이지 않고 대처할 수 있는 문제

    • 런탄임에 발생 : 컴파일은 통과했으나 실제로 실행하면 발생하는 에러
    • 모든 예외는 자바의 Exception 이라는 클래스를 상속받는다

    예) Nullpointer, OutOfIndex, Arithmetic, ClassNotFound

예외

  • 에러보다는 덜 치명적인 비정상 상황
  • 모든 예외클래스 는 java.lang.Exception 클래스를 상속받는다
  • 예외처리를 하게되면 프로그램이 종료되지 않고 계속 정상상태를 유지할 수 있다
    < 예외처리 하는 법>
  • 간단 : try, catch, finally 문법
  • 구체적 :
1
2
3
4
5
6
7
try{
예외가 발생할 가능성이 있는 코드
}catch(예외클래스 변수명){
처리할 내용
}finally{
예외가 있든 없든 처리할 내용
}
  • 예제 코드

  • catch 문법 사용한 함수

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public void printOneElement(int index) {
    // 예외처리하고 정상범위 알려주기
    try {
    System.out.println(arr[index]);
    } catch (Exception e){
    e.printStackTrace(); // 어떤 예외가 발생했는지 로그를 출력

    System.out.println("해당위치는 범위를 넘어섰습니다. "+arr.length+"까지 허용범위입니다.");
    } finally {
    System.out.println("finally 실행");
    }

    System.out.println("printOneElement 끝");
    }
  • 사용 결과

  • 에러가 있음에도 이후의 코드가 실행되었다

Untitled

인터페이스

  • 구현체 implements 인터페이스.

  • 부품들의 결합 방식에 대한 “”약속””. 다형성을 구현하는 매우 중요한 역할.

  • 인터페이스 끼리는 다중상속이 가능하다.

    • 함수의 이름, 파라미터 타입, 파라미터 개수, 리턴타입만 약속
    • 추상클래스는 변수도 있었고, 본문이 있는 함수도 있었고, 추상 함수도 있었다.
  • 추가 정보

    • 박철수 implements 의사

      • 철수는 의사의 역할을 해야되기 때문에 의사면 반드시 구현해야될 행동들을 의무적으로 구현하는 용도
    • interface 의사

      • 수술하다
      • 진료하다
      • 처방하다
    • 박철수 extends 사람

      • 철수가 가지고있는 속성과 행동의 대부분이 사람에 의해 구형되어있기 때문에 상속받는 용도
    • 추상클래스는 ‘존재’의 개념으로 상위개념을 뽑는 개념

    • 인터페이스는 ‘기능’의 강제화의 개념

      • 반드시 이 이름으로, 이 파라미터로, 이 리턴타입으로 함수를 재정의 해야한다는 약속

추상클래스 vs 인터페이스

  • 공통점 : 둘 다 추상메소드를 오버라이팅 해야한다
  • 외우는 것이 아니지만 진짜 이해가 안돼서 외우도록 가이드를 주자면 같은 코드를 반복해야돼서 부모의 것을 물려받아서 중복을 막는다면 추상클래스
    • 반드시 구현해야 하는 기능의 약속이면 인터페이스
    • be(존재)로 구분되면 추상클래스
    • do(하는일)로 구분되면 인터페이스

패키지

  • 패키지는 논리적 주소
  • 폴더는 물리적 주소
  • 실제로 서로 다른 폴더에 있더라도 패키지가 같으면 프로그램은 같은곳에 있다고 인식한다. 물리적 폴더가 없더라도 논리적으로 같은 곳에 있다고 인식한다.
    • 예) a폴더 밑의 b폴더밑의 c폴더에서 import kr.co.human.클래스1
      x폴더 밑의 y폴더밑의 z폴더에서 import kr.co.human.클래스1
      같은 위치의 클래스를 가져올수 있다.
    • 예2)import kr.co.human.클래스2
      import com.google.클래스2
      클래스 이름이 같지만 오류 없이 실행된다
  • 목적 : 같은 이름의 변수를 쓸 수 있게 하기 위함
    • 같은 이름의 변수를 서로 다른 클래스에서 쓸 수 있듯이
    • 같은 이름의클래스를 서로 다른 패키지에서 쓸 수 있다
    • 프로그램이 커지게 되면 같은 이름의 클래스가 생겨날 가능성이 높다

다형성 Polymorphism

  • 관련개념 : 상속, 오버라이딩, 형변환

  • 하나의 코드가 여러 자료형으로 구현되어 다른 실행결과를 실행하도록 하는 기술

  • 하나의 객체가 여러 가지 타입을 가질 수 있는 것

  • 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있다

  • 부모는 자식을 담을 수 있지만, 자식은 부모를 담을 수 없다.

  • 남자는 사람이다. 여자는 사람이다. 는 맞는 말이지만 사람은 여자이다. 는 틀린말

  • 도형 도형1 = new 원(); 도형 도형2 = new 사각형();

  • 자식에만 있는 멤버나 메서드는 버려진다.

  • 예)

    • 함수(몬스터) 함수(플레이어) 함수(골렘)
    • 오버라이드가 작동되면서 같은 함수지만 다르게 작동한다
    • 함수(캐릭터) 하나의 함수로 몬스터, 플레이어, 콜렘도 받을 수 있게 된다
    • 정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 특징 중 하나
    • 다형성을 잘 활용하면 유연하고, 확장성있고 유지보수가 편리한 프로그램을 만들수 있다

Object클래스

  • 어떤 자료형이든 상관없이 다 관리할 수 있는 자료형식.
  • 모든 클래스의 최종 부모는 Object다. 그러므로 모든 클래스는 Object다.
  • 객체라면 기본적으로 가지고있어야할 속성과 행동을 정의하고 있다
    (모든 객체가 공통적으로 가지고있어야 할 속성과 행동이 정의되어 있다. 사실 Object 클래스에는 필드는 없다. 11개의 메소드만 있다.)
    • toString() // 16진수로된 인스턴스의 주소를 출력
    • equals() // 참조변수가 가르키는 값을 비교하기 때문에 주소비교. 같은 인스턴스인가
    • getClass() // 해당객체의 클래스 타입을 반환

static

  • static을 붙이면 전역변수가 된다.

  • 사용한 코드

  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package 스태틱연습;

    public class Main {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    Counter c1 = new Counter();
    Counter c2 = new Counter();
    Counter c3 = new Counter();


    }
    }
  • Counter.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package 스태틱연습;

    //인스턴스가 하나 만들어 질때마다 조회수를 1 높이는 작업
    public class Counter {
    static int count = 0; // 정적화. 전역화 = 프로그램이 생성될때부터 꺼질때가지 유지
    // 전역화 = 정의된 지역에 상관이 프로그램이 실행될때 생성되어 프로그램이 종료될때까지
    // 인스턴스화 하지 않고 클래스를 컴파일할때 메모리에 올라간다
    // 그때 올라가서 프로그램이 종료될 때까지 유지되니 '공유'라는 성질을 갖게 된다.

    public Counter() {
    count++;
    System.out.println("생성됨. count : "+ count);
    }
    }
  • 결과 : static 사용하지 않을 경우

Untitled

  • 결과 : static 사용한 결과

Untitled

부동소수점

  • 10진법, 2진법

  • 고정 소수점 : 소수점의 위치가 고정. 정부부와 소수부로 나뉨

  • 부동 소수점 : 소수점의 위치가 떠다님. 지수부와 가수부로 나뉨

  • type에 대해 이해하기 위해 필요한 개념

  • 코딩이랑 큰 관련 X

  • 0~9 : 범위를 넘어서면 자릿수가 늘어난다.

  • 인류는 손가락이 10개이기 때문에 10진법을 쓰게 되었다.

  • 컴퓨터는 2진법을 쓴다.

  • 컴퓨터는 2진법을 사용한다.

  • 0과 1. true와 false

  • 0010(2) = 0 + 0 + 1*2^1 + 0 = 2

  • 1101(2) = 12^3 + 12^2 + 0 + 1*2^0 = 8 + 4 + 0 + 1 = 13

실습

  • 반복문, 조건문, 배열을 이용하여 문제 해결

  • 부족한 건 구글링으로 보충하자

  • 배열에서 최댓값 찾기 + 위치 찾기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package 자바총복습;

    public class 배열 {
    // 9개의 서로 다른 자연수가 주어질 때, 이들 중 최댓값을 찾고
    // 그 최댓값이 몇 번째 수인지를 구하는 프로그램을 작성하시오
    // 예를 들어, 서로 다른 9개의 자연수
    // 3, 29, 38, 12, 57, 74, 40, 85, 61

    // 입력 : 9개의 자연수가 들어있는 배열
    // 리턴 : 없음
    // 본문 : 최댓값과 몇번째인지 로그로 출력
    // 함수명 : printMaxValIdx

    // 배열, 조건문, 반복문
    int[] arr = {3,29,38,12,57,74,40,85,61};

    public void printMaxValIdx() {

    int max = 0;
    int count=0;
    for(int i=0; i<9; i++) { // 최댓값 찾기
    if(arr[i]>max) {
    max = arr[i];
    count = i;
    }
    }
    System.out.println("Max = " +max);
    System.out.println("해당 숫자의 위치는 : " + count);
    }
    }
  • 큰 수의 각 자릿수를 배열에 담아 0~9가 몇 번 쓰였는지 출력

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    package 자바총복습;

    public class 숫자의갯수 {

    //세 개의 자연수 A, B, C가 주어질 때
    //AxBxC 를 계산한 결과에 각각의 숫자가 몇 번씩 쓰였는지를 구하는 함수를 작성하시오
    //예를 들어 A=150, B=266, C=427이라면
    //AxBxC=150 x 260 x 427 = 17037300이 되고,
    //계산한 결과 1703730에 0이 3번, 1이 1번, 3이 2번, 7이 2번 쓰였다

    //인풋 : 정수 3개
    //리턴 : void
    //본문 : 쓰여진 숫자 : 쓰여진 갯수 출력
    //
    //1. 3개의 자연수를 받은 함수 껍데기 만들기
    //2. 3개의 수를 곱한 결과값 뽑기
    //3. 0부터 9까지 반복하면서 각각의 수가 몇번 쓰였는지 파악하기
    public void numCount(int a, int b, int c) {

    int mul = a * b * c;
    System.out.printf("%d x %d x %d = %d \n", a, b, c, mul);

    int[] arr= new int[10];
    int[] printNum= new int[10];

    for(int i=0; i< 10; i++) { // 예)1000을 1 0 0 0 형태로 배열에 담기
    arr[i] = mul % 10; // 10으로 나눈 나머지 = 1의 자리
    mul = mul / 10;
    System.out.printf("%d ", arr[i]);
    }
    System.out.println("");

    for(int i=0; i<10; i++) { // 출력할 수를 printNum에 담는다
    for(int j=0; j<10; j++) { // printNum의 n번째 자리를 숫자 n으로 인식
    if(arr[i]==j) // 예)printNum의 1번째 자리가 2 = 1을 2번 사용함
    printNum[j] += 1;
    }
    }
    System.out.println(); // 결과 출력
    for(int i=1; i<10; i++) {
    if(printNum[i]!=0) {
    System.out.printf("%d 이 %d 개 사용되었다. \n", i, printNum[i]);
    }
    }
    }
    }
  • 배열에 담긴 것에서 n개를 골라 더하기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package 자바총복습;

    public class 숫자의합 {
    //인풋 : 숫자가 담갠 배열, 자를 자릿수
    //본문 : 배열에의 첫번째요소부터 자를 자릿수만큼의 수를 모두 합친수를 출력
    // 예) 123456, 3 => 1+2+3 = 6
    //함수명 : printCuttedSum

    public void printCuttedSum(int []arr, int cut) {

    int sum=0;
    for(int i=0; i<cut; i++) {
    sum += arr[i];
    System.out.printf(" %d ", arr[i]);
    if(i!=(cut-1))
    System.out.printf("+");
    }

    System.out.printf("= %d", sum);
    }

    }
  • 배열에서 기준보다 작은 것 큰 것을 나눠서 출력

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package 자바총복습;
    import java.util.Arrays;

    public class 배열나눠서오름차순출력 {
    //divideArrbyNum(int[] 인트형배열, int 기준숫자)
    //인트형 배열 안에서 기준숫자 이상인 엘리먼트 (요소=값하나)와
    //기준 숫자 이하인 엘리먼트 2개로 나눠서
    //각각 모든 요소를 오름차순으로 출력해보세요.
    //예) [1, 2, 3, 5, 7, 80, 150, 2022, 30534]
    //기준이 100이라면
    //[1,2,3,5,7,80] / [150,2022,30534] 로 나뉨
    //생각의 깊이 : 나눠서 정렬을 각각 하는거보다 처음에 정렬을 하면 한번만 하면 됨

    public void divideArrbyNum(int[] arr, int criteria) {

    Arrays.sort(arr); // 정렬

    for(int i=0; i<arr.length; i++) {
    if(arr[i]<criteria) {
    System.out.printf(" %d ",arr[i]);
    }
    }
    for(int i=0; i<arr.length; i++) {
    if(arr[i]>=criteria) {
    System.out.printf(" %d ",arr[i]);

    }
    }

    }
    }

JAVA OOP practice

  • 상속, 클래스 등을 이용해 RPG 만들기

복습

  • 오버라이딩

    = 오버라이트로 기억하자

    = 덮어쓰기. 부모의 자식을 새롭게 함수 정의

  • 오버로딩

    = 파라미터 타입이나 갯수가 다를 때 이름이 같으면서 새롭게 함수 정의

    // 새 이름을 고민하는 시간 단축

    // 이름은 그 함수가 하는 일이 함축되어 있기 때문에 하는 일이 같음을 유추할 수 있다

  • 객체

    = 우리가 프로그램으로 구현할 대상

    = 자바에서는 class로 객체를 설계한다

    = 생성자를 통해 인스턴스를 만든다

    = 인스턴스가 되어야 비로소 메모리에 올라가고 실체화 된다

    = 객체는 변수와 메소드의 묶음이다. 속성과 행동의 묶음이다

  • 생성자

    = 인스턴스를 만들 때 new 키워드와 함께 쓰인다

    = 함수와 비슷하게 생겼지만 이름이 클래스와 같고, 리턴타입이 없다

    = 인스턴스를 만들 때 반드시 필요한 데이터를 강제하는 역할을 한다

    // 준비되지 않은 상태라면 인스턴스를 만들 수 없도록 한다.

    • 추가 정보

      • 생성자를 명시하지 않은 경우 컴파일러가 자동으로 부모의 디폴트 생성자를 호출한다. super();

      • 그렇기 때문에 부모의 사용자정의생성자가 있는데도, 자식에서 부모의 생성자를 호출하지 않는다면 컴파일 에러가 발생한다.

      • 자기의 생성자안에는 최종 조상이 있어야 되는 이런 매커니즘은 최종 조상인 object를 생성할 대까지 계속 된다.

        자식 > 부모 > 조부모 > 조무보의 부모 …… > Object

      • 사용자 정의 생성자가 하나라도 있으면 디폴트 생성자는 호출되지 않는다

      // super()를 를 호출했는데 그 생성자는 없기 때문

  • 추상클래스

    = abstract 키워드가 붙은 메소드(추상메소드)가 하나라도 포함된 클래스를 말한다

    = 클래스 앞에도 abstract 키워드를 붙여줘야 한다

    = 목적 : 상속

    : 미구현된 함수가 있으니 반드시 자식에서 오버라이딩 해야함을 명시적으로 알려준다

    : 미구현된 함수 마고는 자식에서 그대로 상속받아 사용할 수 있다.

  • 상속

    = 자식 클래스 extends 부모 클래스

    = 를 하면 부모의 변수와 메소드를 자식에서 코딩하지 않고도 그대로 사용할 수 있다

    = 부모클래스는 하나밖에 못둔다

    = 동시에 2개 이상의 클래스로부터 상속받을 수 없다.

    • 추가 정보

      = 내가 부모클래스를 만들어 상속을 만들려고 함다면 is a 관계인지 확인해야 한다

      = has a 관계로 상속관계를 구현하는 실수를 하기 쉽다

      = 사각형은 도형’이다’ O

      = 도형은 사각형’이다’ X

      • 부모에 선언된 변수와 같은 이름으로 자식에 선언하면 자식의 것이 사용된다. (오버라이딩 개념)

        ⇒ 나로부터 타고 올라간다.

      • 부모에 변수가 있어도 자식에 있으면 자식 것으로 덮어쓰기 때문

        → 최대한 부모에 있는 변수와 같은 이름으로 자식에 쓰지말고

        → 쓸 경우가 생겼다면 부모에만 넣고 지식에 없애면

      -예를 들어, name이라는 값을 썻으면 먼저 나한테 그 변수가 있나 찾는다

      • 없으면 나의 부모를 찾는다

      • 부모에게 없다면 부모의 부모를 찾는다

      • 이런 방식으로 최종 부모인 Object까지 훑고 올라간다

      • 정리하자면 나부터 타고올라가기 때문에 동시에 잇다면 내것이 우선된다

      • 나한테 없더라도 내 조상 누군가에 있다면 그것을 쓸수 있다.

      → 부모에 있는 나한테 또 정의해놨을 경우

      • 부모에서 변수를 사용하면 부모의 것이 사용되지 자식의 것이 사용되지 않는다

      • 자식에서 변수를 사용하면 자식의 것이 사용되지 부모의 것이 사용되지 않는다.

  • 접근제한자

    = 역할 : 접근을 제한하는 역할.

    = 왜 접근을 제한하는가? 다른 사람 (다른 클래스)가 함부로 나의 값에 접근하거나 수정하는 것을 막기 위해서

    = 노출시키지 않고 싶거나, 노출시키면 안되는 정보들이 있기 때문에

    • private : 자기 클래스에서만 사용
    • default : 해당 패키지 내에서만
    • protected : 해당 패키지 + 상속받은 클래스
    • public : 이 프로젝트내 어디서나

학습목표

  1. rpg 완성

    • Player 클래스와 Monster 클래스에 중복된 코드를 Character를 상속받는 코드로 업그레이드
    • 객체는 call by reference이기에 객체를 출력하면 객체의 값이 아니라 주소가 출력된다
    • 객체를 출력했을 때 자동으로 호출되는 함수가 toString이고 사용자정의하지 않았다면 기본적으로 주소가 출력된다.
    • toString을 통해 값을 출력하도록 만들 수 있다
    • 이클립스에서 우클릭 source - generate toString 들어가서 변수들 체크해주면 값들 찍히게 됨

    f3 : 정의부로 이동

    상속 추가 설명

    구현실습

    캐릭터에 상속바디 완료.zip

    접근제한다

    getter, setter

  2. 이클립스 단축기 복습

  • ctrl + space : 자동완성
  • ctrl + shift + r : 파일명으로 바로 찾기
  • ctrl + d : 한줄 지우기
  • ctrl + alt +키보드아래 : 해당블록 복붙
  • f3 : 정의부로 이동
  • alt + shift + s : Source
  • ctrl + shift + 0 : 자동 import
  • ctrl +shift + f : 자동 들여쓰기
  • ctrl + shift + p : 짝 괄호로 이동
  1. 메소드 복습
  • 파라미터

    • parameter = 매개변수 = 정의할 때 사용한 변수
  • 아큐먼트

    • argument = 전달인자 = 호출할 때 사용한 값
1
2
3
4
5
String a = 'a';
public a(String a){
return a;
}
a(a);

오버로딩, 오버라이딩

  1. 로또 번호 추출

    랜덤

    배열

    Game, Lotto

  • F3
    • 호출한 함수에 F3을 찍으면 정의된 함수 위치로 이동한다

실습 - RPG

  • Game.java 가 main 파일이다

  • Game.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    public class Game {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    Player player1 = new Player("kmk");
    Monster enemy1 = new slime("빨간슬라임", 100);
    enemy1.attack(player1);

    // player1.attack(enemy1);
    // player1.attack(enemy1);
    // player1.attack(enemy1);
    // player1.attack(enemy1);
    // player1.attack(enemy1);
    // player1.attack(enemy1);
    // 죽으면 죽었다고 알려주기
    // 죽은 몹에게 공격못하기

    // 무기를 하나 만들어서 그 무기를 장착하면
    // 해당 무기의 데미지만큼 플레이어의 데미지를 올려주세요
    Weapon weapon1 = new Weapon();
    weapon1.name = "창";
    weapon1.damage = 20;
    Weapon weapon2 = new Weapon();
    weapon2.name = "활";
    weapon2.damage = 35;

    player1.setWeapon(weapon2);
    player1.attack(enemy1);

    Potion healPotion = new Potion("회복포션(소)", 30, "빨간색", "회복");
    System.out.println(healPotion.name);

    Potion manaPotion = new Potion("마나포션(소)", 30, "파란색", "마나회복");
    System.out.println(manaPotion.name);

    Golem gol1 = new Golem("바위골렘", 1000);
    System.out.println(gol1.hp);
    gol1.defenceOn();
    player1.attack(gol1);




    }

    }
  • Monster.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    // 내부에 미구현인 abstract 클래스가 하나라도 있으면 abstract라 표시
    public abstract class Monster {
    String name;
    int hp = 100;
    int mana = 50;
    int damage = 10;
    String kind;

    public Monster(String name, int hp) {
    this.name = name;
    this.hp = hp;
    }

    public void attack(Player player) {
    if(player.hp<=0) {
    System.out.println(player.name+"은(는) 이미 죽은상태라 공격할수 없습니다");
    return;
    }
    int afterhp = player.hp - this.damage;
    System.out.printf("%s이(가) %s를 %d의 데미지로 공격합니다.\n", this.name, player.name, this.damage);

    if(afterhp<0) { //적이 이번공격에 죽은경우
    afterhp = 0;
    System.out.printf("적이 이번공격에 죽었습니다.\n");
    player.hp = afterhp;
    return;
    }
    System.out.printf("%s의 체력이 %d에서 %d가 되었습니다.\n", player.name, player.hp, afterhp);
    player.hp = afterhp;
    }

    public void powerUp() {
    this.damage *=2;
    }

    }
  • Player.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    public class Player {
    //name, hp, mana, damage
    //attack, skill1, skill2
    String name;
    int hp = 100;
    int mana = 100;
    int damage = 20;



    public Player(String name) {
    //this 가 자기자신이고 super는 부모다.
    //super(); //부모의 기본생성자를 호출한거다.
    this.name = name;
    }

    public void attack(Monster enemy) {

    if("골렘".equals(enemy.kind)) {
    if(this.damage <= 40) {
    this.damage = 0;
    }else {
    this.damage -= 10;
    }
    System.out.println("골렘은 10의 데미지를 차감합니다.");
    }


    if(enemy.hp<=0) {
    System.out.println(enemy.name+"은(는) 이미 죽은상태라 공격할수 없습니다");
    return;
    }
    int afterhp = enemy.hp - this.damage;
    System.out.printf("%s이(가) %s를 %d의 데미지로 공격합니다.\n", this.name, enemy.name, this.damage);

    if(afterhp<0) { //적이 이번공격에 죽은경우
    afterhp = 0;
    System.out.printf("적이 이번공격에 죽었습니다.\n");
    enemy.hp = afterhp;
    return;
    }
    System.out.printf("%s의 체력이 %d에서 %d가 되었습니다.\n", enemy.name, enemy.hp, afterhp);
    enemy.hp = afterhp;
    }

    public void setWeapon(Weapon weapon) {
    System.out.printf("%s 장착완료. 데미지 %d증가. \n", weapon.name, weapon.damage);
    this.damage += weapon.damage;
    }
    }
  • Character.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class Character {
    String name;
    int hp;
    int mana;
    int damage;
    String kind;

    public Character() {


    }

    public void attack(Character obj) {
    if(obj.hp<=0) {
    System.out.println(obj.name+"은(는) 이미 죽은상태라 공격할수 없습니다");
    return;
    }
    int afterhp = obj.hp - this.damage;
    System.out.printf("%s이(가) %s를 %d의 데미지로 공격합니다.\n", this.name, obj.name, this.damage);

    if(afterhp<0) { //적이 이번공격에 죽은경우
    afterhp = 0;
    System.out.printf("적이 이번공격에 죽었습니다.\n");
    obj.hp = afterhp;
    return;
    }
    System.out.printf("%s의 체력이 %d에서 %d가 되었습니다.\n", obj.name, obj.hp, afterhp);
    obj.hp = afterhp;
    }

    }
  • slime.java

    1
        

실습 - Lotto

  • Game.java가 main 파일이다

  • Game.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package 로또;

    public class Game {

    public static void main(String[] args) {
    // System.out.println((int)(Math.random()*100));
    Lotto lotto = new Lotto();
    lotto.makeLotto();
    System.out.println(lotto);

    Player p1 = new Player("배성원");
    p1.buyLotto(5);
    }
    }
  • Lotto.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    package 로또;
    import java.util.Arrays;
    import java.util.Random;

    public class Lotto {
    //1~45범위에서 중복없이 6개의 번호가 있다
    int [] numArr = new int [6];

    //1. 1부터 45까지의 랜덤 번호 생성
    //2. 배열에 넣기
    //3. 중복이 있으면 다시 뽑기
    //4. 오름차순으로 정렬

    public int getRandomNum(int startNum, int endNum) {
    Random rd = new Random();
    int numArr;
    numArr = rd.nextInt(endNum)+ startNum; // 0~endNum + startNum
    // nextInt(int a) = 0부터 a미만의 랜덤 정수를 리턴
    // 거기에 startNum를 더하면 starNum부터 a+startNum미만의 랜덤정수를 리턴
    // 0부터 45 미만의 수를 뽑아서 1을 더하니까 1부터 46미만의 수를 얻게되는 것
    // System.out.println(num);
    return numArr;
    }
    public Lotto makeLotto() {
    // 1.리턴이 void에서 Lotto로 변경
    // 2.실체화된 인스턴스를 리턴해야 됨
    // 3.int 6개짜리 변수에 랜덤값을 담아 그 Lotto 인스턴스를 반환
    // 4.this로 바꾸는 게 더 좋다

    Lotto lotto = new Lotto();
    int [] newNumberList = new int[6];
    for(int i=0; i<6; i++) {
    int randomNum = getRandomNum(1, 45);
    // 넣기 전에 중복된 것이 있나 검사

    boolean isdup = findDup(numArr, randomNum);
    if(isdup == true) { // 중복이 있다면
    // System.out.printf("%d%s \n", i+1, "번째 숫자 뽑을 때 중복 발생.");
    randomNum = getRandomNum(1, 45); // 새로 뽑기
    // System.out.println("새로 뽑은 값: " + randomNum);
    i--; // 다시 뽑은 것이 중복일 대를 대비하여 방금뽑은걸 다시 검사
    }else {
    newNumberList[i]=randomNum; // 새로뽑은 숫자 현재 자리에 넣기
    }
    }
    sort(newNumberList);
    lotto.numArr = newNumberList;
    return lotto;
    }

    public boolean findDup(int[] arr, int targetNum) {
    //기존의 배열의 값에서 중복된 것이 있나 검색
    for(int i=0; i<arr.length; i++) {
    if(arr[i] == targetNum) {
    return true;
    }
    }
    // System.out.println("중복안됨");
    return false;
    }

    public void sort(int[] arr) {
    Arrays.sort(arr);
    // 정렬 함수
    }
    @Override
    public String toString() {
    return "Lotto [num=" + Arrays.toString(numArr) + "]";

    }
  • Player.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package 로또;
    import java.util.Arrays;

    public class Player {

    String name;
    Lotto[] lottoList;

    public Player(String name) {
    super();
    this.name = name;
    // TODO Auto-generated constructor stub
    }
    public void buyLotto(int n) {
    lottoList = new Lotto[n]; // 인자로 받은 크기로 지정
    for(int i=0; i<n; i++) {
    Lotto lotto = new Lotto();
    lottoList[i] = lotto.makeLotto();
    System.out.println("로또 구매 : "+lottoList[i]);
    }
    // 로또 n 개를 뽑기
    // 뽑은 로또를 내가 보유하고 있는 로또 리스트에 넣기
    }
    @Override
    public String toString() {
    return "Player [name=" + name + ", lottoList=" + Arrays.toString(lottoList) + "]";
    }
    }

배열 (array)

  • 동일한 자료형’의 ‘순차적’인 자료구조

  • 같은 데이터타입의 연관된 여러개의 데이터를 하나의 변수에 담아서 쉽게 관리할수 있도록 해주는 자료구조중 하나

  • 인덱스는 0부터 시작한다.

  • 장점 : 인덱스를 활용하여 빠른 참조가능

  • 단점 : 크기가 선언시의 크기에서 바꿀수 없다.

  • 생성법 : 자료형[] 배열이름 = {값1, 값2, 값3…};

자료형[] 배열이름 = new 자료형[크기];

  • 사용법 : 배열이름[인덱스];

배열의 모든요소 출력 : 반복문쓰거나 Arrays.toString(배열명)

  • 크기 할당 & 초기화 없이 배열 참조변수만 선언

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}};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

### **주소값 비교(==)와 값 비교(equals)**

- 원시형 8가지 type이 아니라면 (==) 는 주소값을 비교한다
- 이런 경우에 실제 값을 비교하려면 equals를 사용

> ==연산자와 equals()메소드의 가장 큰 차이점은 == 연산자는 비교하고자 하는 두개의 대상의 주소값을 비교하는데 반해 String클래스의 equals 메소드는 비교하고자 하는 두개의 대상의 값 자체를 비교한다는 것입니다. 기본 타입의 int형, char형등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용됩니다. 하지만 String은 일반적인 타입이 아니라 클래스입니다. 클래스는 기본적으로 Call by Reference형태로 생성 시 주소값이 부여됩니다. 그렇기에 String타입을 선언했을때는 같은 값을 부여하더라도 서로간의 주소값이 다릅니다.
>

### 실습 - 배열

- 배열 선언법 정리
- ==와 equal 차이 비교
- 랜덤숫자 맞추기 게임 구현으로 응용

- 배열 연습

```java
package 배열;

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;

public class Main {

public static void main(String[] args) {

// 초기화 = 정의 후에 값 할당까지 한 번에 하는 것
int intArr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int[] intArr3;
intArr3 = new int[]{1,2,3,4,5,6,7,8,9,10}; // Java 형식

// if(intArr == intArr3) {
// System.out.println("같음");
// }

String[] strArr1 = {"일", "이", "삼"};
// 스트링배열을 스트링으로 변환할 수 없습니다.

int twoMension[][] = {{1, 2, 3}, {5, 10, 15}};
// System.out.println(twoMension.length);
// System.out.println(twoMension[1]);


// 향상된 for문. iterator = 반복할수 있는 객체
// iterator의 모든요소에 대해서 반복을 수행
// for(int i : twoMension[1]) {
// System.out.print(i + " ");
// }
// System.out.println("");

int [][][] threeDemension = new int[2][4][6];
// 뒤에서부터 읽는다.
// 2개짜리가 4개 있고 그런 놈이 6개있다. X
// 6개짜리가 4개 있고 그런 놈이 2개있다. O

// System.out.println(threeDemension.length);

String[] 계절 = {"봄", "여름", "가을", "겨울"};
String[] 복사본 = 계절; // 배열의 복사. 그냥 =으로 하면 얕은 복사.
String[] 진짜복사본;
// String[] 진짜복사본2 = new String[];


boolean result = Arrays.asList(계절).contains("핵겨율");
// System.out.println(result);
// if( 계절 == 복사본) {
// System.out.println("복사본 : 같다");
// }else {
// System.out.println("복사본 : 틀리다");
// }

진짜복사본 = 계절.clone();
// if( 계절 == 진짜복사본 ) {
// System.out.println("진짜복사본 : 같다");
// }else {
// System.out.println("진짜복사본 : 틀리다");
// }

// 깊은 복사를 하기 위해서 반복문을 돌리든가, system.arraycopy() 메소드를 이용
// System.arraycopy(계절, 0, 진짜복사본2, 0, 계절.length);
// if(계절 == 진짜복사본2) {
// System.out.println("진짜복사본2 : 같다");
// }else {
// System.out.println("진짜복사본2 : 틀리다");
// }

// 영단어가 저장된 배열. 크기는 5. endDic
// apple, banana, peach
// 한글단어가 저장된 배열. 크기는 5. korDic
// 사과, 바나나, 복숭아
// 한글랜덤단어를 보여주고
// 유저는 영단어를 치고
// 답이 맞는지 틀렸는지 판단
// System.out.println("키보드로 뭔가를 입력해보세요 : ");
// Scanner sc = new Scanner(System.in); // 캐보드로 입력받기 위한 객체 생성
// String input = sc.next();
// System.out.println(input);

}
}
  • 영단어 맞추기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    package 배열;

    import java.util.Arrays;
    import java.util.Random;
    import java.util.Scanner;

    public class Main {

    public static void main(String[] args) {


    // 영단어가 저장된 배열. 크기는 5. en1
    // apple, banana, peach
    // 한글단어가 저장된 배열. 크기는 5. kor1
    // 사과, 바나나, 복숭아
    // 한글랜덤단어를 보여주고
    // 유저는 영단어를 치고
    // 답이 맞는지 틀렸는지 판단
    // System.out.println("키보드로 뭔가를 입력해보세요 : ");
    // Scanner sc = new Scanner(System.in); // 캐보드로 입력받기 위한 객체 생성
    // String input = sc.next();
    // System.out.println(input);

    String en1[];
    en1 = new String[]{"apple", "banana", "peach", "watermelon", "pineapple"};
    String kor1[];
    kor1 = new String[]{"사과", "바나나", "복숭아", "수박", "파인애플"};

    Random rd = new Random();
    int randomInt = rd.nextInt(5);
    // System.out.println(randomInt);

    // System.out.printf("%d. %s을(를) 영어로 입력해주세요 : ", randomInt, kor1[randomInt]);

    Scanner sc = new Scanner(System.in); // 캐보드로 입력받기 위한 객체 생성
    // String input = sc.next();
    // System.out.println(input);

    // if(input == en1[randomInt]) {
    // System.out.println("정답입니다!!!");
    // }else {
    // System.out.println("오답입니다");
    // }
    //
    // if(input.equals(en1[randomInt])) {
    // System.out.println("정답입니다!!!");
    // }else {
    // System.out.println("오답입니다");
    // }


    // 문자열 1 == 문자열 2 값을 비교하는게 아니라 주소값 비교
    // 문자열1.equals(문자열2) 값을 비교. 순서 상관 없음.
    }
    }
  • 랜덤 숫자 맞추기 놀이

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    package 배열;

    import java.util.Arrays;
    import java.util.Random;
    import java.util.Scanner;

    public class Main {

    public static void main(String[] args) {

    // 컴퓨터가 랜덤 1~100 까지의 랜덤 숫자 하나를저장
    // 유저가 5번의 기회동안 그 숫자를 찾는 게임
    // 답이 제출한수 보다 높은지, 낮은지 알려준다
    // 게임이 끝나면 이때까지 유저가 제출했던 답과 컴퓨터의 답을 보여주세요

    int randomInt2 = rd.nextInt(100)+1;

    int[] myAnswer = new int[5];

    int count=1;
    int i=0;
    while(count==1) {

    System.out.printf("1~100 사이의 숫자를 입력해주세요 : ");
    int inputNum = sc.nextInt();
    // System.out.println(inputNum);


    if(randomInt2 == inputNum) {
    System.out.println("정답입니다");
    count --;
    }else {
    System.out.printf("다시 입력해주세요 %d %d \n", randomInt2, inputNum);

    if(randomInt2 > inputNum) {
    System.out.println("더 높은 숫자입니다");
    }else {
    System.out.println("더 낮은 숫자입니다");
    }
    myAnswer[i] = inputNum;
    System.out.printf("==================== \n");
    }
    i++;

    if(i==5) {
    count--;
    }
    }
    System.out.printf("==================== \n");
    System.out.printf("==================== \n");
    System.out.printf("==================== \n");
    System.out.printf("지금까지 입력했던 답입니다 :");
    for(int j=0; j<myAnswer.length; j++) {

    if(myAnswer[j]==0) {
    continue;
    }
    else {
    System.out.printf("% d ", myAnswer[j]);
    }
    }
    System.out.println("");
    System.out.printf("정답을 공개합니다 : %d", randomInt2);

    }
    }

JAVA OOP

객체 지향 - class

클래스

  • class는 객체에 대한 설계도
  • 설계도 대로 인스턴스를 하나 만들면 그제서야 메모리에 올라간다

사용법

  • 객체를 사용해보자.
  • 어떻게?
    1. 서로 다른 클래스에 함수를 만든다
    2. main에서 사용할 클래스의 함수를 new로 선언한다. (생성자 이용 가능)
    3. new로 선언한 클래스의 변수나 함수를 호출하여 사용

생성자 Constructor객체

  • 역할 : 객체를 인스턴스화(생성) 하는 역할

  • 문법 : 함수와 비슷하게 생겼는데 이름이 클래스명이고 리턴 값이 없다

  • 객체를 생성할 때 new 키워드와 함께 사용. 생성할 때 필요한 데이터를 강제하는 역할

  • 클래스에는 반드시 최소하나이상의 생성자가 존재

  • 클래스에 생성자가 명시적으로 없더라도 컴파일러가 디폴트 생성자를 넣어주기 때문에 new키워드와 함께 생성자를 호출 가능하다

  • 디폴트 생성자는 매개변수와 구현부가 없다

실습

  • Human 클래스를 만든다
  • 객체로서 필요한 정보(이름,나이 등)를 설정
  • 객체로서 행동(달리기, 동물 기르기 등)을 설정
  • Human.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Human {
// 이름, 나이, 성별
// 길들이다, 먹이를 주다, 달리다

String name = "김씨";
int age = 20;
String gender = "male";

public void taming(Dog animal) {
System.out.println(this.name + "이(가) " + animal.name+"을(를) 길들이겠습니다.");
}
public void feed() {
System.out.println("동물에게 먹이를 주다");
}
public void run() {
System.out.println("달려나가다");
}
}
  • Dog 클래스를 만든다
  • 객체로서 필요한 정보(이름, 나이 등)를 설정
  • 객체로서 행동(달리기, 점프하기 등)을 설정
  • Dog.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Dog {
// 털색, 키, 몸무게, 품종, 나이, 걷기, 뛰기, 점프하기,
// 구르기, 활퀴기, 자기, 먹기, 울음소리
String name = "멍멍이";
String color = "갈색";
double weight = 15.3;
String kind = "달마시안";
int age = 5;

public void walk() {
System.out.println("걷습니다.");
}
public void run() {
System.out.println("달립니다.");
}
public void jump() {
System.out.println("점프합니다.");
}
}
  • Main에서 의도대로 작성한 클래스들을 이용해본다
  • main.java
1
2
3
4
5
6
7
8
9
10
11
public class Main {

public static void main(String[] args) {

Dog mydog1 = new Dog(); // Dog클래스에서 mydog1 객체 생성
System.out.println(mydog1.name); // mydog1 이름 출력

Human kim = new Human(); // Human클래스에서 kim 객체 생성
kim.taming(mydog1); // kim이 mydog1을 인자로 받아서 함수 싱행
}
}
  • 결과
  • main.java 클래스를 실행한 결과이다.

Untitled

생성자 사용 vs 비사용

  • 생성자 = 객체를 생성할 때 new 키워드와 함께 사용. 생성할때 필요한 데이터를 강제하는 역할.

[생성자 비사용]

  • 특징 : 미리 변수의 내용을 설정해야 한다

  • Human.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Human {
    // 이름, 나이, 성별
    // 길들이다, 먹이를 주다, 달리다
    String name="김씨";
    int age=10;
    String gender="male";

    public void walk() {
    System.out.println("여유롭게 걸어갑니다");
    }
    public void run() {
    System.out.println("신속하게 달려나갑니다");
    }
    }
  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Main {

    public static void main(String[] args) {

    Human kim = new Human(); // Human 클래스에서 kim 객체 생성
    System.out.println(kim.name); // kim 이름 출력
    kim.walk(); // kim의 함수 호출

    // Dog dog1 = new Dog(); // Dog 클래스에서 dog1 객체 생성
    // dog1.jump(); // dog1의 함수 호출

    }
    }

Untitled

[생성자 사용]

  • 특징 : 미리 변수의 내용을 설정하지 않아도 작동한다

  • 단, 생성할때 필요한 데이터 입력를 강제한다

  • 생성자 쉽게 생성 = ctrl + space바 + Enter

  • Human.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class Human {
    // 이름, 나이, 성별
    // 길들이다, 먹이를 주다, 달리다
    String name;
    int age;
    String gender;

    public Human(String name, int age) {
    this.name = name;
    this.age = age;

    }
    public void walk() {
    System.out.println("여유롭게 걸어갑니다");
    }
    public void run() {
    System.out.println("신속하게 달려나갑니다");
    }
    }
  • Main.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Main {

    public static void main(String[] args) {

    Human kim = new Human("아무개", 21); // Human 클래스에서 kim 객체 생성
    System.out.println(kim.name); // kim 이름 출력
    kim.walk(); // kim의 함수 호출

    // Dog dog1 = new Dog(); // Dog 클래스에서 dog1 객체 생성
    // dog1.jump(); // dog1의 함수 호출

    }
    }

Untitled

개인 실습

  • 이후에 개인적으로 클래스를 사용해보자
  • 간단한 게임 제작
  • 위에서 한 것처럼 플레이어 클래스, 몬스터 클래스를 생성
  • 서로에게 공격하는 함수를 넣고 main에서 사용해보자

JAVA base

클래스, 상속, 추상화 등의 개념 정리


JAVA

jdk, jre, jvm

  • jdk = 자바 개발도구(Java Development Kit)
  • jre = 자바 실행환경(Java Runtime Environment)
  • jvm = 자바 가상머신(Java Virtual Machine)

버전 명칭

  • version 1.8 = 8 버전
  • version 1.9 = 9 버전

dynamic typed 인터프리터

컴파일

  • 컴파일 = compile = 코드를 기계어(이진수 코드. 0과 1로) 바꾸는 것
  • 컴파일. javac
    • .java 파일을 javac가 컴파일하면 .class파일로 변환된다.
    • .class파일이 JVM의 클래스로더에게 전달되고 JVM은 메모리에 올린다.
    • 프로세스가 실행된다.

프로그램 vs 프로세스

  • 프로그램이 실행되면 프로세스
  • 실행됬다는 것은 메모리에 올라갔다는 의미

변수

  1. 반복해서 사용할 때 코딩의 반복을 막기 위함
  2. 값의 이름을 정의하기 위함
  • 자바에서 변수 선언하는 법
    • 데이터타입 변수명 = 값;
    • 예) int a= 5;

데이터 타입

  1. primitive(기본형)
  • call by value
  • 8가지 기본형
    • boolean
    • char
    • byte, int, short, long
    • float, double
  1. object(객체. 참조형)
    • call by reference
    • a의 주소값은 그대로고 값이 바뀌는 것이 아니라 주소가 변경된다. 원시형 데이터 타입이 아니기 때문.
1
2
string a = “안녕하세요”;
a = "헬로월드";

함수

  • 특정 프로세스를 반복하여 사용할 때 유지보수를 간편하게 한다

  • 이 프로세스가 무엇을 하는지 명확하게 이름을 지어 코드작성과 읽기를 편하게 하기 위함

  • 자바에서 함수 정의하는 법

    • 접근제한자 리턴타입 함수명(데이터타입 이름){본문};
    • 예) public int sum(int a, int b){ returmn a+b; }
  • 함수 호출하는 법

    • 함수명(매개변수);

디버거

  • 사용 목적 : 코드를 컴퓨터가 실행하는 과정으로 각 단계별로 추적하여 버그를 고치는 것을 간편하게 한다
  • 자바스크립트에서 쓰는 법:
    • 멈출 코드의 라인에 debugger;를 작성하고 코드 화면 우클릭하여 디버거 모드로 실행(개발자 모드)
  • 자바에서 사용하는 법
    • 멈출 코드의 라인에 브레이크 포인트를 걸고 디버거 모드로 실행(debug as)

node.js

  • 자바스크립트를 브라우저 외에 환경에서 실행하게 해주는 런타임 환경

부가 설정

  • 일단 이클립스(STS)는 JDK를 통해서 컴파일 하지 않는다.
  • 기본적으로 내장된 컴파일러를 사용한다
  • 성정을 변경하려면 다음과정을 거친다
    • STS → window → preference → compiler 검색 → 버전 변경 : 11
    • STS → window → preference → installed 검색 → jre 11d에 체크

while문

  • 언제 while을 사용하고 언제 for를 사용하는가?
    • 조건이 ‘상환, 컨디션’으로 정해지면 while이 편하고, 조건이 ‘횟수’로 정해지면 for가 편하다.
    • 하지만 for와 while은 서로 변환할 수 있다.

새로 배우기


  • 좋은 설계 = 높은 응집도 and 낮은 결합도

은닉화, 캡슐화

  • 어떻게 동작하는지 원리를 몰라도 사용법만 알면 사용할 수 있다.
  • 전화번호는 국제적으로 어떻게 한 사람이 하나의 번호를 부여받고 통신하는 어떻게 그것을 관리하고
  • 4g,5g는 무엇이고 우리가 전화번호로 통화 버튼을 누르면 어떤 정보가 어디로 가서 어덯게 처리되어 통화 작업이 일어나는지
  • 음성은 어떻게 데이터화되서 전달되는지

클래스

  • class는 객체에 대한 설계도
  • 설계도 대로 인스턴스를 하나 만들면 그제서야 메모리에 올라간다.

오버로드

  • Overload : 오버로드. 이것도 싣도 저것도 싣고.
  • 함수의 이름이 같은데 파라미터가 다를 경우 서로 다른 함수같이 작동되는 매커니즘.
  • 호출할때의 데이터타입과 객수를 보고 그렇게 정의했던 함수가 호출된다.

프로그래밍 패러다임

  • 객체지향 프로그래밍 (OOP = Objected Oriented Promgramming)
  • 절차지향적 → 객체지향적으로 발전에 의해 변경됨
    • 장점 : 사람이 세상을 보는 것과 같은 방식
    • 단점: 간단한 것 하나를 만들려고해도 설계부터 해야한다.

일급 객체

일급객체(First-class Object)란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.

  1. 변수에 할당할 수 있다.
  2. 다른 함수를 인자로 전달 받는다.
  3. 다른 함수의 결과로써 리턴될 수 있다.
  • JAVA의 함수 = 일급 객체

콜백함수

  • 비동기적 프로그래밍을 하기 위해서 콜백함수를 사용.
  • 비동기적 == 비절차적
    • 동기적이지 않다. 즉, a가 시작된 후에 a가 끝나지 않더라도 b가 시작될수 있는 것
  • 동기적 == 절차적
    • a 가 끝나야 b가 시작되는 서로다른 두 객체간의 시간적 값의 일치
  • 왜 비동기적 프로그래밍을 하나요?
  • 동기적 프로그래밍의 단점 :
    • 에러가 나면 정지된다. 하나만 틀려도 전체가 틀어진다.
  • 동기적 프로그래밍의 장점:
    • 병렬적으로 일을 처리할 수 있기 때문에 속도를 높일 수 있다.
  • 반드시 나 이전의 일이 끝나기를 기다릴 필요가없을 때 병렬적으로 일츨 처리하면 속도를 높일 수 있기 때문
1
2
3
4
5
6
7
8
9
10
// 콜백 방식
function matchQuiz(answer, printTrue, printFalse){
if(answer[0]==="무령왕릉"){
printTrue();
}else{
printFalse();
}
}
printTrue() 정의
printFalse() 정의

생성자 Constructor객체

  • 역할 : 객체를 인스턴스화(생성) 하는 역할
  • 문법 : 함수와 비슷하게 생겼는데 이름이 클래스명이고 리턴값이 없다

객체를 생성할 때 new 키워드와 함께 사용. 생성할때 필요한 데이터를 강제하는 역할

클래스에는 반드시 최소하나이상의 생성자가 존재

클래스에 생성자가 명시적으로 없더라도 컴파일러가 디폴트 생성자를 넣어주기 때문에 new키워드와 함께 생성자를 호출가능

디폴트 생성자는 매개변수와 구현부가 없다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Potion {

String name;
int recovery; // 회복양
String color;
String type;


public Potion(String 이름, int 회복량, String 색깔, String 종류) {
name = 이름;
recovery = 회복량;
color = 색깔;
type = 종류;
}

}
  • 생성자 생성
    • Ctrl + Space바 + Enter

생성자가 무엇인지 설명하고 왜 사용하는 설명하라.

 ⇒ 객체를 생성할 때 쓴다.
  • 객체가 생성될 때 필요한 데이터를 강제하는 역할을 한다.

    ⇒ 필요한 데이터가 준비되었다면 쉽게 객체를 만들 수 있도록 한다.

    ⇒ 데이터가 아직 준비되지 않았다면 객체를 생성할 수 없도록 한다.

추상화, 상속

  • 객체 : 소프트웨어로 구현할 대상. 개념

  • 인스턴스 : 클래스(설계도)로 구현된 구체적인 실체

  • 추상클래스 : 자식 extends 부모.  자식은 하나의 부모’만’ 가질수있다.

  • 동물 > 척추동물 > 포유강 > 식육목 > 고양잇과 > 표범과 > 표범

  • 클래스가 미완성이라는 것은 추상메소드가(abstract가 붙은 메소드) 하나 이상 포함된 클래스라는 말

  • 추상클래스로 인스턴스 생성은 불가능. 상속을 통해서 자식클래스에 의해서만 인스턴스를 생성할 수 있다.   부모가 만들어놓은것을 이어받아 자식이 완성시켜야 한다

  • Quiz!

    • 우리 아빠의 그랜저 = 인스턴스
    • 그랜저라는 개념 = 객체
    • 현대자동차의 그랜저 설계도 = 클래스
    • 중국으로 일부 유출된 그랜저 설계도 = 추상클래스

Override

 = 부모에 있는 메소드의 형태와 같은 메소드를 자식에 선언했을 때 자식의 메소드가 부모의 메소드를 덮어쓰는 매커니즘

오버로드 , 오버라이드 **차이점

  • 오버로드 = 과적재 = 이거 싣었다가 저거 싣었다가

    = 함수의 이름이 같고 파라미터가 다른 여러함수를 정의해놨을 때 함수호출시의 파라미터에 맞춰서 그에 맞는 함수가 호출되는 것.

  • 오버라이드 = 오버라이트 = 덮어쓰기

    • 상속이라는 개념을 먼저 알아야 한다. 부모클래스와 extends

추상클래스

  • abstract 키워드가 붙은 메소드가 하나라도 있는 클래스
  • 사실은 구현되다가 만놈(완벽하게 개발을 끝내지 못함)인데 내가 만든 클래스를 다른 사람이 상속받게 되면 미완성인 것을 사용하게 된다.
  • 추상클래스로는 인스턴스를 만들 수 없다. 왜냐? 미완성된 놈이니까.
  • 자식에서 반드시 추상 메소드를 오버라이드 해줘야 한다.

JAVA Debugger

디버거 (debugger)

  • de + bug = 버그를 없애다
  • 개발에 매우 중요한 모드

Java에서 사용하는 법

  • 원하는 라인에 더블클릭 = 파란색 브레이크 포이트 걸기
  • 우클릭 : debug as로 실행

Untitled

  • 디버그 모드 탈출
  • 우측 상단에 벌레 아이콘 옆에 있는 Java 아이콘 클릭
  • 해당 아이콘을 클릭하면 개발자 모드로 돌아올 수 있다.

Untitled

Java Script에서 사용하는 법

  • 지정할 브레이크 포인트에 debugger; 작성

  • 개발자모드를 열어놓은 상태에서 해당 영역에 도달한다

  • 브라우저 → 우클릭: 감사

  • Console 창에서 실행) 함수를 복사해서 붙여넣는다

  • 함수를 호출한다

Untitled

  • 디버거 모드 진입
  • F9
    • 해당 키를 통해서 순차적으로 코드를 살펴보면 된다

Untitled

디버거의 용도

  • 혼자하는 작업만 고려한다면 필수는 아니다
  • 하지만, 수십명이 함께 작업한 코드를 분석할 경우에는 상황이 매우 복잡해지므로
  • 다수가 함게하는 작업에서 특히 유용한 것이 디버거이다
  • 디버거의 활용으로 (초급 개발자) / (중급 개발자)로 나뉜다는 듯

JAVA start

코드 작성 팁

  • System.out.println() 작성하는 단축키
    • Syso + ctrl + space 바
  • 한줄 복사
    • ctrl + alt + 아래방향키

Hello World

  • Spring Tool Suite4 실행
  • 프로젝트 생성
  • 우클릭 : 생성한 프로젝트의 src → New → class

Untitled

  • Main 이라고 명명

Untitled

  • 코드 작성
    • 팁 : ctrl + space바
1
2
3
4
5
6
7
8
package variable;

public class Main {
public static void main(String[] args) {
System.out.println("헬로 월드");
}

}
  • 저장 후 실행 결과

Untitled

  • 여러가지 코드를 작성해보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package variable;

public class Main {
public static void main(String[] args) {
// System.out.println("헬로 월드");

int a = 5;
double b = 5.5;

System.out.println(a+b);

char x = 'a';
String y = "hello";
System.out.println(x+y);

int myNum = a;
myNum = myNum + 10;
System.out.println("Mynum : " + myNum);
System.out.println("a : " + a);

Integer myInt = 5;
Integer bInt = 9;
myInt = bInt; // 9

myInt += 5; // 14
bInt += 10; // 19
System.out.println("myInt : "+myInt);
System.out.println("bInt : "+bInt);
}
}

call by value, call by reference

  • Main.java
  • call by value = 값에 의한 참조
  • call by reference = 주소에 의한 참조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package variable;

public class Main {
public static void main(String[] args) {
// System.out.println("헬로 월드");

int a = 5;
double b = 7.5;

System.out.println(a+b);

// call by value. 기본형. 값에 의한 참조
char x = 'a';
String y = "hello";
System.out.println(x+y);

int myNum = a;
myNum = myNum + 10;
System.out.println("Mynum : " + myNum);
System.out.println("a : " + a);

// call by reference. 참조형. 주소에 의한 참조
String[] imgArr = {"🍕", "🍖"};
String[] stringArr = {"피자", "통닭", ""};
imgArr = stringArr; // 한글이 들어감
stringArr[2] = "아이스크림";

int i=0;
System.out.println(imgArr[0]);
System.out.println(imgArr[1]);
System.out.println(imgArr[2]);

// for(i=0; i<imgArr.length; i++) {
// System.out.println(imgArr[i]);
// }
}
}

연산자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package variable;

public class 연산자 {
public static void main(String[] args) {

int a = 100;
int b = 333;

System.out.println(a++ + ++b); // 100 + 334 = 434
// ++ 이나 -- 증감연산자가
// 뒤에있으면 사용한뒤 값을 변경
// 앞에 있으면 변경한 뒤에 사용

}
}