객제 지향 언어의 특징
- 코드의 재사용성이 높다.
새로운 코드를 작성하더라도, 기존의 코드를 이용해 쉬운 작성이 가능하다
- 코드의 관리가 용이하다
코드간의 관계를 이용하여 적은 노력으로 쉽게 코드를 변경할 수 있다.
- 신뢰성이 높은 프로그래밍을 가능하게 한다.
제어자, 메서드를 이용해 데이터를 보호하고 올바른 값을 유지하도록 하며 코드의 중복을 제거해 코드 불일치로 인한 오동작을 방지한다
클래스와 객체
- 클래스 → 객체를 정의해 놓은 것, 객체의 설계도 또는 틀
⇒ 객체를 생성하는데 사용하며, 객체는 클래스에 정의된 대로 생성된다.
- 객체 → 실제로 존재하는 것, 사물 또는 개념
⇒ 객체가 가진 기능, 속성에 따라 용도가 다르다.
예시
TV를 보기 위해서는 TV(객체)가 필요
⇒ TV 설계도(클래스)를 통해 TV(객체)를 만든 후 사용 가능
- 하나의 멋진 설계도 제작 → 객체 생성 시 편하게 사용 가능
객체와 인스턴스
- 클래스로부터 객체를 만드는 과정 →
인스턴스
- 클래스로부터 만들어진 객체 →
클래스의 인스턴스
- 객체 → 인스턴스를 대표하는 포괄적인 의미
- 인스턴스 → 어떤 클래스로부터 만들어진 것인지 강조하는 구체적인 의미
- ⇒ 용어의 사용을 명확히 구분하기 보다는, 문맥에 따라 구분하는 것이 좋다.
객체의 구성요소 : 속성과 기능
객체 → 속성과 기능이라는 두가지의 구성요소로 구성된다.
⇒ 속성과 기능의 집합을 말한다.
- 객체가 갖고 있는 속성과 기능 → 객체의 멤버(member)
속성(property)
크기, 길이, 높이, 색상, 볼륨과도 같은 요소에 해당한다.
- 멤버 변수(variable)
- ex) int channel
- 특성
- 필드
- 상태
기능(function)
켜기,끄기, 볼륨 높이기, 볼륨 낮추기 등이 기능에 해당한다
- 메서드(method)
- ex) channelUp()
- 함수
- 행위
인스턴스의 생성과 사용
클래스명 변수명; // 클래스 객체를 참조하기 위한 참조변수 선언
변수명 = new 클래스명; // 클래스의 객체 생성 후 객체의 주소를 참조변수에 저장
----
Tv t; //Tv 타입의 t를 참조변수로 선언한다
t = new Tv(); // Tv 인스턴스를 생성 후, 생성된 Tv 인스턴스 주소를 참조변수 t에 저장
class Tv {
// Tv의 속성 (멤버변수)
String color; // 색상
boolean power; // 전원상태 (on/off)
int channel; // 채널
// Tv의 기능 (메서드)
void power() { power = !power; } // TV를 켜거나 끄는 기능을 하는 메서드
void channelUp() { ++channel; } // TV의 채널을 높이는 기능을 하는 메서드
void channelDown() { --channel; } // TV의 채널을 낮추는 기능을 하는 메서드
}
class TvTest {
public static void main(String args[]) {
Tv t; // Tv 인스턴스를 참조하기 위한 변수 t를 선언
t = new Tv(); // Tv 인스턴스를 생성
t.channel = 7; // Tv 인스턴스의 멤버변수 channel의 값을 7로 설정
t.channelDown(); // Tv 인스턴스의 메서드 ChannelDown() 호출
System.out.println("현재 채널은 " + t.channel + " 입니다.");
}
}
Tv t;
- TV 클래스 타입의 참조변수 t선언
⇒ 메모리에 참조변수 t를 위한 공간 마련 → 인스턴스가 생성되지 않아 참조변수 자체로는 아무 것도 할 수 없다!
t = new Tv();
- 연산자 new에 의새 Tv 클래스의 인스턴스가 메모리의 빈 공간에 생성
⇒ 위와 같은 주소(가정)에 각 자료형의 기본값으로 초기화가 이루어진다
- t.channel = 7
- 대입연산자에 의해 초기값이 변경된다
- t.channelDown();
t가 참조하는 Tv 인스턴스의 channelDown() 메서드를 호출한 후, channel에 저장된 값을 1을 감소시키게 된다.
인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수 타입은 인스턴스의 타입과 일치해야 한다.
특징
- 같은 클래스로부터 생성되더라도, 각 속성은 서도 다른 값을 유지가 가능하다
- t1 = t2
- 위의 예시의 경우, 참조변수는 주소를 저장하게 된다.
따라서, 각각 같은 값을 가리키는 것이 되므로, t1이 기존에 참조하던 인스턴스는 사용할 수 없다
- Tv t1, Tv t2를 생성하더라도, 서로 다른 값 유지가 가능하다.
⇒ 해당 내용은 가비지 컬렉터에 의해 자동적으로 메모리에서 제거된다
객체 배열
객체를 배열의 형태로 다루는 것 → 배열 안에는 각각의 객체의 주소가 저장된다
즉, 참조변수들을 하나로 묶은 참조 변수 배열이 저장될 것이다.
TV tv1, tv2, tv3;
TV[] tvArr = new Tv[3];
- 객체 배열 → 참조변수들의 배열이므로, 객체를 생성해서 사용해야 한다
클래스의 또 다른 정의
객체지향 이론 관점의 클래스 → 객체 생성을 위한 틀, 속성과 기능으로 정의됨
프로그래밍 관점에서의 클래스
데이터와 함수의 집합
변수 : 하나의 데이터를 저장할 수 있는 공간
배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
구조체 : 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
클래스 : 데이터와 함수의 결합(구조체 + 함수)
⇒ 객체지향 언어 → 변수와 함수를 하나의 클래스에 정의해, 관계가 깊은 변수와 함수를 함께 다룸
- C언어 → 문자열은 문자의 배열이 됨
- 자바 → 문자열은 클래스로 다루게 됨
⇒ C와는 다르게 문자열과 문자열을 다루는데 필요한 함수를 함께 묶을 수 있다.
private char[] value;
char[] val = value ;
위와 같이 사용하면서, 문자열을 다루는 함수까지 함께 불러오는 것이 가능하다.
사용자 정의 타입
프로그래밍 언어에서 제공하는 자료형 외에 프로그래머가 서로 관련 변수를 묶어 하나의 타입으로 새로 추가하는 것이 가능하다.
class Time{
int hour;
int minute;
float second;
}
제어문을 사용해, 내부에서 유효성을 조건문으로 점검한 후 유효한 값일때만 변경하는 등의 작성 또한 가능하다.
변수와 메서드
선언 위치에 따른 변수의 종류
변수의 종류 → 클래스 변수
, 인스턴스 변수
, 지역 변수
⇒ 각각의 변수는 선언된 위치에 따라 결정 → 어느영역에서 선언되었는지 확인이 필요하다.
class Variables
{
int iv; // 인스턴스 변수
static int cv; // 클래스 변수
void method()
{
int lv = 0; // 지역변수
}
}
인스턴스 변수
- 멤버 변수 중 static이 붙지 않은 것을 말한다.
- 클래스 영역 선언 → 인스턴스 생성 시 만들어진다
⇒ 인스턴스 변수의 값을 활용하기 위해서는 인스턴스 생성이 필요해진다
- 인스턴스 → 독립적인 저장공간, 서로 다른 값을 가지게 된다.
⇒ 인스턴스마다 고유한 상태 유지하며, 인스턴스 변수로 선언할 수 있다.
클래스 변수
- 멤버 변수 중 static이 붙은 것을 말한다.
- 인스턴스 → 독립적인 저장공간, 클래스 변수 → 공통된 저장 공간을 공유한다.
⇒ 한 클래스 안에 모든 인스턴스들이 공통된 값을 유지해야 하는 경우에 사용한다.
- 인스턴스를 생성하지 않고도 바로 사용이 가능하다. 따라서, class 이름. class 변수의 형태로 사용한다.
- 클래스가 메모리에 로딩될때 생성 → 종료될 때 까지 유지된다.
- public → 프로그램 내에서 어디서나 접근 가능한 전역변수가 된다.
지역 변수
- 멤버변수를 제외한 나머지 변수를 말한다.
- 멤버변수 → class 영역에서 선언된 변수를 말한다.
- 생성시기 : 변수 선언문이 수행되었을 때에 생성된다.
- 메서드 내에서만 사용 가능, 메서드 종료시 소멸되어 사용 불가능하다.
클래스 변수와 인스턴스 변수
- 클래스 변수 → Card c1, c2가 있을 때 c1 c2에서 값을 공유한다
⇒ c1의 클래스 변수 값을 변경할 때, c2의 클래스 변수의 값도 변화한다.
메서드
사용하는 이유
- 높은 재사용성
한번 만든 메서드는 몇번이고 호출 가능 → 타 프로그램에서 사용 가능
- 중복된 코드의 제거
같은 문장들이 여러번 나타나는 것을 방지 가능 → 코드가 짧고, 수정해야 할 코드 양의 감소
- 프로그램의 구조화
큰 규모의 프로그램 → 문장을 작업단위로 나누어 구조를 단순화 할 수 있다.
메서드의 선언과 구현
반환타입 메서드이름( argument ) // 선언부
{
//구현부
}
⇒ 함수를 만드는 방식과 동일하다. return하려는 타입과 반환타입을 일치시켜 작성하고, 메서드 이름은 변수명 작성 방식과 동일하다.
JVM의 메모리 구조
메서드 영역
- 클래스의 사용 → 클래스에 대한 정보를 해당 영역에 저장한다
⇒ 이때 클래스 변수도 해당 영역에 생성된다
힙
- 인스턴스가 생성되는 공간, 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 저장된다.
호출 스택
- 메서드의 작업에 필요한 메모리 공간을 제공한다.
- 메서드 호출 → 호출스택에 호출된 메서드를 위한 메모리 할당된다.
- 메모리 → 메서드가 작업을 수행하는 동안 지역변수, 연산의 중간결과 등을 저장
- 메서드의 작업 종류 → 할당된 메모리 공간 반환
기본형 매개변수와 참조형 매개변수
- 기본형 매개변수 → 변수의 값을 읽기만 가능
- 참조형 매개변수 → 변수의 값을 읽고 변경 가능
⇒ 포인터와 비슷하게 이해하기, 주소를 넘겨주는 참조형은 값을 변경이 가능하지만, 주소가 아닌 값을 복사해서 넘겨주는 기본형은 읽기만 가능한것과 같다. 즉, 원본에는 아무런 영향을 미칠 수 없다.
참조형 반환타입
static Data copy(Data d){
Data tmp new Data();
tmp.x = d.x;
return tmp;
}
메서드가 객체의 주소를 반환하는 것과 같다
클래스 메서드(static 메서드)와 인스턴스 메서드
클래스를 설계 시 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 Static을 붙인다
- 생성된 각 인스턴스는 독립적이다.
⇒ 따라서, 각 인스턴스의 변수는 서로 다른 값을 유지하게 된다.
⇒ 같은 값이 유지되어야 하는 변수는 static을 붙여 정의가 필요하다.
클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있다
- static이 붙은 변수는 클래스가 메모리에 올라갈 때 자동적으로 생성된다.
클래스 메서드는 인스턴스 변수를 사용할 수 없다
- 인스턴스 변수는 인스턴스가 존재해야 사용이 가능하다.
- 클래스 메서드 → 인스턴스 생성 없이 호출 가능
- 클래스 메서드 호출 시 인스턴스가 존재하지 않을 수 있음.
- ⇒ 따라서, 클래스 메서드에서 인스턴스 변수의 사용은 불가능하다.*
- 인스턴스 변수 or 인스턴스 메서드 → static이 붙은 멤버 사용하는 것이 가능
⇒ 인스턴스 변수의 존재 → static 변수가 이미 메모리에 존재한다는 것을 의미
메서드 내에서 인스턴스 변수를 사용하지 않는다면 static을 붙이는 것을 고려한다
- 인스턴스 변수 필요 X → static을 붙이는 것이 호출 시간이 짧아지게 됨.
클래스 멤버와 인스턴스 멤버간의 참조와 호출
void instanceMethod(){
}
static void staticMethod2(){
instanceMethod();// 에러! 인스턴스 메서드 호출 불가
}
- 클래스 멤버간의 참조나 호출 → 문제X
- 인스턴스 멤버 → 객체를생성한 후에만 참조 또는 호출 가능
⇒ 클래스 멤버의 인스턴스 멤버 참조/호출 → 객체 생성 필요
- 인스턴스 멤버간의 호출 → 문제X
⇒ 하나의 인스턴스 멤버 존재한다는 것은 인스턴스가 이미 생성되었다는 의미이다.
즉, 다른 인스턴스 멤버들도 존재한다는 것을 의미한다.
오버로딩(overloading)
자바 → 같은 이름을 가진 메서드가 있어도 매개변수의 개수, 타입이 다르면 같은 이름을 사용해서 메서드 정의 가능
오버로딩
한 클래스 내에서 같은 이름의 메서들르 여러개 정의하는 것
오버로딩의 조건
- 메서드 이름이 같아야 한다
- 매개변수의 개수 또는 타입이 달라야 한다
- ⇒ (2) 처럼 서로 달라야 구별이 가능해 오버로딩이 가능하다.
단, 반환타입은 오버로딩을 구현하는데 영향X, 오버로딩 메서드는 매개벼수에 의해서만 구별될 수 있다.
오버로딩의 장점
println의 경우 int타입에 대한 프린트, float 타입에 대한 프린트가 다 다르지만, 하나의 println을 사용한다. 따라서 기억에 대한 부담이 적어진다.
가변인자와 오버로딩
가변인자는 타입… 변수명과 같은 형식으로 선언한다.
public PrintStream printf(String format, Object... args)
- 가변인자는 매개변수 중에서도 제일 마지막에 선언한다.
String concatnate(String s1, String s2)
String concatnate(String s1, String s2, String s3)
String concatnate(String... str) //인자 수가 다를 때 이렇게 표현이 가능하다.
- 가변인자 → 내부적으로 배열 사용
⇒ 선언된 메서드 호출 시마다 배열이 새로 생성된다.
주의사항
static String concatenate(String delim, String... args)
static String concatenate(String... args)
- 가변인자를 사용한 메서드의 오버로딩 → 위처럼 구별이 어려워진다는 단점이 존재한다.
⇒ 따라서, 가변인자의 사용은 가급적 하지 않는 것이 좋다.
생성자
생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드를 말한다. 따라서 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시 실행되어야 할 작업을 위해 사용한다.
⇒ 인스턴스가 생성될때 초기화를 하기 위해 사용!
생성자의 조건
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 생성자는 리턴값이 없다.
- 연산자 new → 인스턴스 생성 ⇒ 생성자 생성은 X.
Card c = new Card();
- 연산자 new에 의해 메모리(heap)에 Card 클래스의 인스턴스 생성
- 생성자 Card()가 호출되어 수행
- 연산자 new의 결과로 생성된 Card 인스턴스의 주소가 반환되어 참조변수 c에 저장
기본 생성자
class Data1{
int value;
}
- 인스턴스 초기화 작업 요구 X → 생성자를 정의하지 않고 사용하는 것이 좋음
⇒ 위와같을 때에는 컴파일러가 제공하는 기본 생성자를 사용하게 된다.
매개변수가 있는 생성자
class Data2{
int value;
Data2(int x){ //매개변수가 있는 생성자
value = x;
}
}
Data2 d2 = new Data2()// 에러
Data2 d2 = new Data2(10); // 에러 X
- 정의된 생성자에 맞추어 초기화 진행 → value = x; 가 실행되기 위해 인자 전달 필요
⇒ 컴파일러 내 기본 생성자 추가 → 클래스 내에 생성자가 없을 때만 추가
생성자에서 다른 생성자 호출하기
아래 조건을 만족할 때, 생성자 간에도 서로 호출이 가능하다
- 생성자의 이름으로 클래스 대신 this를 사용한다
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫줄에만 호출이 가능하다
Car (String color){
door = 5; //첫번째줄
Car(color, "auto", 4); // 두번째 줄에서 타 생성자 호출
//this(color,"auto",4)의 형식을 지켜야 함
}
Car(String color, String gearType, int door){
this.color = color;
this.gearType = gearType;
this.door = door;
}
- 생성자의 매개변수 / 선언된 변수의 이름이 같을 때에는 구분하고자 인스턴스 앞에 this를 사용한다.
- this
- 인스턴스 자신을 가리키는 참조변수로 인스턴스의 주소가 저장된다.
- 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재한다.
- this(), this(매개변수)
생성자, 같은 클래스의 다른 생성자를 호출 시 사용한다.
변수의 초기화
명시적 초기화
int door = 4; // 기본형 변수의 초기화
Engine e = new Engine(); // 참조형 변수의 초기화
초기화 블럭
클래스 초기화 블럭
클래스 변수의 복잡한 초기화에 사용한다
인스턴스 초기화 블럭
인스턴스 변수의 복잡한 초기화에 사용한다
class InitBlock{
static{ //static을 붙인건 클래스 초기화 블럭}
{ //인스턴스 초기화 블럭 }
}
- 클래스 초기화 블럭 → 클래스가 메모리에 처음 로딩될 때 수행
- 기본값 → 명시적 초기화 → 클래스 초기화 블럭
- 인스턴스 초기화 블럭 → 생성자와 같이인스턴스를 생성할 때 마다 수행
- 기본값 → 명시적 초기화 → 인스턴스 초기화 블럭 → 생성자
'Language > Java' 카테고리의 다른 글
[JAVA의 정석] Chapter2-5. JAVA 문법 (0) | 2024.05.02 |
---|---|
[JAVA의 정석] Chapter1. 자바를 시작하기 전 (0) | 2024.05.02 |
보안 전공 개발자지만 대학로에서 살고 싶어요
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!