* 수업 내용 외에 추가로 관련 자료를 찾아서 덧붙임
반복 제어문
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) 멤버 필드의 초기화:
- 클래스가 처음 로딩될 때 단 한번 초기화 된다.
- 프로그램 실행 도중 클래스에 대한 정보가 요구 되어질 때 클래스는 메모리에 로딩된다.
- 클래스 로딩 시점에 초기화가 이루어지며, 이는 프로그램이 실행되는 동안 클래스가 처음 사용될 때 발생합니다.
- 초기화 순서:
- 기본값 초기화: 정적 필드는 기본값으로 초기화됩니다.
- 명시적 초기화: 클래스 선언에서 정적 필드를 명시적으로 초기화합니다. (클래스 안에서 필드를 선언하면서 직접 값을 할당하는 것을 의미)
- 정적 초기화 블록 실행: 클래스가 로딩될 때 정적 초기화 블록이 실행됩니다.
- 인스턴스 멤버 필드의 초기화:
- 객체 생성 시 초기화됨.
- 초기화 순서:
- 기본값 초기화
- 명시적 초기화
- 인스턴스 초기화 블록 실행
- 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 |
---|