생성자 |
생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메서드' 이다.
생성자의 특성
1. 인스턴스 변수의 초기화 작업에 주로 사용 된다.
2. 인스턴스 생성 시에 실행되어야 할 작업을 위해 사용 된다.
3. 생성자의 이름은 클래스의 이름과 같다.
4. 생성자는 리턴 값이 없다.
5. 생성자도 오버로딩이 가능하므로 클래스에 여러개의 생성자가 존재 할 수 있다.
인스턴스의 생성 과정
Constructor con = new Constructor();
1. 연산자 new에 의해서 메모리(heap)에 Constructor클래스의 인스턴스가 생성된다.
2. 생성자 Constructor()가 호출되어 수행된다.
3. 연산자 new의 결과로 생성된 Constructor인스턴스의 주소가 반환되어 참조변수 con에 저장된다.
기본 생성자
클래스이름(){ }
1. 인스턴스를 생성할 때 컴파일러가 제공한 기본 생성자가 사용 된다.
2. 기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐인다.
매개변수가 있는 생성자
Constrouctor con() = new Constructor{"a", 1};
public class Constructor {
String alphabet;
int index;
Constructor(String a, int i){
alphabet = a;
index = i;
}
}
생성자에서 다른 생성자 호출하기 - this(), this
1. 생성자의 이름으로 클래스이름 대신 this를 사용한다.
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다. 이는 생성자 내에서 초기화 작업도중에 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 맴버변수들의 값을 초기화 할 것이므로 다른 생성자를 호출하기 전의 초기화 작업이 무의미해질 수 있다.
Constructor(Stinrg str){
index = 1;
Constructor(str, 3); //에러1. 생성자의 두 번째 줄에서 다른 생성자 호출
//에러2. this(str, 3);로 해야함
}
3. this 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다. 모든 인스턴스메서드에 지역변수로 숨겨진 채로 존재한다.
4. this(), this(매개변수) 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.
this를 사용할 수 있는 건은 인스턴스맴버뿐이다. static메서드(클래스 메서드)에서는 인스턴스 맴버들을 사용할 수 없는 것처험, this역시 사용할 수 없다. 왜냐하면, static메서드는 인스턴스를 생성하지 않고도 호출될 수 있으므로 static메서드가 호출된 시점에 인스턴스가 존재하지 않을 수도 있기 때문이다.
변수의 초기화 |
변수를 선언하고 처음으로 값을 저장하는 것을 '변수의 초기화'라고 한다.
변수의 초기화 특징
1. 맴버변수(클래스변수와 인스턴스변수)와 배열의 초기화는 선택적이지만, 지역변수의 초기화는 필수적이다.
2. 같은 타입의 변수는 콤마(,)를 사용해 함께 선언 되지만 다른 타입은 불가
맴버변수의 초기화 방법
1. 명시적 초기화(explicit initialization)
2. 생성자(constructor)
3. 초기화 블럭(initialization block)
- 인스턴스 초기화 블럭: 인스턴스변수를 초기화 하는데 사용
- 클래스 초기화 블럭: 클래스변수를 초기화 하는데 사용
public class InitBlock {
static {
System.out.println("static block");
}
{
System.out.println("instance block");
}
public InitBlock() {
System.out.println("Constructor");
}
public static void main(String[] args) {
InitBlock initBlock1 = new InitBlock();
InitBlock initBlock2 = new InitBlock();
}
}
//출력 화면
static block
instance block
Constructor
instance block
Constructor
맴버변수의 초기화 시기와 순서
클래스변수의 초기화 시점: 클래스가 처음 로딩될 때 단 한번 초기화 된다.
인스턴스변수의 초기화 시점: 인스턴스가 생성될 때마다 각 인스턴스별로 초기화가 이루어진다.
클래스변수의 초기화 순서: 기본값 -> 명시적초기화 -> 클래스 초기화 블럭
인스턴스변수의 초기화 순서: 기본값 -> 명시적초기화 -> 인스턴스 초기화 블럭 -> 생성자
package와 import |
패키지
- 패키지란, 클래스의 묶음이다. 패키지에는 클래스 또는 인터페이스를 포함시킬 수 있으며, 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리할 수 있다.
- 클래스가 물리적으로 하나의 클래스파일(.class)인 것과 같이 패키지는 물리적으로 하나의 디렉토리이다.
- 하나의 소스파일에는 첫 번째 문장으로 단 한 번의 패키지 선언만 허용한다.
- 모든 클래스는 반드시 하나의 패키지에 속해야 한다.
- 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있다.
- 패키지는 물리적으로 클래스 파일(.class)을 포함하는 하나의 디렉토리이다.
패키지의 선언
클래스나 인터페이스의 소스파일(.java)의 맨위에 다음과 같이 한 줄만 적어주면 된다.
package 패키지명;
1. 패키지 선언문은 반드시 소스파일에서 주석과 공백을 제외한 첫 번째 문장이어야 한다.
2. 하나의 소스파일에 단 한번만 선언될 수 있다.
3. 패키지명은 대소문자를 허용하지만, 클래스명과 쉽게 구분하기 위해서 소문자를 원칙으로 한다.
4. 자바는 기본적으로 '이름없는 패키지'를 제공한다.
아래와 같은 명령어를 자바 파일이 있는 곳에서 실행을 하면 지전된 패키지와 일치하는 디렉토리가 존재하지 않는다면 자동적으로 생성한다.
C:\jdk1.8\project>javac -d . PackageTest.java
윈도우즈에서는 '제어판-시스템-고급 시스템 설정-환경 변수-새로만들기'에서 변수 이름에 CLASSPATH를 입력하고 변수 값에 경로 'C:\jdk1.8\project'를 입력한다.
classpath경로는 ;로 구분되며 C:\Windows>echo %classpath%를 통해 경로 확인이 가능하다
C:\Windows>echo %classpath%
C:\jdk1.8\project
//자바 호출 가능
C:\Windows>java com.PackageTest
C:\Windows>java -cp C:\jdk1.8\project com.PackageTest
임포트
클래스의 코드를 작성하기 전에 import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명은 생략할 수 있다.
임포트의 역할
import문의 역할은 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것이다.
이클립스의 자동 import 단축키는 'ctrl + shift + o' 이다.
임포트의 선언
import문 선언 순서
일반적인 소스파일(*.java)의 구성은 다음의 순서로 되어 있다.
1. package문
2. import문
3. 클래스 선언
import문 선언 방법
import 패키지명.클래스명;
or
import 패키지명.*;
실행 시 성능상의 차이는 전혀 없다.
import java.lang 패키지는 묵시적으로 모든 클래스에 선언되어 있다.
static import문
import static java.lang.Integer.*; //Integer클래스의 모든 static메서드
import static java.lang.Math.random; //Math.random()만, 괄호 안붙힘.
import static java.lang.System.out; //System.out을 out만으로 참조가능
System.out.println(Math.random()); -> out.println(random());
제어자 |
제어자
제어자는 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다. 제어자의 종류는 크게 제어자와 그외 제어자로 나눌 수있다. 하나의 대상에 대해서 여러제어자를 조합하여 사용할 수 있지만, 접근 제어자는 한번에 하나만 가능하다.
접근 제어자: public, protected, default, private
그 외: static, final, abstract, native, transient, synchronized, volatile, strictfp
static
static은 '클래스의' 또는 '공통적인'의 의미를 가지고 있다. 인스턴스변수는 하나의 클래스로부터 생성되었더라도 각기 다른 값을 유지하지만, 클래스변수(static멤버변수)는 인스턴스에 관계없이 같은 값을 갖는다. 그 이유는 하나의 변수를 모든 인스턴스가 공유하기 때문이다.
static이 사용될 수 있는 곳 - 멤버변수, 메서드, 초기화 블럭
- static 멤버변수
모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다.
클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다.
클래스가 메모리에 로드될 때 생성된다.
- static 메서드
인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.
final
final은 '마지막의' 또는 '변경될 수 없는'의 의미를 가지고 있으며 거의 모든 대상에 사용 될 수 있다.
final이 사용될 수 있는 곳- 클래스, 메서드, 멤버변수, 지역변수
- final 클래스
변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.
그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
- final 메서드
변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
- final 멤버변수/지역변수
변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.
final이 붙은 변수는 상수이므로 일반적으로 선언과 초기화를 동시에 하지만, 인스턴스 변수의 경우 생성자에서 초기화 되도록 할 수 있다.
abstract
abstract는 '미완성'의 의미를 가지고있다. 메서드의 선언부만 작성하고 실제 수행 내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다.
- abstract 클래스
클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
-abstract 메서드
선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다.
접근 제어자
접근 제어자는 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다.
접근 제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자
private: 같은 클래스 내에서만 접근이 가능하다
default: 같은 패키지 내에서만 접근이 가능하다.// 접근 제어자가 지정이 되어 있지 않다면 default
protected: 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
public: 접근 제한이 전혀 없다.
- 접근 제어자를 이용한 캡슐화
클래스나 멤버, 주로 멤버에 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서이다.
데이터를 감추는 것은 객체지향개념의 캡슐화에 해당한다.
접근 제어자를 사용하는 이유
1) 외부로부터 데이터를 보호하기 위해
2) 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
ex) 메서드의 접근 제어자가 public이라면 메서드를 변경한 후에 오류가 없는지 테스트해야 하는 범위가 넓어 진다.
반면, private이라면 클래스 하나만 살펴보면 된다.
- 생성자의 접근 제어자
보통 생성자의 접근 제어자는 클래스의 접근제어자와 같지만, 다르게 지정할 수도 있다.
1) 생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.
2) 생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다.
private 생성자를 가진 클래스는 final을 추가하여 상속할 수 없음을 알리는 것이 좋다.
제어자의 조합
대상 | 사용가능한 제어자 |
클래스 | public, (default), final, abstract |
메서드 | 모든 접근 제어자, final, abstract, static |
멤버변수 | 모든 접근 제어자, final, static |
지역변수 | final |
제어자를 조합할 때 주의사항
- 메서드에 static과 abstact를 함계 사용할 수 없다.
static멘서드는 몸통이 있는 메서드에만 사용할 수 있기 때문이다. - 클래스에 abstract와 final을 동시에 사용할 수 없다.
클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고 abstract는 상속을 통해서 완성되어야 한다는 의미이로 서로 모순되기 때문이다. - abstract메서드의 접근 제어자가 private일 수 없다.
abstract메서드는 자손클래스에서 구현해주어야 하는데 접근 제어자가 private이면, 자손클래스에서 접근할 수 없기 때문인다. - 메서드에 private과 final을 같이 사용할 필요는 없다.
접근 제어자가 private인 메서드는 오버라이딩될 수 없기 때문인다. 이 둘 중 하나만 사용해도 의미가 충분하다.
'프로그래밍 > JAVA' 카테고리의 다른 글
[JAVA 이론] 상속 (0) | 2022.01.26 |
---|---|
[JAVA 이론] 오버로딩 & 오버라이딩 (2) | 2022.01.22 |
[JAVA 이론] 객체지향 프로그래밍_1 (2) | 2022.01.19 |
[JAVA 이론] 배열 (0) | 2022.01.15 |
[JAVA 이론] 조건문과 반복문 (0) | 2022.01.12 |