▶ 중첩 클래스 및 중첩 인터페이스를 사용하는 이유


- 자바는 객체 지향 프로그램으로 각 클래스가 관계를 맺으며 상호작용을 한다. 어떤 클래스는 많은 클래스와 상호작용을 하기도 하지만, 다른 어떤 클래스는 특정 클래스하고만 상호작용을 하기도 한다. 여러 클래스와 상호작용을 할 때는 해당 클래스를 독립적으로 생성하는 것이 좋지만, 특정 클래스하고만 상호작용을 할 경우 특정 클래스 내부에 해당 클래스를 생성하는 것이 효율적이다.


- 중첩 인터페이스는 해당 클래스와 깊은 상호작용을 하는 구현 클래스를 생성하기 위해 사용된다.




▶ 중첩 클래스(Nested Class)


- 하나의 클래스 내부에 선언된 다른 클래스를 의미한다. 즉, 포함되어지는 클래스이다.


- 두 클래스의 멤버간에 접근이 용이하다. 중첩 클래스는 자신을 포함하는 클래스의 모든 멤버에 접근할 수 있다. 즉, 접근 제한자가 private인 멤버라 할지라도 중첩 클래스는 접근할 수 있다.


- 불필요한 상호작용을 맺은 클래스들을 외부로부터 감춤으로써 코드가 간결해진다.



class ClassName {

class NestedClassName {

...

}

}





▶ 멤버 클래스


- 클래스의 멤버로서 선언되는 중첩 클래스


- 해당 클래스나 객체가 사용 중일 경우 재사용이 가능하다.


- 멤버 클래스도 하나의 클래스이기 때문에 컴파일하면 바이트 코드 파일(~.class)가 생성된다.


멤버 클래스의 바이트 코드 파일 이름 : 바깥클래스명$ 멤버클래스명.class

로컬 클래스의 경우 : 바깥클래스명$1 로컬클래스명.class


- 인스턴스 멤버 클래스


class A {

class B { ... } // A객체를 생성해야 B 중첩 클래스(인스턴스 멤버 클래스)를 사용할 수 있다.

}


  • 중첩 클래스를 포함한 클래스를 생성해야만 해당 중첩 클래스를 사용할 수 있다.
  • 정적 필드와 메소드는 선언할 수 없다.
  • 외부 클래스에서 인스턴스 멤버 클래스를 생성하려면 바깥 클래스를 먼저 선언(객체 생성)해야 한다.
- 정적 멤버 클래스


class A {

static class B { ... } // A 클래스로 바로 접근 가능한 B 중첩 클래스(정적 멤버 클래스)

}


  • 중첩 클래스를 포함한 클래스로 바로 접근 가능한 중첩 클래스
  • 모든 종류의 필드와 메소드를 선언할 수 있다.
  • 바깥 객체를 생성하지 않아도 바로 정적 멤버 클래스를 이용할 수 있다.



▶ 로컬 클래스

- 메소드 내부에서 선언된 중첩 클래스

- 메소드 실행 시에만 사용되며, 메소드가 종료되면 사라진다.

- 로컬 클래스는 접근 제한자(public, private, protected) 및 static을 붙일 수 없다. 메소드 내부에서 사용되므로 접근을 제한할 필요가 없기 때문이다.

- 정적 필드와 메소드를 선언할 수 없다.

- 로컬 클래스가 선언된 메소드는 new 연산자를 통해 객체를 생성해야 해당 로컬 클래스를 사용할 수 있다.

- 다음과 같이 비동기 처리를 위한 스레드 객체 생성 시 사용된다.

void method() {

class DownloadThread extends Thread { ... } //로컬 클래스

DownloadThread th = new DownloadThread(); // 선언과 초기화 필수

th.start();

}





▶ 중첩 클래스의 접근 제한


- 멤버 클래스

  • 인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드를 통해 객체를 생성하거나 인스턴스 메소드 내부에서 객체를 생성할 수 있지만 정적 필드나 메소드는 해당되지 않는다. 즉, 바깥 클래스의 정적 멤버에 포함될 수 없다.
  • 인스턴스 멤버 클래스 내부에서 바깥 클래스로 접근할 때 모든 필드와 메소드가 가능하다. 즉, 바깥 클래스의 정적 멤버에 접근가능하다.
  • 정적 멤버 클래스는 바깥 클래스의 모든 필드의 초기값으로 혹은 모든 메소드에서 객체를 생성할 수 있다.
  • 정적 멤버 클래스 내부에서는 바깥 클래스의 정적 필드와 메소드에만 접근할 수 있다. 즉, 바깥 클래스의 인스턴스 멤버에 접근할 수 없다.

- 로컬 클래스
  • 로컬 클래스 내부에서는 바깥 클래스로 제한 없이 접근할 수 있다.
  • 로컬 클래스에서 사용되는 매개변수와 로컬 변수는 모두 final 특성(최종값)을 갖는다.
☞ 로컬 클래스의 객체는 메소드 실행이 끝나도 힙 메모리에 남아있으므로 사용할 수 있지만, 메소드의 매개변수 및 로컬변수는 메소드 실행이 끝나면 사라지므로 로컬 객체에서 사용할 경우 에러가 발생한다. 해결 방법으로 컴파일 시 로컬 클래스에서 사용하는 매개변수 및 로컬변수는 로컬 클래스 내부의 기억장소에 두고 사용한다. 그러나 값이 수정되면 복사해 둔 기억장소가 변경되므로 이 문제를 해결하고자 변수를 final로 선언하여 수정을 맞는다. 쉽게 말해, final 로 선언된 매개변수와 로컬변수만 로컬 클래스에서 사용가능하다. 자바 8부터는 final 키워드 없이 선언되어도 여전히 값을 수정할 수 없는 final 특성을 갖는다.

☞ final 키워드의 존재 여부의 차이점은 로컬 클래스의 복사 위치이다. final 키워드가 있을 경우 로컬 클래스를 포함한 메소드 내부에서 지역 변수로 복사된다. 없을 경우 로컬 클래스의 필드로 복사된다.


- 중첩 클래스 내부에서 바깥 클래스의 객체 참조를 얻으려면 아래와 같이 선언해야한다.

바깥클래스명.this.필드명;

바깥클래스명.this.메소드명;




▶ 중첩 인터페이스(Nested Interface)


- 클래스의 멤버로 선언된 인터페이스


- 주로 UI(User Interface) 프로그래밍에서 이벤트를 처리할 때 사용된다. 즉 해당 이벤트를 처리하는 구현 클래스를 만드는 것이다.


class ClassName {

interface NestedInterfaceName {

...

}

}







 

 

무명 클래스(Anonymous class)

 

- 말그대로 몸체는 있으나 이름만 없는 클래스를 의미하며, 하나의 객체만 사용할 경우에 이용한다. , 한번만 사용가능하다.


클래스명 변수명 = new 클래스명 { 클래스 몸체 };

 

- 무명 클래스의 선언은 하나의 실행문이므로 끝에 세미콜론(;)이 무조건 붙는다.

 

- 클래스명에 올 수 있는 것은 상속받고자 하는 부모 클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 적어주면 된다.

 

- 무명클래스는 클래스를 정의하면서 동시에 객체를 생성하게 된다.

 

- 코드의 양을 줄일 수 있다는 장점이 있으나 코드가 난해해진다.

 

 

 

익명 구현 객체

 

- 무명클래스를 통해 인터페이스를 구현하고자 하는 일회성의 구현 객체를 말한다.

 

- 대부분 UI(user interface) 프로그래밍에서 이벤트를 처리하거나 임시 작업 스레드를 만들기 위해 익명 구현 객체를 많이 이용한다.

 

- 형식 


인터페이스타입 변수명 = new 인터페이스타입() {


//인터페이스에 선언된 추상메소드의 실체 메소드 선언


}; 



- 추가적으로 필드와 메소드도 선언이 가능하지만, 익명 객체 안에서만 사용할 수 있고, 해당 변수로는 접근할 수는 없다.







* 인스턴스(instance) 멤버 : 객체를 생성한 후 사용할 수 있는 필드와 메소드를 말한다. 이들은 각각 인스턴스 필드, 인스턴스 메소드라고 부른다. 인스턴스 멤버는 객체 소속된 멤버이기 때문에 객체 없이는 사용할 수 없다.

 

 - 외부 클래스에서 인스턴스 멤버로의 접근 : 외부에서 접근할 때는 객체의 주소가 들어간 참조 변수에 도트 연산자(.)를 통해 접근할 수 있다.

 


Car myCar = new Car(); //객체 생성

myCar.speed = 10; //도트 연산자를 통한 해당 객체의 인스턴스 필드로 접근


 

인스턴스 필드는 heap영역에 객체마다 따로 존재하고, 인스턴스 메소드는 객체 마다 존재하지 않고 메소드 영역에 저장되고 공유된다. 변수는 스택(Stack) 영역에 저장되고 참조 변수일 경우 스택 영역에서 힙 영역에 있는 객체의 주소를 가리킨다.

 


 - 해당 클래스에서 인스턴스 멤버로의 접근

객체 내부에서도 인스턴스 멤버에 접근하기 위해서는 this를 사용할 수 있다. , 객체는 자신을 “this"라고 한다. 따라서 this.필드명 = 데이터; 은 자신이 가지고 있는 필드에 데이터를 대입하는 것이다. 또는 this.메소드명(); 은 자신이 가지고 있는 메소드를 실행하는 것이다.

this를 사용하는 이유는 주로 생성자와 메소드의 매개 변수 이름이 해당 객체의 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시하기 위해서이다.

 


Car(String model) { //생성자

    this.model = model;

}

 

void setModel(String model) { //메소드

    this.model = model;

}




* 정적(static) 멤버 : 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 의미한다. 이들은 각각 정적 필드, 정적 메소드라고 부른다. 정적 멤버는 객체에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 클래스 멤버라 부르기도 한다. 따라서 클래스 로더가 클래스(바이트 코드)를 로딩해서 메소드 영역에 추가할 때 클래스별로 관리된다. 클래스의 로딩이 끝나면 바로 사용할 수 있다.

 

- 정적 멤버 선언 : 선언 시 static 키워드를 추가적으로 붙이면 된다.

 


public class 클래스명 {

//정적 필드

static int field1 = 10;

 

//정적 메소드

static 리턴타입 method1(int parameter) { .... }

}


- 정적 멤버 사용 : 클래스 이름과 함께 도트 연산자(.)로 접근한다. 원칙적으로는 클래스 이름으로 접근해야 하지만 객체 참조 변수로도 접근이 가능하다.

클래스명.필드;

클래스명.메소드();

참조변수명.필드;

참조변수명.메소드();

 

- 정적 초기화 블록 : 정적 필드는 객체 없이도 사용해야 하므로 객체 생성 시에만 실행되는 생성자에서는 초기화 할 수 없다. 따라서 정적 블록(block)을 제공한다.

 


static { //정적 블록

    ...

}


정적 블록은 클래스가 메모리로 로딩될 때 자동적으로 실행된다. 정적 블록은 클래스 내부에서 여러 개 선언되어도 상관없다. 선언된 순서대로 실행된다.

, 정적 블록 안에 객체 자신의 참조인 this키워드와 인스턴스 멤버를 절대 사용할 수 없다.

? 객체가 없어도 실행되기 때문이다.

 


public class 클래스명 {

static int info;

static String str;

 

static {

info = 100;

str = "안녕“ + "하세요.”;

      }

}


 

 

- 구분필드 선언 시 객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언하고, 객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 정적 필드로 선언하는 것이 좋다.

메소드 선언 시 인스턴스 필드를 이용해서 실행해야 한다면 인스턴스 메소드를 선언하고, 인스턴스 필드를 이용하지 않는다면 정적 메소드로 선언한다.

 

 

* 싱글톤(Singleton) : 전체 프로그램에서 단 하나의 객체만 만들고 싶은 경우에 이용된다. , 싱글톤은 단 하나만 생성되는 객체이다. 싱글톤을 만들려면 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 한다. , 생성자의 앞에 private라는 접근 제한자를 붙여주면 된다. 접근 제한자는 뒤에서 배울 것이다.

 

- 싱글톤 사용방법 : 자신의 타입인 정적 필드를 하나 선언하고 자신의 객체를 생성하여 초기화한다. 클래스 내부에서는 new 연산자 사용이 가능하다. 정적필드도 private 접근 제한자를 붙여 외부에서 필드값을 변경하지 못하게 한다.

 


public class 클래스명 {

//정적 필드

private static 클래스명 변수이름 = new 클래스();

 

//생성자

private 클래스명() { ... }

 

//정적 메소드

static 클래스명 정적메소드명() { //메소드이름은 getXXX로 하는 것이 좋다.

       return 변수이름

}

}


외부에서 객체를 얻기 위한 방법은 싱글톤 객체 내부에 있는 정적 메소드를 호출하는 것이다. 여기서 정적메소드는 단 하나의 객체만 리턴하기 때문에 다른 변수에서 호출해도 같은 객체를 가리키는 것이다.

 

클래스 변수1 = 클래스.정적메소드명();

클래스 변수2 = 클래스.정적메소드명();

 

변수1과 변수2같은 객체의 번지를 참조한다.

 

 

* final 필드와 상수(static final)


 - final 필드 : 최종적인 필드라는 의미로, final 필드는 초기값이 저장되면 바꿀 수가 없으므로 프로그램 내에서 수정이 불가능하다.

 - final 필드 선언 : 선언과 동시에 초기값을 주거나 생성자를 통해서 주는 방법 두 가지만 가능하다. 또한 final은 초기화되지 않을 경우 컴파일 에러가 발생한다.

 ex) 아이디나 주민등록번호와 같은 데이터를 저장할 때 사용된다.

 - final 적용 범위 : 필드, 메소드(해당 클래스 상속 시 오버라이딩 불가), 클래스(타 클래스 상속 불가)

 

 - 상수(static final) : 변하지 않는 데이터를 의미한다.

 - 상수의 선언 : 일반적으로 선언과 동시에 초기화하지만 복잡한 초기화일 경우 정적 블록을 통해 이루어지기도 한다. 상수의 이름은 모두 대문자로 작성하는 것이 관례이다.

ex) 원주율과 같은 데이터를 저장할 때 사용된다.

 - 상수의 범위 : 필드, 메소드(해당 클래스 상속 시 오버라이딩 불가), 초기화 블록(클래스가 초기화될 때 수행되고, main()함수보다 먼저 실행된다.)


 - 상수(static final)final은 유사해보이지만 엄연히 다르다.

final 필드는 객체마다 저장되고, 생성자의 매개값을 통해서 여러 가지 값을 가질 수 있지만, 상수는 객체마다 저장할 필요가 없기 때문에 클래스의 모든 객체가 공유하게 되는 공용성을 띄므로 객체를 생성하지 않아도 사용할 수 있다, 또한 불변의 값이므로 여러 가지 값으로 초기화될 수 없다. 상수를 클래스 변수라고 부르며, 클래스에 속한다고 표현한다.

 

 

* 패키지(package) :물리적인 형태는 파일 시스템의 폴더로 컴파일 과정에서 자동적으로 생성되는 폴더이다, 패키지는 클래스를 유일하게 만들어주는 식별자 역할을 한다. 클래스 이름이 동일하더라도 패키지가 다르면 다른 클래스로 인식한다.


- 패키지 선언 클래스의 첫 줄에 선언한다. 패키지의 계층을 구분할 때 도트 연산자(.)를 사용한다. , 이클립스는 선언이 없는 패키지를 default 패키지에 포함시킨다.

 


package 상위패키지.하위패키지; //패키지 선언


 

- 패키지 작성 규칙

  • 숫자로 시작해서는 안 되고, _, $를 제외한 문자를 사용해서는 안 된다.
  • java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용해서는 안 된다.  ex) java.awt.event;
  • 모두 소문자로 작성하는 것이 관례이다.

 

- 다른 패키지의 사용

첫 번째 방법은 패키지와 클래스를 모두 기술하는 것이다. 서로 다른 패키지에 동일한 클래스 이름이 존재하고, 두 패키지가 모두 import되어 있을 경우에는 꼭 필요한 방법이다.

 


//com.hankook패키지의 Tire클래스를 이용해서 필드를 선언하고 객체를 생성한 것이다.

com.hankook.Tire tire = new com.hankook.Tire();


 

두 번째 방법은 사용하고자 하는 패키지를 import문으로 선언하고, 객체를 생성할 때는 패키지명을 생략하는 것이다. , import 문이 작성되는 위치는 패키지 선언과 클래스 선언사이이다.

 


package com.mycompany;

 

import com.hankook.Tire;

// 또는 import com.hankook.*;

//여기서 *는 해당 패키지내의 모든 클래스를 import한다는 의미이다.

 

public class Car {

Tire tire = new Tire();

} 


주의할 점은 import 문으로 지정된 패키지까지만 허용된다. , 지정된 패키지의 하위 패키지의 클래스를 사용하고 싶다면 import문을 하나 더 사용해야 한다.

 

 

* 접근 제한자


 접근 제한자

적용 대상 

접근가능한 클래스 

public

클래스, 필드, 생성자, 메소드 

모두 허용 (다른 패키지 ok)

protected 

필드, 생성자, 메소드

다른 패키지라도 자식 클래스(상속)까지 허용

default

클래스, 필드, 생성자, 메소드 

같은 패키지에 소속된 클래스

private

필드, 생성자, 메소드

같은 패키지라도 해당 클래스만 허용


 - 접근 제한 정도 : public < protected < default < private

 - 접근 가능 범위 : public > protected > default > private



* 메소드(Method)


 - 일반적으로 객체 지향 프로그래밍에서 객체의 데이터는 객체 외부에서 직접적으로 접근하는 것을 막는다. 이는 정보 은닉이라는 특성이 있기 때문이다. 즉, 외부에서 변경할 경우 객체의 무결성이 깨어질 수 있기 때문이다.

 - 주로 객체 지향 프로그래밍에서는 메소드를 통해 데이터를 변경한다.

 - Setter 메소드는 setXXX(매개변수) 로 메소드 이름을 짓는 것이 관례이며, 외부에서 해당 객체의 데이터에 접근할 때 사용하는 메소드이다. 메소드는 매개값을 검증해서 유효한 데이터만 받아들일 수 있기 때문이다.


void setSpeed(double speed) { // 데이터를 설정하므로 리턴값이 없기 때문에 리턴 타입은 void로 한다.

if(speed < 0) {

this.speed = 0;

return;

} else {

this.speed = speed;

}

}



 - Getter 메소드는 getXXX() 로 메소드 이름을 짓는 것이 관례이며, 외부에 해당 객체의 데이터를 전달할 때 사용하는 메소드이다. 주로 필드값을 가공한 후 외부로 전달한다.


double getSpeed() { //전달할 데이터에 맞는 리턴타입을 써야한다.

double km = speed * 1.6;

return km;

}



 - 단, 필드 타입이 boolean인 데이터에 접근할 때는 Getter 메소드는 getXXX()의 형태가 아닌 isXXXX()로 시작하는 것이 관례이다.


private boolean stop;


//Getter

public boolean isStop() {

return stop;

}


//Setter

public void setStop(boolean stop) {

this.stop = stop;

}



* 이클립스에서는 필드 선언 후 메뉴에서 [source → Generate Getters and Setters] 를 선택하면 자동으로 만들어진다.



1. Object-Oriented Programming(객체 지향 프로그래밍)


 - 현실 세계를 모델링하여 소프트웨어도 객체 단위로 개발하는 방법이다.

 - 즉, 자동차도 부품이 있어야 조립되듯이 특정한 기능을 하는 소프트웨어 객체들을 조합하여 자기가 원하는 기능을 구현하는 것을 의미한다.

 - 절차 지향 프로그래밍처럼 데이터보다 함수(문제 해결 절차)에 집중하는 것이 아니라, 데이터와 알고리즘을 함께 고려하여 하나의 객체로 묶어서 하는 방법을 의미한다.


* 자바는 객체 지향 기법을 지원하지만, 절차 지향 기법을 지원하지 않는 것은 아니다. 실제 객체의 내부를 설계할 때 절차 지향 프로그래밍을 이용한다.



2. 객체 지향 프로그래밍의 특징


 - 캡슐화(Encapsulation) : 관련된 데이터와 알고리즘(코드)이 하나로 연관되어 잘 정리되어 있는 것으로 데이터와 알고리즘을 캡슐에 넣어서 포장한다는 것을 의미한다. 자바에서는 이 때 이 캡슐을 클래스라고 부른다.


 - 정보 은닉(Information hiding) : 캡슐화는 내부의 데이터를 캡슐로 보호하는 역할을 한다. 즉, 캡슐화를 통해 데이터를 감추고 외부 세계와의 상호작용은 메소드(함수)를 통해 이루어진다.


 - 상속 : 기존의 코드를 재활용하기 위한 기법으로 이미 작성된 클래스(부모 클래스)를 이어받아서 새로운 클래스(자식 클래스)를 생성하는 기법이다. 즉, 공통적으로 쓰이는 변수나 함수가 있다면, 하나의 클래스로 지정해놓고 세부적으로 변수나 함수를 덧붙여서 그 클래스를 포함하는 새로운 클래스를 작성할 때 사용된다.

예를 들어, Vehicle 이 부모 클래스이고, 나머지 Car, Truck, Bus의 경우 Vehicle의 속성을 물려받은 자식 클래스에 해당한다.


  ┌ Car

ex) Vehicle ─┼ Truck

  └ Bus



 - 다형성 : 객체가 구현한 기능(동작)이 상황에 따라 바뀌는 것을 의미한다. 예를 들어 Animal 클래스에서 speak() 라는 메소드(함수)가 있다면, Animal 클래스를 상속받은 Dog 클래스와 Cat 클래스가 있을 때 speak() 라는 하나의 메소드로 두 가지 동작을 구현할 수 있게 된다.



3. Class(클래스)


 - 객체를 찍어내는 틀 또는 설계도

 - 클래스로부터 만들어지는 각각의 객체를 그 클래스의 인스턴스(instance)라고 한다.

 - 객체를 만드는 과정을 인스턴스화라고한다.

 - 데이터와 알고리즘으로 이루어진다. 

 - 변수(필드)와 함수(메소드 or 생성자)의 기능을 정의한다.

 - 객체는 클래스로부터 new 연산자를 통해 생성되며, new 연산자는 힙(heap) 영역에 객체를 생성시킨 후, 객체의 주소를 리턴한다.

 


4. Object(객체)


 - 클래스를 선언하여 변수와 함수를 상태와 동작으로 구현한 객체를 생성한다.

 - 객체의 상태(state)란 객체의 속성을 의미하고, 객체의 동작(behavior)또는 행동은 객체가 취하는 기능(행위)를 의미한다.

 - 객체 안의 변수를 필드(field)라고 하고, 객체 안의 함수를 메소드(method)라고 부른다. 즉 객체는 필드와 메소드로 이루어져있다.

정리하자면, 필드란 객체의 속성을 나타내고, 메소드란 객체의 동작을 나타낸다.

 - 객체는 힙(heap)이라는 메모리 공간에서 생성된다.

 - 객체의 소멸 : 자바의 실행 환경은 사용이 끝난 객체를 스스로 판별하여 소멸시키고 그 객체가 가지고 있던 자원을 시스템에 반납시킨다. 예시로 객체를 가리키는 참조형 변수가 하나도 사용되지 않거나 소멸되거나 혹은 프로그램에서 의도적으로 null값을 설정했다면, 객체의 사용이 끝났다고 판단할 수 있다.



5. 클래스 선언 시 작성 규칙


 - 하나 이상의 문자로 이루어져야 한다. ex) Car, Sport

 - 첫 번째 글자는 숫자가 올 수 없다. ex) Car, 3Car(X)

 - '$', '_'외의 특수문자는 사용할 수 없다. ex) $Car, _Car, @Car(X)

 - 자바 키워드는 사용할 수 없다. ex) int(X), for(X)



6. 클래스의 구성멤버


 - 필드(Field) : 객체의 고유 데이터, 부품 객체, 상태 정보(속성)을 저장한다. 

  • 선언 형태는 변수(variable)와 비슷하나, 필드를 변수라고 부르진 않는다.
  • 필드는 객체에 소속도니 데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않는다.
  • 변수는 생성자와 메소드 내에서만 사용되고 생성자와 메소드가 실행 종료되면 자동 소멸된다. 그러나 필드는 모든 클래스 내부에서 사용되며, 객체가 소멸되어야 객체와 함께 사라진다.
  • 필드의 선언은 생성자와 메소드 사이나 앞과 뒤에서 존재할 수 있다. 단, 생성자와 메소드 블록 내부에 선언된 것은 필드가 아니라 로컬 변수(local variable)이다.
  • 필드도 변수처럼 자료형(type)이 존재하며, 참조형에는 대표적으로 배열, 클래스, 인터페이스가 올 수 있다.


 - 생성자(Constructor)클래스로부터 new 연산자를 사용하여 객체가 생성될 때 가장 먼저 호출되는 특별한 중괄호 블록(block)이다.

  • 생성자의 역할은 객체 생성 시 초기화를 담당한다.
  • 쉽게 말해서 가장 먼저 실행되는 메소드로 볼 수 있다.
  • 형태는 메소드와 다르다. 생성자의 이름은 무조건 클래스의 이름과 일치해야 하고 리턴타입이 없다.
  • 모든 클래스는 생성자가 반드시 존재하며, 매개변수를 달리하는 생성자 여러 개를 선언할 수 있다. 이것을 생성자 오버로딩이라고 한다.
  • 만약 생성자 선언을 생략하면, 컴파일러는 중괄호 블록 내용이 비어있는 기본 생성자(Default Constructor)를 바이트 코드에 추가한다.


 - 메소드(Method) : 객체의 동작에 해당하는 중괄호 블록(block)이다. 

  • 형태는 C언어의 함수와 비슷하며, 메소드는 호출되면 블록 안의 모든 코드들이 일괄적으로 실행된다. 
  • 메소드의 역할은 객체 간의 데이터 전달의 수단으로 사용된다. 
  • 외부로부터 매개값을 받거나 실행 후 어떤 값을 리턴할 수 있다.
  • 클래스 내부에 매개변수가 다르나 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩(overloading)이라고 한다.
  • 메소드 오버로딩의 조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다. 리턴 타입은 무관하다.



7. 객체의 필드와 메소드 접근


 - 객체의 외부에서 객체에 포함된 멤버(필드와 메소드)를 참조(접근)하려면 도트 연산자(.)를 사용한다.

 - ex) Car 객체의 speed라는 필드를 외부의 객체에서 접근할 때,


class 외부클래스 {

//객체는 참조형 변수로 선언된다. 객체의 주소를 가르키기 때문이다.

Car myCar = new Car(); //객체는 무조건 new 연산자를 통해 생성된다. 대입연산에 관하여 참조형 변수와 기본형 변수는 다르다.


myCar.speed = 100;


}

 - 객체 지향의 개념에서 보면 필드를 외부에서 직접 접근하는 것은 바람직하지 않다. 되도록 객체 내의 필드는 메소드를 통해서 간접적으로 접근하도록 클래스를 설계해야한다.



8. 문자열 객체


 - 문자열은 프로그램에서 많이 자료형으로 문자들의 나열이다. 결론적으로, 자바에서는 문자열을 저장할 수 있는 기본 자료형이 없다. 즉, 문자열은 객체로 취급된다.

 - 문자열은 String 클래스를 이용하여 객체로 생성된다.

 아래의 문장은 "Hello World!" 라는 문자열을 가진 String 클래스의 객체를 생성한 것이다. 이 때, s는 생성된 객체의 주소를 가리키는 참조형 변수이다.


String s = new String("Hello World!); //선언과 동시에 초기화


 - 문자열은 자주 사용되므로 new 연산자를 사용하지 않고 문자열 상수로 표기해도 자동적으로 객체가 생성된다.


String s = "Hello World!";


 - 객체의 메소드 호출 : 도트 연산자(.)를 사용한다.


String s = new String("Hello World!");

int size = s.length(); // 여기서 length()는 String클래스에서 제공하는 메소드이다.


 - 참조 변수끼리의 대입 연산


String s1 = "I am very strong";

String s2 = "You are good boy";


s2 = s1; //객체의 번지를 대입.


여기서 s1과 s2가 가리키고 있던 객체는 서로 다르다. 그러나 아래의 s2에 s1이 가리키는 객체의 번지를 대입하면서 s1과 s2는 같은 String 객체를 가리킨다. 



9. Garbage Collection(쓰레기 수집)


 - 자바 실행 환경이 해당 객체가 더 이상 사용되지 않는 다고 판단되면 소멸시키는 기능

 - stop-the-world : 쓰레기 수집(이하 GC)를 실행하기 위해 자바 가상 기계가 애플리케이션 실행을 멈추는 기능이다. 

stop-the-world가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 작업을 모두 중단한다. 그리고 GC작업이 종료된 후에 나머지 쓰레드가 작업을 다시 시작한다.(여기서 쓰레드는 프로그램의 실행흐름을 의미한다.) 어떤 경우라도 이 기능은 무조건 발생한다. 자바에서는 소스 코드에서 메모리를 확실하게 지정하거나 해제하지 않는다. 간혹 명시적으로 해제하는 방법은 해당 객체를 null로 지정하거나 System.gc()메소드를 호출하는 방법이 있으나, 후자의 경우 시스템의 성능에 영향을 크게 주기 때문에 되도록 사용하지 않는 것을 추천한다. 아무튼 자바에서는 개발자가 메모리를 확실히 해제하지 않기 때문에 쓰레기 수집 기능이 객체를 판별하여 소멸시키는 작업을 하는 것이다.





+ Recent posts