자바(Java)의 기초 박살내기 - 객체지향(클래스)의 기본 개념


안녕하세요? 이번 시간에는 객체지향(클래스)의 기본 개념에 대해 공부하기전에 저번 시간에 냈던 제어문 실습예제 소스 코드 부터 알아보겠습니다.

(소스 코드는 정답이 없습니다. 참고만 해주세요.)


문제1. 1부터 9까지의 정수를 입력 받아서 입력된 단의 구구단을 출력해보세요.

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
import java.util.Scanner;
 
public class Gugudan 
{
    public static void main(String args[])
    {
        for( ; ; )    // 범위가 벗어났을경우 계속 입력하기위한 무한 반복문 사용        
        {
            System.out.print("1부터 9까지의 임의의 숫자를 입력하세요 : ");
            Scanner sDan = new Scanner(System.in);
            int dan = sDan.nextInt();
            
            if(dan < 10)    // 1 ~ 9까지 범위 일때
            {
                for(int su = 1 ; su < 10 ; su ++)    // 단이 정해지면 계산 및 출력하기위한 반복문
                {
                    System.out.println(dan + " * " + su + " = " + (dan * su) + " ");
                }
                break;    // 계산이 완료되면 STOP!
            }else
            { 
                System.out.println("1부터 9까지 다시 입력해주세요.");
                continue;    // 1 ~ 9 까지 범위안에 없을시 다시 for문 처음으로 돌아가기위해 continue 사용
            }
        }    
    }
}
cs



문제2. 입력된 년도가 윤년인지 아닌 지 판별해주는 프로그램을 작성해보세요.

(단, 윤년은 4의 배수이고 100배수는 아니거나 400의 배수이면 윤년)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Scanner;
 
public class Calendar 
{
    public static void main(String args[])
    {
        System.out.print("년도를 입력하세요 : ");
        Scanner s = new Scanner(System.in);
        int year = s.nextInt();
 
        // 윤년은 4의 배수'이고(AND)' 100배수는 '아니거나(OR)' 400의 배수이다.
        if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)    
            System.out.println(year + "년은 윤년입니다.");
        else    // 윤년 아닐시
            System.out.println(year + "년은 윤년이 아닙니다.");
    }
}
cs


여기까지 저번 시간에 냈던 소스코드입니다. 누구한테는 쉽고 누구한테는 어려웠겠지만 쉽다고 자만하지도말고 어렵다고 실망하지마시고 꾸준히 노력하셔야합니다. (물론 저도 노력중입니다.)


이제 이번 시간에 배울 객체지향은 첫 자바의 개요에서 자바를 쓰는이유라고 했던만큼 중요한 개념 입니다.


 1. 클래스와 객체 


- 클래스(class): 사물의 특성을 소프트웨어적으로 추상화하여 모델링 한 것으로 객체를 만들 수 있는 (Template)로써 오브젝트의 정적인 상태를 나타냅니다

- 객체(object): 클래스를 실제 사용할 수 있도록 만든 것으로 메모리 공간을 할당해 놓은 인스턴스(Instance)라고도 하며 클래스의 동적인 상태를 의미합니다.(new 명령어를 통해 생성)


여기서 헷갈려 하실수도있는데 사물에 빗대어 표현하자면 붕어빵틀붕어빵 관계라할 수 있습니다. 붕어빵은 붕어빵틀에서 인스턴스화해서 나온 객체입니다.


- 객체지향의 특징

① 상속성(inheritance)

② 다형성(Polymorphism)

③ 캡슐화(encapsulation)

④ 정보은닉 (information hiding)


- 클래스의 구성요소

① 멤버 변수: 클래스의 속성
② 생성자: 객체의 초기화를 담당
③ 메소드: 클래스의 속성을 조작

④ 내포 클래스(Nested Class): 클래스안에 클래스 존재 가능



 2. 클래스의 정의 

- 형식: [접근지정자] + [클래스 종류] + class + class명 + [extends super] + [implements interface]

- [접근지정자] : public, default, protected(내부 클래스 선언시 사용), private등. 

- [클래스 종류] : abstract, final

- extends : 상속에서 사용 (Java - 단일상속)

- implements - interface로부터 상속받기 위해 사용(Java - 다중 상속)

- 클래스 표기법

클래스 이름

 멤버 변수(필드)

 멤버 메소드


- 접근 지정자의 표현

- public은 앞에 +

- private는 앞에 -

- protected는 앞에 #

- default는 생략


- abstract는 기울임을 이용, static은 밑줄로 표시


(EX)

class Tape

{

private:

  int id; char title[50];  char director[30];

  char actor[50]; char genre[20]; int price;

public:

  void input(); void input(int ); void display() const;

};

 Tape

 -id

-title

-director

-actor

-genre

-price

 +input():void

+input(int):void

+display():void




 3. 객체 생성 & 접근 


 - 참조형 변수객체의 위치 정보만 알고 있으면 됩니다.

 - 객체 생성: Heap이나 Static 메모리를 할당

 - 형식1> 클래스명 객체참조_변수명;

- 객체참조_변수명 = new 클래스_생성자명();

- Ex) Car carEx;

- carEx = new Car();

- 형식2> 클래스명 객체참조_변수명 = new 클래스_생성자명();

- Ex) car carEx = new carEx();


- 객체를 이용한 멤버접근: " . "을 이용하여 멤버에 접근 (자신의 클래스 안에서는 생략)

- Ex) carEx.speed = 10;    // 멤버 변수의 접근

- Ex) carEx.speedUp();    // 멤버 메소드의 접근




 4. 멤버 필드(변수) 



- 변수 종류

- 지역변수 : ① 메소드 안에서 선언된 변수로 접근 지정자 지정X

  ② 자료형 앞에 final만 표시 가능( 변수를 상수화)

  ③ 초기화를 필수적으로 해줘야한다.


- 클래스 변수 : ① static 키워드를 사용해서 생성(객체 사이의 데이터 공유)

 ② 오브젝트 생성없이 클래스이름 만으로 호출가능

 ③ static 영역에서 사용


- 멤버 변수 : ① 클래스안에서 선언되며, 각각 메모리 할당 받아 사용

   ② 자동 초기화(0 or null or false)


- 멤버 필드 선언 

- 형식 : [accessLevel<public,private,proteted, default>]+ + [transient] + [volatile] + [static] + [final]+ type + name


- transient는 파일에 저장X

- volatile는 멀티스레드 환경에서 값의 일관성 보장, 상호배제 수행


<예제 소스코드1 - class student>


1
2
3
4
5
6
7
class Student
{
    // 멤버 변수 
    int m_nKor;
    int m_nEng;
    int m_nMat;
}
cs


<예제 소스코드2 - class InstanceVariable>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class InstanceVariable {
    public static void main(String[] args) {
        Student obj = new Student();
        // obj.m_nKor = 30;
        // 인스턴스 변수는 초기화 하지 않으면 자동으로 0의 값을 가지며
        // 반드시 객체 이름으로만 호출해야 합니다.
        obj.m_nEng = 40;
        obj.m_nMat = 50;
        System.out.println("obj의 국어점수 = " + obj.m_nKor);
        System.out.println("obj의 수학점수 = " + obj.m_nMat);
        System.out.println("obj의 영어점수 = " + obj.m_nEng);
    }
}
 
cs


<결과>



- static 필드 : 객체를 생성해 접근하거나 클래스로도 접근할 수 있는 변수

- 클래스 정의 안에서 static { }안에 초기화 가능

- Ex) 카운트 셀때 많이이용

- static은 공유의 개념이다.


<예제 소스코드1 - class student>

1
2
3
4
5
6
7
8
9
class Student
{
    int m_nKor;
    int m_nEng;
    int m_nMat;
    
    // static 
    static String g_strTeacher = "김구";
}    
cs


<예제 소스코드2 - class InstanceVariable>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class InstanceVariable {
    public static void main(String[] args) {
        Student obj = new Student();
        // obj.m_nKor = 30;
        // 인스턴스 변수는 초기화 하지 않으면 자동으로 0의 값을 가지며
        // 반드시 객체 이름으로만 호출해야 합니다.
        obj.m_nEng = 40;
        obj.m_nMat = 50;
        System.out.println("obj의 국어점수 = " + obj.m_nKor);
        System.out.println("obj의 수학점수 = " + obj.m_nMat);
        System.out.println("obj의 영어점수 = " + obj.m_nEng);
        
        // 클래스로 통해 접근
        System.out.println("Student의 선생님= " + Student.g_strTeacher);
        // 객체 생성을 통해 접근
        System.out.println("obj의 선생님= " + obj.g_strTeacher);
        // 클래스를 통해 접근하여 값 꾸기
        Student.g_strTeacher = "안중근";
        System.out.println("obj의 선생님= " + obj.g_strTeacher);
    }
}
cs


<결과>


- final 필드 : 멤버 필드의 값을 변경하지 못하도록 할 때 사용

- 변수를 상수화 시킬 때 사용

- static과 거의 함께 사용

- 변수명은 대문자


<예제 소스코드1 - class student>

1
2
3
4
5
6
7
8
9
10
class Student
{
    int m_nKor;
    int m_nEng;
    int m_nMat;
 
    // final은 변수를 상수화 시킬때 사용되는데
    // String에 사용됬으므로 에러발생
    static final String Teacher = "김구";
}
cs


<예제 소스코드2 - class InstanceVariable>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class InstanceVariable 
{
    public static void main(String[] args)
    {
        Student obj = new Student();
        
        //obj.m_nKor = 30;
        obj.m_nEng = 40;
        obj.m_nMat = 50;
        
        System.out.println("obj의 국어점수 = " + obj.m_nKor);
        System.out.println("obj의 영어점수 = " + obj.m_nEng);
        System.out.println("obj의 수학점수 = " + obj.m_nMat);
        
        // 클래스로 
        System.out.println("obj의 선생님= " + obj.Teacher);
        Student.Teacher = "안중근";
        System.out.println("obj의 선생님= " + obj.Teacher);
    }
}
cs


<결과>




 5. 메소드 


- 전달받은 인수를 처리하여 결과를 돌려주는 작은 프로그램

- 다른언어에서는 함수(function)라고도 합니다.

- 멤버 메소드의 선언

- 접근지정자 + 특성 + 결과형 + 메소드명(매개변수)

  {

메소드 내용;


// 결과형이 void면 생략가능

[return 값;]

  }

- 접근지정자 : public, private, protected, default

- 특성 : abstract - 추상 메소드 선언

   final - 종단 메소드 선언(오버라이딩 할 수 없음)

   static - 클래스 메소드 선언

   synchronized - 스레드 임계영역 처리(스레드 관련)

   native - c언어와 같은 native 언어의 메소드를 사용할 때 선언

- 결과형 : 메소드 수행 이 후의 반환 값의 자료형 (void - 반환값 없음 의미)

- return : 메소드 수행 후 결과 반환 키워드

- 매개변수는 없으면 생략 가능


<예제 소스코드1 - class student>

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
class Student
{
    // 멤버 변수
    int m_nKor;
    int m_nEng;
    int m_nMat;
    
    // 멤버 변수의 값을 정해주는 set 메소드
    public void set(int a, int b, int c)
    {
        m_nKor = a;
        m_nEng = b;
        m_nMat = c;
    }
    
    // 접근지정자가 public이고
    // 반환값이 double형인
    // 국, 영, 수의 평균을 구하는 함수
    public double calc()
    {
        double avg;
        avg = (m_nKor + m_nEng + m_nMat) / 3.0;
        return avg;
    }
    
    // 접근지정자가 public이고
    // 반환 값이 없고
    // 평균을 출력해주는 함
    public void disp()
    {
        System.out.println("평균은 " + calc() + "입니다.");
    }
}
cs


<예제 소스코드2 - class InstanceVariable>

1
2
3
4
5
6
7
8
9
10
11
12
13
public class InstanceVariable 
{
    public static void main(String[] args)
    {
        Student obj = new Student();    // 객체 생성
        
        // 국, 영, 수 점수 정하기
        obj.set(806585);
        
        //평균 출력
        obj.disp();
    }
}
cs


<결과>


- 접근자 메소드(getter, setter): 

멤버변수는 일반적으로 private를 사용해 보호하고 접근자 메소드를 통해 멤버변수 접근 

(getter - 멤버변수 값 반환 메소드, setter - 멤버변수 값 정해주는 메소드)


- 메소드 오버로딩(Overloading) : 상속관계에 있는 클래스의 메소드와 이름은 동일하고 매개변수의 개수 또는 자료형이 다른경우


- 메소드 인수 전달방식

- 값에 의한 호출(Call by Value)

- 인수의 데이터 형이 기본 형(int ...)

- 전달되는 매개변수의 값을 복사해서 처리

- 메소드의 실행이 전달되는 변수에 영향을 주지 않습니다.

- 레퍼런스에 의한 호출(Call by Reference)

- 인수의 데이터 형이 참조 형(String .... )

- 메소드의 실행이 전달되는 변수에 영향을 주게 됩니다.


<오버로딩 예제 소스코드1 - class student>

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
class Student
{
    int m_nKor;
    int m_nEng;
    int m_nMat;
    
    public void set(int a, int b, int c)
    {
        m_nKor = a;
        m_nEng = b;
        m_nMat = c;
    }
 
    // 오버로딩 : 함수의 이름은 같지만 매개변수의 개수가 다르다.
    public void set(int a, int b)
    {
        m_nKor = a;
        m_nEng = b;
        m_nMat = 0;
    }
    
    public double calc()
    {
        double avg;
        avg = (m_nKor + m_nEng + m_nMat) / 3.0;
        return avg;
    }
    
    public void disp()
    {
        System.out.println("평균은 " + calc() + "입니다.");
    }
}
cs


<오버로딩 예제 소스코드2 - class InstanceVariable>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class InstanceVariable 
{
    public static void main(String[] args)
    {
        Student obj1 = new Student();
        Student obj2 = new Student();
        
        obj1.set(806585);
        obj1.disp();
        
        obj2.set(9087);
        obj2.disp();
    }
}
cs


<결과>


- static 메소드

- 클래스 이름으로도 호출가능 한 메소드

- static 필드와 지역변수만 사용이 가능

- 멤버 필드를 참조하게 되면 에러가 발생

- 객체를 생성하는 메소드를 static으로 정의


<예제 소스코드1>

1
2
3
4
5
6
7
8
9
10
11
public class StaticTest 
{
    String s1 = "static";
    static String s2 = "STATIC";
    
    public static String getString()
    {
        // 여기서 만약 s1을 호출하면 에러 
        return s2;    
    }
}
cs

<예제 소스코드2>
1
2
3
4
5
6
7
public class StaticTestMain 
{
    public static void main(String[] args)
    {
        System.out.println("s2 : " + StaticTest.getString());
    }
}
cs


<결과>


- Varargs(Variable Argument) 기법

- 5.0버전 이후에서 추가된 인자의 개수를 지정하지 않아도 되는 메소드

- 주의사항: 앞 쪽에 지정하게 되면 언제 이 매개변수가 끝나는지 알 수 없게 된다.


<예제 소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class VarTest 
{
    // Varargs 메소드
    public void argTest(int ...n)
    {
        for(int i = 0 ; i < n.length ; i++)
            System.out.println("n[ "+ i + "]:" + n[i]);
        System.out.println("-------------------------");
    }
    
    public static void main(String[] args)
    {
        VarTest vt = new VarTest();
        vt.argTest(150200250300);
        vt.argTest(100,200);
        
    }
}
cs



<결과>



- 접근자 메소드

- 객체지향 언어에서는 멤버 필드에 직접 접근하는 것을 권장하지 않는다.

- 멤버 필드를 private로 지정해 직접 접근을 막고 getter와 setter를 통해 접근을 합니다.

- getter

- 멤버 필드의 값을 반환해주는 메소드

- 필드 타입이 boolean일 경우 get대신 is를 쓰기도 합니다.

- setter

- 멤버 필드의 값을 설정해주는 메소드

- 접근자 메소드에 대해 더 알고 싶은 사람은 디자인 패턴을 공부하면 됩니다.


<예제 소스코드1>

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Data 
{
    // 멤버 필드 선언
    private int number;
    private String name;
    
    // 각 멤버 필드의 관한 getter, setter
    public int getNumber() { return number; }
    public void setNumber(int arg) { this.number = arg; }
    
    public String getName() { return name; }
    public void setName(String arg) { this.name = arg; }
}
cs

※ 멤버 필드가 많아질 경우 직접 getter / setter을 쓰는 노가다(?) 보다는 단축기를 이용해 한번에 만들어 주시면 됩니다. (shift + alt + S 누른후 R 


<예제 소스코드2>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class GetterSetter 
{
    public static void main(String[] args)
    {
        Data obj = new Data();
        
        // setter를 이용한 값 설정
        obj.setNumber(1);
        obj.setName("park");
 
        // getter를 이용한 값         
        System.out.println("obj의 Number: " + obj.getNumber());
        System.out.println("obj의 Name: " + obj.getName());
    }
}
cs


<결과>



- 생성자

- 객체를 생성하기 위해 호출하는 메소드

- 기본 형식

- [public/private/protected] + 클래스이름(매개변수)

  {

...

  }

- 일반메소드와 차이점

- 리턴형이 없음

- 객체를 생성하기위해서 호출

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

- 용도 : 객체의 초기화 과정 처리

- 생략하는경우 클래스 선언시 아무 일도 하지 않는 매개변수가 없는 생성자 자동생성

- 오버로딩 가능

- super() : 부모 클래스의 생성자 호출 - 가장 먼저 와야함

- Ex) class AnimationThread extended Thread

{

public AnimationThread()

{

super("AnimationThread");

...

}

}

 - this() : 자신이 생성자를 호출하는 것으로 생성자가 오버로딩 된 경우 사용가능(super() 다음위치)

 - 생성자 호출 방법: new 생성자(매개변수)


<예제 소스코드1>

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
public class StudentBean 
{
    // 멤버 필드 선언
    private int kor;
    private int eng;
    private int mat;
    
    // 매개변수가 없는 생성자    
    public StudentBean()
    {
        System.out.println("기본 생성자");
    }
    
    // 매개변수가 존재하는 생성자 (위 생성자 메소드 오버로딩)
    public StudentBean(int a, int b, int c)
    {
        this();    // 위 생성자 메소드 호출
        kor = a;
        eng = b;
        mat = c;
    }
    
    // 결과 값 출력 메소드
    public void disp()
    {
        System.out.println("국어 점수의 값= " + kor);
        System.out.println("영어 점수의 값= " + eng);
        System.out.println("수학 점수의 값= " + mat);
    }
}
cs


<예제 소스코드2>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ConstructorTest 
{
    public static void main(String[] args) 
    {    
        // 오버로딩 된 생성자 호출
        StudentBean Obj1 = new StudentBean(70,60,80);
        // 매개변수가 없는 생성자 호출
        StudentBean Obj2 = new StudentBean();
        
        // 결과 값 출력하는 메소드 호출
        Obj1.disp();
        Obj2.disp();
    }
 
}
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
public class Sequence 
{
    int number;
    static int sequence = 0;
    
    public Sequence()
    {
        number = ++sequence;
    }
    
    public void disp(){
        int number = 100;
        System.out.println("지역변수-number:" + number);
        System.out.println("멤버필드-number:" + this.number);
    }
    
    public static void main(String[] args) {
        Sequence obj = new Sequence();
        obj.disp();
    }
}
cs


<결과>


- Singleton 패턴

클래스가 하나의 객체만 생성할 수 있는 패턴

- 상호배제를 위해 사용되며 주로 관리자 클래스에 이용

- 생성자를 private로 만들고 객체를 생성해서 리턴해주는 별도의 메소드 생성해서 사용

- jdk의 클래스중 생성자 호출하지 않는 클래스

- 모든 메소드가 static인 클래스 경우


- GarbageCollection

- heap 메모리 정리

- 호출 시점을 알 수 없다.

- 강제 호출 메소드인 System.gc()가 있지만 바로 호출되지 않을 수 있습니다.

- 우선순위가 낮아서 다른작업이 수행중이면 호출X




- 여기까지 객체지향의 기본 개념에대 대하여 공부 했습니다. 기초부터 세세한거까지 하느라 글이 길어 졌네요. 그리도 java의 꽃은 객체지향이기 때문에 꼭 알아 두시면 좋습니다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유