객체
가장 처음 포스팅을 읽어보면 자바는 객체 지향 언어라고 쓰여있다.
도대체 객체 지향 언어란 무엇일까?
우리가 살고 있는 세계는 객체로 이루어져 있다. 스마트폰도 객체고 공기도 객체고 소리도 객체고 모든것이 객체다.
즉 객체는 독립되고 구분되는 각각의 것을 말하고 모든 사건은 이들간의 상호작용으로 이루어진다.
이것을 컴퓨터로 옮겨놓아 만들어낸 것이 바로 객체 지향 언어인 것이다.
그렇다면 자바에서 객체는 어떤식으로 표현이 될까?
자바에서 객체의 생성은 클래스에 적힌대로 new 연산자를 통해 메모리 영역에 할당하는 것을 말한다.
바로 이전 포스팅에 배열을 다룰 때 new 연산자와 Heap메모리 영역 이야기가 나왔는데
배열 할당이 바로 객체를 생성하는 것이었다.
즉, 'new연산자를 이용해 Heap 메모리 영역에 할당하는 것' 이 바로 객체를 생성하는 방법이다.
그럼 이 객체 생성에서 클래스는 무엇일까?
이전 클래스라는 말은 참 자주 등장했는데 무엇인지는 잘 모르고 사용을 했다.
클래스의 등장 배경을 알기 위해선 변수로 돌아가야한다.
변수는 잘 알고 있듯이 1개의 자료형에 1개의 데이터만 들어간다.
이것을 보완하고자 배열이 생겨났고 배열은 1개의 자료형에 여러 개의 데이터를 담을 수 있게한다.
하지만 우리가 프로그램을 작성할때 한 개의 자료형만을 사용하기는 어렵고
여러개의 자료형에 여러개의 데이터를 담아야하는데 이것을 구조체라 한다.
우리는 이렇게 여러개의 자료형에 여러개의 데이터를 담을수 있게 된다.
그러나 여기서 문제가 발생한다.
어느곳에서나 구조체에 접근 할 수 있기 떄문에 보안에 취약하다.
데이터를 바꾸기가 너무 쉬웠고 삭제도 가능했으며 어떤 데이터가 들어있는지도 알기 쉽다.
그걸 방지하기 위해 데이터 접근 제한을 하면 데이터가 갇혀
아무런 기능을 할 수 없기 떄문에 단순한 데이터 쪼가리가 될 뿐이다.
여기서 등장한 것이 바로 클래스이다.
클래스란 사물이나 개념의 공통적인 부분을 뽑아 추상화하여 객체를 정의한 것으로 캡슐화를 통해 기능을 포함한다.
추상화는 프로그램에서 필요한 공통점을 가져오고 불필요한 공통점을 제거하는 과정이다.
이 과정으로 유연성을 확보할 수 있게 된다.
이러한 객체 지향에는 3대 특징이 있다.
첫번째로 캡슐화, 두번째로 상속, 세번째로 다형성이다.
이것들은 다음 포스팅에서 다루도록 하겠다.
소스파일의 구성
소스파일을 생성하면 아래와 같이 가장 위에 package문이 적혀있다.
소스파일은 3가지로 구성되는데
첫번째로 package문, 두번째로 import문 마지막으로 클래스 선언이다.
먼저 package문부터 알아보자.
package는 서로 관련이 있는 클래스의 묶음인데 폴더와 아주 유사하다.
패키지는 서브 패키지를 가질 수 있고 이를 '.'으로 구분한다.
패키지는 소스파일 가장 첫 문장에 단 한번 선언하고 하나의 소스파일에 2개 이상의 클래스가
포함된 경우엔 모두 같은 패키지에 속한다.
모든 클래스는 하나의 패키지에 속하며 패키지가 선언이 되지않은 클래스는 자동적으로 (default) 패키지에 속하게 된다.
다음 소스파일의 구성요소는 import이다.
사용할 클래스가 속한 패키지를 지정할 때 사용한다.
이것을 사용하면 클래스를 사용할 때 패키지 명을 생략할수 있고
예외적으로 java.lang 패키지의 클래스(String, System 등)는 import를 안해도 사용이 가능하다.
import문은 패키지문과 클래스 선언 사이에 있다.
마지막으로 클래스이다.
변수와 배열과 마찬가지로 클래스도 선언을 해야한다.
클래스의 선언은 아래와 같이 하게 된다.
이 때 접근제한자라는 낯선 말이 써있는데 클래스에서 접근제한자는 2가지 종류가 있다.
public은 그 어떤 곳에서도 전부 접근할 수 있고
(default)는 같은 패키지 내에서만 접근 할 수 있다.
디폴트라고 부르지만 아무것도 적지 않는것이 (default)이다.
필드
필드는 다음과 같이 표현한다.
[접근제한자] [예약어] class 클래스명 {[접근제한자] [예약어] 자료형 변수명 [=초기값];}
필드에서도 클래스처럼 접근제한자가 존재하는데 4가지가 있다.
public protected (default) private
가장 처음에서부터 접근 권한이 줄어드는데 public은 어느곳에서든 접근이 가능하고
private는 해당 클래스 내부에서만 접근이 가능하다.
(default)는 같은 패키지 내에서 접근이 가능하고 protected는 추후 상속에서 다룰건데 후손 클래스가 없다면
(default)와 동일한 접근 제한을 가진다.
두 가지 예약어도 있는데 static은 heap 메모리와 같이 메모리의 한 영역을 말하고 프로그램이 시작되면
static 메모리 영역에 자동 할당되는 멤버에 적용한다.
같은 타입의 여러 객체가 공유할 목적에 필드에 사용된다.
final은 앞서 사용해 본적이 있는데 비슷하게 하나의 값만 저장해야하는 변수에 사용하는 예약어이다.
생성자
객체가 생성될 때 객체 안에서 만들어지는 필드를 초기화한다. 생성자는 메소드의 일종으로 전달된 초기 값을 받아서
객체의 필드에 기록한다. 생성자는 반환값이 없고 생성자명을 반드시 클래스명과 똑같이 지정해줘야한다.
생성자 표현식은 아래와 같다.
여기서 기본 생성자라는 것이 있는데 우리가 여지껏 코딩을 하면서 단 한번도 생성자를 입력하지 않은 이유는
JVM이 생성자를 작성하지 않은 경우 자동으로 기본 생성자를 생성하기 떄문이다.
기본 생성자가 아닌 매개변수 생성자는 객체를 초기화하기 위해 사용하는데
이 매개변수 생성자를 사용하면 JVM이 기본 생성자를 자동으로 생성해주지 않기 때문에
반드시 기본 생성자를 따로 작성해주어야 한다.
이 때 매개변수 생성자는 오버로딩을 사용하여 작성하게 된다.
오버로딩이란 같은 클래스에서 동일한 이름의 메소드를 여러개 작성하는 것이다.
오버로딩을 하기 위해선 메소드 이름이 같아야하며 매개변수의 개수 혹은 타입이 달라야하고 타입과 개수가 같더라도
순서가 다르면 사용이 가능하다.
매개변수 생성자를 사용할 때 this라는 객체를 사용할 건데 전달되는 객체의 주소를 자동으로 받는 역할을 한다.
매개변수명이 필드명과 같으면 매개변수명이 우선이기 때문에 this를 사용하여 필드명을 구분해 준다.
이름이 비슷한 객체로 this()가 있는데 다른 생성자를 호출할 때 사용하고 생성자 내에서 반드시 가장 첫 줄에 선언한다.
메소드
메소드는 호출을 통해 사용하는 일종의 함수이다. 전달값을 전달해서 호출할 수도 있고 전달값이 없이 호출할 수도 있다.
작성된 연산을 하고나서 반환값은 있을 수도 없을 수도 있다.
매소드는 아래와 같이 표현한다.
메소드도 접근제한자가 있는데 필드와 완전히 동일하다.
예약어로는 static, final, abstract, synchronized, static final(final static)이 있고
여기서 abstract는 추후 상속에서 synchronized는 다형성에서 다룬다.
static은 위에서 말한 static 메모리에 할당해서 객체 생성없이 사용할때
final은 상속 시 오버라이딩이 불가능하게 만들고 싶을때 사용하고
static final은 둘의 특성을 모두 갖는다.
반환형은 우리가 많이 사용하던 void가 있고
그 외 기본 자료형, 배열, 클래스가 있다.
void는 반환형이 없음을 말하고 우리가 메소드를 사용할때 반환값이 없이 사용할 수 있었던것은
void를 작성했기 때문이다.
그러나 그 외의 반환형을 사용할땐 반환값이 반드시 있어야한다.
기본 자료형은 연산 수행 후 해당 자료형의 반환값이 있을때
배열은 연산 수행 후 반환값이 배열의 주소값일때
클래스는 연산 수행 후 반환값이 해당 클래스 타입의 객체이고 객체의 주소값이 반환될 때
메소드에도 매개변수가 있다. 지금까진 매개변수를 사용하지 않아서 ()과 같이 작성했지만
마찬가지로 이 외에 매개변수가 존재한다.
기본 자료형 매개변수는 값을 복사하여 전달하고 매개변수 값이 바뀌더라도 본래값이 변경되진 않는다.
배열이나 클래스와 같은 참조형 매개변수를 전달 할땐 주소 값을 전달하기 때문에 매개변수를 수정하면
원래 데이터가 수정된다. 이 때 얕은 복사가 일어난다.
가변인자는 매개변수의 개수를 유동적으로 설정하는 방법인데
가변 매개변수를 제외한 다른 매개변수가 있다면 가변 매개변수를 가장 마지막에 작성해준다.
마지막으로 setter와 getter 메소드에 관해 알아보자.
setter 메소드는 필드의 변경할 값을 전달받아서 필드 값을 변경하는 메소드인데
이 때 해당 필드명 앞에 set을 붙이는 방식으로 명명하는 것이 관례이다.
예를들면 name이라는 필드명을 변경하는 메소드를 명명할땐 setName이라 짓는다.
표현식은 아래와 같다.
getter 메소드는 필드의 기록된 값을 읽어서 그 값을 넘겨주는 메소드이다
setter와 같이 명명할땐 set을 붙여 명명하는게 관례이다.
return은 해당 메소드를 종료하고 자신을 호출한 메소드로 돌아갈 때 사용하는 예약어 이다.
반환값이 있으면 반환값을 가지고 돌아간다.
객체배열
객체에도 배열이 있다. 특성은 배열과 유사하지만 몇 가지 다른점이 있다.
초기화 방법에는 인덱스를 이용한 방법과 선언과 동시에 할당과 초기화를 하는 방법이 있고
전자를 이용한 방법은 배열명[i] = new 클래스명();
후자를 이용한 방법은 클래스명 배열명[] = {new 클래스명(), new 클래스명()); 이다.
객체 배열도 배열과 같이 Heap메모리에 할당되며 주소값을 갖는다.
'프로그래밍 > Java' 카테고리의 다른 글
[Java] 8. API (0) | 2023.03.01 |
---|---|
[Java] 7. 상속 (0) | 2023.02.21 |
[Java] 5. 배열 (0) | 2023.02.21 |
[Java] 4. 제어문 (0) | 2023.02.21 |
[Java] 3. 연산자 (0) | 2023.02.19 |