장점
1. 코드의 재사용성이 높다.
2. 코드의 관리가 용이하다.
3. 신뢰성이 높은 프로그래밍을 가능하게 한다.
객체지향개념을 학습할 때 재사용성과 유지보수, 그리고 중복된 코드의 제거, 이 세 가지 관점에서 보면 보다 쉽게 이해할 수 있다.
클래스의 정의 : 객체를 정의해 놓은 것
클래스의 용도 : 객체를 생성하는데 사용
객체의 정의 : 실제로 존재하는 것 (사물 or 개념)
객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름
클래스는 객체를 만들기 위한 설계도라고 생각하면 된다.
객체는 속성(property)과 기능(function)의 집합이라고 볼 수 있기 때문에
클래스에는 객체가 가지고 있는 속성(variable)과 기능(method)이 정의되어 있다.
class Soldier {
//variable > 멤버변수
int ph;
int attack;
//method > 메서드
void goTo (){...};
void power (){...};
]
하나의 소스파일에 하나의 클래스만을 정의하는 것이 보통이지만, 하나의 소스파일에 둘 이상의 클래스를 정의하는 것도 가능하다.
이때, 소스파일의 이름은 public class의 이름과 일치해야 한다.
즉, 하나의 소스 파일에 둘 이상의 public class는 존재할 수 없다.
클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 부른다.
그리고 어떤 클래스로 부터 만들어진 객체를 인스턴스라고 부른다.
클래스명 변수명; // 참조변수 선언
변수명 = new 클래스명(); // 객체 생성
위와 같이 만들어진 변수는 참조 변수로, 인스턴스가 저장되어 있는 주소를 저장하는 공간이 된다.
인스턴스는 참조 변수를 통해서만 다룰 수 있으며, 참조 변수의 타입은 인스턴스의 타입과 일치해야한다.
class Variables{
int iv; // 인스턴스 변수
static int cv; // 클래스 변수
void method(){
int lv = 0; // 지역변수
}
}
//기본 틀 >> 반환값이 없는 경우 반환 타입에 void
반환타입 method이름 (매개변수){};
//ex)
int add(intx, int y){return x+y}
call stack
호출 스택은 메서드의 작업에 필요한 메모리 공간을 제공한다.
메서드가 호출되면 호출스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수와 연산의 중간 결과를 저장한다.
메서드가 작업을 마치면 할당되었던 메모리 공간은 비워진다.
- 호출 스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.
- 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.
반환타입이 있는 메서드는 종료되면서 결과값을 자신을 호출한 메서드(caller)에게 반환한다. 대기 상태에 있던 caller는 넘겨받은 반환값으로 수행을 계속 진행한다.
자바에서는 메서드를 호출할 때 매개변수로 지정한 값을 복사해서 메서드의 매개변수로 옮겨준다. 이때 기본형 매개변수는 그 값을 복사하고, 참조형 매개변수는 주소값을 복사해서 넘겨주기 때문에 다음과 같은 특징이 나타난다.
→ 기본형 매개변수는 값을 읽기만 할 수 있고, 참조형 변수는 값을 읽고 변경할 수 있다.
public class Main {
public static void main(String[] args) {
Test t = new Test();
t.x = 5;
changeX(t.x);
System.out.println("changeX : "+t.x); //changeX : 5
changeX2(t);
System.out.println("changeX2 : "+t.x);//changeX2 : 10
}
//기본형 매개변수
static void changeX (int x){
x = 10;
}
//참조형 매개변수
static void changeX2 (Test t){
t.x = 10;
}
}
→ 즉, 기본형은 복사본이 변경되었기 때문에 원본은 그대로 5로 출력되고,
참조형은 주소값이 복사되어 원본이 변경되었기 때문에 10으로 출력된다.
class Test {
int a,b;
//인스턴스 메서드
int add(){return a+b;}
//static 메서드
static int add(int a, int b){return a+b;}
}
인스턴스 메서드는 인스턴스 변수 a,b를 이용하여 작업하기 때문에 매개변수가 필요없다.
static 메서드는 인스턴스 변수와 상관없기 때문에 작업할 매개변수를 지정해줘야한다.
자바에서는 한 클래스 내에 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메서드를 정의할 수 있다.
→ 즉, 함수 이름은 같은데 매개변수가 달라지면서 기능을 다르게 가져가는 것이다.
오버로딩 조건
1. 메서드 이름이 같아야한다.
2. 매개변수의 개수 또는 타입이 달라야한다.
3. 반환값, 접근 제어자만 다른 것은 아무런 영향을 주지 못한다.
🔺 오버로딩된 메서드들은 매개변수에 의해서만 구별된다.
생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다.
//ex)
class Test{
int a,b;
//매개변수가 없는 생성자 (기본생성자)
Test(){}
//매개변수가 있는 생성자
Test(int a, int b){
this.a = a;
this.b = b;
}
}
생성자 조건
1. 생성자의 이름은 클래스의 이름과 같아야한다.
2. 생성자는 리턴 값이 없다.
3. 생성자를 작성하지 않으면 기본 생성자를 추가하여 컴파일 한다.
🔺 클래스내에 생성자가 하나라도 있다면 기본 생성자는 추가되지 않으므로 필요하다면 꼭 작성해야 에러가 발생하지 않는다.
Test t1 = new Test();
Test t2 = new Test(4,5);
위와 같이 인스턴스를 생성할 수 있으며, 인스턴스 생성 역할을 하는 연산자는 new이다. 생성자는 인스턴스 변수를 초기화하는 역할을 한다.
class Car {
String color;
int speed;
Car (String color, int speed){
color = color;
speed = speed;
}
}
위와 같이 인스턴스변수와 지역변수의 이름이 같을 때 생성자 안에서 혼란을 줄 수 있다. 이와 같은 상황을 방지하기 위해 this를 사용한다.
class Car {
String color;
int speed;
Car (String color, int speed){
this.color = color;
this.speed = speed;
}
}
this는 참조변수로 인스턴스 자신이며, this를 사용할 수 있는 것은 인스턴스 멤버뿐이다.
static메서드에서 인스턴스 멤버를 사용할 수 없는 것처럼 this도 사용할 수 없다.
같은 클래스 안에서 생성자 간에도 서로 호출이 가능하다.
this()를 사용하면 코드 중복을 줄일 수 있다.
생성자 조건
1. 생성자의 이름으로 클래스 이름 대신 this를 사용한다.
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
class Car {
String color;
int speed;
Car(){
this.color = "white";
this.speed = 100;
}
Car (String color){
this.color = "white";
}
Car (String color, int speed){
this.color = "white";
this.speed = 100;
}
}
위와 같이 작성하는 대신 this()를 사용해보자
class Car {
String color;
int speed;
Car (){
this("white",100);
}
Car(String color){
this(color, 100);
}
Car(String color, int speed){
this.color = "white";
this.speed = 100;
}
}
같은 클래스 내의 생성자들은 일반적으로 서로 관계가 깊은 경우가 많아서 이처럼 서로 호출하도록 하여 유기적으로 연결해주면 더 좋은 코드를 얻을 수 있고, 유지보수에도 용이하다.