본문 바로가기

JAVA/이것이 자바다

Chapter .06-2 클래스

6.9 인스턴스 맴버와 this

- 객체(인스턴스) 마다 가지고 있는 필드와 메소드

   • 이들을 각각 인스턴스 필드, 인스턴스 메소드라고 부름

 

- 인스턴스 멤버는 객체 소속된 멤버이기 때문에 객체가 없이 사용불가

 

인스턴스(instance) 맴버란 객체(인스턴스)를 생성한 후 사용할 수 있는 필드와 메소드를 말하는데, 이들은 각각 인스턴스 필드, 인스턴스 메소드라고 부른다.

 

인스턴스 필드와 메소드는 객체에 소속된 멤버이기 때문에 객체 없이는 사용할 수 없다.

Car 클래스에 gas 필드와 setSpeed() 메소드가 다음과 같이 선언되어 있다고 가정해보자.

public class Car{
    // 필드
    int gas;     
    
    //메소드
    void setSpeed(int speed){
    }
}

 

gas필드와 setSpeed() 메소드는 인스턴스 멤버이기 때문에 외부 클래스에서 사용하기 위해서는 우선 Car 객체(인스턴스)를 생성하고 참조변수 myCar로 접근해야 한다.

Car mycar = new Car();
myCar.gas = 10;
myCar.setSpeed(60);

 

객체 외부에서 인스턴스 멤버에 접근하기 위해 참조 변수를 사용하는 것고 ㅏ마찬가지로 객체 내부에서도 인스턴스 맴버에 접근하기위해 this를 사용할 수 있다.

 

this.model은 자신이 가지고 있는 model 필드라는 것이다.

this는 주로 생성자와 메소드의 매개 변수 이름이 필드와 동일한 경우, 인스턴스 맴버인 필드임을 명시하고자 할 때 사용된다.

Car(String model){
	this.model = model;
}

void setModel(String model){
	this.model = model;
}

 

 

6.10 정적 멤버와 static

- 클래스에 고정된 필드와 메소드 - 정적 필드, 정적 메소드

 

- 정적 멤버는 클래스에 소속된 멤버

  • 객체 내부에 존재하지 않고, 메소드 영역에 존재

  • 정적 멤버는 객체를 생성하지 않고 클래스로 바로 접근해 사용

 

정적(static)은 "고정된" 이라는 의미를 가지고 있다.

정적 멤버는 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말한다.

 

6.10.1 정적 맴버 선언

정적 필드와 메소드를 선언하는 방법은 필드와 메소드 선언 시 static 키워드를 추가적으로 붙이면 된다.

정적 필드와 메소드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리된다. 따라서 클래스 로딩이 끝나면 사용할 수 있다.

 

6.10.2 정적 멤버 사용 

클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름과 함께 도트( . ) 연산자로 접근한다.

 

다음과 같이 Calculator 클래스가 작성 되어 있다고 가정하면 

public class Calculator{
    static double pi = 3.14195;
    static int plus(int x, int y){....}
    static int minus(int x, int y){....}
}

정적 필드 pi와 정적 메소드 plus(), minus는 아래와 같이 사용할 수 있다.

double result1 = 10 * 10 * Calculator.pi;
int result2 = Claculator.plus(10,5);
int result2 = Claculator.minus(10,5);

 

정적 필드와 메소드는 원칙적으로는 클래스 이름으로 접근해야 하지만 다음과 같이 객체 참조 변수로도 접근이 가능하다.

참조변수를 이용한 접근

 

6.10.3 정적 초기화 블록

정적 필드는 선언과 동시에 초기값을 주는 것이 보통이다.

static double pi = 3.14159;

그러나 계산이 필요한 초기 작업이 있을 수 있다.

인스턴스 필드는 생성자에서 초기화 하지만, 정적 필드느 ㄴ개겣 생성 없이도 사용해야 하므로 생성자에서 초기화 작업을 할 수 없다.

생성자는 객체생성 시에만 실행되기 때문이다.

 

그럼 초기화 작업을 어디서 해야 할까?

 

자바는 정적 필드 초기화를 위해 정적 블록을 제공한다.

정적 블록은 클래스가 메모리로 로딩될 떄 자동적으로 실행된다.

정적 블록은 클래스 내부에 여러개가 선언 되어도 상관없다.

클래스가 메모리로 로딩될 때 선언된 순서대로 실행된다.

public class Television{
    static String company = "samsung";
    static String model = "LCD";
    static String info;
    
    static{
    	info = company + model;
    }
}

info 필드에는 company변수와 model 변수가 연결된 samsungLCD가 저장된다.

 

6.10.4 정적 메소드와 블록 선언시 주의점

- 객체가 없어도 실행 가능

- 블록 내부에 인스턴스 필드나 인스턴스 메소드 사용 불가

- 객체 자신의 참조인 this 사용 불가

  • EX) main()

 

 

6.10.5 싱글톤(Singleton)

- 하나의 애플리케이션 내에서 단 하나만 생성되는 객체

 

가끔 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다.단 하나만 생성된다고 해서 싱글톤이라고 한다.

 

싱글톤을 만들려면 클래스 외부에서 new 연산자로 생성자를 호출 할 수 없도록 막아야 한다.생성자를 호출한 만큼 객체가 생성되기 때문이다.

 

public class 클래스{

	//정적필드
    private static 클래스 singleton = new 클래스();

	//생성자
    private 클래스(){  }
    
    //정적 메소드
    static 클래스 getInstance(){
    	return singleton;
    }

}

 

외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 방법이다.getInstance() 메소드는 단 하나의 객체만 리턴하기 때문에 아래 코드에서 변수1과 변수2는 동일한 객체를 참조한다.

클래스 변수1 = 클래스.getInstance();
클래스 변수2 = 클래스.getInstance();

 

6.11 final 필드와 상수

6.11.1 final 필드

- 최종적인 값을 갖고 있는 필드 = 값을 변경할 수 없는 필드

- final 필드의 딱 한번의 초기값 지정 방법

  • 필드 선언 시

  • 생성자

 

 

6.11.2 상수(static final)

- 상수 = 정적 final 필드

  • final 필드:

     - 객체마다 가지는 불변의 인스턴스 필드

  • 상수(static final):

    - 객체마다 가지고 있지 않음

    - 메소드 영역에 클래스 별 로 관리되는 불변의 정적 필드

    - 공용 데이터로서 사용

 

- 상수 이름은 전부 대문자로 작성

 

- 다른 단어가 결합되면 _ 로 연결

 

정적 블록에서도 초기화가 가능하다.

static final 타입 상수 [= 초기값];

static final 타입 상수;
static{
	상수 = 초기값;
}

 

 

6.12 패키지

프로잭트를 개발하다 보면 적게는 수십 개, 많게는 수백개의 클래스를 작성해야 한다.

클래스를 체계적으로 관리하기 위해 패키지(package)를 사용한다.

 

- 클래스를 기능별로 묶어서 그룹 이름을 붙여 놓은 것

  • 파일들을 관리하기 위해 사용하는 폴더(디렉토리)와 비슷한 개념

  • 패키지의 물리적인 형태는 파일 시스템의 폴더

- 클래스 이름의 일부

  • 클래스를 유일하게 만들어주는 식별자

  • 전체 클래스 이름 = 상위패키지.하위패키지.클래스

  • 클래스명이 같아도 패키지명이 다르면 다른 클래스로 취급

 

 

6.12.1 패키지 선언

패키지는 클래스를 컴 파일 하는 과정에서 자동적으로 생성되는 폴더이다.

컴파일러는 클래스에 포함되어 있는 패키지 선언을 보고, 파일 시스템의 폴더로 자동 생성시킨다.

package 상위패키지.하위패키지;

public class ClassName{.....}

 

패키지 명명 규칙

 - 숫자로 시작해서는 안되고, _,$를 제외한 특수문자를 사용해서는 안된다.

 - java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용해서는 안된다.

 - 모두 소문자로 작성하는것이 관례이다.

 

 

6.12.4 import문

같은 패키지에 속하는 클래스들은 아무런 조건 없이 다른 클래스를 사용할 수 있다.

하짐나 다른 패키지에 속한 클래스를 사용하기 위해서는 두가지 방법 중 하나를 선택해야 한다.

1) 패키지와 클래스를 모두 기술한다.

2) 사용하고자 하는 package를 import문으로 선언하고 클래스를 사용할 때는 패키지를 생략한다.

 

//1번방법
package com.mycompany;

public class Car{
	com.hankook.Tire tire = new com.hankook.Tire();
}

//2번방법
package com.mycompany;

import com.hankook.Tire;

public class Car{
	Tire tire = new Tire();
}

 

 

6.13 접근 제한자

- 클래스 및 클래스의 구성 멤버에 대한 접근을 제한하는 역할

  • 다른 패키지에서 클래스를 사용하지 못하도록 (클래스 제한)

  • 클래스로부터 객체를 생성하지 못하도록 (생성자 제한)

  • 특정 필드와 메소드를 숨김 처리 (필드와 메소드 제한)

 

main() 메소드를 가지지 않는 대부분의 클래스는 외부 클래스에서 사용할 목적으로 설계된 라이브러리 클래스이다.

라이브러리 클래스를 설계할때에는 외부 클래스에서 접근할 수 있는 멤버와 접근 할 수 없는 멤버로 구분해서 필드, 생성자, 메소드를 설계하는 것이 바람직하다.

 

접근제한자 종류

접근제한자 종류

 

 

6.14 Getter와 Setter 메소드

클래스 선언할 때 필드는 일반적으로 private 접근 제한

 - 읽기 전용 필드가 있을 수 있음 (Getter의 필요성)

 - 외부에서 엉뚱한 값으로 변경할 수 없도록 (Setter의 필요성)

 

예를들어 자동차의 속도는 -가 될 수 없는데 -로 변경하려고 한다면 무결성이 깨지게 된다.

setSpeed() 메소드로 변경할 경우 다음과 같이 검증 코드를 작성할 수 있다.

void setSpeed(double speed){
	if(speed <0){
    	this.speed = 0;
        return;
    }else{
    	this.speed= speed;
    }
}

 

메소드로 필드 값을 가공한 후 외부로 전달하기 위해 getter를 사용한다.

double getSpeed(){
    double km = speed*1.6;   // 필드 값인 mile을 km단위로 환산 후 리턴
    return km;
}

 

 

6.15 어노테이션 (Annotation)

- 프로그램에게 추가적인 정보를 제공해주는 메타데이터(metadata)

- 어노테이션 용도

  • 컴파일러에게 코드 작성 문법 에러 체크하도록 정보 제공

  • 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동 생성하게 정보 제공

  • 실행 시(런타임시) 특정 기능 실행하도록 정보 제공

 

어노테이션은 메타데이터라고 볼 수 있다.

메타데이터란 애플리케이션이 처리할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코들르 어떻게 컴파일 하고 처리할 것인지를 알려주는 정보이다.

@AnnotationName

 

 

6.15.1 어노테이션 타입 정의와 적용

어노테이션 타입을 정의하는 방법은 인터페이스를 정의하는 것과 유사하다. 

다음과 같이 @interface를 사용해서 어노테이션을 정의하며, 그 뒤에 사용할 어노테이션 이름이 온다.

public @interface AnnotationName{
}

이렇게 정의한 어노테이션은 코드에서 다음과 같이 사용된다.

@AnnotationName

어노테이션은 엘리먼트(element)를 멤버로 가질 수 있다.

public @interface AnnotationName{
	타입 elementName() [default값];
}


public @interface AnnotationName{
	String elementName1();
    int elemnetName2() default 5;
}

 

6.15.2 어노테이션 적용 대상

어노테이션을 적용할 수 있는 대상은 java.lang.annotation.ElementType 열거 상수로 다음과 같이 정의되어 있다.

 

 

 

6.15.3 어노테이션 유지 정책

- 어노테이션 적용 코드가 유지되는 시점을 지정하는 것

- java.lang.annotation.RetentionPolicy 열거 상수로 정의

 

'JAVA > 이것이 자바다' 카테고리의 다른 글

Chapter .08 인터페이스  (0) 2021.07.19
Chapter .07 상속  (0) 2021.07.17
Chapter .06-1 클래스  (0) 2021.07.14
Chapter .05 참조 타입  (0) 2021.07.06
Chapter .04 조건문과 반복문  (0) 2021.07.05