본문 바로가기

Java

[WS live-study] 5주차: 클래스

클래스와 객체

객체는 클래스에서 파생된 객체마다 속성이 각각 다른 상태를 갖게되는 것을 말한다. 즉, 객체는 클래스를 바탕으로 생성된다.

그런데 이 클래스는 모두 객체로 만들어서 사용해야하는게 아닌 객체 생성 없이 사용할 수도 있다.

클래스에서 객체 생성을 해서 사용하는 것을 인스턴스 변수, 인스턴스 메서드라고 하며, 객체 생성없이 바로 호출할 수 있는 것을 클래스 변수(정적 변수), 클래스 메서드(정적 메서드) 라고 한다.

 

객체는 속성이 객체마다 각각 다르다했다. 간단한 예를 들어보겠다.

class Person {
    String name;
    int age;
    String address;

    Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
}
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("김지현", 25, "서울");
        Person p2 = new Person("이병진", 32, "여수");
        Person p3 = new Person("박경우", 27, "인천");
    }
}

 

Person이라는 객체는 각각 다른 속성(name, age, address)을 갖는다.

 

하지만 이를 반대로 생각하면 클래스는 각각 다른 속성을 가질 필요 없다는 특성을 갖는다.

class Calculator {

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

    static int subtract(int a, int b) {
        return a - b;
    }
}
public class Test {
    public static void main(String[] args) {
        int num1 = Calculator.add(3,5);
        int num2 = Calculator.subtract(12, 3);
    }
}

 

 

클래스를 정의하는 방법

일단 클래스의 구조를 살펴보자.

  • 필드 : 필드는 클래스의 속성을 나타내며, 멤버변수라고도 불린다. 여기서 초기화되면 명시적 초기화라고 한다.
    • 인스턴스 변수: 인스턴스가 갖는 변수이며, 인스턴스를 생성할 때마다 만들어진다. 인스턴스마다 독립된 값을 가지므로 heap 영역에 할당되고, gc에 의해 관리된다.
    • 클래스 변수: static 키워드가 필드 타입 앞에 붙으면 클래스 변수이다. 해당 클래스에서 파생된 모든 인스턴스가 이 변수의 값을 공유한다. 그렇기에 메모리 할당도 heap 영역이 아닌 static 영역에서 되고 gc의 관리를 반지 않는다. 앞에 public 키워드가 붙는다면 전역변수라 볼 수 있다.
  • 메서드: 클래스의 행동이라고도 하며, 보통 필드의 값을 조정하는 역할을 한다.
    • 인스턴스 메서드: 인스턴스를 생성해야 사용할 수 있는 메서드이며, 인스턴스 변수와 연관된 작업을 한다.
    • 클래스 메서드: 메서드 선언부에 static 키워드가 붙으며, 일반적으로 인스턴스와 관계없는 메서드를 클래스 메서드라 한다.
  • 생성자 : 객체가 생성된 직후에 객체를 초기화하는데 사용하는 코드블록이다. 메서드와 달리 이름은 클래스 이름과 같아야하며 리턴타입이 없고, 클래스에는 반드시 1개 이상의 생성자가 존재한다.
  • 초기화 블록 : 초기화 블록 내에서는 조건문, 반복문 등을 사용하여 명시적 초기화에서는 불가능한 초기화를 수행할 수 있다.
    • 인스턴스 초기화 : 인스턴스 변수를 초기화하는데 사용된다.
    • 클래스 초기화: 클래스 변수를 초기화하는데 사용된다.
class Class {                   // 클래스
    String instanceVar;         // 인스턴스 변수
    static String classVar;     // 클래스 변수

    static {                    // 클래스 초기화
        classVar = "Class Variable";
    }
    
    {                           // 인스턴스 초기화
        instanceVar = "Instance Variable";
    }

    Class() {                   // 생성자
        instanceVar = "Instance Variable - constructor";
    }

    void instanceMethod() {     // 인스턴스 메서드
        System.out.println(instanceVar);
    }

    static void classMethod() { // 클래스 메서드
        System.out.println(classVar);
    }
}

객체를 만드는 방법

객체는 아래의 예와 같이 생성하고자하는 클래스의 생성자 중 하나를 new 키워드와 함께 사용해야한다. 아래의 예를 보면 new 키워드 옆에 각각 다른 생성자가 호출된 것을 확인할 수 있다.

 

class Person {
    String name;
    int age;
    String address;

    Person(String name) {                           //생성자1
        this.name = name;
    }

    Person(String name, int age) {                  //생성자2
        this(name);
        this.age = age;
    }

    Person(String name, int age, String address) {  // 생성자3
        this(name, age);
        this.address = address;
    }
}
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("김지현");
        Person p2 = new Person("이병진", 32);
        Person p3 = new Person("박경우", 27, "인천");
    }
}

 

new 키워드의 역할은 새 객체에 메모리를 할당하고, 할당된 메모리의 참조값을 반환하여 해당 클래스를 인스턴스화한다.

메서드 정의하는 방법

아래의 예와 함께 같이 설명하겠다.

public class Calculator {
    public static int add(int a, int b) {
        return a + b;
    }

    public static int subtract(int a, int b) {
        return a - b;
    }
}

Calculator 클래스에 메서드 2개가 정의되어 있다.

 

생성자 정의하는 방법

Person() {}

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

Person(String name, int age) {
    this(name);
    this.age = age;
}

생성자를 따로 명시하지 않았다면 컴파일러가 자동으로 기본 생성자를 생성한다. 하지만 생성자를 명시하였다면 컴파일러는 기본생성자를 생성하지 않는다.

this 정의하는 방법

this 키워드는 인스턴스 자신을 가리키는 참조변수이다. this에는 인스턴스 주소가 저장되어 있으며 모든 인스턴스 메서드에 지역변수로 숨겨진 채 존재한다.

public void setName(String name) {
    this.name = name;
}

위의 예에서 보듯이 this는 지역변수와 구분할 수 있다. 메서드 안에서 같은 이름의 멤버변수와 지역변수가 있는 이름을 호출하면 지역변수가 호출이 되기 때문에 멤버변수를 호출하려면 this를 이용해야한다.

 

this()를 이용하여 생성자에서 다른 생성자를 호출할 때 사용할 수도 있다. 단, 다른 생성자 호출은 생성자의 첫문장에서만 가능하다.

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

Person(String name, int age) {
    this(name);
    this.age = age;
}