클래스 선언
- 클래스명 작성 규칙
① 하나 이상의 문자로 구성
② 첫 글자에는 숫자가 올 수 없음
③ '$', '_'외의 특수문자 사용 불가
④ 자바 키워드 사용 불가
- 보통 하나의 소스파일에 하나의 클래스만을 정의하지만, 둘 이상의 클래스를 정의하는 것도 가능
단, 소스파일의 이름(.java)은 반드시 public class의 이름과 일치해야 함
( 소스파일 내에 public class가 없는 경우, 소스 파일의 이름은 어떤 클래스 이름을 사용해도 무관 )
- 클래스 이름을 고쳐야 될 때
① Package Explorer 뷰의 파일 클릭 → 마우스 오른쪽 클릭
② Refactor → Rename : 새로운 이름 설정
③ next 눌러서 확인 → Finish
객체 생성과 클래스 변수
- 클래스 선언은 설계도를 작성한 것일 뿐, 클래스로부터 객체를 생성해야 사용할 수 있음
▶ new 연산자 + 생성자
- new
① 객체를 생성시키는 연산자
② new 연산자로 생성된 객체는 Heap 영역에 생성시킨 후, 객체의 번지를 리턴 → 참조변수에 저장
∴ 참조변수에 저장된 객체의 주소를 이용해 객체 사용 가능
- 생성자
① new 연산자에 의해 호출 → 객체 생성 시 초기화 담당
② 쿨래스 이름과 동일
③ 리턴 타입 없음
① 클래스의 객체를 참조하기 위한 참조변수 선언 클래스명 변수명 ;
② 클래스의 객체 생성 후, 객체의 주소를 참조변수에 저장 변수명 = new 클래스명();
→ 클래스명 변수명 = new 클래스명();
⇒ 정리해보자면,
new 연산자에 의해 객체가 생성되고, 객체가 생성될 때마다 생성자가 호출된다.
호출된 생성자에 의해 인스턴스 초기화가 되고, 참조변수에는 객체의 주소가 저장됨
→ s1과 s2가 참조하는 Student 객체는 완전히 독립된 서로 다른 객체
▷ Student / StudentApp의 클래스 용도
① 라이브러이용 클래스 : class Student
: 다른 클래스에서 이용할 목적으로 설계
② 실행 클래스 : class StudentApp
: 프로그램의 실행 진입점인 main() 메소드를 제공하는 역할
→ 물론 하나의 클래스 내에 라이브러리 클래스와 실행 클래스를 동시에 생성 가능하지만,
대부분의 객체 지향 프로그램은 라이브러리 클래스와 실행 클래스를 분리시킴
클래스의 구성 멤버
public class ClassName {
① 필드 ( Field )
int fieldname;
② 생성자 ( Constructor )
ClassName();
③ 메소드 ( Method )
void methodName() { … }
}
① 필드 ( Field )
- 객체의 데이터가 저장되는 곳
- 필드 vs 변수
· 변수 : 생성자와 메소드 내에서만 사용 → 생성자와 메소드가 종료 시 자동 소멸됨 ( 변수의 scope )
· 필드 : 생성자와 메소드 전체에서 사용 / 객체가 소멸되지 않은 한 객체와 함께 존재
② 생성자 ( Constructor )
- 객체가 생성될 때마다 new 연산자에 의해 호출 → 객체의 초기화 담당
- 클래스 이름과 동일하고, 리턴타입 없음
③ 메소드 ( Method )
- 객체의 동작에 해당
- 메소드 호출 시, 메소드의 중괄호 블록 내 모든 코드들이 일괄적으로 실행
→ 객체 간의 데이터 전달하는 수단 : 외부로부터 매개값을 받아 실행에 이용한 후, 결과값을 호출한 메서드로 다시 리턴함
필드
- 필드 : 객체의 데이터가 저장되는 곳
→ 객체의 고유 데이터, 객체가 가져야 할 부품, 객체의 현재 상태 데이터를 저장
즉, 클래스 설계 시, 이 정보들은 필드에 선언되어야 함
▶ 필드 선언
- 클래스 중괄호 { } 블록 어디서든 선언 가능
단, 생성자와 메소드 중괄호 { } 블록 내부에 선언 시, 모두 로컬 변수가 됨
타입 필드 = 초기값 ;
- 타입 : 필드에 저장할 데이터의 종류
① 기본 타입 : byte, short, int, long, float, double, char, boolean
② 참조 타입 : 배열, 열거, 인터페이스
- 초기값 : 필드 선언 시 주어질 수도 있고 생략될 수도 있음
→ 초기값이 지정되지 않은 필드는 객체 생성 시 자동으로 기본 초기값으로 설정됨
분류 | 타입 | 초기값 | |
기본 타입 | 정수 타입 | byte char short int long |
0 \u0000(빈 공백) 0 0 0L |
실수 타입 | float double |
0.0F 0.0 |
|
논리 타입 | boolean | false | |
참조 타입 | 배열 클래스(String 포함) 인터페이스 |
null null null |
※ null : 객체를 참조하고 있지 않은 상태를 의미
▶ 필드 사용
: 필드값을 읽고 변경하는 작업을 의미
① 클래스 내부의 생성자나 메소드에서 사용할 경우
→ 필드 이름으로 읽고 변경
② 클래스 외부에서 사용할 경우
→ 객체 생성한 뒤, 필드 사용
생성자
- 생성자 ( Constructor ) : 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드
· 인스턴스 변수의 초기화 담당
· 인스턴스 생성 시에 실행되어야 하는 작업을 위해 사용
- 생성자의 조건
① 생성자의 이름은 클래스 이름과 동일
② 리턴값이 없음
③ 모든 클래스는 반드시 하나 이상의 생성자를 가져야 함
→ 지금까지 클래스에 생성자를 만들지 않고 객체를 생성할 수 있었던 이유
: 클래스 내에 생성자가 하나도 없을 경우, 컴파일러가 자동적으로 기본 생성자를 추가해주기 때문
※ 기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스 내에 정의된 생성자가 하나도 없을 때만 해당
데이터 클래스 | 실행 클래스 |
class Data1 { int value; } // Data1 클래스에 정의된 생성자가 하나도 없으므로, 컴파일러에 의해 자동적으로 기본 생성자가 추가됨 class Data2 { int value; Data2 ( int x ) { value = x; } } // Data2에는 기본생성자가 정의되어 있지 않음 |
class DataApp { public static void main( String [] args ) { Data1 d1 = new Data1(); Data2 d2 = new Data2(); // 컴파일 에러 : The constructor Data2 () is undefined } } → 에러 해결 방안 1. Data2에 기본 생성자 추가 2. Data2( int x ) 생성자 사용 |
- 생성자 또한 오버로딩 가능 → 하나의 클래스에 여러 개의 생성자 존재
· 생성자 오버로딩 : 매개변수를 달리하는 생성자를 여러 개 선언하여 다양한 객체 생성 가능
→ 매개변수의 타입, 개수, 순서를 다르게 선언
· new 연산자로 생성자를 호출할 때, 제공되는 매개값의 타입과 수에 의해 호출될 생성자 결정
데이터 클래스 | 실행 클래스 |
public class Car { // 필드 선언 String company = "현대자동차"; String model ; String color ; // ①기본생성자 Car ( ) { } // ② 매개변수 1개인 생성자 Car ( String model ) { this.model = model; } // ③ 매개변수 2개인 생성자 Car ( String model, String color ) { this.model = model; this.color = color; } } |
public class CarEx { public static void main( String [] args ) { Car car1 = new Car(); // ①기본생성자 선택 System.out.println("car1.company = " + car1.company ); Car car2 = new Car("그랜저"); // ② 매개변수 1개인 생성자 선택 System.out.println("car2.company = " + car2.company ); System.out.println("car2.model = " + car2.model ); Car car3 = new Car("그랜저", "블랙"); // ③ 매개변수 2개인 생성자 선택 System.out.println("car3.company = " + car3.company ); System.out.println("car3.model = " + car3.model ); System.out.println("car3.color = " + car3.color); } } |
- 필드 초기화 방법 ❶ 필드 선언 시 초기값 설정 → Car 클래스에 의해 설계된 객체의 company 필드에는 모두 "현대자동차"가 저장됨 ❷ 생성자에서 초기값 설정 → 객체 생성 시점에 매개값을 통해 다양한 값 설정 가능 |
|
출력 결과 ) car1.company = 현대자동차 car2.company = 현대자동차 car2.model = 그랜저 car3.company = 현대자동차 car3.model = 그랜저 car3.color = 블랙 |
▶ 생성자 호출
❶ 기본 생성자 호출
데이터 클래스 | 실행 클래스 |
class Car { // 필드 선언 String model ; String color ; int maxSpeed ; Car () { } // 기본 생성자 - 생략되어도 현재 이 클래스에는 생성자가 없으므 로 자동적으로 추가해줌 } |
public static void main( String [] args ) { Car myCar = new Car(); ① 객체 생성 후 myCar.model = "현대자동차"; ② 객체 초기화 myCar.color = "검정"; myCar.maxSpeed = 300; } |
❷ 매개변수가 있는 생성자 호출
데이터 클래스 | 실행 클래스 |
class Car { // 필드 선언 String model ; String color ; int maxSpeed ; Car ( String m, String c, int s ){ model = m; color = c; maxSpeed = s; } } |
public static void main( String [] args ) { Car myCar = new Car( "현대자동차", "검정", 300 ); // 객체 생성과 동시에 객체 초기화 } |
∴ 실행 클래스에서 기본생성자로 호출하는 방법과 매개변수가 있는 생성자 호출하는 방법을 비교했을 때, 후자가 더 간결한 것을 알 수 있다.
매개변수 있는 생성자의 경우, 1번만 선언해놓으면 실행클래스에서 작성할 코드가 더 간결해지고 데이터 파악이 더 쉬워진다.
▶ 객체 자신을 가리키는 참조변수 : this
- this를 이용해 인스턴스 변수에 접근 가능 / 객체의 주소가 저장되어 있음
- 생성자를 포함한 모든 인스턴스 메소드에는 자신이 관련된 인스턴스를 가리키는 참조변수 this가 지역변수로 숨겨진 채 존재함
( 선언 없이 사용 가능 )
Car ( String model, String color, int maxSpeed ) { model = model; color = color; maxSpeed = maxSpeed; } 생성자의 매개변수로 선언된 변수의 이름과 인스턴스 변수의 이름이 같을 경우, 서로 구별이 안됨 |
→ | Car ( String model, String color, int maxSpeed ) { this.model = model; this.color = color; this.maxSpeed = maxSpeed; } ∴ 인스턴스 변수 앞에 this를 붙여 지역변수와 구별하기 |
▶ 생성자에서 다른 생성자 호출 : this( )
① 생성자 이름으로 클래스 이름 대신 this( ) 사용
② 한 생성자에서 다른 생성자 호출 시, 반드시 첫 줄에서만 호출 가능
Car ( String model ) {
color = "파랑";
Car( model, "빨강", 200 ) ;
}
❶ 첫 줄에서만 호출 가능
∵ 생성자 내에서 초기화 작업 중 다른 생성자를 호출하게 되면, 호출 이전의 초기화 작업이 무의미
❷ 클래스 이름 대신 this 사용
- 다른 생성자 호출해서 중복 코드 줄이기
public class Car { String company = "현대자동차"; String model; String color; int maxSpeed; Car ( String model ) { this.model = model; this.color = "은색"; this.maxSpeed = 250; } Car ( String model, String color ) { this.model = model; this.color = color; this.maxSpeed = 250; } Car ( String model, String color, int maxSpeed ) { this.model = model; this.color = color; this.maxSpeed = maxSpeed; } } |
public class Car { String company = "현대자동차"; String model; String color; int maxSpeed; Car ( ) { } // 매개변수 3개인 생성자 호출 Car ( String model ) { this( model, "은색", 250 ); } // 매개변수 3개인 생성자 호출 Car ( String model, String color ) { this( model, color, 250 ); } Car ( String model, String color, int maxSpeed ) { // 공통 실행 코드를 한번만 작성 this.model = model; this.color = color; this.maxSpeed = maxSpeed; } } |
왼쪽 코드의 3개의 생성자의 내용이 비슷하므로, this( )를 이용해 마지막 생성자를 호출 → 공통 실행 코드를 한번만 작성하기 때문에 중복 코드 최소화 가능 |
'백엔드 > JAVA' 카테고리의 다른 글
접근제어자 및 객체 지향 프로그래밍 (2) (0) | 2023.05.08 |
---|---|
콘솔창에 메뉴 만들기 예제 실습 및 이론 (0) | 2023.05.04 |
가위, 바위, 보 게임 구현하기 예제 실습 (0) | 2023.05.02 |
기본 계산기 만들기 예제 실습 (0) | 2023.05.01 |
1주차 ( ch3~ ch4 ) 이론 추가 (0) | 2023.04.29 |