OOP
객체지향 프로그래밍 (OOP: Object Oriented Programming)
객체들을 먼저 만들고 하나씩 조립해서 완성된 프로그램을 만드는 기법
객체란?
- 물리적으로 존재하거나 추상적으로 생각할 수 있는것 중에서 자신의 속성을 가지고 있고 다른것과 식별 가능한 것.
- 객체는 속성과 동작으로 구성되어있으며, 속성 과 동작들을 각각 필드(field)와 메소드(method)라고 부른다
- 현실의 객체를 소프트 웨어 객체로 설계하는것을 객체 모델링(Object Modeling)이라고 함.
객체의 상호작용
- 객체들은 각각 독립적으로 존재하고, 다른 객체와 서로 상호작용 하면서 동작함.
- 객체들 사이의 상호작용 수단이 메소드 이며, 객체가 다른 객체의 기능을 이용하는것이 바로 메소드 호출임.
리턴값 = 객체.메소드(매개값1, 매개값2, ...); // 메소드 호출 형태
- 매개값은 메소드를 실행하기 위해 필요한 데이터, 리턴값은 메소드 실행 후 호출한 곳으로 돌려주는 값
int result = Calculator.add(10,20) 리턴값 매개값
객체 간의 관계
- 객체는 개별적으로 사용될 수 있지만, 대부분 다른 객체와 관계를 맺고 있음.
- 관계의 종류 로는 집합, 사용, 상속 관계가 있음
- 집합 관계에 있는 객체는 하나의 부품이고 하나는 완성품에 해당
자동차는 엔진,타이어,핸들 등 으로 구성되므로 자동차와 부품들은 집합 관계라고 볼수있음.
- 사용 관계는 객체간의 상호작용을 말함.
사람은 자동차를 사용하므로 사람과 자동차는 사용의 관계라고 볼 수 있음.(사람은 달린다, 멈춘다 등의 메소드를 호출 함)
- 상속관계는 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성하는 관계를 말함.
일반적으로 상위 객체는 종류를 하위객체는 구체적인 사물에 해당( 기계(상위) 자동차(하위) 서로 상속관계)
객체 지향 프로그래밍의 특징
- 캡슐화(Encapsulation)
캡슐화란 객체의 필드, 메소드를 하나로 묶고, 실제 구현 내용을 감추는 것을 말함. 외부 객체는 객체 내부의 구조를 알지 못하며, 객체가 노출해서 제공하는 필드와 메소드만 이용 가능함. 캡슐화하여 보호하는 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 하는데 있음. 자바는 캡슐화된 멤버를 노출시킬 것인지, 숨길 것인지를 결정하기 위해 접근 제한자(Access Modifier) 를 사용(사용을 제한함으로 외부로부터 보호)
- 상속(Ingeritance)
상위 객체는 자기가 가지고 있는 필드와 메소드를 하위 객체에게 물려주어 하위 객체가 사용 가능하도록 함. 상속은 상위 객체를 재사용해서 하위 객체를 쉽고 빠르게 설계 하도록 도와주고, 이미 개발 된 객체를 재사용해 새로운 객체를 만들기 때문에 반복된 코드의 중복을 줄여줌. 상속은 상위 객체의 수정으로 모든 하위 객체들의 수정 효과를 가져오므로 유지보수 시간을 줄여줌.
- 다형성(Polymorphism)
같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질을 말함. 코드 측면에서 보면 다형성은 하나의 타입에 여러 객체를 대입함으로써 다양한 기능을 이용 할 수 있도록 해줌. 다형성을 위해 부모 클래스 또는 인터페이스의 타입 변환을 허용하며, 부모 타입에는 모든 자식 객체가 대입될 수 있고, 인터페이스 타입에는 모든 구현 객체가 대입 될 수 있다. 효과로 객체는 부품화가 가능함.
객체와 클래스
- 자바에서는 설계도가 클래스이며, 클래스에는 객체를 생성하기 위한 필드와 메소드가 정의되어 있음.
- 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance) 라고 함. (자동차 객체는 자동차 클래스의 인스턴스인 셈)
- 클래스로부터 객체를 만드는 과정을 인스턴스화라고 하며, 하나의 클래스로부터 여러개의 인스턴스를 만들수 있음.
객체지향 프로그래밍의 개발은 3가지 단계로 구성되어있음. 첫번째 클래스를 설계한다. 두번째는 설계된 클래스를 가지고 사용할 객체를 생성하고, 마지막 단계는 생성된 객체를 이용한것.
클래스 선언
- 작성규칙
- 하나 이상의 문자로 이루어져야 함.
- 첫 번째 글자는 숫자가 올 수 없음.
- #,_ 이외 특수 문자는 사용 금지
- 자바 키워드는 사용 금지
자바는 대소문자를 서로 다른 문자로 취급하기 때문에 클래스 이름도 영어 대소문자를 구분함. 관례적으로 클래스 이름이 단일 단어라면 첫자를 대문자로 하고 나머지는 소문자로 하며, 다른 단어가 혼합된 이름일 경우 각 단어의 첫글자는 대문자로 작성하는것이 관례이며, 두 개 이상의 클래스가 선언된 소스파일을 컴파일 시 바이트 코드 파일(.class)은 클래스를 선언한 개수만큼 생성 된다. 소스 파일은 클래스 선언을 담고있는 저장 단위 일뿐, 클래스 자체가 아님. 파일 이름과 동일한 이름의 클래스 선언에만 public 접근 제한자를 붙일 수 있음.
객체 생성과 클래스 변수
new 클래스();
new는 클래스로부터 객체를 생성시키는 연산자이다. new 연산자 뒤에는 생성자가 오는데, 생성자는 클래스() 형태를 가지고 있으며, new 연산자로 생성 된 객체는 메모리 힙(heap) 영역에 생성 되고, new 연산자는 힙영역에 객체를 생성 시킨 후 객체의 주소를 리턴 한다. 클래스는 두가지 용도가 존재함. 하나는 라이브러리 (API) 용이고, 다른 하나는 실행용이다. 라이브러리는 다른 클래스에서 이용할 목적으로 설계 되며, 프로그램 전체에서 사용되는 클래스가 100개라면 99개는 라이브러리고, 단 하나가 실행 클래스이다. 실행 클래스는 프로그램의 실행 진입점인 main() 메소드를 제공하는 역할을 함.
클래스의 구성 멤버
- 필드(Field), 생성자(Constructor), 메소드(Method) 이 멤버들은 생략되거나 복수개가 작성될 수 있음.
public class ClassName{ //필드 : 객체의 데이터가 저장되는 곳 int fieldName; //생성자 : 객체 생성 시 초기화 역할 담당 ClassName(){...} //메소드 : 객체의 동작에 해당하는 실행 블록 void methodName(){...} }
생성자
생성자는 new 연산자로 호출되는 특별한 중괄호 {} 블록, 객체 생성 시 초기화를 담당하며, 필드를 초기화 하거나, 메소드를 호출해서 객체를 사용할 준비를 하고, 클래스 이름으로 되어있고 리턴 타입이 없음.
메소드
메소드는 객체의 동작에 해당하는 중괄호 {} 블록을 말함. 중괄호 블럭의 이름은 메소드 이름, 메소드는 필드를 읽고 수정하는 역할도 하지만, 다른 객체를 생성해서 다양한 기능을 수행하기도 하며, 객체간의 데이터 전달의 수단으로 사용 됨.
필드(Field)
필드는 객체 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳, 선언 형태는 변수와 비슷하지만, 필드는 생성자와 메소드 전체에서 사용되며, 객체가 소멸되지 않는 한 객체와 함께 존재 함.
필드 선언
필드 선언은 클래스 중괄호 {} 블록 어디서든 존재할 수 있다. 생성자 선언과 메소드 선언의 앞과 뒤 어떤곳에서도 필드 선언이 가능함. 하지만 생성자와 메소드 중괄호 블록 내부에는 선언 될 수 없다. 생성자와 메소드 중괄호 블록 내부에 선언된 것은 모두 로컬 변수가 됨. 필드 선언은 변수의 선언 형태와 비슷함.
타입 필드 [ = 초기 값];
타입은 필드에 저장할 데이터 종류를 결정함. 기본타입, 참조타입 모두 올 수 있으며, 필드의 초기값은 필드 선언 시 주어질수도, 생략될 수 있음. 초기값이 지정되지 않은 필드들은 객체 생성 시 자동으로 기본 초기값으로 설정 됨.
필드 사용
필드를 사용한다는 것은 필드값을 읽고 변경하는 작업을 말함. 클래스 외부에서 사용할 경우 우선적으로 클래스로부터 객체를 생성한 뒤 필드를 사용해야 함. 필드는 객체에 소속된 데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않음. 사용방법은 변수와 동일하나, 변수는 생성자 또는 메소드 블록 내부에서만 사용 가능하지만, 필드는 생성자와 모든 메소드에서 사용이 가능함. (객체를 우선 생성 후 사용)
생성자(Constructor)
생성자는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당 객체 초기화란 필드를 초기화 하거나, 메소드를 호출해서 객체를 사용 할 준비 하는것을 말함. new 연산자에 의해 생성자가 성공적으로 실행되면 heap 영역에 객체가 생성되고 객체의 주소가 리턴 되며 리턴된 객체의 주소는 클래스 변수에 저장되어 객체에 접근 시 이용 된다. (생성자가 예외 발생 시 객체는 미생성)
기본 생성자
모든 클래스는 생성자가 반드시 존재하며, 하나 이상을 가질 수 있음. 클래스 내부에 생성자 선언을 생략했다면, 컴파일러는 다음과 같이 중괄호 {} 블록 내용이 비어있는 기본 생성자를 바이트 코드에 자동 추가시킴
[public] class() { }
// class 가 public class 로 선언되면 생성자 에서도 public 이 붙지만 클래스가 public 없이 class 로만 선언되면 기본 생성자에도 public 미존재
소스파일 (Car.java) 바이트 코드 파일(Car.class)
------------------ ---------------------------
public class Car { => public class Car {
} public Car() { } // 자동 추가, 기본 생성자
}
클래스에 생성자를 선언하지 않아도 다음과 같이 new 연산자 뒤에 기본생성자를 호출해서 객체를 생성 시킬수 있으며, 클래스에 명시적으로 선언한 생성자가 한개라도 있으면, 컴파일러는 기본 생성자를 추가하지 않음. 명시적으로 생성자를 선언하는 이유는 객체를 다양하게 초기화 하기 위해서임.
Car myCar = new Car();
생성자 선언
클래스(매개변수 선언, ..) {
객체의 초기화 코드
} = > 생성자 블록
생성자는 메소드와 비슷한 모양을 가지고있으나, 리턴 타입이 없고 클래스와 이름이 동일하며, 매개 변수 선언은 생략 할수있고, 여러개를 선언해도 됨.
Car myCar = new Car("부릉이", "검정", 300);
public class Car {
//생성자
Car(String nickname , String color, int maxSpeed){...
}
필드의 초기화
클래스로 부터 객체가 생성될 때 필드는 기본적으로 초기값으로 자동 설정 됨. 다른값으로 초기화를 하고싶다면 하나는 필드를 선언할때 초기값을 주는 방법이고, 또 다른 하나는 생성자에서 초기값을 주는 방법 두가지가 있음.
public class FieldReset {
//필드
String nation = "korea";
String name;
int age;
//생성자
public FieldReset(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
FieldReset F1 = new FieldReset("ji", 20);
FieldReset F2 = new FieldReset("heon", 7);
System.out.println(F1.name + F2.name +" , "+(F1.age + F2.age));
}
매개변수의 이름이 너무 짧으면 코드의 가독성이 좋지 않기때문에 가능하면 초기화 시킬 필드 이름과 비슷하거나, 동일한 이름을 사용할것을 권장함. 관례적으로 필드와 동일한 이름을 갖는 매개 변수를 사용한다. 객체의 필드에 하나가 아닌 여러개가 있고 필드들을 모두 생성자에서 초기화 한다면 생성자의 매개변수의 수는 객체의 필드 수만큼 선언되어야 한다. 실제로는 중요한 몇개 필드만 매개변수를 통해 초기화되고 나머지 필드들은 필드 선언 시에 초기화하거나, 생성자 내부에서 임의의 값또는 계산된 값으로 초기화 하며, 아니면 객체 생성 후에 필드값을 별도로 저장하기도 한다.
생성자 오버로딩(Overloading)
외부에서 제공되는 다양한 데이터들을 이용해서 객체를 초기화 하려면 생성자도 다양화될 필요가 있음. 생성자가 하나뿐이라면 다양한 요구 조건을 수용 불가함. 그래서 자바는 생성자 오버로딩을 제공함. 매개변수를 달리하는 생성자를 여러개 선언하는것을 말함. ```java public class 클래스{ 클래스([타입 매개변수, …]){ }
클래스([타입 매개변수, ...]){
} // 생성자 오버로딩 >> 매개변수의 타입, 개수, 순서가 다르게 선언 } ```
생성자 오버로딩 시 주의할 점은 매개변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우 매개변수 이름만 바꾸는것은 생성자 오버로딩이라고 볼수 없음.
car(String model,String color){...} car(String color, String model){...} // 오버로딩이 아님
생성자가 오버로딩되어 있을 경우, new 연산자로 생성자를 호출할 때 제공되는 매개값의 타입과 수에 의해 호출될 생성자가 결정됨.
다른 생성자 호출(this())
생성자 오버로딩이 많아질 경우 생성자 간 중복된 코드가 발생, 매개 변수의 수만 달리하고, 필드의 초기화 내용이 비슷한 생성자에서 이러한 현상이 나타는데 이 경우에는 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고, 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선가능함.
클래스([매개변수 선언, ...] ){ this(매개변수, ... , 값, ...); 실행문; }
this()는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫줄에서만 허용, this()의 매개값은 호출되는 생성자의 매개변수 타입에 맞게 제공해야 함.
메소드
메소드는 객체의 동작에 해당하는 중괄호 {} 블록을 말함. 중괄호 블록은 이름을 가지고 있는데 이게 메소드 이름, 메소드는 객체간의 데이터 전달의 수단으로 사용된다. 외부로부터 매개값을 받을수도 있고, 실행 후 어떤 값을 리턴할 수도 있음.
메소드 선언
메소드 선언은 선언부(리턴타입,메소드이름, 매개변수선언)와 실행 블록으로 구성됨. 메소드 선언부를 메소드 시그니처(signature)라고도 함.
리턴 타입 메소드이름([매개변수 선언], [...]){
메소드 실행 블록
}
리턴 타입
리턴 타입은 메소드가 실행 후 리턴하는 값의 타입을 말함. 메소드는 리턴값이 있을수도 있고, 없을수도 있으며, 메소드 실행 후 결과를 호출한 곳에 넘겨줄 경우엔 리턴값이 있어야 함.
void PowerOn(){...} // 리턴값이 없는경우
int Number(int x, int y){...} // 리턴값이 있는경우
//호출
PowerOn();
int result = Number(10,20); // 리턴 타입이 있다고해서 리턴값을 저장할 필요는 없음.
Number( 10,20 ); // 리턴값이 중요하지 않고 메소드 실행이 중요한 경우에는 바로 호출함.
PowerOn 메소드는 리턴값이 없기 때문에 변수에 저장할 내용이 없으나, Number 메소드는 저장할 변수가 있어야 함. 리턴값을 받기 위해서 변수는 메소드 리턴 타입인 int 타입으로 선언 되어야 함.
메소드 이름
- 숫자로 시작하면 안되며 $,_ 를 제외한 특수문자를 사용하지 말아야 함.
- 관례적으로 메소드명은 소문자로 작성
- 서로 다른 단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫머리 글자는 대문자로 작성
void run(){...} void methodStart(){...} String getName(){..} int[] getNumber(){...}
매개 변수 선언
매개 변수는 메소드가 실행할때 필요한 데이터를 외부로부터 받기 위해 사용
매개변수의 수를 모를 경우
int sum1(int[] values) { }
int sum2(int ... values) { }
매개 변수를 배열 타입으로 선언함으로 써 해결함. 메소드를 호출할 때 배열을 넘겨줌으로써 배열의 항목 값들을 모두 전달할 가능함. 배열의 항목 수는 호출할때 결정 된다. 하지만 매개변수를 배열 타입으로 선언하면 메소드를 호출하기 전에 배열을 생성해야 하는 불편한 점이 있음. 그래서 배열을 생성하지 않고, 값의 리스트만 넘겨주는 방법도 있다. …을 사용해서 선언하면 메소드 호출 시 넘겨준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 사용된다. … 로 선언된 매개변수의 값은 메소드 호출 시 리스트로 나열해주면 됨.
int result = sum2(1,2,3); int result = sum2(1,2,3,4,5);
리턴(return)문
리턴값이 있는 메소드
- 메소드 선언에 리턴 타입이 있는 메소드는 반드시 리턴(return) 문을 사용해서 리턴값을 지정해야 함.
return 리턴값;
- return 문의 리턴값을 리턴 타입이거나 리턴 타입으로 변환 될 수 있어야 함. 리턴문의 리턴값은 리턴타입이거나 리턴 타입으로 변환될 수 있어야 한다.
리턴값이 없는 메소드
- void 로 선언된 리턴값이 없는 메소드도 return 문을 사용할 수 있음.
- return 문을 사용하면 메소드 실행을 강제 종료 시킴
메소드 호출
메소드는 클래스 내, 외부의 호출에 의해 실행. 클래스 내부의 다른메소드에서 호출할 경우에는 단순한 메소드 이름으로 호출하면 되지만, 클래스 외부에서 호출할경우 우선 클래스로부터 객체를 생성 후 참조 변수를 이용해서 메소드를 호출 해야 함. 이유는 객체가 존재해야 메소드도 존재하기 때문
객체 내부에서 호출
- 클래스 내부에서 다른 메소드를 호출할 경우에는 다음과 같은 형태로 작성
메소드(매개값, ...);
- 메소드가 리턴값이 없거나, 있어도 받고 싶지 않을 경우 모두 호출이 가능하다.
- 리턴값이 있는 메소드를 호출하고 리턴값을 받고 싶다면
타입 변수 = 메소드(매개값,..);
객체 외부에서 호출
- 외부 클래스에서 메소드를 호출하려면 우선 다음과 같이 클래스로부터 객체를 생성
클래스 참조변수 = new 클래스(매개값, ...);
- 참조변수와 함께 도트(.) 연산자를 사용해서 메소드를 호출 가능함.
참조변수.메소드(매개값, ...); // 리턴값이 없거나, 있어도 리턴값을 받지 않을 경우 타입 변수 = 참조변수.메소드( 매개값, ...); // 리턴값이 있고, 리턴값을 받고 싶을 경우
메소드 오버로딩
- 클래스 내에 같은 이름의 메소드를 여러 개 선언하는것을 메소드 오버로딩 이라고 함.
- 메소드 오버로딩의 조건은 매개변수의 타입, 개수, 순서 중 하나가 달라야 함.
class 클래스{ 리턴 타입 / 메소드 이름 / (타입변수, ...) {...} 무관 동일 매개 변수 타입,개수,순서가 달라야함. 리턴 타입 / 메소드 이름 / (타입변수, ...) {...} }
- 메소드 오버로딩이 필요한 이유는 매개값을 다양하게 받아 처리할 수 있도록 하기 위해서임.
- 오버로딩된 메소드를 호출 시 JVM은 매개값의 타입을 보고 메소드를 선택함.
- 매개 변수의 타입이 일치하지 않을 경우, 자동타입 변환이 가능한지 검사함.
- 메소드 오버로딩 시 주의할점은 매개 변수의 타입과 개수, 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 메소드 오버로딩이라고 볼 수 없음.
- 또한 리턴 타입만 다르고 매개 변수가 동일하다면 오버로딩이 아님. 리턴 타입은 JVM가 메소드를 선택 시 아무런 도움을 주지 못하기 때문
- 메소드 오버로딩의 가장 대표적인 예는 System.out.println() 메소드임.
인스턴스 멤버와 this
- 인스턴스 멤버란 객체(인스턴스) 를 생성한 후 사용할 수 있는 필드와 메소드를 말함.
- 이들을 각각 인스턴스 필드, 인스턴스 메소드라고 부름.
- 인스턴스 필드와 메소드는 객체에 소속된 멤버이기때문에 객체없이는 사용 불가.
- 객체 내부에서 인스턴스 멤버에 접근하기 위해 this 사용 가능
정적 멤버와 Static
- 정적 멤버는 고정된 멤버로 객체 생성하지 않고 사용 가능한 멤버(필드,메소드 (클래스 멤버))
정적 멤버 선언
public class 클래스{
//정적 필드
static 타입 필드 [= 초기값];
//정적 메소드
static 리턴 타입 메소드(매개변수...) {...}
}
- 메소드 영역에 적재 할때 클래스별로 관리(클래스 로딩 후 바로 사용 가능)
- 객체마다 가지고 있지않아도 되는 공용적인 데이터면 정적 필드로 선언
- 인스턴스 필드를 이용 하면 인스턴스 메소드로 선언하고 이용하지 않는다면 정적 메소드로 선언
정적 멤버 사용
클래스.필드;
클래스.메소드(매개값...);
- 원칙적으로는 클래스 이름으로 접근 해야 하지만, 객체 참조 변수로도 접근 가능
정적 초기화 블록
- 정적 필드의 복잡한 초기화 작업을 위해 static block 을 제공함.
static{
...
}
----------------------------
static String name = "JAVA";
static Stirng _static = "static";
static String append;
static {
info = name + " " + _static; // JAVA static
}
- 정적 블록은 클래스가 메모리로 로딩될 때 자동으로 실행
- 클래스 내부에 여러개가 선언되도 상관 x
static 메소드와 블록 선언 시 주의사항
- 내부에서 인스턴스 필드나, 인스턴스 메소드 사용 불가
- 객체 자신의 참조인 this 사용 불가
- 정적 메소드,블럭에서 인스턴스 멤버 사용 시 객체 생성 후 참조변수로 접근(코드참고)
static void Method(){ ClassName obj = new ClassName(); // 객체 생성 obj.field = 10; obj.method1(); }
싱글톤 (Singleton)
- 전체 프로그램에서 단 하나의 객체만 만들도록 보장 해야 하는 객체를 싱글톤(Singleton) 이라 함.
public class 클래스{ //정적 필드 private static 클래스 singleton = new 클래스(); //생성자 private(){} //정적 메소드 static 클래스 getInstance(){ // 외부에서 호출 가능한 정적 메소드 getInstance() return singleton; } } //클래스 호출 클래스 변수 = 클래스.getInstance();
- 정적 필드 하나를 선언 후 객체를 생성해 초기화
- 정적 필드도 private 접근 제한자를 붙인 뒤 외부에서 필드값을 변경하지 못하도록 막음
final 필드와 상수
- final 필드는 초기값이 저장되면 실행 도중 수정 불가능함.
final 타입 필드 [=초기값];
상수(static final)
- 불변의 값을 상수(constant)라 칭함.
static final 타입 상수 [= 초기값];
- 상수 이름은 모두 대문자로 작성하는것이 관례
- 다른 언어가 혼합된 이름이라면 언더바로 단어들을 연결
패키지
- 패키지는 클래스를 유일하게 만들어주는 식별자 역할을 함.
패키지 선언
- 숫자로 시작해서는 안되고, _,$ 를 제외한 특수문자를 사용해서는 안됨
- java 로 시작하는 패키지는 자바 표준 API 에서만 사용하므로 사용 금지
- 모두 소문자로 작성하는것이 관례
접근제한자
- 객체 생성을 막기위해 생성자 호출을 못하게 하거나, 특정 데이터를 보호하기 위해 사용
- public, protected, default, private 4가지 있음.
- public - 클래스, 필드, 생성자, 메소드 (제한 없음)
- protected - 필드, 생성자, 메소드 (자식 클래스가 아닌 다른 패키지에 소속된 클래스)
- default - 클래스, 필드, 생성자, 메소드 (다른 패키지에 소속된 클래스)
- private - 필드, 생성자, 메소드 (모든 외부 클래스)
클래스의 접근 제한
- 클래스에 적용 가능한 접근제한은 public, default
- default
public 생략 시 default 접근 제한을 가지게 됨.
- public
제한없이 접근 가능함.
- default
생성자의 접근 제한
- 클래스가 default 접근 제한자를 가지면 기본생성자도 default 접근 제한 을 가짐.
Getter, Setter 메소드
- OOP에서는 외부에서 직접 접근을 막음.( 객체의 무결성(결점이 없는성질)이 깨질 수 있기때문)
- 데이터는 외부에서 접근을 막고 메소드는 공개해서 외부에서 메소드를 통해 데이터에 접근 하도록 유도(메소드는 매개값을 검증 후 유효한 값만 데이터로 저장)
- 이러한 역할을 하는 메소드가 Setter
private 타입 fieldName;
//Getter
public 리턴타입 getFieldName(){ //접근제한자: public, 리턴타입: 필드타입, 메소드이름: get+필드이름(첫문자 대문자),리턴값 : 필드값
return fieldName;
}
//Setter
public void setFieldName(타입 fieldName){ // 접근제한자 : public , 리턴타입:void, 메소드이름: set+필드이름(첫문자 대문자), 매개변수타입: 필드타입
this.fieldName = fieldNam;
}
어노테이션(Annotation)
- 어노테이션은 메타데이터 라고 볼 수 있음.
- 메타데이터란 애플리케이션이 처리해야 할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일 하고 처리할 것인지 알려주는 정보
@AnnotationName
- 메타데이터란 애플리케이션이 처리해야 할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일 하고 처리할 것인지 알려주는 정보
- 어노테이션의 용도
- 컴파일러에게 코드 문법 에러를 체크하도록 정보 제공
- 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
- 실행(런타임) 시 특정 기능을 실행하도록 정보 제공
어노테이션 타입 정의와 적용
public interface AnnotationName{
String value(); <-- 기본 엘리먼트 선언
타입 elementName() [default 값]; <-- 엘리먼트(파라미터, 속성) 선언
...
}
- 정의한 어노테이션은 아래와 같이 사용
@AnnotationName
- 엘리먼트 타입으로는 기본 데이터, 참조, 열거, class 타입, 배열 타입 모두 사용 가능
@AnnotationName("값"); <-- 코드에서 적용 시 값만 기술 가능함. @AnnotationName(value="값", elementName =3); <-- value 엘리먼트와 다른 엘리먼트 동시 값을 줌
- 어노테이션 적용 대상을 지정 시 어노테이션 사용
@Target
어노테이션 유지 정책
- SOURCE : 소스상에서만 어노테이션 정보를 유지
- CLASS : 바이트 코드 파일까지 어노테이션 정보를 유지
- RUNTIME : 바이트 코드 파일까지 어노테이션 정보를 유지하고 리플렉션을 이용하여 런타임 시 어노테이션 정보를 얻음
- 리플렉션 ? 런타임 시 클래스의 메타정보를 얻는 기능