[ JAVA ] 클래스와 객체

Wooju Kang ·2025년 3월 30일
post-thumbnail

GIF 출처 : https://www.amigoscode.com/courses/java

🖥 Contents


1 ) 객체 지향과 자바

2 ) 클래스와 객체

3 ) 생성자

4 ) 객체 배열

5 ) 메소드

6 ) 접근 지정자

7 ) static 멤버

8 ) final

9 ) 익명 클래스




1 ) 객체 지향과 자바


  • 객체 ( Object ) 란?

    : 객체란 자신만의 고유한 특성 ( State )행동 ( Behavior ) 을 가지며 다른 객체들에게 행동을 요청하거나 정보를 주고받는 등 상호작용하는 존재를 의미한다.

    객체지향에서는 고유한 특성을 필드 ( Field ) 라고 하며 객체의 행동을 메소드 ( Method ) 라 한다.


  • 캡슐화 ( Encapsulation )

    : 캡슐화란 객체를 캡슐로 싸서 내부를 보호하고 볼 수 없게 하는 것을 의미한다.

    • 객체의 구성
      : 객체는 클래스 ( Class ) 라는 캡슐을 사용하며 , 필드 ( 맴버 변수 )메소드 ( 멤버 함수 ) 로 구성된다.
    출처: https://runestone.academy/runestone/static/JavaReview/JavaBasics/Summary.html



  • 상속 ( Inheritance )

    : 상위 개체의 속성이 하위 개체에 물려져 하위 개체가 상위 개체의 속성을 모두 가지는 관계를 의미한다. 자바의 상속은 자식 클래스가 부모 클래스의 속성을 물려받고 기능을 추가하여 확장 ( extends ) 하는 개념이다. 이때 부모 클래스를 슈퍼 클래스 ( Super Class ) 라고 하며 자식 클래스를 서브 클래스 ( Sub Class ) 라고 한다.

    ex) 자바에서의 상속
    : 해당 예시의 경우 Car , Bus 클래스는 Automobiles를 확장 ( extends ) 하고 있으며 해당 클래스 또한 자식 클래스 ( Sub Class ) 로써 Vehicle 클래스를 확장하고 있다.

    출처 : https://techvidvan.com/tutorials/java-inheritance/



  • 다형성 ( Polymorphism )

    : 다형성은 같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 동작하도록 구현되는 것을 의미한다. 자바에서의 다형성은 두가지 케이스가 존재한다.

    1) 오버라이딩 ( Overiding )
    2) 오버로딩 ( Overloading )

    ① 오버라이딩 ( Overiding )
    : 오버라이딩이란 서브 클래스에서 슈퍼 클래스의 메소드를 재정의 하여 서브 클래스의 메소드의 경우 다르게 동작하도록 구현하는 것을 의미한다.

    ② 오버로딩 ( Overloading )
    : 오버로딩이란 같은 이름의 메소드에 대하여 매개 변수 타입 혹은 매개 변수의 개수를 달리하여 같은 이름을 가지더라도 서로 다르게 동작하도록 하는 것을 의미한다.




2 ) 클래스와 객체


  • 인스턴스 ( Instance )

    : 자바에서 클래스 ( Class ) 는 객체를 만들어 내기 위한 설계도 혹은 틀이며 , 클래스 모양 그대로 생성된 실체가 객체 ( Object ) 이다. 이러한 연유로 객체를 클래스의 인스턴스 ( Instance ) 라고 한다.

  • 클래스의 구성
    : 자바 클래스는 Class 키워드를 사용하여 선언한다. 클래스를 생성할 경우 다음과 같은 구조를 가진다.

    ex) 자바 클래스의 구성요소

    출처 :https://tcpschool.com/java/java_class_declaration

    ① 클래스 선언 : 사용자가 선언할 클래스의 이름을 결정한다. Class 키워드와 클래스 이름으로 선언하고 중괄호 ({}) 안에 필드 ( Field ) 와 메소드 ( Method ) 를 모두 작성한다. 클래스 외부에는 어떤 필드와 메소드를 둘 수 없는데 이는 캡슐화의 원칙 때문이다.

    ② 필드와 메소드 : 객체 내에 값을 저장한 멤버 변수를 필드 ( Field ) 라 하며 이는 객체의 특성을 나타낸다. 또한 메소드 ( Method ) 는 함수이며 객체의 행동을 구현한다.

    ③ 접근 지정자 : 접근 지정자는 특정 클래스나 특정 디렉토리에서 접근할 수 있는 범위를 나타낸다.

    ④ 생성자 ( Constructor ) : 생성자는 객체가 생성될 때 자동으로 호출하는 특별 메소드로 객체의 필드값을 초기화할 수 있다.


  • 레퍼런스 변수 ( Reference Variable )

    : 객체를 가리키는 변수를 의미한다. 레퍼런스 변수의 경우 선언 자체로는 객체를 생성하지 않으며 new 키워드를 통해서 초기화할 경우에 생성된 객체를 가리킨다.

    pizza = new Circle();
    // pizza 레퍼런스 변수는 새로운 Circle 객체를 가리킨다.
    

    위 문장의 실행 순서는 다음과 같다.

    1st. Circle 타입 크기의 메모리 할당
    2nd. Circle() 생성자 코드 실행


  • 객체 맴버 접근
    : 객체의 맴버에 접근할때는 레퍼런스 변수 뒤에 점(.) 연산자를 붙여서 접근한다. 예시로 Pizza 클래스에는 멤버 변수로 radius가 존재한다고 가정해보자.

class Pizza{
        int radius;
        public Pizza(int radius){
            this.radius = radius;
        }
    }

이때 , pizza의 radius 필드에 값을 대입하고자 하는 경우 점 연산자를 통해 대입할 수 있다.

pizza.radius = 10;



3 ) 생성자


  • 생성자 ( Constructor )

    : 객체가 생성될 때 객체의 초기화를 위해 실행되는 메소드를 의미한다. 생성자는 객체가 생성되는 순간에 자동으로 호출되는 메소드이다.

class Pizza{
        int radius;
        public Pizza(int radius){
            this.radius = radius;
        }
    }

해당 클래스에서 radius 필드는 선언되었을 뿐 아직 초기화 되기 전의 상태이다. 앞선 코드에서 new 키워드를 통해 객체를 초기화하였는데 그때 , 생성자가 다음과 같이 구현이 되어있을 경우 초기화를 할 수 있다.

  • 생성자 특징

① 오버로드 ( Overload )
: 오버로드는 클래스가 같은 이름의 생성자를 여러개를 가지는 것을 의미한다. 오버로드는 다음과 같은 규칙이 존재하며 이를 준수해야한다.

1 ) 생성자가 여러개 존재한다.
2 ) 생성자에 들어가는 파라미터의 개수 혹은 타입이 달라야 한다.

② 리턴 타입 지정불가
: 생성자의 경우 어떤 값도 리턴하지 않기 때문에 리턴타입을 선언해서는 안되며 리턴 값이 없다고 해서 void를 리턴 타입으로 지정해서는 안 된다.


  • this 레퍼런스
    : this는 자바에서 객체 자신을 가리키는 레퍼런스이다. 이는 현재 겍체에 대한 레퍼런스로 해당 키워드를 통해 객체의 맴버에 접근할 수 있다. this 레퍼런스의 경우 다음과 같은 상황에서 사용할 수 있다.
public Circle(int radius){
         this.radius = radius; }

해당 코드의 경우 생성자의 파라미터가 맴버변수와 동일함을 알 수 있다. 이때 , 사용자가 맴버 변수를 가리키기 위해 this 키워드를 사용하여 구분하기 위함이다.

this 레퍼런스의 다른용도로는 생성자가 다른 생성자를 호출할 때 사용한다. 오버로드된 다른 생성자를 호출하기 위함이다.

class Pizza{
        int radius;
        String name;
        // 1번 생성자
        public Pizza(int radius){
            this(radius,"반지름");
        }
        // 2번 생성자
        public Pizza(int radius,String name){
            this.radius = radius;
            this.name = name;
        }
    }

예를 들어 생성자가 2개가 존재한다고 가정해보자. 1번 생성자는 int 타입의 매개변수인 radius를 받는다. 이때 , this()를 통해 2번 생성자에 접근하고자 한다.

중요한 것은 원하는 생성자를 호출하고자 한다면 해당 생성자의 매개변수 개수 및 타입을 지켜줘야한다. 이를 통해 1번 생성자에 접근하게 되면 자동적으로 2번 생성자를 호출하여 초기화를 진행하게 된다.

  • this 사용 시 주의점
    ① this()는 반드시 생성자 코드에서만 호출할 수 있다.
    ② this()는 반드시 같은 클래스 내 다른 생성자를 호출할 때 사용된다.
    ③ this()는 반드시 생성자의 첫 번째 문장이 되어야 한다.

⭐️ 객체 치환시 주의점
: 연산자로 객체를 치환하는 코드를 종종 사용하곤 한다. 객체의 치환은 객체를 복사하는 것이 아니라는 점을 레퍼런스 변수를 통해 알고 있다. 만약 객체를 연산자로 치환하게 될 경우 다음과 같은 상황이 발생한다.

Circle ob1 = new Circle(1);
Circle ob2 = new Circl2(2);
s = ob2;
ob1 = ob2;

해당 상황에서 s는 ob2가 가리키는 객체를 가리킨다. 이때 , ob1또한 ob2가 가리키는 객체를 가리키게 되는데 문제는 ob1이 기존에 가리키고 있던 객체에 대한 레퍼런스 변수가 사라지게 된다. 이를 가비지 ( Garbage ) 라 한다.

자바의 경우 가비지 콜렉터 ( Garbage Collector ) 를 통해 자동적으로 가비지를 회수하여 재사용하나 이러한 코드 사용방식은 지양할 필요가 있다.




4 ) 객체 배열


: 자바에서는 기본 타입 데이터뿐 아니라 , 객체를 원소로 하는 객체 배열 또한 생성이 가능하다. 자바의 객체 배열은 객체에 대한 레퍼런스를 원소로 갖는 배열을 의미한다.

Circle[] c = new Circle[5];

다른 배열 사용법과 같이 [] 키워드를 사용해서 배열을 생성한다.




5 ) 메소드


  • 인자전달

    : 메소드는 클래스의 멤버 함수로서 호출 시 ' 값에 의한 호출 ( call - by - value ) '이다. 호출하는 실인자의 값이 복사되어 메소드의 매개 변수에 전달된다.

    • 매개변수 전달타입

    ① 기본 타입
    : 메소드의 매개변수가 기본 타입으로 선언된 경우 , 호출자 ( caller ) 가 건네는 값이 매개변수에 복사되어 전달된다.
    int n = 10;
    method(n);

    ② 객체 타입
    : 메소드의 매개변수가 클래스 타입인 경우 , 객체가 아니라 객체의 레퍼런스 값이 전달된다. 이때 , 객체에 대한 레퍼런스만 전달될 뿐 객체가 통째로 복사되지 않는다는 점을 유의해야한다.
    Circle c = new Circle();
    method(c);

    ③ 배열 타입
    : 메소드의 매개변수가 배열인 경우 배열에 대한 레퍼런스만 전달된다.
    int a[] = {1,2,3,4,5};
    method(a);


  • 객체 소멸

    : 객체 소멸이란 new에 의해 생성된 객체 공간을 자바 가상 기계에게 돌려주어 가용 메모리 ( Available Memory ) 에 포함시키는 것을 의미한다.

    자바에는 객체를 생성하는 new 연산자가 존재하나 객체를 소멸시킬 수 있는 연산자가 존재하지 않는다. 그러므로 자바에서는 사용자가 마음대로 객체를 소멸시킬 수 없다.

    이때 앞서 언급한 가비지 컬렉터 ( Garbage Collector ) 가 사용하지 않는 객체 메모리 즉 , 가비지 ( Garbage )를 자동으로 수집하여 가용 메모리에 반환하는 역할을 한다.

    자바 플랫폼은 가용 메모리가 일정 크기 이하로 줄어들면 자동으로 가비지를 회수하여 가용 메모리를 늘린다. 가비지 컬렉션은 자바 플랫폼에 의해 준비된 가비지 컬렉션 스레드 ( Garbage Collection Thread ) 에 의해 처리된다.

    • 가비지 컬렉션 강제 요청
      : 응용프로그램에서 사용자가 System 혹은 Runtime 객체의 gc() 메소드를 통해서 가비지 컬렉션 강제로 요청할 수 있다.
      System.gc()



6 ) 접근 지정자


  • 접근 지정자 ( Access Specifier )
    : 접근 지정자는 클래스나 멤버들을 다른 클래스에서 접근해도 되는지 여부를 선언하는 지시어이다. 자바에는 총 4가지 접근 지정자가 존재한다.

    • 클래스 접근 지정

    ① public 클래스
    : 클래스 이름 앞에 public으로 선언하여 사용하는 클래스로 패키지에 상관없이 다른 어떤 클래스에게도 사용이 허용된다.
    public class Circle

    ② default 클래스 ( 접근 지정자 생략 )
    : 접근 지정자를 사용 없이 클래스를 선언하는 경우로 같은 패키지내의 클래스들에게만 사용이 허용된다.
    class Circle


    • 멤버 접근 지정

    ① public 멤버
    : public 멤버는 패키지에 상관없이 모든 클래스에서 접근이 가능하다.
    public class Circle { }

    ② private 멤버
    : 클래스 내의 멤버들에게만 접근이 가능하다.
    private class Circle { }

    ③ protected 멤버
    : 보호된 공개를 지시하는 것으로 두 가지 유형에 해당하는 클래스에 대하여 접근을 허용한다.
    1 ) 같은 패키지의 모든 클래스
    2 ) 자식 클래스

    ④ default 멤버
    : 접근 지정자가 생략된 멤버로 동일한 패키지 내에 있는 클래스들만 디폴트 멤버를 자유롭게 접근 할 수 있다.

    멤버 접근 지정에 대하여 정리하면 다음과 같다.

    멤버에 접근하는 클래스privatedefaultprotectedpublic
    같은 패키지의 클래스xooo
    다른 패키지의 클래스xxxo
    접근 가능 영역클래스 내동일 패키지 내동일 패키지와 자식 클래스모든 클래스



7 ) static 멤버


  • static 멤버

    : 해당 멤버는 클래스당 하나씩 생성이 가능하며 클래스 멤버라고도 부른다. 이와 반대로 각 객체마다 한개씩 생성되는 멤버도 존재하는데 이를 인스턴스 멤버라 한다.

non - static 멤버static 멤버
선언int n;static int n;
공간적 특성멤버는 객체마다 별도 존재
- 인스턴스 멤버라고 부른다.
멤버는 클래스 당 하나
- 멤버는 객체 내부가 아닌 별도의 공간에 생성
- 클래스 멤버라고 부르기도 한다.
시간적 특성객체 생성 시에 멤버 생성된다.
- 객체가 생길 때 멤버도 생성
- 객체 생성 후 멤버 사용 가능
- 객체가 사라지면 멤버도 사라진다.
클래스 로딩 시에 멤버 생성
- 객체가 생기기 전에 이미 생성된다.
- 객체가 생기기 전에도 사용가능
- 객체가 사라져도 멤버는 사라지지 않는다.
- 멤버는 프로그램이 종료될 때 사라진다.
공유의 특성공유되지 않는다.
- 멤버는 객체 내에 각각의 공간을 유지한다.
동일한 클래스의 모든 객체들에 의해 공유된다. 즉 , 여러 객체들이 공유하여 사용하기에 값 변동에 민감하다.

출처 : https://javaconceptoftheday.com/final-keyword-in-java/#google_vignette

static 멤버와 마찬가지로 static 키워드를 사용하는 메소드의 경우 static 멤버만 접근할 수 있다.

예를 들어 클래스 내부에 static 과 non static 멤버가 존재하는 경우가 존재한다고 생각해보자.

class staticMethod {

            static int m;
            int n;
            void f1( int x ){ // 정상
                n = x;
            }
            void f2( int x ){ // 정상 
                m = x;
            }
            
            static void s1(int x){
                n = x; // 컴파일 오류 : static 메소드에 일반 맴버 변수 사용 불가 
            }
            
            static void s2(int x){
                m = x; // 정상 : static 메소드는 static 필드 사용 가능 
            }
        }

s2 메소드의 경우 static 변수인 m 을 사용하였기에 정상적으로 작동하나 s1 메소드의 경우 일반 멤버변수인 n 을 사용하였기 때문에 컴파일 오류가 발생한다.




8 ) final


final은 더이상 클래스를 상속받을 수 없음을 나타내는 키워드이다. 해당 키워드를 이용한 클래스 , 메소드 , 멤버는 다음과 같은 특징을 가진다.

① final 클래스
: final 클래스는 더이상 클래스 상속을 받을 수 없다.

final class FinalClass { // 해당 클래스는 상속 불가
            
        }
        
        class SubClass extends FinalClass{ // 컴파일 오류 발생 
            
        }

② final 메소드
: final 메소드는 오버라이딩할 수 없는 메소드를 의미한다.

public class SuperClass {
            protected final int finalMethod(){
                System.out.println("final Method");
            }
        }
        
        class SubClass extends SuperClass{
            @Override // 컴파일 오류 
            protected int finalMehtod(){
                
            }
        }

③ final 필드
: final로 필드를 선언할 경우 상수가 된다.

 public class FinalClass {
            final int ROWS = 10;
            void f(){
                int[] intArray = new int[ROWS];
                ROWS = 30; // 컴파일 오류 
            }
            
        }



9 ) 익명 클래스


  • 익명 클래스 ( Anonymous Class )
    : 익명 클래스는 내부 클래스 ( Inner Class ) 의 일종으로 말 그대로 이름이 없는 클래스를 의미한다. 익명 클래스가 이름이 없는 클래스인 이유는 한번 사용된 후 버려지는 클래스이기 때문이다.

    익명 클래스는 클래스 정의와 동시에 객체를 생성할 수 있다. 따라서 클래스 정의 없이 메소드 내에서 바로 클래스를 생성해 인스턴스화하여 사용할 수 있으며 해당 섹션이 종료된 후에는 해당 클래스는 일회용으로 사용되고 버려진다.

class person {
            public String say(){
                return "나는 사람.";
            }
        }
        
        person dog = new person() {
            @Override
            public String say(){
                return "나는 woojuice.";
            }
        };

profile
배겐드 📡

0개의 댓글