제어문
목표
자바의 Class에 대해 학습.
목차
- 클래스 정의하는 방법
- 기본 구조
- 접근제어 지시자
- 클래스와 변수,메소드의 접근
- public 클래스
- 어떤 클래스를 public으로 선언할지...
- 객체 만드는 방법 (new 키워드 이해하기)
- 기본 구조
- 객체 생성 new 키워드
- 참조변수
- 인스턴스변수, 인스턴스 메소드
- 객체 생성과 참조의 관계
- 참조변수와 메소드의 관계
- 메소드 정의하는 방법
- 기본 구조
- 메소드의 호출
- 값을 반환하는 메소드
- Access 메소드
- static 변수, static 메서드
- 생성자 정의하는 방법
- 기본 형식
- 생성자의 필요성
- 생성자의 특징
- 값을 전달받는 생성자와 디폴트 생성자(Default Constructor)
- 클래스는 default이면서 생성자는 private?
- this 키워드 이해하기
- 인스턴스 멤버와 매개변수 구분
- 오버로딩 된 생성자 호출
public class classNAme
{
...
}
접근제어 지시자(public), 반환형(public), 클래스 이름(className)으로 구성되어 있다.
접근제어 지시자
명시형으로 public, private, protected 로 세가지이며 접근제어 지시자의 생략도 가능하기 때문에 총 네가지 형태의 접근제어 선언이 가능하다.
private으로 선언되는 인스턴스 변수와 메소드는 선언된 클래스 내부에서만 접근이 가능하다.
객체지향 특성상 대부분의 인스턴스변수는 private으로 선언한다.(그러나 클래스 중에 데이터의 표현에만 초점을 맞춰서 설계된 매우 간단하게 정의된 클래스는 public으로 선언하는 예외도 있다.)
외부에서 private으로 선언된 이 변수의 간접접근을 허용하기 위한 유형의 메소드를 가리켜 'Access 메소드'라 한다.
클래스와 변수,메소드의 접근
접근제어 지시자로 데이터의 접근 허용을 제어한다.
변수, 메소드의 접근이라 함은 그 초기화나 호출을 뜻한다.
클래스의 접근이라 함은 어떤 영역에서 인스턴스 생성을 의미한다.
예를 들면 어떤 클래스가 default로 생성되었을 때, 접근 허용 규칙에 따라
다른 패키지에서는 default 클래스의 인스턴스를 생성할 수 없다.
public 클래스
1) 하나의 소스파일에는 하나의 클래스만 public으로 선언할 수 있다.
2) public 클래스의 이름과 소스파일의 이름은 일치해야 한다.
이 규칙은 프로그램의 기능이나 내용을 이해하는 것에 중요한 역할을 하는 public클래스와 소스파일의 관계 형성을 하기 위함이다.
이 라이브러리의 사용자는 계산기클래스에만 접근하면 될 뿐, 덧셈 클래스와 뺄셈 클래스에는 접근하지 않아도
계산기 클래스를 통해 그 기능을 사용할 수 있다. 덧셈과 뺄셈 클레스는 디폴트로 선언되었지만 계산기 클래스와 같은 패키지이기 때문이다. 꼬리에 꼬리를 물어 데이터와 기능에 접근할 수 있다는 개념이다.
그렇기 때문에 라이브러리의 사용자는 계산기 클래스만 알면 되지, 이외의 클래스는 알지도 못하고 알 필요도 없다.
ClassName name = new ClassName();
위의 문장만으로 메모리 공간에 객체가 생성되는데, 이렇게 객체를 생성하는 행위를 가리켜 '인스턴스화' 한다고 표현한다. 그리고 이렇게 생성된 객체를 가리켜 '인스턴스'라고도 부른다.
클래스에 존재하는 데이터(변수와 메소드)들은 메모리 공간에 할당된 형태로 존재하지 않고, 접근도 호출도 불가능한 하나의 틀로서만 역할을 한다.
반면 객체는 메모리 공간에 할당이 이뤄져 구성하는 모든 변수는 그 크기대로 메모리 공간에 할당이 되고 메소드도 호출할수 있는 형태로 메모리 공간에 존재하게 된다.
참조변수
대입연산자 왼편의 "ClassName name" 부분은 int num 과 같이 변수의 선언문 과 같은 형식이다.
사실 클래스를 정의하는 것 자체가 자료형을 정의하는 것이다. 클래스를 정의하는 것은 자바에서 제공하는 기본 자료형 이외에 개발자가 새로운 이름의 자료형을 정의하는 것과 같다.
ClassName 객체를 생성하고 이를 name이라는 이름의 변수로 참조하는 것이다.
위의 문장이 실행된 이후 부터는 ClassName이라는 이름을 통해 객체에 접근할 수 있다.
그래서 ClassName과 같은 변수를 가리켜 '참조변수'라고 한다.
인스턴스변수, 인스턴스 메소드
위 설명에서 참조변수를 통해 클래스의 객체에 접근할 수 있다고 했다.
이 클래스 내에 저장되어 있는 변수. 즉 new 키워드를 통해 인스턴스화하여만 접근이 가능한 변수와 메소드를 가리켜 각각 인스턴스변수, 인스턴스메소드라 한다.
객체 생성과 참조의 관계
new에 의해 반환되는 주소 값(참조변수가 저장하고 있는 값)을 가리켜 '참조' 또는 reference라 한다.
new에 의한 객체 생성시 생성된 객체는 메모리에 저장되고 저장된 메모리의 주소 값이 반환되어 참조변수에 저장된다. 참조변수에 의한 객체 접근이 가능한 이유도 이 때문이며, 주소의 값이 저장되었기 때문에 다음과 같은 문장도 가능하다.
ClassName name = new ClassName();
ClassName name2 = name; // 저장된 주소
simpleMethod의 매개변수에 nInst에 저장된 주소 값을 전달하고 있다.
메인메소드 안에 Number객체형 Inst변수가 선언되어 있고,
simpleMethod에도 Number객체형 변수 numb가 선언되어 있다.
위 코드는 메소드의 매개변수로 선언된 변수와 메인메소드 안에 선언된 변수가
같은 참조 값을 가지고 있음을 나타낸다.
public static void className(int a) {
...
}
접근 지시자(public), static, 반환형(void), 메소도의 이름(className), 매개변수(int a) 순으로 적혀있다.
public class Program {
public static void main(String[] args) {
sayAge(20);
sayAge(21);
}
public static void sayAge(int age) {
System.out.println("...");
System.out.println("I`m " + age + "years old.");
}
}
sayAge라는 메소드를 만들었다. 메소드의 이름 오른편에 매개변수를 쓰는데, 메소드 호출 시 전달되는 값의 자료형과 매개변수의 자료형은 일치해야 한다.
메소드가 정의되는 위치는 프로그램에 영향을 미치지 않는다. 위의 예제의 경우 main 메소드와 sayAge메소드의 위치 순서와 상관없이 실행결과에는 아무런 차이가 없다.
main 메소드를 포함한 다른메소드의 void 키워드는 "호출한 영역으로 값을 전달하지 않음"을 뜻한다.
메소드 내의 return 키워드는 '값의 반환'과 '메소드의 종료'를 의미한다.
메소드 중간에 return문이 실행되면 나머지 부분은 실행이 되지 않고 메소드를 빠져나가게 된다느 사실을 기억하자.
그리고 반환형이 void인 메소드 내에서도 값의 반환 목적이 아닌 메소드의 종료 목적으로 return문을 사용할 수 있다.
public class Program2 {
public static void main(String[] args) {
divide(4,2);
divide(4,0);
}
public static void divide(int num1, int num2) {
if(num2==0) {
System.out.println("0으로는 값을 나누지 못함.");
return;
}
System.out.println("나눗셈 : " + (num1/num2));
}
}
위와 같이 두번 째 인자가 0일 경우, 반환의 대상을 명시하지 않음으로써 메소드를 종료시킬 수 있다.
class Person
{
private int age;
public void setAge(int ag) { age=age;}
public int getAge() { return age }
}
setAge와 getAge와 같은 메소드가 Access 메소드이다.
static멤버는 인스턴스가 생성되기 이전에 별도의 메모리 공간에 할당되어 초기화까지 완료된다.
이 초기화 시점은 JVM에 의해서 클래스가 메모리 공간에 올라가는 순간이다.
때문에 static 변수를 생성자를 통해 초기화하는 실수를 범하면 안된다. 인스턴스가 생성될 때마다 새로운 값이 대입되는 꼴이 되어버리기 때문에 static으로써의 의미를 잃는다.
static 변수는 인스턴스 간에 데이터 공유가 필요한 상황에 유용하고,
static final로 선언된 변수는 클래스 내부 또는 외부에서 참조의 용도로만 필요한 상황에 유용하다.
static 메서드는 단순히 외부에 기능을 제공할 뿐, 메서드를 구성하는 데이터들이 인스턴스 변수에 저장된 값을 변경하거나 참조하는 일(인스턴스 단위로 행하여지는 일)을 하지 않을 경우 유용하다.
그리고 static 메서드 안에서는 인스턴스 변수에 접근이 불가능하다. 한클래스 내에 선언되었다 하더라도 불가능하다.
이유는 static 메서드와 인스턴스 멤버가 존재하는 경계가 다르다.
다수의 인스턴스가 static 메서드를 공유하는 구조이기 때문에
static 메서드는 인스턴스의 소유가 아닌, 다른 경계에 존재해야 하기 때문이다.
같은 클래스의 인스턴스 a,b,c가 생성되어 있다는 가정 하에, 스태틱메서드로 인스턴스 변수를 변경했을 때 a,b,c중 어떤 인스턴스 변수를 변경해야하는가? 이러한 인스턴스 변수와 static 메소드의 관계를 통해 접근이 불가능한 이유를 이해할 수 있다.
인스턴스 에서는 static 메서드에 접근할 수 있지만 static메서드에서는 인스턴스 멤버에 접근할 수 없다는 사실에 대해 착각하지 않도록 주의해야 한다.
class Number {
int num;
public Number() // 생성자
{
num = 10;
System.out.println("생성자 호출 됨");
...
}
}
생성자의 필요성
자바와 같은 객체지향 프로그래밍에서 인스턴스의 생성은 매우 빈번한 일이다.
빈번한 인스턴스의 생성 및 초기화를 간편하고 안전하게 할 방법이 필요하다.
생성자의 특징
생성자는 인스턴스 생성시 딱 한번 호출되는 메소드로써, 인스턴스 변수 초기화를 목적으로 정의되는 메소드이다.
Number num = new Number();
그리고 위 코드를 보면인스턴스의 생성과정에서 호출될 생성자를 명시하는 부분이 보인다.
즉, Number()는 인자를 전달받지 않는 생성자의 호출을 의미한다.
"new Number"은 Number의 인스턴스 생성을 의미하고,
"Number()"은 생성자 호출을 의미한다.
이렇게 보면 인스턴스 생성 과정에서 Number에 대한 의미 해석이 두 번 이뤄진다고 생각할 수 있다.
하지만 클래스의 이름과 생성자의 이름은 항상 동일해야 하기 때문에 지극히 당연한 것으로 볼 수 있다.
그리고 자바에서 인스턴스 생성시에는 반드시 생성자가 호출되어야 한다는 중요한 사실을 기억해두도록 하자.
class Number
{
public Number();
{
// 비어있음.
}
}
그리고 class를 default로 선언하고 생성자는 public으로 선언하는 경우도 같은 양상을 보인다.
이러한 아구가 맞지 않는 경우는 상황에 따라서 적절치 않을 수 있으니 주의해야 한다.
this는 인스턴스 자신을 의미하는 키워드이다.
method의 매개변수와 method 내에서 접근하고자 하는 인스턴스 변수 이름이 같을 때 사용.
this는 인스턴스 자신을 의미하는 키워드로써, 이를 통해 인스턴스 변수와 인스턴스 method에 접근한다.
public void cons(int a, int b, int c, int d, int e)
{
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
}
public void cons2(int a, int c, int d)
{
this(a, 0, c, d);
}
public void cons(int a, int b, int c, int d)
{
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
참고 서적 : 난 정말 JAVA를 공부한 적이 없어요 (ORANGE MEDIA 윤성우 저)