신용권 님의 ''이것이 자바다'' 6장 공부 기록
책을 보면서 새롭게 눈에 들어온 부분만 담았다. 이전에 배운 부분이기도 하고, 비교적 간단한 내용을 다루고 있기 때문이다.
소프트웨어를 개발할 때 부품에 해당하는 객체들을 먼저 만들고, 이것들을 하나씩 조립해서 완성된 프로그램을 만드는 기법을 객체 지향 프로그래밍(OOP:Object Oriented Programming)이라고 한다.
객체란 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고 있고 다른 것과 식별 가능한 것을 말한다.
객체들은 각각 독립적으로 존재하고, 다른 객체와 서로 상호작용하면서 동작하는데, 이 때 객체들의 상호작용 수단이 메소드이다. 객체가 다른 객체의 기능을 이용하는 것이 메소드 호출이다.
메소드 호출은 도트(.)연산자를 통해서 할 수 있다. 도트 연산자는 객체의 필드와 메소드에 접근할 때 사용한다.
ex) 객체.필드, 객체.메소드(매개값), 리턴값 = 객체.메소드(매개값)
매개값은 메소드를 실행하기 위해 필요한 데이터이다. 리턴 값은 메소드가 실행하고 나서 호출한 곳으로 돌려주는 값이다.
객체의 상호작용은 객체 간의 메소드 호출을 의미하며, 매개값과 리턴값을 통해서 데이터를 주고 받는다.
필드는 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳이다. 변수와 선언 형태가 비슷하나, 변수는 아니다. 필드는 객체가 소멸되지 않는 한 계속 존재한다는 점이 다르다.
클래스 중괄호 블록 어디든 존재할 수 있으나, 생성자와 메소드 블록 안에 들어가면 로컬 변수가 되므로 불가하다.
모든 데이터 타입이 사용 가능하고, 초기값을 지정하지 않고 선언시 기본 초기값으로 설정된다.
필드를 사용한다는 것은 필드값을 읽고 변경하는 작업을 말한다. 이 때 클래스 내부의 생성자나 메소드에서는 단순히 필드 이름으로 읽고 변경하나, 클래스 외부에서 사용시에는 우선적으로 클래스로부터 객체를 생성한 후 도트 연산자를 통해 사용할 수 있다.
생성자는 new 연산자로 호출되는 특별한 중괄호 블록이다. 객체 생성시 초기화를 담당한다. 리턴타입이 없다.
객체 초기화란 필드를 초기화하거나, 메소드를 호출하여 객체를 사용할 준비를 하는 것을 말한다.
//생성자의 명시적 선언 기본 형태
클래스(매개변수선언, ... ){
//객체의 초기화 코드
}
public 클래스이름(매개변수1){
this.매개변수1 = 매개변수;//this를 붙이면 필드의 매개변수1을 참조한다.
}
클래스( 매개변수선언 ...){
this(매개변수, ... 값 ...);//클래스의 다른 생성자 호출
실행문;
}
car(String model){
this(model, 은색);
}
car(String model, String color){
this.model = model;
this.color = color;
}
선언부(리턴타입, 메소드이름, 매개변수선언)와 실행 블록으로 구성된다. 메소드 선언부를 메소드 시그니처(signature)라고도 한다.
리턴값이 없는 경우 리턴 타입에 void가 오고, 리턴값이 있는 메소드는 리턴 값의 타입이 와야 한다. 그러나 리턴 타입이 있다고 해서 반드시 리턴값을 변수에 저장할 필요는 없다.
메소드 이름은 기능 이름으로 지어주는 것이 좋다.
매개변수는 메소드 실행 시 필요한 데이터를 외부로부터 받기 위해 사용된다. 매개 값을 받을 때 자동변환이 사용될 수 있다.
매개 변수의 수를 모를 경우
int[] values = {1, 2, 3};
int result = sum1(values);
int result = sum1(new int []{1,2,3,4,5});
int sum2(int ··· values){}
//ex 사용시
int result = sum2(1,2,3);
int result = sum2(1,2,3,4,5);
메소드 선언에 리턴 타입이 있는 메소드는 반드시 리턴문을 사용해서 리턴값을 지정해야한다. 없을 시 컴파일 오류가 발생한다. return 문 실행시 메소드는 즉시 종료된다.
리턴문에서 리턴 값은 리턴 타입이거나 리턴 타입으로 변환될 수 있으면 된다.
리턴문 이후 실행문은 실행되지 않는다.(Unreachable code 컴파일 오류 발생) 다만 if문과 같은 경우 가능할 수 있다.
리턴 값이 없는 메소드에서도 return값을 사용하여 메소드 실행을 강제 종료시킬 수 있다. while문이 있고 뒤에 실행문이 더 있는 경우라면, break문을 사용할 수도 있다.
클래스내에 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩이라고 한다.
조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야한다.
주의할 점은 매개 변수의 타입과 개수, 순서가 같을 경우 매개변수 이름만 바꾸는 것은 메소드 오버로딩이 아니다. 또한 리턴 타입만 다르고 매개변수가 동일하다면 오버로딩이 아니다. 리턴 타입은 자바 가상 기계가 메소드를 선택할 때 아무런 도움을 주지 않는다.
메소드 오버로딩의 가장 대표적인 예는 System.out.println() 메소드이다.(여러 타입 대입 가능)
인스턴스(intstance) 멤버란 객체를 생성한 후 사용할 수 있는 필드와 메소드를 말하며, 이들을 각각 인스턴스 필드, 인스턴스 메소드라고 부른다. 인스턴스 필드와 메소드는 객체 생성 없이 사용할 수 없다.
정적 멤버는 클래스에 고정(static)된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말한다. 이들을 각각 정적 필드, 정적 메소드라고 부른다. 이들은 객체가 아닌 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 한다.
public class 클래스 {
//정적 필드
static 타입 필드 [=초기값];
//정적 메소드
static 리턴타입 메소드 (매개변수선언···){···};
}
클래스.필드;
클래스.메소드(매개값);
static {
...
}
public class 클래스{
//정적 필드
private static 클래스 singleton =new 클래스();
//생성자
private static 클래스(){}
//정적 메소드
static 클래스 getInstance(){
return singleton;
}
}
클래스 변수1 = 클래스.getInstance();
클래스 변수2 = 클래스.getInstance(); // 동일한 객체를 참조한다.
final 타입 필드[= 초기값]; // 선언 방식
final 필드의 초기값은 필드 선언 시 주는 방법과, 생성자에서 주는 방법 두 가지이다.복잡한 초기화 코드가 나오거나 객체 생성 시 외부 데이터로 초기화를 해야하는 경우 생성자에서 초기값을 지정해야 한다. 초기화 되지 않은 final 필드는 컴파일에러를 발생시킨다.
객체 마다 가지는 불변의 인스턴트 필드라고 할 수 있다.
상수는 불변의 값을 뜻한다.
final 필드와 다른 것은,객체 마다 저장할 필요가 없는 공용성을 띠며, 여러 값으로 초기화될 수 없다는 것이다.
static final 필드는 객체마다 저장되지 않고, 클래스에만 포함된다. 또한 초기값이 저장되면 변경할 수 없다.
static final 타입 상수 [=초기값];
패키지는 자바에서 클래스를 체계적으로 관리하기 위해 사용하는 파일 시스템의 폴더라고 할 수 있다.
또한 클래스를 유일하게 만들어주는 식별자 역할을 한다.
상위패키지.하위패키지.클래스
클래스를 이동할 경우 피키지 전체를 이동시켜야 한다.
패키지는 클래스를 컴파일하는 과정에서 자동으로 생성되는 폴더이다. 이 때 클래스를 해당 폴더로 자동 생성시킨다.
package 상위패키지.하위패키지;
public class ClassName{...};
흔히 회사의 도메인 이름으로 패키지를 만든다.
cmd에서 패키지 포함된 클래스를 선언할 경우, javac 명령어 다음에 -d 옵션을 추가하고 경로를 지정해야 한다.
패키지 선언이 없는 클래스 파일은 default 패키지로 가게 된다.
다른 패키지에 속한 클래스들을 사용하려면?
package com.mycompany;
public class Car{
com.hankook.Tire tire = new com.hankook.Tire(); // com.hankook 패키지 소속 Tire 클래스 선언함
}//코드가 조금 난잡해질 수 있다.
// 서로 다른 패키지에 동일한 클래스 이름이 존재하고, 두 패키지가 모두 import되어 있을 경우 반드시 이 방법을 사용한다.
package com.mycompany;
import com.hankook.Tire; // 혹은 import com.hankook.*;
public class Car{
Tire tire = new Tire(); // com.hankook 패키지 소속 Tire 클래스 선언함
}
객체 생성을 막기 위해 생성자를 호출하지 못하게 하거나 객체의 특정 데이트를 보호하기 위해 해당 필드에 접근하지 못하도록 막을 때, 그리고 특정 메소드를 호출할 수 없도록 할 때 접근 제한자(Access Modifier)를 사용한다.
접근 제한자는 public, protected, default, private가 있다.
public 접근 제한자는 외부클래스가 자유롭게 사용할 수 있는 공개 멤버를 만든다. 이는 클래스, 필드, 생성자, 메소드가 적용된다.
protected 접근 제한자는 같은 패키지 또는 자식 클래스에서 사용할 수 있는 멤버를 만든다. 필드, 생성자, 메소드가 적용된다.
private 접근 제한자는 개인적인 것이라 외부에 노출되지 않는 멤버를 만든다. 필드, 생성자, 메소드에 적용된다.
default 접근 제한자는 위 세 접근 제한자가 적용되지 않은 멤버인데, 같은 패키지에 소속된 클래스에서만 사용할 수 있는 멤버이다. 클래스, 필드, 생성자, 메소드가 적용된다.
필드와 메소드를 선언할 때는 클래스 내부에서만 사용할 것인지, 패키지 내부에서만 사용할 것인지, 다른 패키지에서도 사용할 수 있도록 할 것인지를 결정해야 한다. 이 때 접근 제한자를 사용한다.
public 필드와 메소드는 모든 패키지에서 접근 가능하다. 이 경우 클래스도 public 접근 제한자를 가져야 한다.
protected 필드와 메소드는 같은 패키지에서만 접근 가능하나, 다른 패키지라도 자식 클래스라면 접근 가능하다.
default 필드와 메소드는 같은 패키지에서만 접근이 가능하다.
private 필드와 메소드는 오로지 클래스 내부에서만 사용가능하다.
private 타입 fieldName;
//Getter
public 리턴타입 getFieldName(){
return fieldName;
}
//Setter
public void setFieldNam(타입 fieldName){
this.fieldName = fieldName;
}
어노테이션(Annotation)은 메타데이터(metadata)이다. 메타데이터란 애플리케이션이 처리해야 할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지를 알려주는 정보이다.
어노테이션 타입을 정의하는 방법은 인터페이스를 정의하는 것과 유사하다.
public @interface Annotation{
}
어노테이션은 엘리먼트(element)를 멤버로 가질 수 있다.
public @interface AnnotationiName{
타입 elementName() [default 값]; //엘리먼트 선언
}
public @interface AnnotationName{
String elementName1();
int elementName2() default 5;
}
AnnotationName(elementName1="값", elementName2 =3);
//디폴드 값이 있다면 생략가능하다.
AnnotationName(elementName1="값");
@AnnotationName("값"); //자동으로 value 값으로 설정된다.
@AnnotationName(value ="값",elementName2 =2);
@Target({ElementType.TYPE, ElementType.Field, ElementType.METHOD})
public @interface AnnotationName{
} // 클래스와 필드, 메소드만 어노테이션을 적용할 수 있다.
@AnnotationName
public class ClassName{
@AnnotationName
private String fieldName;
//@AnnotationName -> 안됨
public ClassName(){}
@AnnotationName
public void methodName(){}
}
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationName{
} //런타임 유지 정책을 적용한 어노테이션
확인문제를 풀면서 알게 된 점
ex20 계좌만들기