Java/보충수업

[2024-09-13] 자바 보충수업 2일차

dev.jelee 2024. 9. 14. 17:56

* 수업 내용 외에 추가로 관련 자료를 찾아서 덧붙임

 

반복 제어문

1. while 문 - 반복 제어문

  • 조건이 참인 경우 중괄호 { } 안의 명령문을 반복적으로 수행하는 제어문이다.
  • 수행해야할 명령문이 한 개일 경우에는 중괄호는 생략 가능하다.
  • 조건이 참인 경우 명령문을 반복 수행한다.
// 기본 형식
while (조건) {
	명령문1;
	명령문2;
	...
	명령문n;
}

2. do~while문 - 반복 제어문

  • 명령문을 먼저 실행하고 조건을 비교한다.
  • 최소 한번은 반드시 수행한다.
  • while문 뒤에 세미콜론 ; 을 써야한다.
  • 조건에 따라 수행해야 할 명령문이 한 개일 경우에는 중괄호는 생략 가능하다.
// 기본 형식
do {
	명령문1;
	명령문2;
	....
	명령문n;
} while (조건);

3. for문 - 반복 제어문

  • 조건이 참인 경우 중괄호 { } 안의 명령문을 반복적으로 수행하는 제어문이다.
  • for문의 괄호 ( ) 안에는 3개의 명령어를 쓸 수 있는데 이 명령은 세미콜론 ; 으로 분리한다.
    • 3개의 명령 중 필요 없는 명령은 생략이 가능하다.
  • for문 내에서 초기값과 증가/감소 값이 여러 개인 경우 콤마 , 로 나열한다.
  • 조건이 여러개인 경우는 && 또는 || 연산자로 조건을 연결해야 한다.
    • 콤마로 나열 시 가장 우측에 있는 조건만 수행한다.
  • 조건이 참인 경우 명령문을 반복 수행한다.
    • 초기 값은 반복 수행되지 않는다.
// 기본 형식
for (초기값; 조건; 증/감값) {
	명령문1;
	명령문2;
	...
	명령문n;
}
  • for문의 ( ) 소괄호 안에 있는 조건의 생략 가능에 대한 예시 코드
// 1. 조건 생략 가능
// for 루프의 조건을 생략하고, while(true)처럼 무한 루프를 만든 후, 
// break 문을 사용하여 반복문을 종료
int i = 0;
for (;;) {  // 조건 생략
    if (i >= 5) {
        break;  // 조건을 대신하여 break로 반복문 종료
    }
    System.out.println("i = " + i);
    i++;
}


// 2. 증가/증감 생략
// 증가/감소 부분을 for 루프의 소괄호에서 생략하고, 반복문 내부에서 직접 i++를 수행
for (int i = 0; i < 5; ) {  // 증가/감소 생략
    System.out.println("i = " + i);
    i++;  // 반복문 내에서 증가
}


// 3. 초기화, 조건, 증가/증감 모두 생략
// 초기화와 조건, 증가/감소 모두 생략하고 반복문을 사용
int i = 0;
for (;;) {  // 조건 및 초기화 생략
    if (i >= 5) {
        break;
    }
    System.out.println("i = " + i);
    i++;
}

4. break문 - 기타 제어문

  • 반복 명령의 실행 도중 강제적으로 반복문을 빠져나올 때 사용되는 명령어이다.
  • 여러 개의 반복문이 중첩되어 있는 경우 반복문 한 개만 빠져나온다.
// 예시
for (int i = 0; i < 5; i++) {
    System.out.println("i = " + i);
    if (i == 2) {
        break;
    }
}

// 1. i가 2일 경우 해당 반복 제어문을 빠져나온다.
// 2. 출력값은 0, 1 이다.

5. continue문 - 기타 제어문

  • 반복문의 나머지 부분을 무시하고 반복문의 선두로 이동할 때 사용.
  • 여러 개의 반복문이 중첩되어 있는 경우 continue 명령이 있는 반복문의 선두로 이동한다.
// 예시
for (int i = 0; i < 5; i++) {
	if (i == 2) {
		continue;
	}
	System.out.println("i = " + i);
}

// 1. i가 2인 경우 해당 실행문은 건너뛰고 다음 실행문이 실행된다.
// 2. 출력값은 0, 1, 3, 4 이다.

배열 (Array)

1. 특징

  • 배열은 같은 타입의 변수가 여러개 필요한 경우 이용한다.
  • 같은 타입의 변수가 하나의 배열 이름으로 연속적인 메모리에 할당된다.
  • 배열은 선언하면 초기 값을 지정할 수 있다.
  • 배열의 초기 값은 여러개 존재하기 때문에 중괄호 { } 안에 차례때로 쓴다. (아래 예시 있음)
  • 초기 값과 배열의 크기가 일치하면 배열의 크기를 생략할 수 있다.
  • 배열의 크기보다 적은 개수의 초기 값을 할당하게 되면 나머지 배열의 값은 0으로 초기화된다.
  • 배열은 한 번 생성되면 크기를 변경할 수 없기 때문에 보다 큰 배열을 만들고 이전 배열로부터 내용을 복사해야 한다.
  • 반복문을 이용하여 복사할 수 있다. (for문 사용)
    • 이런식으로 가능 for(int i = 0; i < score.length; i++) { System.out.println ( score[i] ) }
  • System클래스의 arraycopy() 사용하여 배열에 저장되어 있는 값만 복사할 수 있다.
    • 참조 변수 배열인 경우에는 단지 주소 값 만을 복사하고 객체를 복사하지 않는다.

2. 배열의 선언과 초기화

  • 생성된 배열을 다루기 위해 참조 변수의 공간을 확보한다.
  • 타입[] 변수 이름; or 타입 변수 이름[];
  • 변수 타입에 따른 기본값은 다르다.
자료형 기본값
Boolean false
char '\u0000'
byte 0
short 0
int 0
long 0
float 0.0f
double 0.0d 또는 0.0
참조형 변수  
  • 사용 예시
// 사용 예1 - 선언
int[] score;
String[] name;

// 사용 예2 - 선언
int score[];
String name[];

// 사용 예3 - 선언+초기화
int arr[] = {1, 2, 3};

// 사용 예4 - 선언, 초기화 따로
// 정수 배열 생성
int[] score;
score = new int[5]; // 값을 넣은 것은 아니기 때문에 기본값 0으로 초기화되어서 저장된다.
// tip: 배열 객체의 멤버 필드 length가 배열의 크기에 대한 정보를 담고 있다.
// score.length는 5

// 참조 변수 배열 생성
String[] name;
name = new String[3]; // 각 배열 요소는 자동적으로 null값으로 초기화 된다.

// int형 배열
int[] score = new int[5]; // 0으로 자동 초기화 된다.

// 각 index마다 값을 저장할 수 있다.
socre[0] = 100;
socre[1] = 90;
socre[2] = 80;
socre[3] = 70;
socre[4] = 60;

// 아래와 같은 방식으로 선언과 초기화를 할 수 있다.
int[] score = {100, 90, 80, 70, 60};
int[] score = new int[]{100, 90, 80, 70, 60};

3. 배열의 메모리 공간

배열 메모리 공간 예시 그림

  • int arr[] = {1, 2, 3} 이란 배열을 하나 생성했다.
  • int형 타입이며 [ ] 대괄호를 사용하여 배열을 생성하였고 이름은 arr이다.
  • int arr[] 은 100번지에 저장되어 있다.
  • int arr[] 에는 1, 2, 3이란 값이 들어있는데 index순으로 0번은 1이란 값, 1번은 2라는 값, 2번은 3이란 값을 가지고 있다.
  • int arr[] 은 100번지에 저장되어 있지만 int타입은 4byte씩 메모리 공간을 차지하기 때문에 100, 104, 108 이라는 규칙으로 메모리 공간을 차지하게 되는 거다.

클래스 & 객체

1. 클래스 (Class)

  • 클래스는 객체를 정의한다.
  • 객체의 모든 속성과 기능이 정의 되어 있다.
    • 서로 관련된 변수들을 정의하고 이들에 대한 작업을 순행하는 함수들을 함께 정의한다.
  • 클래스(class)의 기본 구성은 접근 지정자+멤버 변수+ 멤버 메소드 이다.
  • 모든 코드는 class안에 포함되어야 한다.
    • class 밖에서 쓰일 수 있는 것은 package, import, 다른 class 이다.
  • 즉, 클래스는 객체를 생성하기 위한 템플릿 또는 설계도이다. 클래스는 객체가 가질 속성과 기능을 정의한다.

2. 객체 (Object)

  • 객체는 다수의 속성과 다수의 기능을 갖는다.
  • 클래스에 정의된 내용대로 메모리에 생성된 것.
  • 객체를 선언한다는 것은 데이터 타입을 선언한다는 의미다.
  • 객체를 생성한다는 것은 메모리 공간을 생성한다는 거다.

객체 구성 요소

  • 클래스로부터 객체를 생성하면 클래스에 정의된 속성기능을 가진 객체가 만들어진다.
  • 객체는 다수의 속성과 다수의 기능의 집합이다.

(1) 속성(Property)

  • 객체의 상태를 나타내는 변수이다. 속성은 객체의 특성을 설명한다.
  • 멤버 변수(member variable), 특성(attribute), 필드(field), 상태(state)
    • 멤버 변수(member variable): 클래스 안에서 정의된 변수로, 객체의 속성을 저장.
    • 특성(attribute): 객체의 상태나 특성을 나타내는 변수입니다. 멤버 변수와 같은 개념.
    • 필드(field): 객체의 데이터를 저장하는 변수로, 멤버 변수와 동일.
    • 상태(state): 객체가 현재 가진 데이터의 조합을 말하며, 이는 속성(멤버 변수)의 값들에 의해 결정.
  • 멤버 변수, 특성, 필드는 객체의 속성을 나타내는 변수를 의미하고 상태는 이러한 변수들의 현재 값으로 객체의 전체적인 상태를 표현한다.
public class Person {
    // 멤버 필드 (Member Fields)
    String name;
    int age;
    String address;

    // 메서드
    void displayInfo() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Address: " + address);
    }
}

// 멤버 필드 (Member Fields): name, age, address는 Person 클래스의 멤버 필드이다.
// 각각 Person 객체의 속성을 저장합니다.

// 상태 (State): Person 객체의 상태는 name, age, address 필드의 현재 값들로 정의된다.
// 예를 들어, name이 "Alice", age가 30, address가 "123 Street"일 때, 
// 이 객체의 상태는 "Alice", 30, "123 Street"이다.

// 멤버 필드는 객체의 데이터를 저장하는 변수들이고, 
// 상태는 이러한 데이터들이 조합되어 표현되는 객체의 전체적인 특성을 의미한다.

 

(2) 기능(Function)

  • 객체가 수행할 수 있는 작업이나 동작을 정의하는 메소드이다. 기능은 객체가 수애할 수 있는 행동을 설명한다.
  • 메서드(method), 행위(behavior), 함수(function)
    • 메소드 (Method): 객체의 동작을 정의하는 함수.
    • 행위 (Behavior): 객체가 수행할 수 있는 동작을 설명하는 또 다른 용어.
    • 함수 (Function): 메소드와 같은 의미로 사용되지만, 자바에서는 주로 메소드라는 용어를 사용.
  • 메소드와 함수는 객체의 기능을 정의하고, 행위는 이 기능이 실제로 어떤 동작을 수행하는지를 설명한다.
// chatGPT를 통해 얻은 예시

public class Fan {
    // 멤버 필드 (Member Field) - 선풍기의 상태
    boolean isOn = false;

    // 메소드 (Method) - 선풍기를 켜는 동작
    void turnOn() {
        isOn = true;
        System.out.println("The fan is now ON.");
    }

    // 메소드 (Method) - 선풍기를 끄는 동작
    void turnOff() {
        isOn = false;
        System.out.println("The fan is now OFF.");
    }
    
    // 메소드 (Method) - 선풍기의 현재 상태를 출력
    void checkStatus() {
        if (isOn) {
            System.out.println("The fan is currently ON.");
        } else {
            System.out.println("The fan is currently OFF.");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // Fan 객체 생성
        Fan myFan = new Fan();
        
        // 메소드 호출 - 선풍기 상태 조작 및 출력
        myFan.turnOn();       // 출력: The fan is now ON.
        myFan.checkStatus();  // 출력: The fan is currently ON.

        myFan.turnOff();      // 출력: The fan is now OFF.
        myFan.checkStatus();  // 출력: The fan is currently OFF.
    }
}


// 메소드 (Method):
// turnOn(): 선풍기를 켜는 메소드.
// turnOff(): 선풍기를 끄는 메소드.
// checkStatus(): 선풍기의 현재 상태를 출력하는 메소드.

// 행위 (Behavior):
// turnOn(), turnOff(), checkStatus() 메소드는 Fan 객체가 수행할 수 있는 동작을 설명한다.
// 이 예제에서는 Fan 객체가 turnOn()과 turnOff() 메소드를 통해 선풍기의 상태를 조절하고, 
// checkStatus() 메소드를 통해 현재 상태를 확인할 수 있습니다.

 

(3) 객체의 선언과 생성

  • Car myCar = new Car();
    • 레퍼런스 변수, 클래스 객체
    • 여기서 myCar는 레퍼런스 변수다. 이 변수는 Car 클래스의 객체를 참조한다. 즉, myCar라는 레퍼런스 변수는 Car 클래스의 인스턴스 객체에 접근할 수 있는 주조를 저장하고 있다.
    • new Car();는 Car 클래스의 새로운 인스턴스를 생성하는 코드이며, 생성된 이 인스턴스가 클래스 객체이다.
    • 종합적으로 Car myCar = new Car();라는 코드는 Car 클래스의 객체를 생성하고, 그 객체의 메모리 주소를 myCar라는 레퍼런스 변수에 저장하는 것이다.
  • 객체의 선언
    • 변수의 데이터 타입으로 클래스를 사용하여, 해당 클래스의 객체를 참조할 수 있는 변수를 선언한다. 즉 데이터 타입을 선언한다는 의미이다. 
    • 클래스명 객체참조변수(변수이름);
    • Car myCar;
  • 객체의 생성
    • 메모리 공간을 생성(할당)하는 과정이다.
    • 객체참조변수(변수이름) = new 클래스명();
    • myCar = new Car();
  • 객체의 선언과 생성
    • 클래스명 객체참조변수(변수이름) = new 클래스명();
    • Car myCar = new Car();

3. 인스턴스 (Instance)

(1) 특징

  • 클래스로부터 만들어진 각각의 객체를 그 클래스의 인스턴스(instance)라고 한다.
  • 인스턴스는 참조 변수를 통해서만 다룰 수 있다.
  • 참조 변수의 타입은 인스턴스의 타입과 일치해야 한다. (반드시 일치해야하는 건 아니다. 아래 예시 참고)
  • 자신을 참조하고 있는 참조 변수가 하나도 없는 인스턴스는 가비지 컬렉터(Garbage Collector)에 의해서 자동으로 메모리에서 제거 된다.
    • 해당 객체가 더 이상 사용되지 않거나 접근할 방법이 없을 때, 자바 가상 머신(JVM)이 자동으로 메모리에서 제거해준다는 것을 의미한다. 이를 **가비지 컬렉션(Garbage Collection)**이라고 한다.
    • 가비지 컬렉터는 더 이상 참조되지 않는 객체를 메모리에서 제거하여 메모리를 효율적으로 관리하는 역할을 한다.
// 참조 변수의 타입은 인스턴스의 타입과 일치해야 한다. (반드시 일치해야하는 건 아니다. 아래 예시 참고)
// chatGPT 예시 참고
class Animal { // class Aniaml 생성
    void makeSound() {
        System.out.println("Some sound");
    }
}

class Dog extends Animal { // Animal 상속받는 Dog Class 생성
    void makeSound() {
        System.out.println("Bark");
    }
}

public class Main {
    public static void main(String[] args) {
        // Animal 타입의 참조 변수 animal
        Animal animal;

        // Dog 타입의 인스턴스를 생성하고, animal 참조 변수에 대입
        animal = new Dog();

        // animal 참조 변수를 사용하여 메서드 호출
        animal.makeSound();  // 출력: "Bark"
    }
}


// 위 소스코드처럼 Animal 타입의 참조 변수 animal을 생성하고
// Dog 타입의 인스턴스를 생성한 뒤 animal 참조 변수에 대입할 수 있다.
// 이러한 경우 Dog Class의 메서드인 makeSound()를 호출할 수 있다.
// 가비지 컬렉션 이해를 돕기 위한 chatGPT 예시

// Sample.java
public class Sample {
    String name;

    Sample(String name) {
        this.name = name;
    }

    void display() {
        System.out.println("Name: " + name);
    }
}

// GarbageCollectionExample.java
public class GarbageCollectionExample {

    public static void main(String[] args) {
        // 1. Sample 객체를 생성하고, 참조 변수 s1에 할당
        Sample s1 = new Sample("Object 1");

        // 2. 참조 변수 s1을 사용하여 객체의 메서드 호출
        s1.display(); // 출력: Name: Object 1

        // 3. s1에 새로운 객체를 할당
        s1 = new Sample("Object 2");

        // 4. 이제 첫 번째 객체는 참조 변수가 없어졌으므로 가비지 컬렉션의 대상이 됨
        s1.display(); // 출력: Name: Object 2

        // 5. 강제로 가비지 컬렉터를 호출하여 가비지 컬션을 시도 (일반적으로 JVM이 자동으로 관리함)
        System.gc();
        
        // 추가 작업: 가비지 컬렉션 이후의 메인 메서드 작업
        System.out.println("Main method continues...");
    }
}

 

(2) 인스턴스 생성

  • Car myCar = new Car; 
    • 클래스명 변수명;  // 클래스의 객체를 참조하기 위한 참조변수를 선언한다.
    • 변수명 = new 클래스명();  // 클래스 객체를 생성 후 객체의 주소를 참조 변수에 저장.
    • Car myCar // Car 클래스 타입의 참조변수 myCar를 선언.
    • myCar = new Car(); // new 키워드를 통해 Car 인스턴스를 생성한 후, 생성된 Car 인스턴스의 주소를 myCar에 저장
    • 클래스명 인스턴스명 = new 클래스명();

4. 패키지 (Package)

(1) 특징

  • 서로 관계가 있는 클래스들의 묶음.
  • 클래스를 조직화하고 관리하기 위한 방법을 제공한다.
  • 클래스, 인터페이스, 서브 패키지 등을 그룹화하여 코드의 구조를 체계적으로 정리하고, 이름 충돌을 방지하며, 접근 제어를 쉽게 설정할 수 있게 도와준다.
  • 물리적으로 클래스 파일을 포함하는 하나의 디렉토리이다.
  • 패키지는 두 가지 주요 범주로 나눌 수 있다.
    • 사용자 정의 클래스: 개발자가 직접 작성한 클래스
    • 라이브러리 클래스: 자바 표준 라이브러리 또는 서드파티 라이브러리에서 제공하는 클래스
  • 하나의 소스 파일에는 첫 번째 문장으로 단 한번의 패키지 선언 만을 허용한다.
  • 모든 클래스는 반드시 하나의 패키지에 속해야 한다.
    • 패키지에 속한 클래스는 해당 디렉토리에 존재하는 class 파일이어야 한다.
    • 동일한 이름의 클래스가 서로 충돌하는 것을 피할 수 있다.

(2) 패키지 선언

  • Pacakge 패키지명;
  • 사용자 정의 패키지를 만들려면 클래스의 첫 부분에 패키지 구문을 포함 시킨다.
    • Package userpackage;
  • (규칙임) 최상위 패키지의 이름은 java로 시작할 수 없다.
    • Java패키지는 표준 API들의 모음을 구성해 놓은 패키지이다.
    • 예시:
      • java.lang: 자바의 기본 클래스들 (예: String, Math, Object 등)이 포함된 패키지
      • java.util: 데이터 구조 및 유틸리티 클래스들 (예: ArrayList, HashMap, Date 등)이 포함된 패키지
      • java.io: 입출력 관련 클래스들 (예: File, InputStream, OutputStream 등)이 포함된 패키지
  • 대분류와 소분류 패키지를 구분할 때는 . 을 사용한다.
    • Java.lang.String
    • 클래스의 이름은 패키지 명을 포함한다.
  • 예약어를 패키지 이름으로 사용할 수 없다.
    • 예약어란 abstract, assert, boolean, break, byte, case, catch, char, class, continue 등등을 말한다.
    • 특정 기능이나 의미를 갖는 단어들로, 패키지, 클래스, 메서드, 변수 등의 이름으로 사용할 수 없다.
  • 패키지를 선언하지 않으면 기본적으로 제공하는 '이름없는 패키지'에 포함된다.
    • 기본 패키지(default package)또는 이름 없는 패키지 (unnamed package) 라고도 말한다.
    • 개발자가 패키지 이름을 지정하지 않을 때 사용된다.

5. 임포트 (Import)

(1) 특징 

  • 다른 패키지의 클래스를 사용하려면 패키지 명이 포함된 클래스 이름을 사용해야 한다.
  • 소스 파일에 사용된 클래스의 패키지에 대한 정보를 컴파일러에게 제공
    • 다른 패키지에 있는 외부 클래스를 사용하고 싶은 경우 import 키워드를 사용하여 해당 클래스의 전체 경로를 지정해줘야 한다.
    • Import문으로 클래스의 패키지를 명시해 주면 소스코드에 사용되는 클래스 이름에서 패키지 명을 생략할 수 있다.
    • 같은 패키지 내의 클래스들은 import문을 지정하지 않고 생략할 수 있다.

(2) Import문 선언

  • package문 다음에 그리고 클래스 선언문 이전에 선언해야 한다.
  • 한 소스 파일에 여러번 선언할 수 있다.
  • import 패키지명.클래스명; // 해당 패키지에서 특정 클래스
  • import 패키지명.*;  // 해당 패키지 전체
  • 클래스 이름 대신 * 를 사용하는 것이 하위 패키지에 적용되지 않는다.
    • import com.example.* // com.example 패키지의 모든 클래스를 포함.
    • import com.example.subpackage 하위 패키지인 com.example.subpacakge 패키지의 클래스는 자동으로 포함되지 않는다.

멤버 필드와 멤버 메서드, 그리고 지역 변수

1. 변수 (Variable, Member)

변수가 선언된 위치에 따라 변수의 종류가 결정된다.

  • 인스턴스 멤버
  • 정적 멤버(static 멤버)
  • 지역 변수

(1) 인스턴스 멤버 (Instance Member)

  • 클래스 영역에서 선언된 멤버들
  • 인스턴스를 생성해야지만 접근하여 사용할 수 있다.
    • 인스턴스 멤버를 참조 또는 호출하기 위해서 인스턴스를 생성해야 한다.
  • 인스턴스가 생성 되었을 때 생성 된다.
  • 인스턴스마다 독립적인 저장 공간을 갖는다.

(2) 정적 멤버(Static Member)

  • static 키워드가 붙어 있는 멤버
  • 모든 인스턴스가 공유하며, 클래스 이름을 통해 직접 접근할 수 있다.
  • 모든 객체를 통틀어서 하나만 생성되고 모든 객체가 이것을 공유하게 된다.
    • 주의! class 내에서 1개만 생성이 된다는 의미는 아니다. 무슨 말이냐면 static int num;이 2개로 존재할 수 없다는 의미이다.
    • static int num; static int num2; 이렇게는 존재가 가능하다.
  • static 멤버 필드(정적 멤버 필드(변수) )
    • 모든 객체에 공통인 필드(변수)이다.
      • 클래스의 모든 객체가 공유하는 필드이다. 즉, 클래스의 어떤 인스턴스에서 이 필드를 수정하면 다른 인스턴스에서도 그 변경 사항이 반영된다.
    • 하나의 클래스에 하나만 존재한다.
    • 클래스 영역에서 선언된다.
      • class Hello { static int num; }  // root 식 대입해서 설명하자면 클래식 바로 하위에 존재한다.
  • static 멤버 메소드(정적 멤버 메소드)
    • static 수식자를 메소드 앞에 붙이며 클래스 이름을 통하여 호출되어야한다.
    • 모든 인스턴스에 공통적으로 사용해야 하는 것에 static을 붙인다.

(3) 지역 변수 (Local Variable )

  • 클래스 영역 이외의 영역
    • 메서드
    • 생성자
    • 초기화 블록 내부
  • 메서드 내부에서 변수의 선언문이 실행되었을 때 생성된다.
  • 메서드, 생성자 또는 블록 내에서 선언된 변수로, 해당 블록 내에서만 유효하다. 블록이 종료되면 메모리에서 사라진다.

2. 메서드 (Method)

(1) 특징

  • 어떤 작업을 수행하기 위한 명령문의 집합
  • 입력을 받아서 처리를 하고 결과를 반환한다.
  • 하나의 메서드는 한 가지 기능만 수행하도록 작성한다.

(2) 메서드 작성 방법

리턴 타입 메서드이름(타입 변수명, 타입 변수명…) {
	//메서드 호출시 수행될 코드
}

int add(int a, int b) {
	int result = a + b;
	return result; // return 데이터 타입은 자동형변환이 가능한 byte, short, char 중 하나
}

void power() {
	power = !power;
}

 

(3) 메서드 호출

  • 1) 인스턴스 메서드 호출: 참조변수.메서드이름();
  • 2) 매개변수가 있는 메서드 호출: 참조변수.메서드이름(값1, 값2, ...);
  • 3) 같은 클래스의 메서드끼리는 참조 변수를 사용하지 않고 호출이 가능하다.
    • this 키워드 사용해서 호출 가능하다. (생략도 가능)
  • 4) static 멤버 메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없다.
    • static 멤버 메서드는 인스턴스 메서드에 직접 접근할 수 없다.
// 1) 인스턴스 메서드 호출: 참조변수.메서드이름();
class Dog {
    void bark() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog(); // 인스턴스 생성
        myDog.bark(); // 메서드 호출
    }
}


// 2) 매개변수가 있는 메서드 호출: 참조변수.메서드이름(값1, 값2, ...);
class Calculator {
    int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        int result = calc.add(5, 3); // 메서드 호출
        System.out.println("Sum: " + result);
    }
}


// 3) 같은 클래스 내에서 호출 가능
class Example {
    void methodA() {
        System.out.println("This is method A.");
        methodB(); // 다른 메서드 호출. this.methodB(); 로 해도 되지만 this 생략가능
    }

    void methodB() {
        System.out.println("This is method B.");
    }

    public static void main(String[] args) {
        Example example = new Example();
        example.methodA(); // methodA 호출
    }
}


// 4) static 멤버 메서드는 인스턴스 멤버 메서드에 직접 접근할 수 없다.
// 인스턴스를 생성해야지만 호출할 수 있다.
class Example {
    void instanceMethod() {
        System.out.println("This is an instance method.");
    }

    static void staticMethod() {
        System.out.println("This is a static method.");
        // instanceMethod(); // 이 줄은 오류가 발생합니다.
    }

    public static void main(String[] args) {
        Example.staticMethod(); // 정적 메서드 호출
        Example example = new Example();
        example.instanceMethod(); // 인스턴스 메서드 호출
    }
}

 


3. 접근 제어자 (Access Modifier)

(1) 캡슐화 (Encapsulation)

  • 외부로부터 데이터를 보호하기 위해 접근을 제한한다.

(2) 정보 은닉 (Information Hiding)

  • 객체를 캡슐로 감싸서 내부를 보호한다.
  • 객체의 실제 구현 내용을 외부에 감춘다.
  • 외부에서 접근할 필요가 없는 멤버는 private으로 지정하여 접근을 차단한다.

(3) 다형성 (Polymorphism)

  • 동일한 이름의 메서드가 다양한 방식으로 동작할 수 있는 능력.
  • 메서드 오버로딩 (Method Overloading)
  • 메서드 오버라이딩 (Method Overriding)

(4) 접근 제어자의 종류

  • private: 같은 클래스 내에서만 접근 가능.
  • default: 같은 패키지 내에서만 접근 가능.
  • protected: 같은 패키지 및 다른 패키지의 자손 클래스에서 접근 가능.
  • public: 접근 제한이 없음.

(5) 사용 가능한 접근 제어자

  • 클래스: public, default
  • 메서드/멤버 변수: public, protected, default, private
  • 지역 변수: 접근 제어자를 사용하지 않음.

(6) Setter

  • 멤버 변수의 값을 설정하는 메서드.
  • 일반적으로 setAge(int age) 형태로 정의.
  • 매개변수명은 멤버 필드명과 동일하게 하거나 앞에 _를 붙이기도 한다.
// 형식
void set멤버필드명(매개변수) {
    // 코드 정의
}

 

(7) Getter

  • 멤버 필드의 값을 반환하는 메서드.
// 형식
반환자료형 get멤버필드명() {
    // 코드 정의
    return 멤버필드명;
}

 

(8) 기본형 & 참조형 매개 변수

  • 메서드를 호출할 때 매개변수로 지정한 값을 복사해서 전달한다.
  • 메소드로 기본형 변수가 전달되는 경우
    • 기본형 값이 복사 된다.
    • 변수의 값을 읽기만 할 수 있다.
  • 메소드로 객체가 전달되는 경우
    • 객체가 복사되어 전달되는 것이 아니고 참조 변수의 값이 복사되어서 전달된다.
    • 변수의 값을 읽고 변경할 수 있다.
    • 인수와 매개변수 모두 동일한 객체를 가리킨다.
  • 메소드로 배열이 전달되는 경우
    • 배열도 객체이기 때문에 배열을 전달하는 것은 배열 참조 변수를 복사하는 것이다.

(9) 메서드 오버로딩 (Method Overloading)

  • 한 클래스 내에 같은 이름의 메서드를 여러 개 정의할 수 있다.
  • 메서드 타입을 구분하기 위해서 메서드명과 매개변수의 정보를 상요한다.
  • 오버로딩 성립 조건:
    • 메서드 이름이 동일해야 한다.
    • 매개변수의 개수 또는 타입이 달라야 한다.
    • 리턴 타입은 함수 타입 구분 정보가 포함되지 않는다.
// 잘못된 메서드 오버로딩 예
int add(int a, int b) {
    return a + b;
}
int add(int x, int y) {
    return x + y;
}

int add(int a, int b) {
    return a + b;
}
long add(int a, int b) {
    return (long)(a + b);
}


// 올바른 메서드 오버로딩 예
int add(int a, long b) {
    return a + b;
}
long add(long a, int b) {
    return a + b;
}

 


생성자 (Constructor)

1. 생성자 정의

  • 객체가 생성될 때 필드에 초기값을 제공하고 초기화 절차를 실행하는 메소드.
  • 클래스 내에서 선언되며, 리턴 값이 없지만 void 키워드를 사용하지 않고 생략한다.
  • 하나의 클래스에 여러 개의 생성자를 정의할 수 있다.
  • 인스턴스 초기화 메서드로도 불린다.

2. 생성자의 조건

  • 생성자의 이름은 클래스의 이름과 같아야 한다.
  • 생성자는 리턴 값이 없다.

3. 생성자 정의 형

클래스이름(타입 변수명, 타입 변수명, ...) {
	// 초기화코드
}

class Test {
	Test() {	//기본 생성자함수
	}
	
	Test(String str, int num) { //매개변수가 있는 생성자함수
		// 수행코드
	}
}
Test tst = new Test();

// 1. 연산자 new에 의해서 메모리에 Test클래스의 인스턴스가 생성된다.
// 2. 생성자 Test()가 호출되어 수행한다.
// 3. Test인스턴스의 주소가 반환되어 참조 변수 tst에 저장된다.

 

4. 기본 생성자

  • 모든 클래스는 반드시 하나 이상의 생성자가 정의되어 있어야 한다.
  • 기본 생성자는 컴파일러에 의해 자동 생성된다.
    • 소스 파일의 클래스에 생성자가 하나도 정의되지 않은 경우 자동으로 추가한다.
    • 클래스의 접근 제어자가 public인 경우, 기본 생성자도 “public 클래스 이름() {}” 형식으로 추가된다.

5. 매개변수가 있는 생성자

  • 생성자는 매개변수를 사용하여 호출 시 값을 받아 인스턴스 초기화 작업에 사용할 수 있다.
public class Test00 {
	public static void main(String[] args) {
		Data1 d1 = new Data1();
		Data2 d2 = new Data2(100);
	}
}

 

6. this 포인터

  • 메소드나 생성자에서 this는 현재 객체를 나타낸다.
    • 인스턴스 자신을 가리키는 참조 변수이다.
    • 인스턴스 멤버에 대해서만 사용할 수 있다.
    • 모든 인스턴스에 지역 변수로 숨겨진 채로 존재한다.
  • this() 사용
    • 같은 클래스의 다른 생성자를 호출할 때 사용한다.
    • 생성자 간의 호출에서 생성자의 이름 대신 this를 사용한다.

7. 생성자 호출 조건

  • 생성자의 이름 대신 this를 사용하여 호출한다.
  • 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.

8. 생성자 오버로딩

  • 메소드처럼 생성자도 오버로딩이 가능하다.

초기화 (Initialization)

1. 멤버 필드와 배열의 초기화

  • 멤버 필드와 배열은 선택적으로 초기화 가능.
  • 초기화를 하지 않아도 자료형에 맞는 기본값으로 자동 초기화됨.

2. 지역 변수

  • 지역 변수는 사용하기 전에 반드시 초기화해야 함.
class InitTest {
	int x;
	int y = x;
	
	void method1() {
		int i;
		int j = i; //컴파일러 에러
	}
}

// 1. int x; 는 인스턴스 멤버 필드이므로 자동으로 초기화 값이 들어간다.
// 2. void method1() {} 안에 만들어진 int i;는 지역 변수로 초기화 값이 없으면 안된다. 그렇기 때문에 이 실행문은 에러가 난다.

 

3. 기본값

자료형 기본값
boolean false
char ‘\u0000’
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d 또는 0.0
참조형 변수 null

4. 초기화 방법

  • 명시적 초기화: 변수를 선언할 때 값을 직접 지정.
  • 초기화 블록: 인스턴스나 정적 필드를 초기화하기 위한 블록.
  • 생성자: 객체 생성 시 필드 초기화.

5. 인스턴스 초기화 블록

  • 인스턴스 멤버 필드를 초기화하는 데 사용.
  • 인스턴스 멤버 필드의 복잡한 초기화에 사용된다.
  • 인스턴스 생성 시마다 수행됨.
public class InstanceInitBlockExample {
    private int x;
    
    // 인스턴스 초기화 블록
    {
        x = 10; // 인스턴스 생성 시 x를 10으로 초기화
        System.out.println("Instance initialization block executed");
    }
    
    // 생성자
    public InstanceInitBlockExample() {
        System.out.println("Constructor executed");
    }
    
    public static void main(String[] args) {
        InstanceInitBlockExample obj = new InstanceInitBlockExample();
        System.out.println("Value of x: " + obj.x);
    }
}


//출력
Instance initialization block executed
Constructor executed
Value of x: 10


// 1. { } 인스턴스 초기화 블록은 인스턴스가 생성될 때마다 실행되기 때문에 
//    x = 10; 으로 초기화가 먼저 실행되고 
//    그 다음 Instance initialization block executed 가 처음에 출력됨.
// 2. main 메서드에서 InstanceInitBlockExample클래스의 인스턴스를 
//    생성했기 때문에 Constructor executed 가 한번 출력 됨.
// 3. 인스턴스 obj를 생성한 다음 obj.x 호출하면 맨 처음에 
//    인스턴스 초기화 블록에서 int x의 값을 10으로 초기화 시켰기 때문에 10이 출력됨.

 

6. 정적 초기화 블록 (static 초기화 블록)

  • 클래스 변수를 초기화하는 데 사용.
  • 인스턴스 초기화 블록 앞에 static을 붙인다.
  • 클래스가 메모리에 처음 로딩될 때 한 번만 수행됨.
// 예시
public class StaticInitBlockExample {
    private static int count;
    
    // 정적 초기화 블록
    static {
        count = 5; // 클래스 로딩 시 count를 5로 초기화
        System.out.println("Static initialization block executed");
    }
    
    // 정적 메소드
    public static void printCount() {
        System.out.println("Value of count: " + count);
    }
    
    public static void main(String[] args) {
        StaticInitBlockExample.printCount();
    }
}


// 출력
Static initialization block executed
Value of count: 5

// 1. 정적 초기화 블록은 클래스가 처음 로드될때 한번만 실행되기에 
//    우선 정적 초기화 블록에서 count의 값이 5로 초기화 됨.
// 2. 그 다음에 Static initialization block executed 이 출력됨
// 3. main 메서드에서 printCount() 메서드 호출해서 Value of count: 5 가 출력됨.

 

7. 문법 예시

class InitBlock {
    static { // 정적 초기화 블록
        // 실행문
    }
    
    { // 인스턴스 초기화 블록
        // 실행문
    }
}

 

8. 요약

  • 인스턴스 초기화 블록: 객체가 생성될 때마다 실행되며, 생성자와 함께 인스턴스 필드의 초기화를 수행할 수 있다.
  • 정적 초기화 블록: 클래스가 로드될 때 한 번만 실행되며, 정적 필드의 초기화 작업을 수행할 수 있다.

9. 멤버 필드의 초기화 시기와 순서

  • 정적(static) 멤버 필드의 초기화:
    • 클래스가 처음 로딩될 때 단 한번 초기화 된다.
    • 프로그램 실행 도중 클래스에 대한 정보가 요구 되어질 때 클래스는 메모리에 로딩된다.
    • 클래스 로딩 시점에 초기화가 이루어지며, 이는 프로그램이 실행되는 동안 클래스가 처음 사용될 때 발생합니다.
    • 초기화 순서:
      1. 기본값 초기화: 정적 필드는 기본값으로 초기화됩니다.
      2. 명시적 초기화: 클래스 선언에서 정적 필드를 명시적으로 초기화합니다. (클래스 안에서 필드를 선언하면서 직접 값을 할당하는 것을 의미)
      3. 정적 초기화 블록 실행: 클래스가 로딩될 때 정적 초기화 블록이 실행됩니다.
  • 인스턴스 멤버 필드의 초기화:
    • 객체 생성 시 초기화됨.
    • 초기화 순서:
      1. 기본값 초기화
      2. 명시적 초기화
      3. 인스턴스 초기화 블록 실행
  • chat gpt의 의견
    • 클래스 멤버 필드의 초기화 순서
      • 기본값 (Default Values): 클래스 로딩 시 정적 필드와 인스턴스 필드는 기본값으로 초기화됩니다.
      • 정적 필드의 명시적 초기화 (Explicit Static Field Initialization): 정적 필드는 선언 시 명시적으로 초기화됩니다.
      • 정적 초기화 블록 (Static Initialization Block): 클래스 로딩 시 정적 초기화 블록이 실행됩니다.
      • 인스턴스 필드의 명시적 초기화 (Explicit Instance Field Initialization): 인스턴스 필드는 선언 시 명시적으로 초기화됩니다.
      • 인스턴스 초기화 블록 (Instance Initialization Block): 각 인스턴스 생성 시 인스턴스 초기화 블록이 실행됩니다.
    • 클래스 멤버 필드의 초기화 순서에 대해서 실행문을 어떤 순서로 작성했느냐에 따라서 이뤄지는 것이 아니냐는 질문을 하니 아니라는 답변을 해줬다.
      • 클래스 멤버 필드의 초기화 순서는 코드의 작성 순서에 의존하지 않습니다. Java에서의 초기화 순서는 다음과 같은 규칙에 따라 결정됩니다.
      • 작성 순서와 관계없이, 정적 멤버는 클래스가 로드될 때, 인스턴스 멤버는 객체가 생성될 때 초기화됩니다.

 

 

 

'Java > 보충수업' 카테고리의 다른 글

[2024-09-12] 자바 보충수업 1일차  (0) 2024.09.12