자바 수업 4일차



* 엘리베이터 코딩 깜빡했다.


* 다른 시각으로 바라보는 것이 필요하다.

  - 고정관념 버리기

  - 새로운 방법으로 시도하기

  - 자바 관련 도서, 다른 저자가 쓴 것도 봐라.


* 다이어그램 등에서 상속을 설명할 때 화살표 방향은 일반적으로 생각하는 것과 반대이다.

  - 객체 생성의 화살표 방향은 일반적으로 생각하는 대로이다.


* 클래스 상속의 이점

  - 코드를 간결하게 할 수 있다.

  - 코드의 재사용성을 높인다.


* 캡슐화

  - 캡슐로 된 감기약과 같은 개념

    ~ 캡슐에는 많은 성분이 포함되어 있지만, 단순히 감기를 낫게 해 준다고 생각

    ~ 개별 성분은 알 수 없지만, 약의 효과만 알고 선택하는 것과 같다.

  - 꼭 필요한 내용만 보여주고, 불필요한 내용을 감춘다는 개념이다.

  - 클래스를 작성할 때는 꼭 필요한 내용만 공개해야 한다.

  - 클래스를 작성할 때 캡슐화 개념을 적용하지 않으면, 클래스가 잘못 사용될 수 있다.

  - 캡슐화의 개념을 적용하여 정보 은폐(information hiding)를 달성할 수 있다.

  

* 캡슐화를 통한 '정보의 은폐(information hiding)'의 장점

  - 객체에 포함된 정보의 손상과 오용을 막을 수 있다.

  - 객체 내부의 조작 방법이 바뀌어도 사용법은 바뀌지 않는다.

  - 데이터가 바뀌어도 다른 객체에 영향을 주지 않아 독립성이 유지된다.

  - 처리된 결과만 사용하므로 객체의 이식성이 좋다.

  - 객체를 부품화 할 수 있어 새로운 시스템의 구성에 부품처럼 사용할 수 있다.


* 캡슐화의 방법

  - private 한정자(접근 제한자)를 지정하여 캡슐화가 가능하다.


* 추상화

  - 실세계의 문제를 객체로 변환할 때 적용할 수 있는 개념이다.

  - 여러 개의 문제에서 공통적인 속성을 추출하여 상위 클래스에 작성하고, 나머지 클래스를 하위 클래스로 구성하는 것이 추상화의 핵심이다.

  - 추상화와 상속은 다형성을 제공하는 기반이다.


* 추상화의 단계

  - 1단계 : 현실 세계의 문제들이 가지는 공통적인 속성을 추출

  - 2단계 : 공통 속성을 가지는 추상 클래스 작성

  - 3단계 : 추상 클래스들의 하위 클래스로 현실 세계의 문제들을 구현


* 다형성(Polymorphism)

  - 객체지향의 중요한 개념 중 하나. 다양한(poly) 변신(morphism)을 의미한다.

  - 서로 다른 객체가 동일한 메시지에 대하여 서로 다른 방법으로 응답할 수 있는 기능이다.



☞ 클래스


* 자바 프로그램은 클래스로부터 객체를 생성하여 프로그램이 작성된다.

  - 객체를 생성하기 위해서는 클래스를 작성해야 한다.


* 클래스의 구성 요소

  - 멤버 변수, 생성자(또는 생성자 메소드), 메소드로 구성된다.

  - 클래스가 항상 3가지 요소를 모두 가지는 것은 아니다.


* 클래스의 예

  a. 멤버 변수, 생성자 메소드를 가지는 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Box {
    int width;   // 속성 - 멤버 변수
    int height;
    int depth;
    public Box(int w, int h, int d) {   // 기능 - 생성자 메소드
        width = w;
        height = h;
        depth = d;
    }
    public void volume() {   // 기능 - 메소드
        int vol;
        vol = width * height * depth;
        System.out.println("Volume is " +vol);
    }
}
cs


  b. 속성만 가지는 클래스

1
2
3
4
5
public class Box {
    int width;   // 속성 - 멤버 변수
    int height;
    int depth;
}
cs


  c. 속성과 메소드를 가지는 클래스

1
2
3
4
5
6
7
8
9
10
public class Box {
    int width;   // 속성 - 멤버 변수
    int height;
    int depth;
    public void volume() {   // 기능 - 메소드
        int vol;
        vol = width * height * depth;
        System.out.println("Volume is " +vol);
    }
}
cs


* 클래스 선언

  - [형식]

1
2
3
4
5
[public/final/abstractclass Class-name {
    ......
    ......  // 클래스의 속성과 기능을 기술
    ......
}
cs


* 클래스의 한정자

  - public : 모든 클래스에서 접근 가능

  - 한정자 사용 안 함 : 같은 패키지 내의 클래스에서만 접근 가능

  - final : 서브 클래스를 가질 수 없는 클래스

  - 추상(abstract) : 객체를 생성할 수 없는 클래스


* 다수 개의 클래스가 하나의 프로그램에 정의될 때

  - 클래스에 붙이는 public 한정자는 main() 메소드를 가진 클래스에만 붙여야 한다.

  - 프로그램의 이름은 main() 메소드를 가진 클래스의 이름과 동일해야 한다.

  - 한 패키지에는 동일한 이름의 클래스가 중복될 수 없다.


* 객체의 생성

  - [형식]

객체 변수명 = new 클래스명;

1
2
3
mybox1 = new Box();
student1 = new Avg();
name = new String("J.Hong");
cs


* 객체의 선언과 생성

  - [형식]

클래스명 객체 변수명 = new 클래스명;

1
2
3
Box mybox1 = new Box();
Avg student1 = new Avg();
String name = new String("J.Hong");
cs


* 멤버 변수

  - 클래스 내에 메소드 밖에 선언된 변수

  - 객체 변수, 클래스 변수, 종단 변수로 구분된다.


* 생성자, 메소드 변수

  - 생성자나 메소드에는 자체적으로 선언하여 사용하는 지역 변수와 호출 시 지정되는 매개 변수로 구분된다.


1
2
3
4
5
6
7
8
9
10
11
class A {
    int a;   // 멤버 변수
    int b;
    public int A1()    {
        int c;   // 지역 변수
        return 7;
    }
    public int A2(int d) {   // 매개 변수
        return 8;
    }
}
cs


* 멤버 변수의 선언

  - [형식]

[public/private/protected][static][final] 변수형 변수명;

1
2
3
4
5
6
7
public int width;
private double rate;
static int idnumber;
final int MAX = 100;
public Box mybox1;
private String passwd;
public final int MIN = 1;
cs


- static : 클래스 변수

- final : 종단 변수


생성자나 메소드의 변수(매개 변수와 지역 변수)

  - [형식]

[final] 변수형 변수명;

1
2
3
4
5
public void cc(final int x, final int y) {   // 메소드의 매개 변수에 final을 지정
    final int Max = 10;      // 메소드의 지역 변수로 final을 선언
    String name = "J.Hong";  // 지역 변수로 문자열 변수 선언
    private int num;         // 오류 발생. 객체 변수에만 사용 가능.
}
cs


* 객체 변수나 지역 변수는 변수가 가지는 값의 형에 따라 다른 특성을 가진다.

  - 기본 자료형 : 값을 가진다.

  - 참조 자료형 : 주소를 가진다.


1
2
3
4
5
6
......
int my_count1 = 100;
int my_count2 = my_count1;  // 별도의 기억 장소에 값을 복사
Box mybox1 = new Box();
Box mybox2 = mybox1;  // 두 객체 변수가 같은 장소를 가리킨다.
......
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Box2 {
    int width = 10;  // 3개의 속성과 값을 설정
    int height = 20;
    int depth = 30;
}
public class Box2Test1 {
    public static void main(String args[]) {
        int myint1 = 100;  // 기본 자료형 변수값을 배정
        int myint2 = myint1;
        
        System.out.println("첫 번째 값 : " + myint1 + ", 두 번째 값 : " + myint2);
        
        myint1 = 200;  // 한 변수의 값을 변경하여 출력
        System.out.println("첫 번째 값 : " + myint1 + ", 두 번째 값 : " + myint2);
        
        Box2 mybox1 = new Box2();  // 두 개의 서로 다른 참조 자료형 변수 생성
        Box2 mybox2 = new Box2();
        
        mybox1.width = 20;  // 각각의 변수를 통하여 속성값을 변경
        mybox2.depth = 123;
        
        System.out.println("mybox1.width : " + mybox1.width);
        System.out.println("mybox1.height : " + mybox1.height);
        System.out.println("mybox1.depth : " + mybox1.depth);
        
        System.out.println("mybox2.width : " + mybox2.width);
        System.out.println("mybox2.height : " + mybox2.height);
        System.out.println("mybox2.depth : " + mybox2.depth);
        // 서로 영향을 받지 않는다.
        
        Box2 mybox3 = mybox2;  // 참조 자료형 변수에 다른 참조 자료형 변수를 대입
        mybox2.width = 1000;  // 값을 변경
        mybox2.height = 2000;
        
        System.out.println("mybox3.width : " + mybox3.width);
        System.out.println("mybox3.height : " + mybox3.height);
        System.out.println("mybox3.depth : " + mybox3.depth);
        // 다른 자료형 변수의 변경에 따라 값이 바뀐다.
    }
}
 
cs



* 객체 변수와 지역 변수들은 초기화 과정에서 약간의 차이가 있다.

  - 객체 변수들은 변수를 초기화하지 않아도 객체가 생성되면 묵시적 값이 자동으로 설정된다. (사실은 객체가 생성되면서 묵시적 값으로 초기화를 수행한다.)

  - 메소드 지역 변수는 변수의 값을 명시적으로 초기화하지 않으면 구문 오류가 발생한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Initial {
    int number;   // 클래스의 속성으로 값을 지정하지 않고
    double rate;  // 객체 변수만 선언
    String name;
    int[] score;
    public void aMethod() {  // 메소드 선언
        int count;           // 메소드 지역 변수 선언
        System.out.println(number);   // 객체 변수의 값 출력
        //System.out.println(count);  // 오류 발생. 초기화되지 않은
                                      // 지역 변수값 출력 불가.
    }
}
public class InitialTest1 {
    public static void main(String args[]) {
        int var1;  // 메소드의 지역 변수로 값을 지정하지 않고 변수 선언
        double var2;
        Initial ob1 = new Initial();  // 객체의 생성. 객체 변수의 초기화 수행.
//        System.out.println("지역 변수 var1의 값은 : " + var1);  // 오류 발생. 초기화가
//        System.out.println("지역 변수 var2의 값은 : " + var2);  // 이루어진 다음 사용 가능.
        System.out.println("객체 변수 number의 값은 : " + ob1.number);  // 묵시적인 값이 출력
        System.out.println("객체 변수 rate의 값은 : " + ob1.number);
        System.out.println("객체 변수 name의 값은 : " + ob1.name);
        System.out.println("객체 변수 score의 값은 : " + ob1.score);
        ob1.aMethod();  // 객체의 메소드 호출
    }
}
cs



* 클래스 변수

  - static을 사용하여 선언한다.

  - 전역 변수(global variable)의 개념이다.

  - [형식]

static [final] 변수형 변수명;

1
2
static idnumber;  // 클래스 변수 idnumber 선언
static final fixnumber;  // 클래스 변수이면서 값이 변할 수 없는 종단 변수
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Box3 {
    int width;
    int height;
    int depth;
    long idNum;
    static long boxID = 0;  // 클래스 변수로 boxID 선언
    public Box3() {         // 생성자에서 클래스 변수값을 증가시켜 속성 idNum에 배정
        idNum = ++boxID;
    }
}
class Box3Test1 {
    public static void main(String args[]) {
        Box3 mybox1 = new Box3();  // 객체를 생성. 생성자 수행.
        Box3 mybox2 = new Box3();
        Box3 mybox3 = new Box3();
        Box3 mybox4 = new Box3();
        
        // 객체의 idNum이 증가되면서 출력
        System.out.println("mybox1의 id 번호 : " + mybox1.idNum);
        System.out.println("mybox2의 id 번호 : " + mybox2.idNum);
        System.out.println("mybox3의 id 번호 : " + mybox3.idNum);
        // 객체명을 통하여 클래스 변수값 출력
        System.out.println("mybox4의 id 번호 : " + mybox4.idNum);
        // 클래스명을 통하여 클래스 변수값 출력
        System.out.println("마지막 생성된 박스 번호는 " + Box3.boxID + "번입니다.");
    }
}
cs



* 종단 변수

  - final을 사용하여 선언하며, 변할 수 없는 상수값을 갖는다.

  - [형식]

final 변수형 변수명 = 초기값;

1
2
3
4
5
6
7
8
9
final int MAX = 100;
static final int SONATA_LENGTH = 3200;
final int MIN;  // 오류 발생. 종단 변수는 반드시 초기화 요구.
public void inc() {
    MAX = ++MAX;  // 오류 발생. 종단 변수값은 변경할 수 없다.
}
public void max(final int x) {  // 메소드 매개 변수를 final로 선언.
    x++;  // 오류 발생. 종단 변수값은 변경할 수 없다.
}
cs



* 변수의 유효 범위

  - 그 변수가 사용될 수 있는 영역을 의미한다.


* 유효 범위 측면에서의 변수들을 구분

  - 멤버 변수

  - 메소드 매개 변수와 지역 변수(블록 변수)

  - 예외 처리기 매개 변수(exception handler parameter)


* 접근 제한자(한정자)

  - 클래스 내의 멤버 변수 접근을 제한할 수 있는 방법이다.

  - 접근 제한은 캡슐화와 정보 은폐를 제공한다.

  - 자바의 명시적인 접근 한정자 : public/private/protected


* public 접근 한정자는 항상 접근 가능함을 의미한다.

  - 꼭 공개해야 하는 정보만 public으로 선언한다.


* private 접근 한정자는 소속된 클래스 내에서만 사용 가능하다.


* 접근 한정자를 지정하지 않은 경우

  - 같은 패키지 내의 클래스에서 사용 가능하다.

  - 접근 한정자를 지정하지 않는 것은 좋은 습관이 아니다.


* 생성자는 메소드와 비슷하지만, 주로 객체의 초기화 과정을 수행한다.

  - 생성자는 객체가 생성될 때 자동으로 수행된다.

  - 주로 객체의 초기화를 위해 사용한다.

  - 생성자의 이름은 클래스의 이름과 동일하다.

  - [형식]

[public/private] 클래스 이름([매개 변수], [매개 변수], ...) {

    초기화 문장들

}

※ 생성자는 반환값이 없다.


  a. 묵시적 생성자가 없는 경우

1
2
3
4
5
6
7
8
class Cons1 {  // 생성자 없이 클래스 생성
    public int num;
}
public class ConsTest1 {
    public static void main(String args[]) {
        Cons1 cons = new Cons1();  // 클래스로부터 객체 생성
    }
}
cs


  b. 묵시적 생성자를 지정하는 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
class Cons2 {
    public int num;
    public Cons2() {  // 매개 변수가 없는 묵시적 생성자 선언
        System.out.println("묵시적 생성자");
    }
}
public class ConsTest2 {
    public static void main(String args[]) {
        Cons2 cons = new Cons2();  // Cons 클래스로부터 객체 생성.
                                   // new 명령어에 의해 묵시적 생성자가
                                   // 수행되어 "묵시적 생성자"가 출력된다.
    }
}
cs


  c. 명시적 생성자가 있는 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Cons3 {
    public int num;
    public Cons3(String s) {  // 매개 변수가 있는 명시적 생성자 선언
        System.out.println(s + " 명시적 생성자");
    }
}
public class ConsTest3 {
    public static void main(String args[]) {
        Cons3 cons1 = new Cons3("1번째");  // 매개 변수를 지정하여 객체 생성.
                                          // "1번째 명시적 생성자" 출력
        //Cons3 cons2 = new Cons3();      // 오류 발생. 해당되는 생성자가 없다.
                                          // 클래스에 어떠한 생성자도 없는 경우에는 묵시적 생성자가 없어도 객체가 생성되지만,
                                          // 명시적 생성자가 하나라도 있으면 묵시적 생성자를 사용하기 위해서는
                                          // 반드시 정의해야 한다. (생성자 오버로딩)
    }
}
cs



* 하나의 클래스에 여러 개의 생성자가 있다 : 생성자 오버로딩

  - 생성자 매개 변수의 타입과 개수가 달라져야 한다.


* 생성자나 메소드에서 this가 사용되면, this는 자신을 가동시킨 객체를 의미한다.


* this의 또 다른 용도 : 생성자 내에서 단독으로 사용

  - 다른 생성자를 호출한다.

  - 생성자 내에서 사용될 경우에는 반드시 첫 번째 라인에 위치해야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Box7 {
    int width;
    int height;
    int depth;
    public Box7() {
        this(111);  // this를 이용하여 매개 변수를 가진 생성자 호출
        System.out.println("매개 변수 없는 생성자 수행");  // 생성자 내에서 출력문 수행
    }
    public Box7(int width) {
        this(width, 11);  // this를 이용하여 3개의 매개 변수를 가진 생성자 호출
        System.out.println("매개 변수(1개) 생성자 수행");
    }
    public Box7(int width, int height) {
        this(width, height, 1);  // this를 이용하여 3개의 매개 변수를 가진 생성자 호출
        System.out.println("매개 변수(2개) 생성자 수행");
    }
    public Box7(int width, int height, int depth) {
        System.out.println("매개 변수(3개) 생성자 수행");
        this.width = width;  // 객체의 속성에 매개 변수의 값을 배정
        this.height = height;
        this.depth = depth;
    }
}
public class Box7Test1 {
    public static void main(String args[]) {
        Box7 mybox1 = new Box7();
        int vol = mybox1.width * mybox1.height * mybox1.depth;
        System.out.println("박스의 부피(매개 변수 없음) : " + vol);
        mybox1 = new Box7(10);
        vol = mybox1.width * mybox1.height * mybox1.depth;
        System.out.println("박스의 부피(매개 변수 1개) : " + vol);
        mybox1 = new Box7(1020);
        vol = mybox1.width * mybox1.height * mybox1.depth;
        System.out.println("박스의 부피(매개 변수 2개) : " + vol);
        mybox1 = new Box7(102030);
        vol = mybox1.width * mybox1.height * mybox1.depth;
        System.out.println("박스의 부피(매개 변수 3개) : " + vol);
    }
}
cs


※ 내일까지 <윤성우의 열혈 Java 프로그래밍> 21~24장 읽어오기


* 메소드
  - 클래스의 핵심으로서 클래스의 기능을 나타낸다.
  - [형식]
[public/private/protected][static/final/abstract/synchronized] 반환값형 메소드 이름([매개 변수들])
{
    ......
    지역 변수 및 메소드의 행위 기술
    ......
}

// static : 클래스 메소드
// final : 종단 메소드
// abstract : 추상 메소드
// synchronized : 동기화 메소드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Box8 {
    int width;
    int height;
    int depth;
    public Box8(int width, int height, int depth) {
        this.width = width;
        this.height = height;
        this.depth = depth;
    }
    int volume() {  // 메소드 volume()에서 부피를 계산하여 결과를 반환 
        int vol = width * height * depth;
        return vol;
    }
}
public class Box8Test1 {
    public static void main(String args[]) {
        Box8 mybox1 = new Box8(10,20,30);
        //mybox1.width = 20;  // 접근 한정자를 사용하지 않았으므로,
                              // 값을 변경할 수 있다.
        int vol1 = mybox1.volume();  // 메소드를 호출하여 부피를 구한다.
        System.out.println("정수 박스의 부피 : " + vol1);
    }
}
 
cs


* 메소드 선언 시 사용되는 접근 한정자는 멤버 변수와 같이 public, private, protected가 사용된다.
1
2
3
4
5
6
7
8
public class Test1 {
    public int a;  // public으로 선언된 객체 변수
    int b;         // 접근 한정자를 지정하지 않고 선언된 객체 변수
    private int c;              // private로 선언된 객체 변수
    public void method1() { }   // public으로 선언된 메소드
    void method2() { }          // 접근 한정자를 지정하지 않고 선언된 메소드
    private void method3() { }  // private로 선언된 메소드
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Box9 {
    private int width;  // 객체의 모든 속성들을 private로 선언
    private int height;
    private int depth;
    private int vol;
    public Box9(int width, int height, int depth) {
        this.width = width;
        this.height = height;
        this.depth = depth;
        volume();  // 생성자에서 volume() 메소드 호출
    }
    private void volume() {  // volume() 메소드를 private로 선언
        vol = width * height * depth;
    }
    public int getvolume() {  // 부피를 단순하게 변환하는 메소드,
                              // public으로 선언
        return vol;
    }
}
public class Box9Test1 {
    public static void main(String args[]) {
        Box9 mybox1 = new Box9(10,20,30);
        // mybox1.width = 20;           // 객체의 속성값을 변경하거나
        // int vol1 = mybox1.volume();  // 메소드를 호출하면 오류 발생
        
        // 부피를 읽어오는 메소드를 호출하여 값을 출력
        System.out.println("정수 박스의 부피 : " + mybox1.getvolume());
    }
}
 
cs


* 클래스 변수와 같이 메소드에도 static을 붙여 클래스 메소드로 선언한다.
  - 클래스 변수와 같이 클래스 이름으로 접근한다.
  - 객체를 생성하지 않아도 사용 가능한 함수같은 메소드이다.
1
2
3
4
Arrays.toString(a);
Arrays.sort(b);
Integer.parseInt(args[0]);
String.valueOf(number);
cs

  - 클래스 메소드 내에서는 클래스 변수만 사용이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
class Box {
    int width;
    int height;
    int depth;
    long idNum;
    static long boxID = 100;
    static long getcurrentID() {
        int count = 1;
        idNum = idNum + count;
        boxID = boxID + count;
        return boxID++;
    }
}
cs


* final로 선언된 메소드
  - 서브 클래스에서 오버라이딩overriding 될 수 없음을 의미한다.

* abstract로 선언된 메소드
  - 추상 메소드로서 추상 클래스 내에서 선언될 수 있다.
  - 추상 메소드는 선언 부분만 가지고 몸체 부분이 없는 메소드로서 하위 클래스에서 오버라이딩된다.

* synchronized 메소드
  - 스레드를 동기화할 수 있는 기법을 제공하기 위해 사용되는 메소드이다.

* 메소드는 상호 호출될 수 있다.
  - 하나의 메소드에서 다른 메소드가 호출되면, 그 메소드는 수행이 중지되고 호출된 메소드로 제어가 넘어간다.
  - 호출된 메소드의 수행이 완료되면 호출한 메소드는 중지된 시점에서 다시 실행된다.

* 메소드 선언부에서 반환값의 자료형이 지정되어야 한다.
  - 반환값의 자료형이 지정된 경우, 명시적으로 return문에 의해 값이 반환되어야 한다.
  - 반환값은 기본 자료형 뿐만 아니라 참조 자료형도 반환될 수 있다.
  - 반환값이 없는 경우에는 void로 지정한다.

1
2
3
4
5
public int sum(int a, int b) {  // 반환되는 값의 형을 int로 지정한다.
    int c;
    c = a + b;
    return c;  // 정수값을 반환한다.
}
cs

1
2
3
4
5
public void calc(int x, int y) {  // 반환되는 값이 없다는 의미이다.
    ......
    if ( a < 0 ) return;  // 조건이 참이면 메소드의 실행을 종료한다.
    ......
}
cs

1
2
3
4
5
6
7
8
9
public Box volume_compute(Box instance_box) {  // 반환되는 값의 형을 Box로 지정한다.
    ......
    Box v_box = new Box();  // Box 객체를 생성하여 반환값으로 사용한다.
    v_box.width = instance_box.width;
    v_box.height = instance_box.height;
    v_box.depth = instance_box.depth;
    v_box.volume = v_box.width * v_box.height * v_box.depth;
    return v_box;  // Box 객체를 반환한다.
}
cs

* main() 메소드
  - 특수한 메소드로서 자바 프로그램의 실행이 시작되는 첫 메소드를 의미한다.

* 클래스 메소드 main()의 의미
  - main() 메소드는 클래스 메소드이므로 이 메소드에서 사용 가능한 속성 역시 클래스 속성만 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Sample {
    int count=10;       // 객체 변수 선언
    static int num=20;  // 클래스 변수 선언
    public int sum(int x, int y) {  // 메소드 선언
        return x+y;
    }
    static int mul(int x, int y) {  // 클래스 메소드 선언
        return x*y;
    }
 
    public static void main(String[] args) {
        int same;
        same = count;      // 오류 발생. 클래스 메소드는 클래스 변수만 사용 가능.
        same = num;        // 사용 가능.
        same = sum(55);  // 오류 발생. 클래스 메소드에서는 클래스 메소드만 사용 가능.
        same = mul(55);  // 사용 가능.
    }
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Sample1 {
    int count=10;
    static int num=20;
    public int sum(int x, int y) {
        return x+y;
    }
    static int mul(int x, int y) {
        return x*y;
    }
 
    public static void main(String[] args) {
        Sample1 s = new Sample1();  // main() 메소드가 속한 클래스로부터 객체 생성.
        int same = s.count;  // 객체(객체의 속성)에 접근 가능.
        same = s.num;        // Sample1.num도 가능.
        same = s.num(55);  // 객체(객체의 메소드)에 접근 가능.
        same = s.mul(55);  // Sample1.mul(5, 5)도 가능.
    }
}
cs


* main() 메소드의 매개 변수
  - 문자열의 배열로 정의
1
2
3
4
5
6
7
8
public class Sample2 {
    public static void main(String[] args) {
        String s1 = args[0];
        String s2 = args[1];
        System.out.println("첫 번째 매개 변수값 : " + s1);
        System.out.println("두 번째 매개 변수값 : " + s2);
    }
}
cs

* 생성자의 오버로딩과 같이 메소드도 오버로딩 할 수 있다.
  - 같은 클래스에 같은 이름의 메소드를 중첩하여 사용한다.
  - 메소드 매개 변수의 개수와 형이 달라야 한다.
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Box11 {
    private int ivol;
    private double dvol;
    public Box11(int w, int h, int d) {
        volume(w,h,d);  // 오버로딩된 메소드 volume()을 호출함.
    }
    public Box11(double w, double h, double d) {
        volume(w,h,d);
    }
    private void volume(int w, int h, int d) {
        ivol = w * h * d;  // 오버로딩된 메소드 volume()을 호출함.
    }
    private void volume(double w, double h, double d) {  // 동일한 이름의 메소드가 오버로딩으로 선언.
        dvol = w * h * d;
    }
    public int get_ivol() {
        return ivol;
    }
    public double get_dvol() {
        return dvol;
    }
}
public class Box11Test1 {
    public static void main(String args[]) {
        Box11 mybox1 = new Box11(10,20,30);
        System.out.println("박스의 부피(정수 매개 변수) : " + mybox1.get_ivol());
        mybox1 = new Box11(10.520.530.5);
        System.out.println("박스의 부피(실수 매개 변수) : " + mybox1.get_dvol());
        mybox1 = new Box11(102030.5);
        System.out.println("박스의 부피(정수와 실수 혼합) : " + mybox1.get_dvol());
    }
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Overload {
    public void calc() {  // 오버로딩된 메소드
        System.out.println("매개 변수가 없습니다.");
    }
    public void calc(int width) {
        System.out.println("정사각형의 넓이 : " + width * width);
    }
    public void calc(int width, int height) {
        System.out.println("직사각형의 넓이 : " + width * height);
    }
    public void calc(int width, int height, int depth) {
        System.out.println("직육면체의 부피 : " + width * height * depth);
    }
}
public class OverloadTest1 {
    public static void main(String args[]) {
        Overload ol = new Overload();  // 객체를 생성.
        int input[] = new int[args.length];  // 입력한 매개 변수의 크기와 같은 정수 배열 생성.
        for(int i=0; i<args.length; i++)           // 실행 시 입력한 문자열 배열의 요소를
            input[i] = Integer.parseInt(args[i]);  // 정수로 바꾸어 정수 배열에 저장.
        switch (args.length) {  // 정수 배열의 길이를 기준으로 switch문 수행.
        case 0:                 // 배열의 길이에 따라 메소드 호출.
            ol.calc();
            break;
        case 1:
            ol.calc(input[0]);
            break;
        case 2:
            ol.calc(input[0], input[1]);
            break;
        case 3:
            ol.calc(input[0], input[1], input[2]);
            break;
        default:
            System.out.println("인수의 개수가 많습니다.");
        }
    }
}
cs


* 메소드 호출 시 매개 변수로 지정되는 실매개 변수
  - 기본 자료형과 참조 자료형

* 자바의 매개 변수 전달 기법은 call by value(값을 복사) 기법을 사용한다.
  - 값-전달 기법은 메소드 호출 시 실매개 변수의 값을 형식 매개 변수에 복사해 주는 방식이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Argument {
    public void change(int i, int j[]) {
        i = 20;      // 기본 자료형 변수 i의 값을 변경.
        j[3= 400;  // 참조 자료형 배열의 4번째 요소의 값을 변경.
    }
    public void display(int i, int j[]) {  // 변수 i의 값과 배열을 출력.
        System.out.println("객체 변수 i의 값 : " + i);
        System.out.print("배열의 값 : ");
        for(int value : j)
            System.out.print(value + " ");
        System.out.println();
    }
}
 
class ArgumentTest1 {
    public static void main(String args[]) {
        Argument d = new Argument();
        int a = 10;
        int b[] = { 1234 };
        System.out.println("첫 번째 display() 메소드 호출");
        d.display(a, b);
        d.change(a, b);
        System.out.println("===============================");
        System.out.println("값을 변환한 다음 두 번째 display() 호출");
        d.display(a, b);
    }
}
 

cs




☞ 상속

* 자바에서의 상속은 확장(extends)의 개념
  - 하위 클래스 = 상위 클래스 + 하위 클래스에 추가된 기능과 속성

* 상속의 효과
  - 클래스 검색이 쉽다.
    ~ 상속을 통하여 클래스를 체계화할 수 있다.
  - 클래스 확장이 쉽다.
    ~ 상속을 통하여 새로운 클래스를 생성하기가 용이하다.
  - 클래스 변경이 쉽다.
    ~ 상속을 통하여 기존 클래스의 기능을 쉽게 변경할 수 있다.

* 자바 상속의 특징
  - 다중 상속을 허용하지 않는다.
  - 자바의 모든 클래스는 Object 클래스로부터 상속된다.
    ~ Object 클래스 : 자바의 최상위 클래스. 명시적으로 상속하지 않아도 묵시적 상속이 이루어진다.

* 클래스 선언 시 상속을 지정하기 위해 extends라는 예약어를 사용한다.
  - [형식]
class 클래스 이름 extends 상위 클래스 이름 {
    ......추가되는 멤버 변수
    ......생성자(생성자는 상속되지 않는다.)
    ......추가되는 메소드
}

* 자바에서 한정자를 사용할 수 있는 대상
  - 클래스
  - 멤버 변수
  - 메소드
  ※ 생성자(생성자의 한정자는 별 의미가 없다. public이나 붙이지 않거나, private가 사용될 수 있다.)

* public, 한정자 없음, private 외에 추가로 protected가 있다.
  - public : 동일 패키지나 상속 관계 등에 상관없이 모든 클래스에서 사용 가능하다.
  - protected : 동일한 패키지이면 상속 여부에 상관없이 사용 가능하고, 다른 패키지의 클래스에서는 상속된 경우에만 사용 가능하다.
  - default(한정자 없음) : 동일한 패키지이면 상속 여부에 상관없이 사용 가능하다.
  - private : 어떠한 경우에도 사용이 불가능하다. 해당 클래스 내부에서만 사용 가능하다.

* 클래스의 상속에서 생성자는 상속되지 않지만, 다음과 같은 특성을 가진다.
  - 상속 관계에서 하위 클래스에 묵시적 생성자가 있는 경우, 하위 클래스로부터 객체가 생성될 때 상위 클래스의 묵시적 생성자가 우선 수행된다.
  - 상속 관계에서 하위 클래스에 명시적(매개 변수가 있는) 생성자만 있는 경우, 상위 클래스의 묵시적 생성자가 우선 수행된다.
  - 상속 관계에서 하위 클래스에 명시적 생성자와 묵시적 생성자가 모두 있는 경우, 하위 클래스의 어떠한 생성자가 호출되더라도 상위 클래스의 묵시적 생성자가 우선 수행된다.
  - 결론, 상위 클래스의 생성자가 먼저 실행된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class DA1 {
    public double d1;
    public DA1() {
        System.out.println("클래스 DA1의 묵시적 생성자 수행");
        d1 = 10*10;
    }
}
class DA2 extends DA1 {
    public double d2;
    public DA2() {
        System.out.println("클래스 DA2의 묵시적 생성자 수행");
        d2 = 10*10*10;
    }
}
class DA3 extends DA2 {
    public double d3;
    public DA3() {
        System.out.println("클래스 DA3의 묵시적 생성자 수행");
        d3 = 10*10*10*10;
    }
}
public class DefaultInheritanceTest1 {
    public static void main(String args[]) {
        DA3 super1 = new DA3();
        System.out.println("10의 2제곱 : " + super1.d1);
        System.out.println("10의 3제곱 : " + super1.d2);
        System.out.println("10의 4제곱 : " + super1.d3);
        DA2 super2 = new DA2();
    }
}
cs

* 오버라이딩(overriding)
  - 상속 관계에 있는 클래스들간에 같은 이름의 메소드를 정의하는 경우이다.
  - 상위 클래스의 메소드와 하위 클래스의 메소드가 메소드 이름은 물론 매개 변수의 타입과 개수까지도 같아야 한다.
  ※ 메소드 오버로딩(overloading)과 혼동하지 말 것.

* 동일한 클래스 내에서 이루어지는 오버로딩을 중첩(같은 메소드 여러 개 존재)으로 표현한다면, 오버라이딩은 치환(상위 클래스의 메소드를 하위 클래스의 메소드로 교체)으로 표현할 수 있다.


오늘도 수고 많으셨습니다.


+ Recent posts