성장일기

내가 보려고 정리하는 공부기록

언어/자바

[JAVA] 객체와 클래스

와나나나 2024. 6. 11. 10:58
728x90

자바가 객체지향 언어라는건 자바에 관심이 있는 사람이라면 알고 있을 사실이다. 그렇다면 객체는 무엇일까 ?

 

1. 객체

객체는 클래스에서 정의된 것을 기반으로 메모리에 할당된 것을 의미한다. 객체는 속성과 행위를 가지고, 우리는 객체의 속성을 필드, 행위를 메소드라고 부른다.

 

클래스를 통해 생성된 객체를 클래스의 인스턴스라고 한다.

 

여기서 인스턴스는 객체와 비슷한 의미를 가지는데, 객체는 모든 인스턴스를 포괄하고 인스턴스는 어떤 객체가 어느 클래스에서 생성된 건지 강조한다.

 

정리하면, 클래스를 new를 이용해 생성하여 메모리에 할당된 것을 객체라고 한다는 것이다.

빵 틀이 클래스라면 그 틀로 구운 빵이 인스턴스인 셈이다.

 

 

객체 간의 관계

객체는 개별로 사용될 수 있으나, 대부분 다른 객체와 관계를 맺고 있다. 크게 집합 관계, 상속 관계, 사용 관계가 있다.

  1. 집합관계
    • 객체 하나당 하나의 부품인 경우
    • 엔진객체, 타이어객체, 핸들객체는 자동차객체와 집합관계에 있다고 할 수 있다.
  2. 상속관계
    • 부모객체를 기반으로 자식객체를 생성하는 관계
    • extends 를 이용하여 상속한다
  3. 사용관계
    1. 객체 안에서 다른 객체의 메소드를 사용하는 관계

 

그럼 클래스를 자세히 살펴보자

 

2. 클래스

클래스의 구성요소

클래스의 구성요소는 다음과 같다.

  • 필드
  • 생성자
  • 메소드
public class Car {
	
    // 필드
	private String color;
    private String name;
    
    // 생성자
    public void Car(String color, String name) {
    	this.color = color;
        this.name = name;
    } 
    
    // 메소드
    public String getName() {
    	return this.name;
    }
    ...
}

 

필드

필드는 객체의 데이터가 저장되는 곳이다. 학생이라는 클래스를 만들었다면 그의 데이터인 학생 이름, 나이, 학교 등이 필드가 되어 저장될 수 있다.

 

필드에 직접적으로 접근을 하지 않고 생성자를 이용해 초기화하고, 메소드를 이용해 접근한다. 그래서 private을 사용한다.

추가로, 초기화를 필수로 해야하는 지역변수와는 다르게, 필드는 초기화를 하지 않으면 JVM에서 자체적으로 해준다. int형은 0, 객체인 String은 null로 초기화 한다. 

 

필드는 객체를 생성한 후 접근해야 하며, 도트(.) 연산자를 통해 접근한다. 이는 메소드도 동일하다.

Car car = new Car();
car.name; // private이 붙어있어 접근불가능
car.getName(); // public인 getter 메소드 이용해 접근

 

private에 대한 설명은 다음 게시글에서 다룰 예정이다.

 

 

생성자

생성자는 객체 생성시 초기화를 담당한다. 클래스이름과 동일한 이름으로 짓는다.

생성자는 매개변수를 넣어 직접 만들수 있고, 만들지 않았다면 기본 생성자가 자동으로 생성된다.

public Car() {} // 기본생성자
public Car(String name, int price) {} // 이렇게도 가능

 

이렇게 매개변수의 개수, 타입을 다르게 해서 다양한 형태로 생성자를 만들 수 있는데, 이런 방식을 생성자 오버로딩이라고 한다. 

 

추가로 클래스가 public class라면 기본생성자에도 public이 붙으나, 클래스가 그냥 class로 선언되면 기본 생성자에도 붙지 않는다.

 

메소드 

메소드는 객체간 데이터 전달 수단이라고 생각하면 된다. 외부로부터 매개값을 받을 수 있고, 값을 반환할 수도 있다.

기본적으로 값을 넣고, 반환할 수는 있어야 하기 때문에 getter, setter를 만들어둔다. (intellij에서 윈도우 기준 alt + insert로 자동 생성이 가능하다)

 

 

클래스는 여러개 생성이 가능하지만 public은 한 개에만 붙일 수 있고, public이 붙는 클래스의 이름은 파일 이름과 동일해야한다.

 

public class Main {
	public static void main(String[] args) {
    	Car car = new Car();
    }
}

 

이렇게 new를 이용해 객체를 생성하는데, 객체는 메모리 힙 영역에 생성된다.

그래서 객체를 반환하면, 그 값이 아닌 객체의 주소를 반환하게 된다.

 

 

 

예 1

대표적인 객체 중 Array도 통째로 출력하면 배열의 주소값이 반환된다.  그리고 new를 할 떄마다 새로운 주소에 객체가 생성된다.

 

예 2

String도 객체라서, 생성하는 방식이 크게 두가지가 있다.

String str1 = “hello”; // 리터럴 방식

String str2 = “hello”

String str3 = new String(”hello”); // 객체생성 방식

 

이때 str1과 str2의 내용이 같기 때문에, 가리키는 메모리주소는 같다.

그 원리를 설명하자면, 리터럴 형식으로 쓰면 heap 내부에 있는 String Constant Pool에 저장된다. 이때 같은 문자열이 있는지 확인하고 넣기 때문에, str2가 들어갈 땐 str1과 같은 주소를 가리키게 된다.

 

하지만 str3은 다른 주소를 갖게 되는데, 객체로 생성하게 되면 매번 새로운 주소에 객체를 생성하기 때문이다!