[Java] 객체지향 프로그래밍(1)

Minit88·2023년 2월 23일
0

[Java]

목록 보기
6/18
post-thumbnail

Lab_01 - 클래스와 객체

클래스

클래스(Class)란 이러한 객체를 정의한 '설계도(blueprint)' 또는 '틀(frame)’이라 정의할 수 있습니다.

클래스는 객체를 생성하는데 사용되고 반대로 객체는 클래스에 정의되고 설계된 내용 그대로 생성된다. 따라서, 클래스는 객체 그 자체가 아니라 단지 객체를 생성하는 데 사용되는 하나의 틀이다.
[그림] 클래스와 객체
그림에서 알 수 있듯이 설계도(클래스)를 통해 생성된 객체를 우리는 해당 클래스의 인스턴스라 한다.

클래스의 구성요소와 기본 문법

클래스는 기본적으로 class 키워드를 사용해 정의한다. 주로 대문자로 시작하는 것이 관례이다.

class 클래스명 { // 클래스 정의
	-- 생략 --
}
public class ExampleClass {
	int x = 10; // (1)필드
	void printX() {...} // (2)메서드
	ExampleClass {...} // (3)생성자
	class ExampleClass2 {...} // (4)이너 클래스
}

클래스는 네 가지의 요소로 구성되어 있다.

  • 필드 : 클래스의 속성을 나타내는 변수이다.
  • 메서드 : 클래스의 기능을 나타내는 함수
  • 생성자 : 클래스의 객체를 생성하는 역할
  • 클래스 : 클래스 내부의 클래스

객체

객체는 크게 속성과 기능이라는 두 가지 구성요소로 이뤄져있다.
속성과 기능은 각각 필드와 메서드로 정의되는데, 일반적으로 하나의 객체는 다양한 속성과 기능의 집합으로 이뤄져있다.

객체의 생성은 다음과 같이 new 키워드를 사용하여 다음과 같이 실제 객체를 생성할 수 있다.

class CarTest {
	public static void main(String[] args) {

	Car bmw = new Car(); // Car 클래스를 기반으로 생성된 bmw 인스턴스
	Car tesla = new Car(); // Car 클래스를 기반으로 생성된 tesla 인스턴스
	Car audi = new Car(); // Car 클래스를 기반으로 생성된 audi 인스턴스
}

객체를 생성한 후에는 포인트 연산자(.)를 통해 해당 객체의 멤버에 접근이 가능하다.

객체의 생성

클래스명 참조_변수명 = new 생성자();

을 살펴보면,
객체는 new 생성할 수 있다. 참조변수는 실제 데이터 값이 아니라 실제 데이터가 저장되어 있는 힙 메모리의 주소값을 가리킨다. new 키워드는 생성된 객체를 힙 메모리에 넣으라는 의미를 가지는데, 생성자를 통해 객체가 만들어지면 해당 객체를 힙 메모리에 넣는 역할을 수행하게 된다.
[그림] 클래스 메모리 개념
클래스 person과 참조변수 p는 각각 클래스 영역과 스택 영역이라는 다른 위치에 저장된다. 생성자로 만들어지는 인스턴스는 힙 메모리 영역에 들어가며 객체 내부에는 클래스의 멤버들이 위치한다. 참조 변수는 객체의 실제 값이 아닌 힙에 저장되어 있는 주소값을 가리키게 된다.
생성된 객체에서 필드값은 실제 저장공간이 객체 내부에 있다는 것과 메서드는 다른 영역에 하나만 저장해놓고 공유한다.

객체의 활용

포인트 연산자(.)은 ' 해댕 위치에 있는 객체 안을 보세요' 라는 뜻을 가진다. 포인트 연산자를 활용하여 인스턴스 객체의 필드와 메서드 즉, 객체의 멤버들에 접근할 수 있다.

참조 변수명.필드명 // 필드값 불러오기
참조 변수명.메서드명() // 메서드 호출

Lab_02 - 필드와 메서드

필드

필드는 ‘클래스에 포함된 변수'를 의미하는 것으로 객체의 속성을 정의할 때 사용됩니다.

자바에서 변수는 다음과 같이 구분된다

  • 클래스 변수
  • 인스턴스 변수
  • 지역 변수

이 중 우리가 필드라 부른 것은 클래스 변수와 인스턴스 변수이며, static 키워드의 유무로 구분된다.
static 키워드가 함께 선언된 것은 클래스 변수, 그렇지 않은 것은 인스턴스 변수이다. 이 두 가지 변수 유형에 포함되지 않고 메서드 내에 포함된 모든 변수를 지역변수라 부른다.
이 세 가지 유형의 변수들은 주로 선언된 위치에 따라 그 종류가 결정되며 각각 다른 유효 범위를 가지게 된다.

class Example { // => 클래스 영역
	int instanceVariable; // 인스턴스 변수
	static int classVariable; // 클래스 변수(static 변수, 공유변수)

	void method() { // => 메서드 영역
		int localVariable = 0; // 지역 변수. {}블록 안에서만 유효
	}
}
  • 인스턴스 변수 : 인스턴스가 가지는 각각의 고유한 속성을 저장하기 위한 변수로 new 생성자를 통해 인스턴스가 생성될 때 만들어진다.
  • 클래스 변수 : 독립적인 저장 공간을 가지는 인스턴스 변수와 다르게 공통된 저장공간을 공유한다. 클래스 변수는 인스턴스 변수와 달리 인스턴스를 생성하지 않고도 클래스명.클래스변수명 을 통해 사용이 가능하다.
  • 지역 변수: 메서드 내에 선언되며 메서드 내{ 블록} 에서만 사용가능하다.

static 키워드

앞에서 클래스 변수와 인스턴스 변수를 구분하기 위해 static 키워드의 유무를 확인했다.
static 은 클래스 멤버(필드,메서드,이너 클래스)에 사용하는 키워드이다. static 키워드가 붙어있는 멤버를 우리는 '정적 멤버'라 부른다.static 변수는 프로세스가 메모리에 로드 되는 순간 정적변수 영역(데이터 영역)에 생성되는 변수이다.

ublic class StaticTest {
    public static void main(String[] args) {
        StaticExample staticExample = new StaticExample();
        System.out.println("인스턴스 변수: " + staticExample.num1); // static 키워드가 없는 인스턴스 변수
        System.out.println("클래스 변수: " + StaticExample.num2); //static 키워드가 있는 클래스 변수
    }
}

class StaticExample {
    int num1 = 10;
    static int num2 = -10;
}

//출력값
인스턴스 변수: 10
클래스 변수: -10

위 코드를 통해 예시를 보면,
num1은 static이 없어, 인스턴스 변수이다. 참조를 하기 위해 staticExample 객체를 통해 num1이 호출이 되고, Num2 는 객체 없이 StaticExample 클래스에 포인트 연산자를 이용해 바로 호출이 가능하다.
또한 정적 필드는 객체 간 공유 변수의 성질이 있다.

public class StaticFieldTest {
    public static void main(String[] args) {
        StaticField staticField1 = new StaticField(); // 객체 생성
        StaticField staticField2 = new StaticField();

        staticField1.num1 = 100; 
        staticField2.num1 = 1000;

        System.out.println(staticField1.num1);
        System.out.println(staticField2.num1);

        staticField1.num2 = 150;
        staticField2.num2 = 1500;
        System.out.println(staticField1.num2);
        System.out.println(staticField2.num2);

    }
}

class StaticField {
    int num1 = 10;
    static int num2 = 15;
}

위 코드를 통해 예시를 살펴보자.

[그림] 위 코드의 실행결과

staticFiled1 , staticFiled2 두 객체를 선언하고 각각 인스턴스 변수 num1를 초기화 하여 그 결과값을 출력해보면 100, 1000이 출력됨을 알 수 있다. 즉, 인스턴스 변수는 객체들과의 공유가 일어나지 않음을 알 수 있다.
이와는 달리, 정적 변수는 최종 num2=1500으로 초기화가 된 1500값으로 두 객체 모두 같은 값을 가지게 된다. 참조를 할 때에 정적 변수는 데이터 영역에 있는 num2를 호출하게 되어 객체 간의 공유가 가능해진다.

메서드

메서드는 “특정 작업을 수행하는 일련의 명령문들의 집합"을 의미하며, 앞서 본 것처럼 클래스의 기능에 해당하는 내용들을 담당합니다.

메서드는 크게 머리에 해당하는 메서드 시그니터와 몸통에 해당하는 메서드 바디로 구분할 수 있다.

자바제어자 반환타입 메서드명(매개 변수) { // 메서드 시그니처
	메서드 내용 // 메서드 바디
}

public static int add(int x, int y) { // 메서드 시그니처
	int result = x + y; // 메서드 바디
	return result;
}

메서드의 호출

메서드도 클래스의 멤버이므로 클래스 외부에서 메서드를 사용하기 위해서는 먼저 인스턴스를 생성해야 한다. 인스턴스를 생성한 후에 앞서 보았던 것처럼 포인트 연산자(.)를 통해 메서드를 호출할 수 있다.

메서드의 오버로딩

메서드 오버로딩이란 하나의 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것을 의미합니다.

public class Overloading {
    public static void main(String[] args) {
        Shape s = new Shape(); // 객체 생성
 
        s.area(); // 메서드 호출
        s.area(5);
        s.area(10,10);
        s.area(6.0, 12.0);
    }
}

class Shape {
    public void area() { // 메서드 오버로딩. 같은 이름의 메서드 4개.
        System.out.println("넓이");
    }
    public void area(int r) {
        System.out.println("원 넓이 = " + 3.14 * r * r);
    }

    public void area(int w, int l) {
        System.out.println("직사각형 넓이 = " + w * l);
    }

    public void area(double b, double h) {
        System.out.println("삼각형 넓이 = " + 0.5 * b * h);
    }
}

//출력값
넓이
원 넓이 = 78.5
직사각형 넓이 = 100
삼각형 넓이 = 36.0

Shape 클래스 안에 모든 메서드들이 area()라는 메서드 명을 가지고 있음에도 각기 다른 출력값을 리턴한다.
무조건 같은 메서드명을 사용한다고 해서 오버로딩이 되는 것이 아니다.
오버로딩이 성립하기 위해서는 크게 두 가지 조건이 성립되어야한다.

  • 같은 이름의 메서드명을 사용
  • 매개변수의 개수나 타입이 다르게 정의

참고로, 반환 타입은 오버로딩이 성립하는 데에 영향을 주지 못한다. 즉, 다른 반환 타입을 지정했다고 해서 가상 머신은 다른 메서드라 인식하지 못한다.

🎓Reference

static 변수

profile
" To be BE "

0개의 댓글