이것이 자바다_6장

윤득렬·2022년 6월 16일
0

이것이 자바다?!

목록 보기
2/3

6. 클래스


6.1 객체 지향 프로그래밍

컴퓨터 프로그램을 '객체'들의 모임으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임 중 하나
OOP(Object Oriented Programming)

6.1.1 객체란?

물리적으로 존재하거나 추상적으로 생각할 수 있는 것들 중에서 자신의 속성을 가지고 다른 것과 식별 가능한 것을 칭한다.

  • 객체 = 속성(field) + 동작(method)

6.1.2 객체의 상호작용

  • 객체들은 각각 독립적으로 존재하고, 다른 객체와 서로 상호작용하며 동작한다.
  • 객체들 사이의 상호작용 수단은 메소드이이며, 객체가 다른 객체의 기능을 이용하는 것을 메소드 호출이라 한다.
  • 메소드 호출은 도트(.) 연산자를 통해 사용하며, 객체의 필드와 메소드에 접근할 때 사용한다.
    ex) 리턴값 = 객체.메소드(매개값) ==> int result = Calculator.add(10, 20);

6.1.3 객체 간의 관계

객체는 대부분 다른 객체와 관계를 맺는다. 관계의 종류는

  • 집합 관계 : 한 객체는 부품이고 다른 객체는 완성품에 해당한다. ex) 자동차, 타이어
  • 사용 관계 : 객체 간의 상호작용을 말한다. ex) 사람, 자동차
  • 상속 관계 : 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성하는 관계. ex) 기계, 자동차

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

  • 캡슐화(Encapsulation)

    • 객체의 필드, 메소드를 하나로 묶고, 접근 제한자를 사용해 실제 구현 내용을 감추는 것을 말한다.
    • 외부 객체는 객체 내부의 구조를 알지 못해, 객체가 노출해서 제공하는 필드와 메소드만 이용 가능
    • 외부의 잘못된 사용으로 객체가 손상되지 않도록 예방하기 위해 캡슐화를 하여 필드와 메소드를 보호
  • 상속(Inheritance)

    • 상위 객체의 필드와 메소드를 하위 객체에게 물려주어 하위 객체가 사용할 수 있도록 하는 것을 말한다.
    • 상위 객체를 재사용해서 하위 객체를 쉽고 빨리 설계 가능, 코드의 중복 회피, 유지 보수 시간을 최소화 시켜주기도 한다.
  • 다형성(Polymorphism)

    • 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질을 말한다.
    • 자바는 다형성을 위해 부모 클래스 또는 인터페이스의 타입 변환을 허용

6.2 객체와 클래스

  • 설계도 = 클래스. 클래스에는 객체를 생성하기 위한 필드와 메소드가 정의
  • 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance)라 한다.
  • 클래스로부터 객체를 만드는 과정을 인스턴스화라고 한다.
  • main() 메소드가 없는 클래스는 객체 생성 과정을 거쳐 사용해야 한다.

6.3 클래스 선언

  • 클래스 이름은 자바 식별자 작성 규칙에 따라 만들고, "클래스이름.java"로 소스 파일을 생성해야 한다.
  • 'public class' 키워드는 클래스 선언 시 사용하며 반드시 소문자로 작성
public class 클래스 이름{
}
  • 두 개 이상의 클래스가 선언된 소스 파일을 컴파일하면 바이트 코드 파일은(.class) 클래스를 선언한 개수만큼 생긴다. 결국 소스 파일은 클래스 선언을 담고 있는 저장 단위일 뿐, 클래스 자체가 아니라는 것을 알 수 있다.
  • 파일 이름과 동일한 이름의 클래스 선언에만 public 접근 제한자를 붙일 수 있다.

6.4 객체 생성과 클래스 변수

  • new는 클래스로부터 객체를 생성시키는 연산자
  • new 연산자로 생성된 객체는 메모리 힙(heap) 영역에 생성, 객체의 주소를 리턴하여 참조타입인 클래스 변수에 저장하여 객체를 사용
    클래스 변수 = new 클래스();
  • 클래스는 라이브러리(API)용, 실행용으로 용도가 나뉜다.
    • 라이브러리 클래스는 다른 클래스에서 이용할 목적으로 설계된다.
    • 실행 클래스는 프로그램의 실행 진입점인 main() 메소드를 제공하는 역할을 한다.

6.5 클래스의 구성 멤버

클래스에는 객체가 가져야할 구성 멤버가 선언된다. 구성 멤버로는 필드(Field) , 생성자(Constructor) , 메소드(Method)가 있다.

  • 필드(Field) : 객체의 데이터가 저장되는 곳
  • 생성자(Constructor) : 객체 생성 시 초기화 역할 담당
  • 메소드(Method) : 객체의 동작에 해당하는 실행 블록
public class ClassName{
	int fieldNamd; // 필드
    ClassName() { ~~~ } // 생성자
    void methodName() { ~~~ } // 메소드 

6.6 필드

객체의 고유 데이터, 객체가 가져야할 부품, 객체의 현재 상태 데이터를 저장하는 곳이다.

  • 필드 선언은 클래스 중괄호 {} 블록 어디서든 존재할 수 있으며, 생성자와 메소드 중괄호 블록 내부에는 선언될 수 없다. 생성자와 메소드 중괄호 블록 내부에 선언된 것은 모두 로컬 변수가 되기 때문이다.
  • 타입에는 기본 타입, 참조 타입 모두 올 수 있고, 필드의 초기값은 선언 시 주어질 수도, 생략될 수도 있다.
  • 필드를 사용한다는 것은 필드값을 읽고, 변경하는 작업을 말한다. 필드값을 사용하려면 객체를 우선 생성해야 한다.

6.7 생성자

new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당

6.7.1 기본 생성자 (Default Constructor)

  • 모든 클래스는 생성자가 반드시 존재하며, 하나 이상을 가질 수 있다.
  • 클래스 내부에 생성자 선언을 생략했다면 컴파일러는 중괄호 {} 블록 내용이 비어있는 기본 생성자를 바이트 코드에 자동 추가 시킨다.
  • 클래스가 public class로 선언되면 기본 생성자에서도 public이 붙지만, 클래스가 public 없이 class로만 선언되면 기본 생성자에도 public이 붙지 않는다.
    (public의 의미는 6.13 접근 제한자에 기술)
    Car myCar = new Car(); => Car()가 기본 생성자

6.7.2 생성자 선언

  • 생성자는 리턴 타입이 없고 클래스 이름과 동일
  • 매개 변수 선언은 생략 가능, 여러개 선언도 가능
  • 클래스에 생성자가 명시적으로 선언되어 있을 경우에는 반드시 선언된 생성자를 호출해서 객체를 생성해야 한다.

6.7.3 필드 초기화

  • 클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정된다.
  • 객체 생성시 필드를 다른 값으로 초기화하고 싶다면 밑에 두가지 방법이 존재
    • 필드 선언시 초기값을 주는법
    • 생성자에서 초기값을 주는법
  • 필드와 매개 변수 이름이 동일하면 매개 변수의 사용 우선순위가 높기 때문에 필드에 접근할 수 없다. 이를 해결하기 위해 필드 앞에 'this.'를 붙인다.
public Korean(String name){
	this.name = name;
    //   필드    매개변수
}

6.7.4 생성자 오버로딩 (Overloading)

매개 변수를 달리하는 생성자를 여러개 선언하는 것을 의미

  • 외부에서 제공되는 다양한 데이터들을 이용해 객체를 초기화하려면 생성자도 다양화될 필요가 있어, 자바는 다양한 방법으로 객체를 생성할 수 있도록 생성자 오버로딩을 제공한다.
  • 매개 변수의 타입과 개수, 선언된 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 생성자 오버로딩이라고 볼 수 없다.
  • 생성자 오버로딩되어 있을 경우, new 연산자로 생성자를 호출할 때 제공되는 매개값의 타입과 수에 의해 호출될 생성자가 결정된다.

6.7.5 다른 생성자 호출 (this())

  • 생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있다. 이 경우 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선한다.
클래스([매개변수 선언, ~~]){
	this(매개변수,  ~~,, ~~); //클래스의 다른 생성자 호출 부분
    실행문;
}
  • this는 반드시 생성자의 첫줄에서만 허용된다.
car(String model){
	this(model, "은색", 250); //밑의 생성자를 호출한 부분
}

car(String model, String color, int maxSpeed){
	this.model = model;
    this.color = color;
    this.maxSpeed = maxSpeed;
}

6.8 메소드

메소드는 객체의 동작에 해당하는 중괄호 {} 블록을 말한다.

6.8.1 메소드 선언

  • 선언부(리턴타입, 메소드이름, 매개변수선언)와 실행 블록으로 구성되며 메소드 선언부를 메소드 시그너처(signature)라고도 한다.
리턴타입 메소드이름 ([매개변수선언, ~~]){
	실행코드; //중괄호 부분이 메소드 실행 블록
}
  • 메소드 이름은 기능 이름으로 지어주는 것이 좋고, 자바 식별자 규칙에 맞게 작성하면 된다.
  • 매개 변수의 수를 모를 경우 매개 변수를 배열 타입으로 선언해 사용한다.
int sum1(int[] values) { }
  • 매개 변수를 배열 타입으로 선언하면, 메소드를 호출하기 전에 배열을 생성해야 하는 불편한 점이 있어 값의 리스트만 넘겨주는 방법도 있다.
int sum2(int ··· values) { }
int result = sum2(1,2,3);
int result = sum2(1,2,3,4,5);
  • ···으로 선언된 매개 변수의 값은 메소드 호출 시 리스트로 나열해주면된다.

6.8.2 리턴(return)문

  • 메소드 선언에 리턴 타입이 있는 메소드는 반드시 리턴문을 사용해 리턴값을 지정해야 한다.
  • return문의 리턴값은 리턴 타입이거나 리턴 타입으로 변환될 수 있어야 한다.
  • 리턴값이 없는 메소드(void)도 return을 메소드 강제 종료시키는 방식으로 사용할 수 있다.

6.8.3 메소드 호출

  • 클래스 내부의 다른 메소드에서 호출한 경우 단순한 메소드 이름으로 호출하면되지만, 클래스 외부에서 호출할 경우 우선 클래스로부터 객체를 생성한 뒤, 참조 변수를 이용해서 메소드를 호출해야 한다.

6.8.4 메소드 오버로딩

  • 클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩(overloading)이라고 한다.
  • 메소드 오버로딩 조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다.
  • 매개값을 다양하게 받아 처리할 수 있도록 하기 위해 메소드 오버로딩이 필요하다.
  • 주의할 점은 매개 변수의 타입과 개수, 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 메소드 오버로딩이라고 볼 수 없다.

6.9 인스턴스 멤버와 this

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

  • 인스턴스 필드는 객체마다 따로 존재하며, 인스턴스 메소드는 객체마다 존재하지 않고 메소드 영역에 저장되고 공유된다.

6.10 정적 멤버와 static

정적(static)은 '고정된'이란 의미를 가지고 있다.

6.10.1 정적 멤버 선언

  • 정적 필드와 정적 메소드를 선언하는 방법은 필드와 메소드 선언 시 static 키워드를 추가적으로 붙이면 된다.
  • 정적 필드와 정적 메소드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때 클래스 별로 관리된다.
  • 필드를 선언할 때
    • 객체마다 가지고 있으야 할 데이터라면 인스턴스 필드로 선언
    • 객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 정적 필드로 선언
  • 메소드 선언 시
    • 인스턴스 필드를 이용해서 실행해야 한다면 인스턴스 메소드로 선언
    • 인스턴스 필드를 이용하지 않는다면 정적 메소드로 선언

6.10.2 정적 멤버 사용

  • 클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름과 함께 도트(.) 연산자로 접근한다.
  • 정적 필드와 정적 메소드는 원칙적으로는 클래스 이름으로 접근해야 하지만 객체 참조 변수로도 접근이 가능하다. 그래도 정적 요소는 클래스 이름으로 접근하자!

6.10.3 정적 초기화 블록

  • 정적 필드는 필드 선언과 동시에 초기값을 주는 것이 보통이지만, 정적 필드 초기화 작업을 위해 정적 블록을 java에서 제공한다.
static{
	~~~
}
  • 정적 블록은 클래스가 메모리로 로딩될 때 자동적으로 실행되며 클래스 내부에 여러개가 선언되어도 상관없다.
public class TV{
	static String company = "google";
    static String model = "LCD";
    static String info;
    
    static{
    	info = company + "-" + model;
    }
}

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

  • 정적 메소드와 정적 블록을 선언할 때 주의할 점은 객체가 없어도 실행된다는 특징 때문에, 이들 내부에 인스턴스 필드나 인스턴스 메소드를 사용할 수 없다.
  • 정적 메소드와 정적 블록에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참조 변수로 접근해야 한다.

6.10.5 싱글톤(Singleton)

  • 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다. 단 하나만 생성된다고 해서 이 객체를 싱글톤(Singleton)이라고 한다.
  • 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 한다. 생성자를 외부에서 호출할 수 없도록 하려면 생성자 앞에 private 접근 제한자를 붙여주면 된다.
public class 클래스{
	//정적 필드
    private static 클래스 singleton = new 클래스();
    
    //생성자
    private 클래스() {}
    
    //정적 메소드
    static 클래스 getInstance() {
    	return singleton;
    }
}
  • 외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 방법이다.

6.11 final 필드와 상수

6.11.1 final 필드

final 필드는 초기값이 저장되면 이것이 최종적인 값이 되어서 프로그램 실행 도중에 수정할 수 없다는 것이다.

final 타입 필드 [= 초기값];
  • final 필드의 초기값을 줄 수 있는 방법은 딱 두가지 밖에 없다.
    • 필드 선언 시에 주는 방법
    • 생성자에서 주는 방법
  • 생성자는 final 필드의 최종 초기화를 맟쳐야 하는데, 만약 초기화 되지 않는 final 필드를 그대로 남겨두면 컴파일 에러가 발생한다.

6.11.2 상수(static final)

불변의 값을 상수라 부른다. 따라서 상수는 static이면서 final이여야 한다.

static final 타입 상수 [= 초기값];
  • 상수 이름은 모두 대문자로 작성하는 것이 관례이며 서로 다른 단어가 혼합된 경우 _로 연결해준다.

6.12 패키지

  • 자바에서는 클래스를 체계적으로 관리하기 위해 패키지를 사용한다.
  • 패키지의 물리적인 형태는 파일 시스템의 폴더이다.
  • 클래스를 유일하게 만들어주는 식별자 역할을 한다.

6.12.1 패키지 선언

  • 패키지는 클래스를 컴파일하는 과정에서 자동적으로 생성되는 폴더이다. 컴파일러는 클래스에 포함 되어 있는 패키지 선언을 보고, 파일 시스템의 폴더로 자동 생성시킨다.
//패키지 선언 방법
package 상위패키지.하위패키지;
public class ClassName {~}
  • 중복을 피하기 위해 회사들은 주로 회사 도메인 이름으로 패키지를 만든다.

6.12.2 패키지 선언이 포함된 클래스 컴파일

  • 패키지 선언이 포함된 클래스를 컴파일할 경우, 단순히 javac ClassName.java로 컴파일해선 패키지 폴더가 생성되지 않는다.
  • 패키지 폴더가 자동으로 생성되려면 javac 명령어 다음에 -d 옵션을 추가, 생성 경로를 지정해야 한다.

6.12.3 이클립스에서 패키지 생성과 클래스 생성

툴에서의 예제이므로 생략

6.12.4 import문

  • 다른 패키지에 속하는 클래스를 사용하려면 두가지 방법 중 하나를 선택해야 함

    • 패키지와 클래스를 모두 기술
    package com.mycompany;
    
    public class Car{
    	com.hankook.Tire tire = new com.hankook.Tire();
    }
    • import문을 사용하는 방법
    package com.mycompany;
    
    import com.hankook.Tire; // 혹은 Tire 대신 *
    
    public class Car{
    	Tire tire = new Tire();
    }
  • 서로 다른 패키지에 동일한 클래스 이름이 존재하고, 두 패키지가 모두 import 되어 있을 때 정확히 패키지 이름 전체를 기술해야 한다.


6.13 접근 제한자

  • public, protected, default, private 4가지 종류로 이루어진다.

6.13.1 클래스의 접근 제한

  • 클래스에 적용할 수 있는 접근 제한은 public, default 두가지
  • default는 같은 패키지에서는 아무런 제한이 없고, 다른 패키지에서는 사용할 수 없도록 제한된다.
  • public은 같은 패키지 뿐만 아니라 다른 패키지에서도 제한 없이 사용 가능

6.13.2 생성자의 접근 제한

  • 생성자가 어떤 접근 제한을 갖느냐에 따라 호출 가능 여부가 결정
  • 클래스에 생성자를 선언하지 않으면 컴파일러에 의해 자동적으로 클래스의 접근 제한과 동일한 생성자가 생성
  • public : 모든 패키지에서 아무런 제한 없이 생성자를 호출
  • protected : 같은 패키지에 속하는 클래스에서 생성자를 호출할 수 있도록 함. (단, 달라도 child 클래스면 호출 가능)
  • default : 같은 패키지는 문제 없이 호출 가능하나 다른 패키지에서는 생성자 호출 불가
  • private : 동일 패키지, 다른 패키지 상관없이 생성자 호출 불가

6.13.3 필드와 메소드의 접근 제한

같아서 생략


6.14 Getter와 Setter 메소드

  • 객체 지향 프로그래밍에서는 객체의 데이터는 객체 외부에서 직접 접근하는 것을 막는다. 무결성이 깨질 수 있기 때문에 메소드를 통해 데이터 변경 방법을 선호한다.
  • Setter는 메소드를 통해 데이터를 변경하는 방법, Getter는 객체 데이터를 읽을 때 사용하는 방법

6.15 어노테이션

어노테이션(Annotation)은 메타데이터라고 볼 수 있다. 메타데이터란 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지 알려주는 정보

  • 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공 (ex, @Override)
  • 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
  • 실행 시(런타임 시) 특정 기능을 실행하도록 정보를 제공

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

  • @interface를 사용해서 어노테이션을 정의하며, 그 뒤에 사용할 어노테이션 이름이 온다.
  • 어노테이션은 엘리먼트를 멤버로 가질 수 있다.
public @interface AnnotationName{
	타입 elementName() [default];
    // ex, int elementName() default 5;
}
  • 디폴트 값이 없다면 값을 반드시 기술해야한다.
@AnnotationName(value = '값', elementName = 3);

6.15.2 어노테이션 적용 대상

  • 어노테이션을 적용할 수 잇는 대상은 java.lang.annotation.ElementType 열거 상수이다.
  • 적용 대상을 지정할 때에는 @Target 어노테이션을 사용
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})

6.15.3 어노테이션 유지 정책

  • 어노테이션 정의 시 사용 용도에 따라 @AnnotationName을 어느 범위까지 유지할 것인지 지정해야 함
  • 리플렉션(Reflection)이란 런타임 시에 클래스의 메타 정보를 얻는 기능을 말한다.

6.15.4 런타임 시 어노테이션 정보 사용하기

예제로 설명해야 한다......

profile
Backend server 개발자가 되고 싶은

0개의 댓글