Post

java 공부 2024.05.09

생성자

생성자 이미지 1

생성자 이미지 2

파라미터에 아무것도 안주면 에러가 남

생성자 이미지 3

레퍼런스변수

레퍼런스변수 이미지 1

레퍼런스변수 이미지 2

레퍼런스변수 이미지 3

레퍼런스변수 이미지 4

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

// 클래스 AvangerTest의 정의 시작
public class AvangerTest {
    // main 메소드 시작: 프로그램의 시작점
	public static void main(String[] args) {
		// Avenger 클래스의 객체 thor를 생성, 이름은 "토르", 체력은 150
		Avenger thor = new Avenger("토르", 150);
		// Avenger 클래스의 객체 thanos를 생성, 이름은 "타노스", 체력은 160
		Avenger thanos = new Avenger("타노스", 160);

		// thor가 thanos에게 펀치를 가함 (thanos의 체력이 10 감소)
		thor.punch(thanos);
		// thor가 thanos에게 다시 펀치를 가함 (thanos의 체력이 다시 10 감소)
		thor.punch(thanos);
		// thanos가 thor에게 펀치를 가함 (thor의 체력이 10 감소)
		thanos.punch(thor);
	}
	// main 메소드 끝
}

// Avenger 클래스의 정의 시작
class Avenger {
	// Avenger의 이름을 저장하는 String 타입의 인스턴스 변수 name
	String name;
	// Avenger의 체력을 저장하는 int 타입의 인스턴스 변수 hp
	int hp;
	
	// Avenger 클래스의 생성자, 이름과 체력을 초기화
	Avenger(String s, int i) {
		name = s; // 이름 초기화
		hp = i;   // 체력 초기화
	}
	
	// punch 메소드 정의: 다른 Avenger 객체를 매개변수로 받아 펀치를 가하는 메소드
	void punch(Avenger enemy) {
		// 펀치하는 Avenger의 이름을 출력
		System.out.printf("[%s]의 펀치!", name);
		// enemy Avenger의 체력을 10 감소
		enemy.hp -= 10;
		// enemy Avenger의 남은 체력을 출력
		System.out.printf(" -> %s의 체력 : %d\n", enemy.name, enemy.hp);
	}
	// punch 메소드 끝
}
// Avenger 클래스의 정의 끝

160 체력이 리셋이 안되는 이유 :

객체의 상태가 메소드 호출에 따라 지속적으로 변경되기 때문.

Java에서 객체의 상태는 필드(예: 변수)에 의해 저장되며, 객체의 메소드를 통해 그 상태가 변경될 수 있다. 여기서 Avenger 클래스의 hp 필드는 Avenger 객체의 체력을 나타냄. 객체의 메소드인 punch를 호출할 때마다 해당 객체의 hp 필드가 수정됨.

분석

  1. 객체 생성 시 체력 설정
    • thor 객체는 생성될 때 체력이 150으로 설정.
    • thanos 객체는 생성될 때 체력이 160으로 설정.
  2. punch 메소드 호출
    • thor.punch(thanos); 호출 시, thanos의 체력은 160에서 10 감소하여 150이 됨.
    • 다음 thor.punch(thanos); 호출 시, thanos의 체력은 다시 10 감소하여 140이 됨.
    • thanos.punch(thor); 호출 시, thor의 체력은 150에서 10 감소하여 140이 됨.

상세 설명

  • thanos의 체력이 160에서 “리셋”되지 않는 이유는, 프로그램에서 thanos 객체의 hp 필드가 punch 메소드에 의해 계속 감소하기 때문이다. 객체의 필드 값은 메소드를 통해 변경될 때 이전 상태를 “기억”하고, 새로운 상태로 계속 유지됨.
  • 객체 지향 프로그래밍에서 객체의 필드(여기서는 hp)는 클래스의 인스턴스가 살아있는 동안 계속 그 값을 유지함. 따라서, 한 번 hp가 감소하면, 그 변경된 값이 계속 객체에 반영된다.
  • 만약 thanos의 체력을 특정 동작 후 원래 값(160)으로 리셋하고 싶다면, 직접 hp 필드를 원하는 값으로 설정하는 로직을 추가해야 함.

예시: 체력 리셋 메소드 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Avenger {
    String name;
    int hp;
    int originalHp; // 원래 체력을 저장하는 필드 추가

    Avenger(String s, int i) {
        name = s;
        hp = i;
        originalHp = i; // 생성자에서 원래 체력도 초기화
    }

    void punch(Avenger enemy) {
        System.out.printf("[%s]의 펀치!", name);
        enemy.hp -= 10;
        System.out.printf(" -> %s의 체력 : %d\n", enemy.name, enemy.hp);
    }

    // 체력을 원래 값으로 리셋하는 메소드
    void resetHp() {
        hp = originalHp;
        System.out.printf("%s의 체력이 %d로 리셋되었습니다.\n", name, hp);
    }
}

이제 thanos.resetHp();를 호출하면 thanoshporiginalH p (160)로 리셋됨.

static

스테틱 이미지 1

스테틱 이미지 2

스테틱 이미지 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
package today0509;

// 클래스 StudentTest의 정의 시작
public class StudentTest {
    // main 메소드 시작: 프로그램의 시작점
	public static void main(String[] args) {
	    // Student 클래스의 객체 park 생성, 학번은 201922104, 이름은 "Park"
		Student park = new Student(201922104, "Park");
		// Student 클래스의 객체 kim 생성, 학번은 201922104, 이름은 "Kim"
		Student kim = new Student(201922104, "Kim");
		// Student 클래스의 객체 lee 생성, 학번은 201922104, 이름은 "Lee"
		Student lee = new Student(201922104, "Lee");

		// Student 클래스의 static 변수 count를 사용하여 현재 생성된 Student 객체의 수를 출력
		System.out.printf("Student 객체의 수 : %d", Student.count);
	}
	// main 메소드 끝
}

// Student 클래스의 정의 시작
class Student {
	// 클래스 변수(static 필드), 모든 Student 객체가 공유하는 변수로, 생성된 Student 객체의 수를 저장
	static int count = 0;
	
	// 인스턴스 변수(non-static 필드), 각 Student 객체의 고유한 데이터를 저장
	int id;   // 학번을 저장하는 인스턴스 변수
	String name; // 이름을 저장하는 인스턴스 변수
	
	// 생성자 시작
	// Student 객체를 생성하면서 학번(id)과 이름(name)을 초기화
	Student(int _id, String _name) {
	    // Student 클래스의 static 변수 count를 1 증가시킴
		Student.count++;
		id = _id; // 인스턴스 변수 id를 매개변수 _id로 초기화
		name = _name; // 인스턴스 변수 name을 매개변수 _name로 초기화
	}
	// 생성자 끝
}
// Student 클래스의 정의 끝

스테틱 이미지 6
스테틱 이미지 7
스테틱 이미지 8

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
package today0509;

// MyMathTest 클래스 정의
public class MyMathTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // MyMath 클래스의 max 메소드를 호출하여 1.23과 3.45 중 더 큰 값을 출력
        System.out.println(MyMath.max(1.23, 3.45));
        // MyMath 클래스의 min 메소드를 호출하여 5.43과 3.21 중 더 작은 값을 출력
        System.out.println(MyMath.min(5.43, 3.21));
    }
}

// MyMath 클래스 정의
class MyMath {
    // max 메소드 정의: 두 double 타입의 값을 비교하여 더 큰 값을 반환
    static double max(double a, double b) {
        // a와 b를 비교하여 더 큰 값(a 또는 b)을 반환
        return (a > b) ? a : b;
    }
    
    // min 메소드 정의: 두 double 타입의 값을 비교하여 더 작은 값을 반환
    static double min(double a, double b) {
        // a와 b를 비교하여 더 작은 값(a 또는 b)을 반환
        return (a < b) ? a : b;
    }
}

스테틱 이미지 9

접근제한자

제한자 이미지 1
제한자 이미지 2
제한자 이미지 4
제한자 이미지 5
제한자 이미지 6
제한자 이미지 7
제한자 이미지 8

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
package today0509;

// AccountTest 클래스 정의
public class AccountTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Account 클래스의 객체 acc 생성
        Account acc = new Account();
        
        // acc 객체의 setBalance 메소드를 사용하여 잔액을 1000으로 설정
        acc.setBalance(1000);
        // acc 객체의 getBalance 메소드를 사용하여 잔액을 가져와 출력
        System.out.printf("잔액 : %d", acc.getBalance());
    }
}

// Account 클래스 정의
class Account {
    // balance 필드(변수) 정의, private 접근 지정자를 사용하여 클래스 외부에서의 접근을 제한
    private int balance;
    
    // 게터
    // getBalance 메소드 정의: balance 필드의 값을 반환하는 게터 메소드
    public int getBalance() {
        return balance;
    }
    
    // 세터
    // setBalance 메소드 정의: balance 필드의 값을 설정하는 세터 메소드
    public void setBalance(int b) {
        // 매개변수로 받은 b 값을 balance 필드에 저장
        balance = b;
    }
}
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
package today0509;

// AccountTest 클래스 정의
public class AccountTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Account 클래스의 객체 acc 생성
        Account acc = new Account();
        acc.balance = 10;
        // acc 객체의 setBalance 메소드를 사용하여 잔액을 1000으로 설정
        // acc.setBalance(1000);
        // acc 객체의 getBalance 메소드를 사용하여 잔액을 가져와 출력
        System.out.printf("잔액 : %d", acc.getBalance());
    }
}

// Account 클래스 정의
class Account {
    // balance 필드(변수) 정의, private 접근 지정자를 사용하여 클래스 외부에서의 접근을 제한
    int balance;
    
    // 게터
    // getBalance 메소드 정의: balance 필드의 값을 반환하는 게터 메소드
    public int getBalance() {
        return balance;
    }
    
    // 세터
    // setBalance 메소드 정의: balance 필드의 값을 설정하는 세터 메소드
    public void setBalance(int b) {
        // 매개변수로 받은 b 값을 balance 필드에 저장
        balance = b;
    }
}

private 접근 지정자를 사용해 필드(변수)를 선언하고 게터(getter)와 세터(setter) 메소드를 제공하는 방식은 객체 지향 프로그래밍에서 매우 중요한 설계 원칙인 캡슐화와 관련이 깊음.

캡슐화의 중요성

  1. 데이터 은닉과 보호:

    private 키워드로 클래스의 필드를 선언하면, 그 필드는 클래스 외부에서 직접 접근할 수 없다. 이는 클래스의 데이터를 보호하고, 외부에서 예상치 못한 방식으로 그 데이터가 변경되는 것을 방지함. 데이터가 유효한 상태를 유지할 수 있도록 내부에서만 관리된다.

  2. 인터페이스와 구현의 분리:

    클래스를 사용하는 코드는 해당 클래스의 메소드를 통해서만 데이터에 접근할 수 있다. 이는 클래스의 내부 구현이 변경되더라도, 그 변경이 클래스를 사용하는 코드에 영향을 미치지 않도록 할 수 있다. 예를 들어, 필드에 대한 계산 방식이나 유효성 검사 로직이 바뀌어도, 게터와 세터의 시그니처(메소드 이름, 인자)가 바뀌지 않는 한 사용자 코드는 수정할 필요가 없다.

  3. 유효성 검사:

    게터와 세터를 사용하면 데이터를 설정하거나 반환하기 전에 추가적인 로직을 실행할 수 있다. 예를 들어, 계좌 잔액(balance)이 절대 음수가 되지 않도록 세터에서 유효성 검사를 할 수 있다.

  4. 추가 로직의 삽입:

    게터와 세터 메소드를 통해 값을 설정하거나 가져올 때, 로깅(log 기록), 권한 검사, 캐싱 등 추가적인 기능을 쉽게 구현할 수 있다.

  5. 데이터 포맷팅:

    게터에서는 클래스 사용자에게 데이터를 특정 포맷으로 제공할 수 있다. 예를 들어, 날짜 필드가 있을 때 내부적으로는 Timestamp 타입을 사용하지만, 이를 문자열로 포맷하여 반환할 수 있다.

예시

다음은 Account 클래스에서 balance 필드를 private으로 선언하고, 게터와 세터를 통해 접근하는 예시. 세터에서는 음수 값을 설정하지 못하도록 유효성 검사를 추가한 모습.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Account {
    private int balance; // balance는 클래스 외부에서 직접 접근할 수 없습니다.

    // balance의 값을 반환하는 게터 메소드
    public int getBalance() {
        return balance;
    }

    // balance의 값을 설정하는 세터 메소드
    public void setBalance(int b) {
        if (b >= 0) { // balance에 음수가 설정되지 않도록 검사
            balance = b;
        } else {
            System.out.println("잔액은 음수가 될 수 없습니다.");
        }
    }
}

문제

제한자 이미지 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
47
48
package today0509;

// CoffeeTest 클래스 정의
public class CoffeeTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Coffee 클래스의 객체 c 생성, 커피 이름은 "아메리카노", 가격은 3000원
        Coffee c = new Coffee("아메리카노", 3000);
        
        // 객체 c의 getName 메소드와 getPrice 메소드를 호출하여 커피 이름과 가격을 출력
        System.out.printf("%s(%d원) -> ", c.getName(), c.getPrice());
        
        // 객체 c의 setPrice 메소드를 호출하여 커피 가격을 현재 가격에 500원 추가
        c.setPrice(c.getPrice() + 500);
        
        // 가격 변경 후, 객체 c의 getName 메소드와 getPrice 메소드를 호출하여 커피 이름과 가격을 출력
        System.out.printf("%s(%d원)", c.getName(), c.getPrice());
    }
}

// Coffee 클래스 정의
class Coffee {
    // name 필드(변수) 정의, private 접근 지정자로 클래스 외부에서의 접근을 제한
    private String name;
    // price 필드(변수) 정의, private 접근 지정자로 클래스 외부에서의 접근을 제한
    private int price;
    
    // Coffee 클래스의 생성자
    public Coffee(String n, int p) {
        name = n; // 생성자의 매개변수 n을 name 필드에 할당
        price = p; // 생성자의 매개변수 p를 price 필드에 할당
    }
    
    // name 필드의 값을 반환하는 게터 메소드
    public String getName() {
        return name;
    }
    
    // price 필드의 값을 반환하는 게터 메소드
    public int getPrice() {
        return price;
    }
    
    // price 필드의 값을 설정하는 세터 메소드
    public void setPrice(int p) {
        price = p; // 매개변수로 받은 p 값을 price 필드에 저장
    }
}

자바 API

api 1
api 2
api 3

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
package today0509;
import java.util.Scanner; // Scanner 클래스를 사용하기 위해 java.util 패키지에서 Scanner를 가져옴

// UserInput 클래스 정의
public class UserInput {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Scanner 객체 input 생성, 표준 입력 스트림(System.in)을 사용
        Scanner input = new Scanner(System.in);
        
        // 사용자에게 이름 입력을 요청
        System.out.print("이름: ");
        // 사용자로부터 이름을 입력받음
        String name = input.next();
        
        // 사용자에게 학번 입력을 요청
        System.out.print("학번: ");
        // 사용자로부터 학번을 입력받음, 정수로 처리
        int number = input.nextInt();
        
        // 사용자에게 학점 입력을 요청
        System.out.print("학점: ");
        // 사용자로부터 학점을 입력받음, 실수로 처리
        double grade = input.nextDouble();
        
        // 입력받은 이름, 학번, 학점을 포맷에 맞게 출력
        System.out.printf("[%s]님의 학번은 %d이며, 학점은 %.2f 입니다.", name, number, grade);
        
        // Scanner 객체 input을 닫음
        input.close();
    }
}

api 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package today0509;
import java.lang.Math; // Math 클래스를 사용하기 위해 java.lang 패키지에서 Math를 가져옴

// MathTest 클래스 정의
public class MathTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Math.PI를 사용하여 수학 상수 π(파이, 원주율)의 값을 출력
        System.out.printf("수학의 파이(원주율) 값 : %f\n", Math.PI);
        
        // Math.random()을 사용하여 0.0 이상 1.0 미만의 임의의 난수를 생성하여 출력
        System.out.printf("임의 난수 값 : %f\n", Math.random());
        
        // Math.floor(9.81)을 사용하여 9.81의 내림값을 계산하여 출력
        System.out.printf("9.81의 내림값 : %f\n", Math.floor(9.81));
        
        // Math.sqrt(4)을 사용하여 4의 제곱근을 계산하여 출력
        System.out.printf("4의 제곱근 : %f\n", Math.sqrt(4));
        
        // Math.pow(2, 3)을 사용하여 2의 3승을 계산하여 출력
        System.out.printf("2의 3승 : %f\n", Math.pow(2, 3));
    }
}

api 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
package today0509;
import java.util.*; // java.util 패키지에서 모든 클래스를 가져옴

// RandomTest 클래스 정의
public class RandomTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Random 객체 random 생성
        Random random = new Random();
        
        // n을 10으로 초기화
        int n = 10;
        
        // random.nextInt()를 사용하여 임의의 정수 출력
        // 첫 번째 출력은 형식 지정자(%d)를 사용하는 방식으로, 
        // 올바르게 출력되지 않으므로 수정이 필요합니다.
        System.out.println("임의의 정수 : " + random.nextInt());
        
        // 0 이상 n(10) 미만의 임의 정수 출력
        System.out.printf("0이상 N(%d)미만의 임의 정수 : %d\n", n, random.nextInt(n));
        
        // random.nextDouble()를 사용하여 0.0 이상 1.0 미만의 임의 실수 출력
        System.out.printf("임의의 실수 : %f\n", random.nextDouble());
        
        // random.nextBoolean()를 사용하여 임의의 참/거짓 값 출력
        System.out.printf("임의의 참/거짓 : %b\n", random.nextBoolean());
    }
}

api 6

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 today0509;
import java.util.ArrayList; // ArrayList 클래스를 사용하기 위해 java.util 패키지에서 ArrayList를 가져옴

// ArrayListTest 클래스 정의
public class ArrayListTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // String 타입의 ArrayList 생성
        ArrayList<String> names = new ArrayList<String>();
        
        // names 리스트에 "Kim" 추가
        names.add("Kim");
        // names 리스트에 "Lee" 추가
        names.add("Lee");
        // names 리스트에 "Park" 추가
        names.add("Park");
        // names 리스트에 "Choi" 추가
        names.add("Choi");
        
        // names 리스트의 0번째 인덱스의 값을 "Han"으로 변경
        names.set(0, "Han");
        // names 리스트의 1번째 인덱스의 값을 제거하고, 제거된 값을 removed 변수에 저장
        String removed = names.remove(1);
        
        // names 리스트의 모든 요소를 출력
        for (int i = 0; i < names.size(); i++) {
            System.out.printf("%s ", names.get(i));
        }
    }
}

상속

상속 2
상속 3
상속 4
상속 1

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

// RPGTest 클래스 정의
public class RPGTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Wizard 클래스의 객체 wizard 생성
        Wizard wizard = new Wizard();
        
        // wizard 객체의 name 필드에 "간달프" 할당
        wizard.name = "간달프";
        // wizard 객체의 hp 필드에 100 할당
        wizard.hp = 100;
        // wizard 객체의 mp 필드에 80 할당
        wizard.mp = 80;
        
        // wizard 객체의 punch 메소드 호출
        wizard.punch();
        // wizard 객체의 fireball 메소드 호출
        wizard.fireball();      
    }
}

// Novice 클래스 정의
class Novice {
    // 초보자의 이름을 저장하는 필드
    String name;
    // 초보자의 체력을 저장하는 필드
    int hp;
    
    // punch 메소드 정의: 펀치를 날리는 행동을 출력
    void punch() {
        System.out.printf("%s(HP: %d)의 펀치!\n", name, hp);
    }
}

// Wizard 클래스 정의: Novice 클래스를 상속받음
class Wizard extends Novice {
    // 마법사의 마력을 저장하는 필드
    int mp;
    
    // fireball 메소드 정의: 파이어볼을 사용하는 행동을 출력
    void fireball() {
        System.out.printf("%s(HP: %d, MP : %d)의 파이어볼!\n", name, hp, mp);
    }
}

상속 5

상속 6

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
package today0509;

// RPGTest 클래스 정의
public class RPGTest {
    // main 메소드 정의: 프로그램의 실행 시작점
    public static void main(String[] args) {
        // Knight 클래스의 객체 knight 생성
        Knight knight = new Knight();
        
        // knight 객체의 name 필드에 "킹아서" 할당
        knight.name = "킹아서";
        // knight 객체의 hp 필드에 100 할당
        knight.hp = 100;
        // knight 객체의 stamina 필드에 70 할당
        knight.stamina = 70;
        
        // knight 객체의 punch 메소드 호출
        knight.punch();
        // knight 객체의 slash 메소드 호출
        knight.slash();      
    }
}

// Novice 클래스 정의
class Novice {
    // 초보자의 이름을 저장하는 필드
    String name;
    // 초보자의 체력을 저장하는 필드
    int hp;
    
    // punch 메소드 정의: 펀치를 날리는 행동을 출력
    void punch() {
        System.out.printf("%s(HP: %d)의 펀치!\n", name, hp);
    }
}

// Wizard 클래스 정의: Novice 클래스를 상속받음
class Wizard extends Novice {
    // 마법사의 마력을 저장하는 필드
    int mp;
    
    // fireball 메소드 정의: 파이어볼을 사용하는 행동을 출력
    void fireball() {
        System.out.printf("%s(HP: %d, MP : %d)의 파이어볼!\n", name, hp, mp);
    }
}

// Knight 클래스 정의: Novice 클래스를 상속받음
class Knight extends Novice {
    // 기사의 스태미나를 저장하는 필드
    int stamina;
    
    // slash 메소드 정의: 슬래쉬 공격을 사용하는 행동을 출력
    void slash() {
        System.out.printf("%s(HP: %d, ST : %d)의 슬래쉬!\n", name, hp, stamina);
    }
}

의문

  1. 어떻게 main 메서드를 찾는걸까? : main 메타데이터를 가지고 있음. 한 줄씩 main을 찾는게 아님
  2. 왜 String만 대문자로 double이나 int는 소문자일까? : 이미지
    • String은 객체.
      Java에서 String은 불변(immutable) 객체로, 한 번 생성되면 그 내용을 변경할 수 없다.

    • 리터럴 vs. new 키워드
      • String s1 = "Hello";와 같이 리터럴 방식으로 String을 생성하면, JVM은 “Hello”라는 값을 String Pool 내에 저장하고, 동일한 리터럴 값으로 선언된 모든 String 변수는 메모리 내 같은 객체를 참조하게 된다. 따라서 s1s2는 같은 메모리 주소를 참조.
      • String s3 = new String("Hello");는 매번 새로운 String 객체를 메모리에 생성. 따라서 s3s4는 내용은 같지만, 서로 다른 메모리 주소를 가지게 됨.
    • 기본 타입(primitive type).
      int**는 Java의 기본 자료형 중 하나로, 메모리에 직접 값을 저장하며 객체가 아니다.

    • 값에 의한 비교 int 타입의 변수들은 그들의 값에 의해 직접 비교됨. 예를 들어, 두 int 변수가 같은 값을 가지고 있으면, 그들은 같다고 평가함.

    • == vs. equals()

    • == 연산자: 주소 값을 비교. 따라서, 두 String 변수가 같은 객체를 참조하고 있는지 확인한다.
    • equals() 메소드: 내용 자체를 비교. String 클래스에서 equals() 메소드는 두 문자열의 내용이 같은지 비교하도록 오버라이드되어 있다.

    • 요약

    • String s1 = "Hello";String s2 = "Hello";는 같은 String Pool 내 객체를 참조하므로 s1 == s2true이다.
    • String s3 = new String("Hello");String s4 = new String("Hello");는 내용은 같지만, 서로 다른 객체를 참조하므로 s3 == s4false이다. 하지만 s3.equals(s4)true이다, 왜냐하면 equals()는 값의 내용을 비교하기 때문임.

    이렇게 Java에서는 객체와 기본 타입을 다르게 처리하며, String의 경우 특별한 메모리 관리 방식을 통해 효율성을 높이고 있음.

This post is licensed under CC BY 4.0 by the author.