Java/Java 개념 정리

[이것이 자바다] 06 클래스 - 1

안정민 2023. 4. 7. 09:31

1. 클래스의 두 가지 용도

-라이브러리 클래스)  실행할 수 없으며 다른 클래스에서 이용하는 클래스

-실행클래스) main()메소드를 가지고 있는 실행 가능한 클래스

-Student 클래스는 라이브러리 클래스, StudentExample클래스는 실행 클래스

-일반적으로 자바 프로그램은 하나의 실행 클래스와 여러 개의 라이브러리로 구성, 실행 클래스는 실행하면서 라이브러리 클래스를 내부에서 이용한다.

 

 

2. 필드와 로컬변수의 차이점 

*** 이 부분은 교수님 수업 시간에 확실하게 이해가 된 부분이지만 그래도 정리하면서 복습하자

- 로컬 변수는 생성자와 메소드 블록에서 선언되며 생성자와 메소드 호출 시에만 생성되고 사용된다

-필드는 클래스 블록에서 선언되며, 객체 내부에서 존재하고 객체 내외부에서 사용 가능하다.

구분 필드 로컬변수
선언 위치 클래스 선언 블록 생성자, 메소드 선언 블록
존재 위치 객체 내부에 존재 생성자, 메소드 호출 시에만 존재
사용 위치 객체 내외부 어디서든 사용 가능 생성자, 메소드 블록 내부에서만 사용

*** 필드의 타입은 참조타입도 가능(배열, 클래스, 인터페이스)

 

 

3. 생성자 선언과 호출

*** 스터디 하면서 제일 이해가 어려웠던 부분이지만 다시 보니까 한 번에 이해됐음! 까먹지 말고 더 필요한 개념들이 있으면 확실하게 채우자

*** 생성자의 영어 명칭은 "constructor" , 솦프가 영어 강의여서 시험도 영어로 출제될 거고 앞으로를 위해서 알아두기

 

-new 연산자는 객체를 생성한 후 연이어 생성자를 호출하여 객체를 초기화하는 역할을 함, 객체 초기화란 필드 초기화를 하거나 메소드를 호출하여 객체를 사용할 준비를 하는 것을 의미.

-생성자가 성공적으로 실행이 끝나면 new 연산자는 객체의 주소를 리턴, 리턴된 주소는 클래스 변수에 대입되어 객체의 필드나 메소드 접근 시 이용한다.

- 생성자가 메소드와 다른 점은 리턴 타입에 대한 선언이 없다는 점인데, 항상 객체의 주소를 리턴타입으로 가지기 때문에 관용적인 부분에 있어 생략함.

-모든 클래스는 생성자가 존재하며 하나 이상을 가질 수 있음, 클래스에 생성자 선언이 없다면 컴파일러는 다음과 같은 기본 생성자를 바이트코드 파일에 자동으로 추가시킨다.

public class_name(){};

-객체를 다양하게 초기화하기 위해서 개발자는 생성자를 직접 선언할 수 있음

-생성자는 메소드와 비슷한 모양을 가지고 있으나 리턴 타입이 없고 클래스 이름과 동일하다.

-클래스에 개발자가 선언한 생성자가 있다면 컴파일러는 기본 생성자를 추가하지 않음, 기본 생성자를 사용하기 위해서 추가적으로 개발자가 직접 기본 생성자를 추가해주어야 함.

public class Car{
	Car(String model, String color, int maxSpeed){
    	...}
} // 생성자 선언
public class CarExample{
	public static void main(String[] args){
    	Car myCar = new Car("그랜저", "검정", 250);
    }
} //기본 생성자 호출 시 에러

- 생성자를 이용한 초기화를 할 때, 매개변수의 이름이 너무 짧으면 코드의 가독성이 좋지 않기 때문에 가능하면 초기화 시킬 필드 명과 동일한 이름을 사용하는 것이 좋음

- 위와 같은 경우에는 매개변수명이 필드 명과 동일하기 때문에 필드임을 구분하기 위해 this 키워드를 필드명 앞에 붙여줌, this는 현재의 객체를 이야기하며, this.name은 현재 객체 데이터(필드)로서의 name을 뜻한다.

public class Korean{
	String nation="대한민국";
    String name;
    String ssn;
    public Korean(String name, String ssn){
		this.name=name;
    	this.ssn=ssn;
	}
}

-객체마다 동일한 값을 가진다면 필드 선언시 초기화를 해 주는 것 좋고, 객체마다 다른 값을 가진다면 생성자에서 필드를 초기화하는 것이 좋다.

 

-매개값으로 객체의 필드를 다양하게 초기화하기 위해서는 생성자 오버로딩 (Overloading)이 필요, 생성자 오버로딩이란 매개변수를 달리하는 생성자를 여러 개 선언하는 것을 이야기한다.

-매개변수의 타입과 개수, 그리고 선언된 순서가 동일하고 매개변수의 이름만 바꾸는 것은 생성자 오버로딩이 아니다.

Car(String model, String color){...}
Car(String color, String company){...} // 오버로딩이 아님, 컴파일 에러 발생

-생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생 가능, 생성자 내부의 코드 중복은 코드를 가독성이 떨어지게 함.

-이 경우 공통 코드를 한 생성자에만 집중적으로 작성하고, 나머지 생성자는 this(...)를 사용하여 공통 코드를 가지고 있는 생성자를 호출하는 방법으로 개선이 가능하다.

Car(String model){
	this(model, "은색", 250);
}

Car(String model, String color){
	this(model, "은색", 250);
}

Car(String model, String color, int maxSpeed){
	this.model=model;
    this.color=color;
    this.maxSpeed=maxSpeed; // 공통 초기화코드 위에 호출
}

-this(매개값)는 생성자의 첫줄에 작성이 되며, 다른 생성자를 호출하는 역할을 함, 호출하고 싶은 생성자의 매개변수에 맞게 매개값을 제공하면 된다.

 

 

4. 가변길이 매개변수 (varargs)

-메소드를 호출할 때에는 매개변수의 개수에 맞게 매개 값을 제공해야 함, 만약 메소드가 가변길이 매개변수를 가지고 있다면 매개변수의 개수와 상관 없이 매개값을 줄 수 있다.

-가변길이 매개변수는 선언에 있어 ... 키워드를 사용하며 메소드 호출 시 매개값을 쉼표로 구분하여 개수와 상관 없이 제공할 수 있음, 이는 내부적으로 배열을 생성하여 이들을 저장하는 것이기 때문에 남발하지는 말아야 함.

int sum(int...values){}
int result=sum(1,2,3);
int result2=sum(1,2,3,4,5);

-다시 한 번 이야기하면, 매개값들은 자동으로 배열 항목으로 변환되어 메소드에서 사용, 그렇기 때문에 메소드 호출 시 직접 배열을 매개값으로 제공해도 된다.

int[] values={1,2,3}
int result=sum(values); //이렇게 해도 되고
int result=sum(ner int[] {1,2,3}); // 이렇게 해도 된다