1 객체지향언어
1.1 객체지향언어의 역사
객체지향이론의 기본 개념
실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다!
초기에는 절차적 언어들이 대세였다
FORTRAN, COBOL
커져가는 프로그램의 규모 빨라지는 사용자들의 요구에 맞추기 위해 객체지향 방법론이 대안으로 떠올랐으며 그 입지를 점차 넓혀 가고 있다.
현재 자바가 1995년에 발표되고 90년대 말 인터넷의 발전과 함께 크게 유행하면서 객체지향언어는 프로그램 언어의 주류로 자리잡게 되었다.
1.2 객체지향언어
객체지향언어는 기존의 프로그래밍언어와 전혀 다른 것이 아니다!
기존의 프로그래밍 언어에 몇가지 새로운 규칙을 추가한 보다 발전된 형태의 것이다.
절차적 언어에 익숙한 사람이라면 자바의 객체지향적 인 부분만 새로 배우면 될 것이다.
1.2 객체지향언어
객체지향언어의 주요특징
코드의 재사용성이 높다
새로운 코드를 작성할때 기존의 코드를 이용하여 쉽게 작성이 가능
코드의 관리가 용이하다
코드간의 관계를 이용해서 적은 노력으로 쉽게 코드 변경이 가 능
신뢰성이 높은 프로그래밍이 가능하다
제어자와 메서드를 이용해서 데이터를 보안과 정합성을 유지하 도록 하며 코드의 중복을 제거하여 코드의 불일치로 인한 오동 작방지
1.2 객체지향언어
객체지향 프로그래밍은 프로그래머에게 거시적 관점 에서 설계할 수 있는 능력을 요구한다.
설령 객체지향개념을 이해했다 하더라도 이를 이용한 프로 그램작성은 쉬운 일이 아니다.
너무 처음부터 객체지향 개념에 얽매여서 고민하기 보다는 일단 프로그램의 기능적인 부분을 먼저 고려한 다음,
어떻게 하면 보다 객체지향적인 코드로 개선할 수 있는지 로 고민하여 점차 개선해 나가는 것이 좋다.
2 클래스와 객체
2.1 클래스와 객체의 정의와 용도
객체 정의서 또는 객체의 청사진
클래스는 객체를 생성하는 데에 사용됨 : 용도
즉, 객체는 클래스에 정의된 대로 생성됨 : 클래스의 정의
객체의 사전적 정의 : 실제로 존재하는 것
그러나 프로그래밍에서는 유형적인 실존재하는 사물뿐 아니라
개념과 논리같은 무형의 것도 객체로 간주가 가능하다
프로그래밍에서의 객체
클래스에 정의된대로 메모리에 생성된 것을 의미
클래스와 객체와의 관계
예) TV설계도(클래스) TV(객체)
예) 건축설계도(클래스) 건축물(객체)
예) 붕어빵기계(클래스) 붕어빵(객체)
2.2 객체와 인스턴스
클래스로 부터 객체를 만드는 것을 인스턴스화라고 한다
특정 클래스로 부터 만들어진 객체를 인스턴스라고 한다
예를 들어 TV 클래스로 부터 만들어진 객체를 TV클래스 의 인스턴스라고 한다.
객체와 인스턴스는 비슷한 의미이지만
객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있으 며,
인스턴스는 어떤 클래스로 부터 만들어진 것인지를 강조하는 보다 구체적인 의미를 갖고 있다.
2.3 객체의 구성요소 : 속성과 기능
객체는 속성과 기능의 두 가지 요소를 지닌다.
속성 : 멤버변수, 특성, 필드, 상태
기능 : 메서드, 행위, 함수
예를 들어 TV의 경우,
속성으로는 전원상태, 크기, 길이, 높이, 색상, 볼륨, 채널등
기능으로는 끄기, 켜기, 볼륨높이기, 볼륨 낮추기, 채널변경 하기
객체지향언어에서는 속성과 기능을 각각 변수와 함수로 표현한다.
속성 멤버변수
기능 메서드
2.3 객체의 구성요소 : 속성과 기능
위의 내용을 바탕으로 TV클래스를 만들면 다음과 같다.
class TV{
String color;
boolean power;
int channel;
void power(){~}
void channelUp(){~}
void channerlDown(){~}
}
2.4 인스턴스의 생성과 사용
TV class의 인스턴스를 만드는 법
클래스명 변수명;
변수명 = new 클래스명(); //생성자라는 표현이 더 정확 하다
예
TV tv;
tv= new TV();
2.4 인스턴스의 생성과 사용
TV class를예로들어설명
class TV {
// Tv의속성(멤버변수)
String color;// 색상
boolean power;// 전원상태(on/off)
int channel;// 채널
// Tv의기능(메서드)
//TV를켜거나끄는기능을하는메서드
void power() {
power = !power;
}
//TV의채널을높이는기능을하는메서드
void channelUp() {
++channel;
}
// TV의채널을낮추는기능을하는메서드
void channelDown() {
--channel;
}
}
2.4 인스턴스의 생성과 사용
TV class를 테스트
class TVTest{
public static void main(Stringargs[]) {
TV t;// Tv인스턴스를참조하기위한변수t를선언
t = new TV();//Tv인스턴스를생성한다.
t.channel= 7;//Tv인스턴스의멤버변수channel의값을7로한다.
t.channelDown();//Tv인스턴스의메서드channelDown()을호출한다.
System.out.println("현재채널은"+t.channel+ " 입니다.");
}
}
결과
현재 채널은 6입니다.
2.4 인스턴스의 생성과 사용
예제를 그림과 함께 단계별로 살펴보겠다.
TV t;
TV 클래스 타입의 참조변수 t를 선언한다. 메모리에 참조변수 t를 위한 공간이 마련된다.
t = new TV();
연산자 new에 의해 TV 클래스의 인스턴스가 메모리의 빈공간에 저장됨
주소가 0X100인 곳에 생성되고 멤버변수는 자료형의 기본값으로 초기 화된다.
t
0X100
0X100
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
t.channel = 7;
참조변수 t에 저장된 주소에 있는 인스턴스의 멤버변수 channel에 7을 저장한다.
인스턴스의 멤버변수(속성)를 사용하려면 참조변수.멤버변 수와 같이한다
0X100
0X100
null : color
t
false : power
7 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
t.channelDown();
참조변수t가참조하고있는TV인스턴스의channelDown 메서드를 호출
channelDown 메서드는 멤버변수 channel에 저장되어 있는 값을 1감소
channelDown()에 의해서 channel은 7에서 6이 된다.
0X100
0X100
null : color
t
false : power
6 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
System.out.println(“현재 채널은 “ + t.channel + “ 입니다.”);
참조변수 t가 참조하고 있는 channel에 저장된 값을 출력 한다.
channel의 값은 6이므로 현재 채널은 6입니다가 출력된 다.
인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참 조변수의 타입은 인스턴스의 타입과 일치해야 한다!
2.4 인스턴스의 생성과 사용
TV class를 테스트(2)
class TvTest2 {
public static void main(Stringargs[]) {
TV t1 = new TV();
TV t2 = new TV();
System.out.println("t1의channel값은" + t1.channel + "입니다.");
System.out.println("t2의channel값은" + t2.channel + "입니다.");
t1.channel = 7; // channel 값을7으로한다.
System.out.println("t1의channel값을7로변경하였습니다.");
System.out.println("t1의channel값은" + t1.channel + "입니다.");
System.out.println("t2의channel값은" + t2.channel + "입니다.");
}
}
2.4 인스턴스의 생성과 사용
TV class를 테스트(2)
결과
t1의 channel값은 0입니다.
t2의 channel값은 0입니다.
t1의 channel값을 7로 변경하였습니다.
t1의 channel값은 7입니다.
t2의 channel값은 0입니다.
2.4 인스턴스의 생성과 사용
두번째 예제도 그림과 함께 단계별로 살펴보겠다.
TV t1 = new TV();
TV t2 = new TV();
TV 클래스 타입의 참조변수 t1, t2를 선언한다. 메모리에 참조변수 t1, t2를 위한 공간이 마련된다.
아울러 new에 의해 TV 클래스의 인스턴스가 메모리의 빈공간에 저장
주소가 0X100, 0X200인 곳에 생성되고 멤버변수는 자료형의 기본값으 로 초기화된다.
0X100
0X100
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
0X200
0X200
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
t1.channel = 7;
t1이 가리키고 있는 인스턴스의 멤버변수 channel의 값 을7로변경!
0X100
0X100
null : color
t
false : power
7 : channel
power();
channelUp();
channelDown();
0X200
0X200
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
TV class를 테스트(3)
class TvTest3 {
public static void main(Stringargs[]) {
Tvt1 = new Tv();
Tvt2 = new Tv();
System.out.println("t1의channel값은" + t1.channel + "입니다.");
System.out.println("t2의channel값은" + t2.channel + "입니다.");
t2 = t1;
t1.channel = 7; // channel 값을7으로한다.
System.out.println("t1의channel값을7로변경하였습니다.");
System.out.println("t1의channel값은" + t1.channel + "입니다.");
System.out.println("t2의channel값은" + t2.channel + "입니다.");
}
}
2.4 인스턴스의 생성과 사용
TV class를 테스트(3)
결과
t1의 channel값은 0입니다.
t2의 channel값은 0입니다.
t1의 channel값을 7로 변경하였습니다.
t1의 channel값은 7입니다.
t2의 channel값은 7입니다.
2.4 인스턴스의 생성과 사용
세번째 예제도 역시 그림과 함께 단계별로 살펴보겠다.
TV t1 = new TV();
TV t2 = new TV();
TV 클래스 타입의 참조변수 t1, t2를 선언한다. 메모리에 참조변수 t1, t2를 위한 공간이 마련된다.
아울러 new에 의해 TV 클래스의 인스턴스가 메모리의 빈공간에 저장
주소가 0X100, 0X200인 곳에 생성되고 멤버변수는 자료형의 기본값 으로 초기화된다.
0X100
0X100
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
0X200
0X200
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
t2 = t1;
t1은 참조변수여서 주소값을 저장하고 있다.
위 코드의 의미는 t1의 주소값을 t2에 저장하게끔 하느 것이다.
따라서 t2역시 t1이 참조하고 있는 인스턴스를 참조한다.
0X100
0X100
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
0X200
0X200
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
t1.channel = 7;
t1이 가리키고 있는 인스턴스의 멤버변수 channel의 값 을7로변경!
0X100
0X100
null : color
t
false : power
7 : channel
power();
channelUp();
channelDown();
0X200
0X200
null : color
t
false : power
0 : channel
power();
channelUp();
channelDown();
2.4 인스턴스의 생성과 사용
System.out.println(t1.channel);
System.out.println(t2.channel);
t1이 참조하는 인스턴스와 t2가 참조하는 인스턴스가 동 일하다.
따라서 결과 값은 같은 7이 된다.
2.5 클래스의또다른정의
클래스는 객체를 생성하기 위한 틀
클래스는 속성과 기능으로 정의되어 있다.
클래스
데이터와 함수의 집합
언어상 데이터 처리를 위한 데이터 저장형태의 발전과정은 다음 과 같다.
변수 배열 구조체 클래스
변수 : 하나의 데이터를 저장할 수 있는 공간
배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
구조체 : 서로 관련된 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
클래스 : 데아터와 함수의 결합(구조체 + 함수)
2.5 클래스의또다른정의
클래스 : 사용자정의 타입
언어에서 제공하는 기본 자료형 외에 프로그래머가 서로 관련된 변수들을묶어서하나의타입으로새로추가하는것
기본형은 8개로 정해져 있음에 비해 참조형은 사용자가 필요에 의 해 추가가 가능하기 때문에 개수가 정해져 있지 않다.
예
int hour;
int minute;
float second;
시간을 표현 하기 위해서 3개의 변수를 선언하였다.
만일 3가지의 시간을 표현해야 한다면 다음과 같아야 할 것이다.
int hour1, hour2, hour3;
int minute1, minute2, minute3;
float second1, second2, second3;
2.5 클래스의또다른정의
클래스 : 사용자정의 타입(계속)
아니면 다음과 같이 해야 할 것이다.
int[] hour = new int[3];
int[] minute = new int[3];
float[] second = new float[3];
그러나 이러한 방법도 시, 분, 초가 서로 분리되어 있어 프로 그램 수행중에 서로 따로 뒤섞여서 올바르지 않은 데이터가 될 가능성이 있다.
이럴 경우 시, 분, 초를 묶는 하나의 사용자정의 타입, 즉 클 래스를 정의하여 사용해야 한다.
class Time{
int hour;
int minute;
float second;
}
2.5 클래스의또다른정의
클래스 : 사용자정의 타입(계속)
위와 같이 클래스를 정의하면 시, 분, 초가 하나의 단위로 묶여지기 때문에 다른 데이터와 섞이는 문제는 없겠지만, 다음의 추가적인 제약조건이 있다.
시, 분, 초는 모두 0보다 크거나 같아야 한다.
시의 범위는 0~23, 분과 초의 범위는 0~59이다.
이러한 조건들을 객체지향언어에서는 접근제어자와 메서 드를 이용하여 코드에 쉽게 반영할 수 있다.
아직 자세히 소개하지는 않았지만 위의 조건들을 반영한 클래스는 다음과 같다.
2.5 클래스의또다른정의
완성된 Time 클래스
public class TimeTest {
private int hour;
private int minute;
private float second;
public int getHour() {
return hour;
}
public void setHour(inthour) {
if(hour< 0 || hour > 23) return;
this.hour= hour;
}
public int getMinute() {
return minute;
}
public void setMinute(intminute) {
if(minute< 0 || minute > 59) return;
this.minute= minute;
}
public float getSecond() {
return second;
}
public void setSecond(floatsecond) {
if(second< 0 || second > 59) return;
this.second= second;
}
}
3 변수와 메서드
3.1 선언된 위치에 따른 변수의 종류
변수의 종류 : 클래스변수, 인스턴스변수, 지역변수
이의 구분은 ‘변수의 선언된 위치’
멤버변수를 제외한 나머지는 모두 지역변수 이며
멤버변수 중 static이 붙은 것은 클래스변수,
붙지 않은 것은 인스턴스변수이다.
아래의 예에는 모두 3개의 int형 변수가 선언되어 있다.
class Variables{
int iv;
static int cv;
void method(){
int lv= 0;
}
}
iv는 인스턴스변수, cv는 클래스변수, lv는 로컬변수이다.
3.1 선언된 위치에 따른 변수의 종류
변수의 생성시기
변수의 종류
선언위치
생성시기
클래스변수
클래스영역
클래스가 메모리에 올라갈때
인스턴스변수
클래스영역
인스턴스가 생성되었을때
지역변수
클래스이외의 영역
(메서드, 생성자, 초기화 블럭내)
변수 선언문이 수행되었을때
3.1 선언된 위치에 따른 변수의 종류
인스턴스 변수
선언위치 : 클래스영역
생성시기
클래스의 인스턴스를 생성할때
따라서 인스턴스 변수의 값을 읽어 오거나 저장하기 위해서는 인 스턴스를 생성해야 함
특징
인스턴스는 독립된 저장공간을 가지므로 서로 다른 값을 가질 수 있슴
인스턴스마다 고유한 상태를 유지해야 하는 속성의 경우 인스턴 스변수로 선언하여 사용
3.1 선언된 위치에 따른 변수의 종류
클래스 변수
선언방법 : 변수 앞에 static을 붙이면 됨
특징
인스턴스 변수가 인스턴스마다 독립적인 공간을 가지는 것과는 달리, 클래스변수는 모든 인스턴스가 공통적인 저장공간(변수)를 공유하게 됨
따라서 클래스변수를 공유변수(shared variables)라고도 함
인스턴스 변수는 인스턴스를 생성해야 사용이 가능하지만, 클래 스변수는 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다.
클래스명.클래스변수와 같은 형식으로 사용할 수 있다.
3.1 선언된 위치에 따른 변수의 종류
지역변수
선언위치 : 메서드 내
특징
메서드내에서만 사용이 가능 : 메서드가 종료되면 소멸된다.
for, while문에 선언된 변수는 {}안에서만 유효하다.
반드시 초기값을 지정해 주어야 한다 : 안되면 컴파일에러 발생!
3.2 클래스변수와 인스턴스변수
예제
class CardTest{
public static void main(String[] args){
System.out.println("Card.width= " + Card.width);
System.out.println("Card.height= " + Card.height);
Card c1 = new Card();
c1.kind = "Heart";
c1.number = 7;
Card c2 = new Card();
c2.kind = "Spade";
c2.number = 4;
System.out.println("c1은" + c1.kind + ", " + c1.number + "이며, 크기는(" + c1.width + ", " + c1.height + ")");
System.out.println("c1은" + c2.kind + ", " + c2.number + "이며, 크기는(" + c2.width + ", " + c2.height + ")");
c1.width = 50;
c1.height = 80;
System.out.println("c1은" + c1.kind + ", " + c1.number + "이며, 크기는(" + c1.width + ", " + c1.height + ")");
System.out.println("c1은" + c2.kind + ", " + c2.number + "이며, 크기는(" + c2.width + ", " + c2.height + ")");
}
}
3.2 클래스변수와 인스턴스변수
예제(계속)
class Card{
String kind;
int number;
static int width = 100;
static int height = 250;
}
결과
Card.width = 100
Card.height = 250
c1은 Heart, 7이며, 크기는 (100, 250)
c1은 Spade, 4이며, 크기는 (100, 250)
c1은 Heart, 7이며, 크기는 (50, 80)
c1은 Spade, 4이며, 크기는 (50, 80)
3.2 클래스변수와 인스턴스변수
해설
Card 클래스의 클래스변수인 width, height는 Card 클 래스의 인스턴스를 생성하지 않고도 ‘클래스명.클래스변수’ 와 같은 방식으로 사용이 가능하였다.
Card.width와 Card.height
그리고 Card 클래스의 인스턴스인 c1과 c2는 클래스 변 수인 width와 height를 공유하기 때문에
c1.width = 50;
c1.height = 80;
으로 변경하면 c2가 참조하는 값 역시 같으므로 같은 결 과를 얻게 된다.
3.2 클래스변수와 인스턴스변수
결론
인스턴스변수는 인스턴스가 생성될때 마다 생성되므로 인 스턴스마다 각기 다른 값을 유지할 수 있지만,
클래스변수는 모든 인스턴스가 하나의 저장공간을 공유하 므로, 항상 공통되 값을 가진다.
3.3 메서드
정의 : 특정 작업을 수행하기 위한 명령문의 집합
주로 어떤 값을 받아서 처리하고 그 결과를 되돌려 준다.
경우에 따라서는 어떤 값을 받지 않을 수도 있고 결과를 반환하지않을수도있다.
3.3 메서드
메서드를 사용하는 이유
반복적으로 사용되는 코드를 줄이기 위해서 자주사용하는 코드를 메서드로 작성해 놓고 필요한 곳에서 호출하면 되 기 때문이다.
코드의 양도 줄이고 한곳에 모으면 관리가 편하다.
즉,
하나의 메서드는 한가지 기능만 수행하도록 작성하는 것이 좋다.
반복적으로 수행되어야 하는 여러 문장을 하나의 메서드로 정의 한다.
관련된 여러 문장을 하나의 메서드로 만들어 놓는 것이 좋다.
이렇게 되면 프로그래머는 내부 코드를 몰라도 호출할 줄 만알면프로그램을작성할수있다.
3.3 메서드
구조
선언부
구현부
선언부
접근지정자
리턴타입
메서드의 수행결과를 어떤 자료형으로 반환할지 알려주는 것
리턴타입이 없으면 void라고 표현한다.
메서드명
매개변수 : 괄호안에 싸여있다.
구현부
메서드가 호출되었을때 수행되어야 할 코드
리턴문 : 없을 때도 있다.
3.4 return 문
메서드가 정상적으로 종료되는 경우는 다음의 두 가지
메서드의 블럭내에 있는 모든 문장을 수행한 경우
메서드 블럭내의 문장을 수행중 return문을 만난 경우
3.4 return 문
반환값의 여부에 따라
반환값이 없는 경우 : return문만 써주면 된다.
return;
반환값이 있는 경우 : return뒤에 반환값을 지정해 주면 된 다.
return 반환값;
반환값이 있는 경우 반환값은 메서드의 선언부에 정의된 반 환타입과 일치하거나 자동형변환(upcasting)이 가능하여야 한다.
int add(int a, int b){
int result = a + b;
return result;
}
타입이 일치해야 한다.
3.4 return 문
예제
int add(inta, int b){
if(a> b) return a;
}
이 경우 return이 있지만 컴파일 오류가 발생한다.
if문의 조건식의 결과에 따라 return문이 실행될 수도 그렇지 않을 수 도 있기 때문이다.
이처럼 반환값이 있는 메서드의 경우 어떠한 경우라도 return문에 의해 결과가 반환되어야 한다.
위의 메서드는 아래와 같이 수정되어야 한다.
int add(inta, int b){
if(a> b) return a;
else return b;
}
3.5 메서드의 호출
메서드의 호출방법
참조변수.메서드명();
매개변수가 없는 메서드
참조변수.메서드명(값1, 값2, …)
매개변수가 있는 메서드
즉, 매개변수를 맞추어 호출하면 된다.
단, 클래스메서드(static 메서드)의 경우 다른 일반 메서드 를 호출할 수는 없다!
이는 차후에 설명하기로 한다.
3.5 메서드의 호출
예제
class MyMath{
long add(longa, long b){
return a+b;
}
long subtract(longa, long b){
return a -b;
}
long multiply(longa, long b){
return a * b;
}
double divide(doublea, double b){
return a / b;
}
}
3.5 메서드의 호출
예제(계속)
class MyMathTest{
public static void main(Stringargs[]){
MyMathmm = new MyMath();
long result1 = mm.add(5L, 3L);
long result2 = mm.subtract(5L, 3L);
long result3 = mm.multiply(5L, 3L);
double result4 = mm.divide(5L, 3L);
System.out.println("add(5L, 3L) = " + result1 + ", subtract(5L, 3L) = " + result2);
System.out.println("multiply(5L, 3L) = " + result3 + ", divide(5L, 3L) = " + result4);
}
}
결과
add(5L, 3L) = 8, subtract(5L, 3L) = 2
multiply(5L, 3L) = 15, divide(5L, 3L) = 1.6666666666666667
3.5 메서드의 호출
예제 설명
메서드를 호출할 때에는 매개변수의 자료형을 고려하여 호출하여야 한다.
여기서 divide(double a, double b)를 호출하는 코드에 주목
정작 호출은 이렇게 하였다.
divide(5L, 3L)
컴파일 에러도 없었고 정상적으로 수행도 되었다.
이는 long의 자료형이 자동적으로 double 타입으로 자동형변환 이 가능하기 때문에 별 이상 없이 호출이 가능하였다.
3.6 JVM의 메모리구조
JVM의 메모리 관리 영역 세가지
메서드영역
호출스택
힙메모리
3.6 JVM의 메모리구조
메서드영역
프로그램 실행 중 사용되는 클래스의 정보(메타정보)를 로드
아울러 클래스변수(static variable)도 이 영역에 저장됨
힙메모리
인스턴스가 생성되는 공간
프로그램 실행 중 생성되는 인스턴스는 모두 여기에 저 장됨
호출스택
메서드의 작업에 필요한 공간을 제공
메서드 호출
호출스택에 메서드를 위한 메모리 할당
메서드수행시 지역변수들과 연산의 중간결과 저장에 사용됨
3.6 JVM의 메모리구조
호출스택
메서드들 간의 작업 공간은 서로 구별됨
호출스택 메모리의 메카니즘
맨 처음 호출된 메서드의 공간은 제일 하단에 마련된다.
첫 메서드 수행중 다른 메서드를 호출하는 경우
호출된 메서드의 바로 위에 두번째 메서드의 공간이 마련됨
그리고 두번째 메서드가 수행된다
수행이 마치면 두번째 메서드에 할당된 메모리 공간은 소멸
첫번째 메서드가 계속 수행됨
메서드 수행이 완료되면 호출스택상의 메모리는 소멸된다
3.6 JVM의 메모리구조
호출스택
class CallStackTest{
public static void main(String[] args) {
firstMethod();
}
static void firstMethod() {
secondMethod();
}
static void secondMethod() {
System.out.println("secondMethod()");
}
}
3.6 JVM의 메모리구조
CallStackTest class 를 실행했을 때 호출 스택의 변화
3.6 JVM의 메모리구조
CallStackTest class 를 실행했을 때 호출 스택의 변화
(1)~(2) 위의예제를컴파일한후실행시키면, JVM에의해서main 메 서드가호출됨으로써프로그램이시작된다. 이때, 호출스택에는 main메서드를위한메모리공간이할당되고main 메서드의코드가 수행되기시작한다.
(3) main메서드에서firstMethod()를호출한상태이다. 아직main메서 드가끝난것은아니므로main 메서드는호출스택에대기상태로남 아있고firstMethod()의수행이시작된다.
(4) firstMethod()에서secondMethod()를호출했다. firstMethod()는 secondMethod()가수행을마칠때까지대기상태에있게된다. secondMethod()가수행을마쳐야firstMethod()의나머지문장들 을수행할수있기때문이다.
3.6 JVM의 메모리구조
CallStackTest class 를 실행했을 때 호출 스택의 변화
(5) secodnMethod()에서println() 메서드를호출한다. println()메서드 에의해서‘secondMethod()’가화면에출력된다.
(6) println()메서드의수행이완료되어호출스택에서사라지고자신을 호출한secondMethod()로되돌아간다. 대기중이던 secondMethod()는println()메서드를호출한이루부터수행을재 개한다.
(7) secondMethod()에더이상수행할코드가없으므로종료되고, 자 신을호출한firstMethod()로돌아간다.
(8) firstMethod()에도더이상수행할코드가없으므로종료되고, 자신 을호출한main메서드로돌아간다.
(9) main메서드에서도더이상수행할코드가없으므로종료되어호출스 택은완전히비워지게되고프로그램은종료된다.
3.7 기본형 매개변수와 참조형 매개변수
메서드를 호출할 때 매개변수로 지정한 값을 메서드 의 매개변수에 복사해서 넘겨준다.
기본형 매개변수의 경우 : 기본형 값이 복사됨
참조형 매개변수의 경우 : 인스턴스의 주소값이 복사됨
메서드의 매개변수를 기본형으로 하면 단순히 저장된 값을 가질 수 있지만,
참조형으로 선언하면 값이 저장된 곳의 주소를 알 수 있기때문에값을읽어오는것은물론값을변경하 는 것도 가능하다.
3.7 기본형 매개변수와 참조형 매개변수
class Data { int x; }
class ParameterTest {
public static void main(String[] args) {
Data d = new Data();
d.x= 10;
System.out.println("main() : x = " + d.x);
change(d.x);
System.out.println("Afterchange(d.x)");
System.out.println("main() : x = " + d.x);
}
static void change(intx) { // 기본형매개변수
x = 1000;
System.out.println("change() : x = " + x);
}
}
결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 10
3.7 기본형 매개변수와 참조형 매개변수
class Data { int x; }
class ParameterTest2 {
public static void main(String[] args) {
Data d = new Data();
d.x= 10;
System.out.println("main() : x = " + d.x);
change(d);
System.out.println("Afterchange(d) main() : x = " + d.x);
}
static void change(Datad) { // 참조형매개변수
d.x= 1000;
System.out.println("change() : x = " + d.x);
}
}
3.7 기본형 매개변수와 참조형 매개변수
결과
main() : x = 10
change() : x = 1000
After change(d) main() : x = 1000
두 예제에서 큰 차이점을 발견하지 못할 수도 있다.
다만 참조형변수를 매개변수로 받아들였을 경우에는 해당 클래스의 멤버에 접근 할 수 있다는 사실에 주 목하였으면 한다.
3.8 클래스 메서드와 인스턴스 메서드
메서드 앞에 static이 붙어있으면 클래스 메서드이다.
클래스메서드는 클래스 변수와 같이 클래스명.메서드 명과 같은 식으로 호출이 가능
인스턴스메서드는 반드시 객체를 생성한 후 호출이 가능함.
인스턴스메서드는 인스턴스변수와 밀접한 관계를 가 지고 있는 경우가 많다.
따라서 인스턴스변수를 사용하는 메서드는 인스턴스메서드 로 선언하는 것이 옳다.
반면, 인스턴스변수와 관계가 없는 메서드의 경우 클래스메 서드로 정의하면 된다.
꼭 그럴 필요는 없지만 되도록 그러는게 좋은 권고 사항이다.
3.8 클래스 메서드와 인스턴스 메서드
클래스변수, 클래스메서드
클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용하는 멤버(변수, 메서드)에 static 을 붙인다.
클래스변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
static이 붙으면 클래스가 메모리에 로딩도리때 이미 같 이 자동적으로 로딩되기 때문이다.
3.8 클래스 메서드와 인스턴스 메서드
클래스변수, 클래스메서드
클래스메서드는 인스턴스 변수를 사용할 수 없다.
클래스메서드는 인스턴스 생성없이 호출이 가능하다.
반면 인스턴스 변수는 인스턴스 생성이 되어야 사용할 수 있 다.
따라서 클래스메서드가 직접적으로 인스턴스 변수를 사용할 때 인스턴스의 생성이 안되어 있을 위험이 내포되어 있어 문 법적으로 사용을 금지시켰다.
단, 메서드내에서 직접 인스턴스를 생성한 후에는 접근이 가 능하다.
메서드내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
클래스의 멤버변수 중 모든 인스턴스가 공유해야 하는 것이 있다면 static으로 선언해야 한다.
3.8 클래스 메서드와 인스턴스 메서드
class MyMath2 {
long a, b;
// 인스턴스변수a, b만을이용해서작업하므로매개변수가필요없다.
long add() { return a + b; } // a, b는인스턴스변수
long subtract() { return a -b; }
long multiply() { return a * b; }
double divide() { return a / b; }
// 인스턴스변수와관계없이매개변수만으로작업이가능하다.
static long add(longa, long b) { return a + b; } // a, b는지 역변수
static long subtract(longa, long b) { return a -b; }
static long multiply(longa, long b) { return a * b; }
static double divide(doublea, double b) { return a / b; }
}
3.8 클래스 메서드와 인스턴스 메서드
class MyMathTest2 {
public static void main(Stringargs[]){
// 클래스메서드호출
System.out.println(MyMath2.add(200L, 100L) + ", " + MyMath2.subtract(200L, 100L));
System.out.println(MyMath2.multiply(200L, 100L) + ", " + MyMath2.divide(200.0, 100.0));
MyMath2 mm = new MyMath2();
mm.a= 200L;
mm.b= 100L;
// 인스턴스메서드는객체생성후에만호출이가능함.
System.out.println(mm.add() + ", " + mm.subtract() + ", " + mm.multiply() + ", " + mm.divide());
}
}
3.8 클래스 메서드와 인스턴스 메서드
결과
300, 100
20000, 2.0
300, 100, 20000, 2.0
클래스메서드와 그렇지 않은 메서드의 용법에 주 목하기 바란다!
동일 클래스내의 멤버간에는 별도의 인스턴스를 생성 하지 않고도 서로 참조와 호출이 가능하다.
그러나 클래스멤버(static멤버)가 인스턴스 멤버를 호출할 때에는 인스턴스 생성이 필수적이다!
class TestClass{
void instanceMethod(){}
static void staticMethod(){}
void instanceMethod2(){
instanceMethod();
staticMethod();
}
static void staticMethod2(){
instanceMethod();//complieerror!
staticMethod();
}
}
3.9 클래스멤버와 인스턴스 멤버간의 참조와 호출
3.9 클래스멤버와 인스턴스 멤버간의 참조와 호출
위의 예제에서 static method에서 non-static인 즉 인스턴스 메서드를 호출했을 때에 컴파일 에러가 발 생한다.
이는 메서드 뿐만이 아니라 인스턴스 변수에도 접근 이 불가하다.
class TestClass2{
int iv;
static int cv;
void instanceMethod2(){
System.out.println(iv);
System.out.println(cv);
}
static void staticMethod2(){
System.out.println(iv);//compile error!
System.out.println(cv);
}
}
클래스멤버는 언제나 참조 및 호출이 가능하기 때문 에 인스턴스 멤버가 클래스 멤버를 사용하는 것은 문 제 없다.
그러나 인스턴스 멤버는 반드시 인스턴스를 생성한 후에야 사용(호출 및 참조)이 가능하기 때문에 클래스 멤버가 인스턴스멤버를 호출 및 참조하기 위해서는 반드시 인스턴스를 생성해야 한다.
3.9 클래스멤버와 인스턴스 멤버간의 참조와 호출
4 메서드 오버로딩
4.1 메서드 오버로딩이란?
한 클래스 내에 같은 이름의 메서드를 여러 개 정의
자바에서는 메서드의 구분을 이름으로 하는 것이 아니다.
메서드의 구분은 매개변수의 자료형과 개수에 따른다.
오버로딩은 과적하다라는 의미
하나의 메서드 이름에 하나의 기능만을 구현해야 하는데 하 나의 메서드 이름으로 여러 기능을 구현하기 때문에 붙여진 이름이다.
4.2 메서드 오버로딩의 조건
1.
메서드명이 같아야 한다.
2.
매개변수의 개수 또는 타입이 달라야 한다
3.
매개변수는 같고 리턴타입이 다른 경우는 오버로딩이 성립되지 않는다.
리턴타입은 오버로딩을 구현하는데 아무런 영향이 없다!
4.3 메서드 오버로딩의 예
가장 대표적인 것은 println 메서드이다.
이 메서드의 ()안에 값만 지정해 주면 화면에 출력하는데에 아 무런 어려움이 없다.
하지만 실제로는 println 메서드를 호출할 때 매개변수로 지정 하는 값의 타입에 따라 호출되는 println메서드가 달라진다.
PrintStream 클래스에는 어떤 종류의 매개변수를 지정해도 출 력할 수 있도록 다음과 같이 10개의 println 메서드를 정의해 놓았다.
void println()
void prinrln(boolean x)
void prinrln(char x), void prinrln(char[] x)
void prinrln(double x), void prinrln(float x)
void prinrln(int x), void prinrln(long x)
void prinrln(Object x), void prinrln(String x)
4.3 메서드 오버로딩의 예
매개변수의 이름만 다른 경우
오버로딩이 아니다.
int add(inta, int b){
return a+b;
}
int add(intx, int y){
return x+y;
}
이 두 메서드는 매개변수의 이름만 다를 뿐이지 실제로는 같은 메서드이다.
컴파일을 하면 같은 메서드가 이미 선언되어 있다는 오류 메시 지가 보일 것이다.
add(int,int) is already defined
4.3 메서드 오버로딩의 예
리턴타입만 다른 경우
오버로딩이 아니다.
int add(inta, int b){
return a+b;
}
long add(inta, int b){
return a+b;
}
이 경우도 다른 메서드가 아니다.
매개변수의 개수와 타입이 일치하기 때문이다.
4.3 메서드 오버로딩의 예
매개변수의 자료형이 다른 경우
오버로딩이다.
long add(inta, int b){
return a+b;
}
long add(longa, long b){
return a+b;
}
이 경우 매개변수의 타입이 다르기 때문에 오버로딩이 성립된다.
즉, 컴파일시 아무런 문제가 안된다.
4.3 메서드 오버로딩의 예
매개변수의 개수가 다른 경우
오버로딩이다.
long add(inta, int b){
return a+b;
}
long add(inta, int b, int c){
return a+b+c;
}
이 경우 매개변수의 개수가 다르기 때문에 오버로딩이 성립된다.
즉, 이 역시 컴파일시 아무런 문제가 안된다.
4.3 메서드 오버로딩의 예
같은 일을 하지만 매개변수를 달리해야 하는 경우에 는 이와 같이 이름은 같고 매개변수를 달리하여 구현 한다.
int add(inta, int b){returna+b;}
long add(longa, long b){returna+b;}
int add(int[] a){
int result = 0;
for(inti=0; i<a.length; i++){
result += a[i];
}
return result;
}
정의된 매개변수가 다르다고 해도 모두 매개변수로 넘겨받 은 값을 더해서 그 결과를 돌려주는 역할을 한다.
4.4 메서드 오버로딩의 장점
만일 메서드의 구분을 메서드명으로만 한다면?
println 메서드는 다음과 같이 바뀌었어야 할 것이다.
void println()
void prinrlnBoolean(boolean x)
void prinrlnChar(char x), void prinrlnCharArray(char[] x)
void prinrlnDouble(double x), void prinrlnFloat(float x)
void prinrlnInt(int x), void prinrlnLong(long x)
void prinrlnObject(Object x), void prinrlnString(String x)
즉, 이런 경우 매개변수에 맞게 호출하지 않으면 안된다.
그러나 오버로딩 기법 때문에 우리는 여러 개의 println 메 서드를 마치 하나의 메서드인양 호출이 가능한 것이다.
5 생성자
5.1 생성자란?
생성자는 인스턴스가 생성될 떄 호출되는 인스턴스를 초기화 하기 위한 메서드이다.
따라서 인스턴스 변수의 초기화 작업에 주로 사용되 며 인스턴스 생성시에 실행되어야 할 작업을 위해서 사용된다.
생성자의 특징은 다음과 같다.
클래스의 이름과 동일하다.
리턴타입이 없다
그렇다고 void라고 해도 안 된다.
5.1 생성자란?
형태
클래스이름(매개변수, 매개변수…){
//인스턴스생성시수행될코드
//주로인스턴스변수의초기화코드를넣는다!
}
5.1 생성자란?
연산자 new가 인스턴스를 생성하는 것이지 생성자가 인 스턴스를 생성하는 것이 아니다.
생성자라는 용어 때문에 오해가 생기기가 쉽다.
단순히인스턴스변수들의초기화에사용되는조금특별 한 메서드일 뿐이다.
예를 들어 Card 클래스의 인스턴스를 생성하는 코드를 예를 들어 수행되는 과정을 단계별로 나누어 보면 다음과 같다.
Card c = new Card();
1.
연산자new에의해서메모리(heap)에Card 클래스의인스턴스가생성
2.
생성자 Card()가호출되어수행된다.
3.
연산자new의결과로, 생성된Card인스턴스의주소가반환되어참조변수 c에저장된다.
5.2 기본생성자(Default Constructor)
지금까지는 생성자를 모르고 프로그래밍을 해 왔지만 사실 모든 클래스에는 하나 이상의 생성자가 있어야 한다.
그러나 이제까지 확인한 예제에는 생성자가 없었다.
그 이유는 바로 컴파일러가 제공한 기본생성자 때문이었다.
기본생성자란 소스파일에 아무런 생성자가 지정되지 않은 경우 컴파일러가 자동적으로 추가해 주는 매개 변수가 하나도 없는 생성자를 의미한다.
그래서 예제에 특별한 생성자를 작성하지 않아도 되 는 것이었다.
5.2 기본생성자(Default Constructor)
class Data1 {
int value;
}
class Data2 {
int value;
Data2(int x) { // 매개변수가있는생성자.
value = x;
}
}
class ConstructorTest {
public static void main(String[] args) {
Data1 d1 = new Data1();
Data2 d2 = new Data2(); // compile error발생
}
}
5.2 기본생성자(Default Constructor)
컴파일 결과
ConstructorTest.java:15: cannot find symbol
symbol : constructor Data2()
location: class Data2
Data2 d2 = new Data2();// compile error발생
^
1 error
설명
Data2 클래스에는 Data2()라는 생성자가 없다.
기본생성자가 자동적으로 추가되는 경우는 해당 클래스에 생성자가 하 나도 정의되어 있지 않았을 경우만이다.
그래서 Data2 d2 = new Data2();의 코드가 에러가 발생하는 것이다.
컴파일 에러를 없앨 려면,
Data2 클래스에 매개변수 없는 생성자를 추가하거나,
아니면 Data2 d2 = new Data(10);와 같이 d2를 초기화해야 한다.
5.3 매개변수가 있는 생성자
생성자도 메서드와 같이 매개변수를 선언하여 호출시 값을 넘겨 받아 인스턴스의 초기화작업에 사용이 가 능하다.
이는 자바에서는 인스턴스의 초기화 방법을 다양하게 할 수 있는 방법을 제공한다고 이해하면 될 것이다.
다음의 예제를 보자
5.3 매개변수가 있는 생성자
class Car{
String color;
String gearType;
int door;
Car(){}
Car(Stringc, String g, int d){
color = c;
gearType= g;
door = d;
}
}
5.3 매개변수가 있는 생성자
설명
Car 클래스는 세 개의 인스턴스 변수와 두 개의 생성자로 구성되었다.
Car 클래스의 인스턴스를 만들 때 생성자 Car()를 사용한 다면 인스턴스를 생성한 후 별도로 세 개의 인스턴스변수 를 초기화 시켜줘야 한다.
그러나 Car(String, String, int)를 사용한다면 인스턴스의 초기화 동시에 원하는 값으로의 변수 초기화를 도모할 수 있다.
즉,
Car c = new Car();
c.color= “white”;
c.gearType= “auto”;
c.door= 4;와
Car c = new Car(“white”, “auto”, 4);중
어느코드가더직관적이고간결한지생각해보면될것이다.
5.3 매개변수가 있는 생성자
class CarTest{
public static void main(String[] args) {
Car c1 = new Car();
c1.color = "white";
c1.gearType = "auto";
c1.door = 4;
Car c2 = new Car("white", "auto", 4);
System.out.println("c1의color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
System.out.println("c2의color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
}
}
결과
c1의 color=white, gearType=auto, door=4
c2의 color=white, gearType=auto, door=4
5.4 생성자에서 다른 생성자 호출하기 – this()
같은 클래스의 멤버 메서드를 서로 호출이 가능 한 것 처럼 생성자도 호출이 가능하다.
단, 다음의 조건을 만족해야 한다.
생성자의 이름으로 클래스명 대신 this()를 사용한다.
한 생성자에서 다른 생성자 호출시 반드시 생성자의 맨 첫 줄에서 호출한다.
class Car2 {
String color; // 색상
String gearType; // 변속기종류-auto(자동), manual(수동)
int door; // 문의개수
Car2() {
this("white", "auto", 4);
}
Car2(String color) {
this(color, "auto", 4);
}
Car2(String color, String gearType, int door) {
this.color= color;
this.gearType= gearType;
this.door= door;
}
}
5.4 생성자에서 다른 생성자 호출하기 – this()
예제
class CarTest2 {
public static void main(String[] args) {
Car2 c1 = new Car2();
Car2 c2 = new Car2("blue");
System.out.println("c1의color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
System.out.println("c2의color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
}
}
결과
c1의color=white, gearType=auto, door=4
c2의color=blue, gearType=auto, door=4
설명
생성자 Car(), Car(String) 모두 Car(String, String, int)를 호출함
이의 호출시 this()를 사용하는 것이다.
5.4 생성자에서 다른 생성자 호출하기 – this()
5.5 this의 다른 용법
첫번째
다음의 예를 보자
Car2(String color, String gearType, int door) {
this.color= color;
this.gearType= gearType;
this.door= door;
}
이렇게 매개변수와 인스턴스변수가 이름이 중복되는 경우 가종종발생한다.
이 경우 인스턴스변수 앞에 this를 붙이면 매개변수와의 구 별이 용이하다.
이것이 this의 다른 용법 중 하나이다.
5.5 this의 다른 용법
두번째
자기 자신을 참조할 수 있는 참조값
클래스를 만들고(디자인) 있을 때 클래스 내부에서만 사용할수있 는 가상의 참조 변수
메모리가 생성된 후가 아니라 클래스를 만들고 있을 때 사용할 수 있는 가상의 참조 변수이다.
즉, this의 정의란
언젠가 생성될 객체의 참조 값을 의미한다.
5.5 this의 다른 용법
두번째 : 예제
class TopThis{
public void printSelf(){
System.out.println(this); //클래스내에서this 사용
}
} //end of TopThisclass
public class TopThisMain{
public static void main(String[] args){
TopThist1 = new TopThis(); //객체의메모리생성
System.out.println("t1객체:" + t1); //t1 객체출력
t1.printSelf(); //메모리가생성된후this 출력
TopThist2 = new TopThis(); //객체의메모리생성
System.out.println("t2객체:" + t2); //t2 객체출력
t2.printSelf(); //메모리가생성된후this 출력
} //end of main
} //end of TopThisMainclass
5.5 this의 다른 용법
this의다른용법: 두번째
결과
t1객체:TopThis@c17164
TopThis@c17164
t2객체:TopThis@1fb8ee3
TopThis@1fb8ee3
설명
각 라인의 결과값은 실행시마다 달라질 것이다.
객체의 주소값을 나타내는 것이기 때문이다.
단 첫번째와 두번째라인, 세번째와 네번째 라인의 결과값 이 일치한 것에 유의하면 될 것이다.
6 변수의 초기화
6.1 변수의 초기화
변수를 선언하고 처음으로 값을 지정해 주는 것
경우에 따라 필수적이기도 선택적이기도 하지만 가능하면 선언과 동시에 적절한 초기값을 지정해 주는 것이 좋다.
변수의 선언위치에 따라 초기화의 선택여부가 결 정된다
인스턴스변수 : 초기화 하지 않아도 자동적으로 지정됨
지역변수 : 반드시 초기화를 해줘야 한다.
지역변수를 초기화 하지 않으면 컴파일단계에서 에러 가 발생한다.
6.1 변수의 초기화
인스턴스 변수는 초기화를 하지 않아도 자동적으로 값이 지정된다.
자료형
기본값
Boolean
false
char
‘\u0000’
byte
0
short
0
int
0
long
0L
float
0.0f
double
0.0d, 0.0
참조형
null
6.1 변수의 초기화
인스턴스변수의 초기화 방법에는 다음의 세가지 방 법이 있다.
명시적 초기화
생성자
초기화 블록
인스턴스 초기화 블럭
클래스 초기화 블럭
6.2 명시적 초기화
변수를 선언함과 동시에 초기화 하는 것
가장 기본적이면서 간단한 초기화 방법임
따라서 가장 우선적으로 프로그래밍 시 고려되어야 한다.
class Car{
int door = 4;
Engine e = new Engine();
…
}
6.3 초기화 블록
초기화 블록에는 클래스 초기화 블록과 인스턴스 초기화 블록 두 가지 종류가 있다.
클래스 초기화 블록 : 클래스 변수의 초기화에 사용
인스턴스 초기화 블록 : 인스턴스 변수의 초기화에 사용
만드는 방법
클래스내에 {}를 만들고 그 안에 코드를 작성하면 되며 클래스 초기화 블록인 그 앞에 static만 붙이면 된다.
실행시기
클래스 초기화 블록 : 클래스가 메모리에 처음 로딩될때 한번만 수행
인스턴스 초기화 블록 : 인스턴스가 생성될때 마다 실행
6.3 초기화 블록
용도
인스턴스 초기화 블록의 기능은 생성자와 비슷하기 때문 에 그다지 자주 사용되지 않는다.
다만 클래스내의 여러 생성자가 존재하고 여기에 공통적 으로 수행되어야 할 코드가 있는 경우 사용한다.
실행순서
클래스 초기화 블록이 먼저 수행되고 그 다음에 생성자 마지막으로 인스턴스 초기화 블록이 수행된다.
6.3 초기화 블록
class BlockTest{
static{System.out.println("static{ }");}
{System.out.println("{ }");}
public BlockTest() {
System.out.println("생성자");
}
public static void main(Stringargs[]) {
System.out.println("BlockTestbt= new BlockTest(); ");
Bl
ockTestbt= new BlockTest();
System.out.println("BlockTestbt2 = new BlockTest(); ");
BlockTestbt2 = new BlockTest();
}
}
6.3 초기화 블록
결과
static { }
BlockTest bt = new BlockTest();
{ }
생성자
BlockTest bt2 = new BlockTest();
{ }
생성자
초기화 블록과 생성자의 실행 순서에 주목하자
1.
클래스 초기화 블록
2.
생성자
3.
인스턴스 초기화 블록
6.4 멤버변수의 초기화 시기와 순서
초기화가 수행되는 시기와 순서
클래스변수의 초기화 시점
클래스가처음로딩될때단한번
인스턴스변수의 초기화 시점
인스턴스가 생성될때 마다 각 인스턴스 별로 초기화가 이루어 진다
클래스변수의 초기화 순서
기본값 명시적초기화 클래스 초기화 블록
인스턴스변수의 초기화 순서
기본값 명시적초기화 인스턴스 초기화 블록 생성자
6.4 멤버변수의 초기화 시기와 순서
프로그램이실행도중특정클래스에대한정보가 요구되어 질때 클래스는 메모리에 로딩된다.
예를 들면 클래스 멤버를 사용했을때 인스턴스를 생 성할때 등이 이에 해당한다.
하지만 해당 클래스가 이미 메모리에 로딩되어 있다 면 또다시 로딩되지 않으며 초기화도 다시 수행되지 않는다.
6.4 멤버변수의 초기화 시기와 순서
class Product {
static int count = 0; // 생성된인스턴스의수를저장하기위한변수
int serialNo; // 인스턴스고유의번호
{
++count;
serialNo= count;
}
public Product() {}
}
class ProductTest {
public static void main(Stringargs[]) {
Product p1 = new Product();
Product p2 = new Product();
Product p3 = new Product();
System.out.println("p1의serial no는" + p1.serialNo);
System.out.println("p2의serial no는" + p2.serialNo);
System.out.println("p3의serial no는" + p3.serialNo);
System.out.println("생산된제품의수는모두"+Product.count+"개입니다.");
}
}
6.4 멤버변수의 초기화 시기와 순서
결과
p1의serial no는1
p2의serial no는2
p3의serial no는3
생산된 제품의 수는 모두 3개 입니다.
count라는 클래스변수가 어떤 인스턴스가 생성되더라도 그 값을 공유한다는 것을 보여주는 예제이다.
6.4 멤버변수의 초기화 시기와 순서
class Document {
static int count = 0;
String name; // 문서명(Document name)
public Document() { // 문서생성시문서명을지정하지않았을때
this("제목없음, count = " + ++count);
}
public Document(Stringname) {
this.name= name;
System.out.println("문서" + this.name+ "가생성되었습니다.");
}
}
class DocumentTest {
public static void main(Stringargs[]) {
Document d1 = new Document();
Document d2 = new Document("자바.txt");
Document d3 = new Document();
Document d4 = new Document();
}
}
6.4 멤버변수의 초기화 시기와 순서
결과
문서 제목없음, count = 1가 생성되었습니다.
문서 자바.txt가 생성되었습니다.
문서 제목없음, count = 2가 생성되었습니다.
문서 제목없음, count = 3가 생성되었습니다.
이 예제도 역시 count라는 클래스변수가 어떤 인스턴스 가 생성되더라도 그 값을 공유한다는 것을 보여주는 예 제이다.