Language_Study/JAVA

[JAVA, App] 7.클래스

Godwony 2020. 12. 23. 23:02
반응형

객체 지향 프로그래밍(Object Oriented Programming - OOP)

1.객체 지향 특징

1) Encapsulation(캡슐화) : 관련있는 속성과 메소드를 묶는 것

  • 클래스를 만드는 방법

2) Inheritance(상속성): 상위 클래스의 모든 것을 하위 클래스가 물려 받는 것

3) Polymorphism(다형성): 동일한 메시지에 대하여 다르게 반응하는 성질

  • 동일한 코드가 호출하는 객체에 따라서 다른 메소드를 호출하는 것

2.객체 지향의 장점

  • 코드의 재사용성이 뛰어남

3.객체 지향의 단점

  • 함수형 프로그래밍 방식에 비해서 무겁다.

4.클래스와 인스턴스(객체 - 예전에는 Object)

  • 최근에는 클래스도 오브젝트로 간주합니다.
  • 클래스는 인스턴스들의 공통된 특징을 소유한 객체
  • 클래스를 기반으로 해서 생성된 객체들을 인스턴스 라고 하기도 합니다.
  • 클래스는 정적(한 번 만들면 수정이 안됨)이고 인스턴스는 동적(만들고 수정하고 삭제 할 수 있습니다)
  • 클래스는 만들고 처음 사용할 때 메모리에 로드가 되서 프로그램이 종료될 때 까지 절대로 소멸되지 않습니다.
  • 인스턴스는 만들어서 사용하다가 필요하면 언제든지 제거할 수 있습니다.

5.자바에서 클래스를 생성하는 방법

[접근지정자] + [클래스 종류] + class + 클래스이름 + [extends 상위클래스이름] + [implements 인터페이스이름]{
    클래스의 구성 요소 나열
}

6.클래스를 이용해서 인스턴스를 생성하는 기본 방법

new 생성자이름(매개변수 나열)

  • new 는 생성자를 기반으로 메모리 할당(allocation)을 하고 초기화(initialize)를 한 후 그 참조를 리턴합니다.
  • 자바는 생성자 이름이 클래스 이름이어야 합니다.

7.클래스의 구성 요소

  • 속성(attribute - 변수)
  • 메소드(method): 클래스 안에 만들어져서 클래스 이름이나 인스턴스 이름으로 호출하는 함수를 메소드라고 합니다.
  • cpu가 작업을 하는 단위
  • 생성자(constructor)

8.클래스나 인스턴스를 가지고 자신의 멤버 접근

  • 클래스. 또는 인스턴스. 속성이름 또는 메소드이름(매개변수 나열) 의 형태로 접근 합니다.

클래스 생성

1.클래스의 접근 지정자

  • 생략(default, package - 디렉토리): 현재 패키지에서는 마음대로 사용할 수 있지만 다른 패키지에서는 사용을 못함
  • public: 어디에서든지 이 클래스를 사용할 수 있습니다.
  • private: 다른 클래스에서 이 클래스를 사용할 수 없도록 할 때 사용, 내부 클래스에만 적용
  • protected: 상속받은 클래스에서는 사용이 가능, 내부 클래스에만 적용 가능

2.자바에서는 클래스 별로 별도의 파일에 작성하는 것을 권장

3.클래스를 생성하고 인스턴스 만들기

1) 클래스 만들기

  • src 디렉토리 위에 마우스 포인터 올리고 마우스 오른쪽을 누른 후 [New] - [class]를 선택하고 옵션을 작성
  • 클래스 이름의 첫글자는 대문자로 시작하도록 권장
//main 메소드가 없는 클래스 - 실행할 수 없는 보조적인 역할을 수행하는 클래스
public class SampleClass {

}

2) 실행 클래스를 만들고 위에서 만든 SampleClass의 인스턴스 만들기

public class MainClass {

    public static void main(String[] args) {
        //SampleClass 의 인스턴스 만들기
        //new SampleClass() 가 인스턴스를 만드는데 
        //위의 구문은 수행을 하고 인스턴스의 참조를 리턴합니다.
        //이 인스턴스를 재사용할려면 인스턴스의 참조를 동일한 자료형의 변수에 대입을 해야 합니다.
        SampleClass obj = new SampleClass();
    }
}

속성 또는 변수

1.변수의 종류

  • 동일한 영역에서 동일한 이름으로 변수를 2번 생성할 수 없습니다.

1) Local Variable(지역 변수)

  • 메소드 안에서 만들어져서 메소드 안에서만 사용 가능한 변수

  • 메소드 안에 존재하는 다른 블록 안에서 만들어지면 그 블록 안에서만 사용이 가능합니다.

  • 접근 지정자를 사용하지 않습니다.

  • 생성

자료형 변수이름;
자료형 변수이름 = 값;
  • 처음에 값을 대입하지 않으면 변수는 생성되지 않습니다.
    • 지역변수는 처음 값을 대입할 때 생성됩니다.

2) Member Variable(멤버 변수)

  • 클래스 내부에서 메소드 바깥에 선언된 변수로 static 이라는 키워드가 없이 만들어진 변수
  • 클래스로부터 만들어지는 각 인스턴스가 자신의 특성을 표현하기 위해서 별도로 소유
  • 생성할 때는 접근지정자와 함께 생성
  • 변수를 만들 때 값을 대입하지 않아도 기본값으로 초기화가 됩니다.
  • false, 0, 0.0, null 등으로 초기화
    • 접근지정자 자료형 변수명 으로 선언

3) Static Variable(클래스 변수)

  • 클래스 내부에서 메소드 바깥에 선언된 변수로 static 이라는 키워드와 함께 만들어진 변수
  • 동일한 클래스로부터 생성된 모든 인스턴스가 공유하기 위한 변수
  • 이 변수는 1개만 생성되고 생성되면 소멸되지 않습니다.
  • 생성할 때는 접근지정자와 함께 생성
  • 변수를 만들 때 값을 대입하지 않아도 기본값으로 초기화가 됩니다.
  • false, 0, 0.0, null 등으로 초기화
    • static 접근지정자 자료형 변수명 으로 선언

2.final

  • 변수 앞에 붙이면 변수의 값을 변경하지 못하도록 read only를 만들어주는 키워드

3.멤버 메소드나 멤버 변수의 접근 지정자

1) private: 클래스 내부의 메소드에서만 사용할 수 있도록 해주는 지정자

2) default(package - 생략): 동일한 패키지 내에서는 public 이고 다른 패키지에서는 private

3) protected: default에 상속받은 클래스에서도 사용할 수 있도록 해주는 지정자

4) public: 클래스 내부의 메소드에서 사용 가능하고 클래스 외부에서 인스턴스나 클래스를 이용해서 접근 가능

4.static 변수는 클래스와 인스턴스 모두 접근 가능하지만 member variable 은 인스턴스만 접근 가능

  • static 은 공통된 내용을 저장할 때 사용하고 member variable 은 각각의 특징을 저장할 때 사용

5.실습

1) final 이 붙으면 변수의 값을 수정할 수 없습니다.

  • MainClass 의 main 메소드에 final 변수를 선언
//final 변수는 생성과 동시에 값을 할당
//값을 변경할 수 없기 때문입니다.
//final 변수의 이름은 모두 대문자로 만드것이 관례

final int TEN = 10;
//TEN = 11; //이 문장은 에러
  • final은 클래스 안에서 옵션을 만들 때 주로 이용
    • 일반 정수 데이터를 의미있는 이름을 부여해서 이해하기 쉽게 할 목적

2) SampleClass 에 변수를 선언

    //static 변수 - 클래스로 접근 가능하고 인스턴스로도 접근 가능
    //모든 인스턴스가 공유
    static int share = 1;

    //인스턴스 변수(멤버 변수) - 인스턴스만 접근이 가능하고 각 인스턴스가 별도로 소유
    String name;

3) MainClass 클래스의 main 메소드에서 static이 붙은 것과 그렇지 않은 변수의 차이를 알아보는 코드 작성

        // SampleClass의 인스턴스를 2개 생성
        SampleClass ob1 = new SampleClass();
        SampleClass ob2 = new SampleClass();

        //인스턴스 변수에 값 대입
        ob1.name = "첫번째 인스턴스";
        ob2.name = "두번째 인스턴스";
        //static이 붙지 않은 멤버는 클래스는 호출할 수 없습니다.
        //SampleClass.name 은 안됨

        //인스턴스 변수의 값 출력 - 인스턴스 변수는 각각 소유하기 때문에 서로 다른 값 출력
        System.out.println(ob1.name);
        System.out.println(ob2.name);

        //static 변수에 값 대입
        //클래스와 인스턴스 모두 접근 가능
        ob1.share = 100;
        SampleClass.share = 200;
        //static 변수는 하나만 만들어서 공유
        //출력을 해보면 동일한 값을 출력
        System.out.println(ob1.share);
        System.out.println(ob1.share);
        System.out.println(SampleClass.share);

4) private 과 public 차이

  • 클래스 안에서 private으로 만들어지면 클래스 안에서만 사용 가능

  • public으로 만들어지면 클래스 외부에서 클래스 이름이나 인스턴스를 통해서 사용이 가능

  • 클래스 안에서 사용을 할 때는 특별한 경우가 아니라면 이름만 호출하면 됩니다.

  • SampleClass에서 share 변수 선언문 앞에 private을 추가하고 저장을 하면 main 메소드에 에러가 발생합니다.

  • 이 에러는 없다라고 에러 메시지가 뜨지 않고 존재하지만 보이지 않는다는 에러 메시지가 출력

5) static 멤버를 인스턴스를 이용해서 접근하면 경고가 발생

  • static 멤버는 클래스 이름을 통해서 접근하는 것을 권장

6.static initializer

  • 클래스 안에
static{
    내용
}
  • 을 작성하면 클래스가 메모리에 로드될 때 1번만 { }안의 내용을 수행
  • 여기에는 static 변수는 사용할 수 있지만 member(instance) 변수는 사용할 수 없음
  • 주로 static 변수의 초기화에 이용
  • 여러 번 작성하면 작성 한 순서대로 실행

실습)

  • SampleClass에 static 초기화 블럭을 작성하고 MainClass 실행
    • 가장 먼저 내용이 출력
//static 초기화 블럭
static {
    System.out.println("클래스가 처음 호출될 때 1번만 수행");
}

Method

  • 전달받은 데이터를 이용해서 처리를 수행한 후 결과를 돌려주는 작은 프로그램
  • Function 이라고도 하는데 보통은 Function은 아무곳에서나 호출할 수 있는 것을 의미하고 Method는 클래스나 인스턴스를 통해서만 호출할 수 있는 것을 의미합니다.

1.메소드의 생성 - 선언

[접근지정자] + [특성] + 리턴타입 + 메소드이름(매개변수자료형 매개변수이름,....) {
    메소드의 내용;
    [return 데이터;]
}

1) 접근 지정자

  • private: 클래스 내부에서만 호출해서 사용
  • default(package): 패키지(디렉토리)내에서는 public 밖에서는 private
  • protected: default에 상속받은 클래스에서도 사용이 가능
  • public: 클래스 외부에서 클래스나 인스턴스를 통해서 사용 가능

2) 특성

  • abstract(추상) - 내용이 없는 메소드
  • final(종단) - 재정의 할 수 없는 메소드
  • static - 클래스 메소드
  • synchronized - 동기화 메소드 : 작업 수행 도중에는 다른 스레드를 수행할 수 없도록 하는 메소드
  • native - C언어에서 만든 운영체제에게 직접 전달해서 실행하도록 해주는 메소드

자바 <-> JVM(Java Virtual Machine) <-> 운영체제

  • 자바 만을 가지고 운영체제를 핸들링하는 프로그램을 만들 수 없어서 C언어로 만든 메소드를 호출해서 운영체제를 핸들링 합니다.

3) return type

  • 메소드는 호출되면 자신의 작업을 수행하고 호출한 곳으로 돌아오는데 이것을 return 이라고 합니다.
  • 이 때 데이터를 가지고 return 할 수 있는데 이 데이터의 자료형이 return type 입니다.
  • 데이터를 가지고 오지 않는 경우에는 void 라고 기재합니다.

4) argument(매개변수)

  • 함수를 호출할 때 넘겨주는 데이터
  • 자바에서는 반드시 자료형과 함께 기재해야 하고 없는 경우에는 생략이 가능

2.메소드 호출

  • 자신의 클래스 내부에서는 메소드이름(매개변수 나열) 의 형태로 호출 가능
  • 클래스 외부에서는 클래스이름.메소드이름(매개변수 나열) 또는 클래스이름 대신에 인스턴스를 기재

3.메소드 원형

  • 메소드의 내용은 생략하고 결과형 메소드이름(매개변수) 만을 의미

4.메소드 사용 이유

1) 자주 사용하는 코드를 하나의 이름으로 묶어서 유지 보수를 편리하게 하기 위해서

2) 프로그램을 적절한 크기로 모듈화하기 위해서

  • 프로그램을 적절한 크기로 분할하지 않으면 읽기가 어려워지고 메모리 부족 현상이 벌어질 수 있습니다.
  • 프로그래밍언어나 IDE 에 따라서 Stack의 크기가 정해진 경우가 있는데 이 Stack의 사이즈보다 더 큰 메모리를 사용할려고 하는 경우 Stack Overflow라는 예외가 발생합니다.

5.실습

1) Hello Java를 3번 출력하는 메소드를 소유한 클래스

public class MethodClass {
    //매개변수가 없고 리턴 타입이 void 메소드
    public void disp() {
        //메소드의 내용
        for(int i=0; i<3; i=i+1) {
            System.out.println("Hello Java");
        }
    }
}

2) main 메소드를 소유한 Main 클래스에서 위의 메소드 호출

public class Main {
    public static void main(String[] args) {
        //MethodClass 의 인스턴스를 생성
        MethodClass obj = new MethodClass();
        //메소드 호출 - 수행할 내용을 변경하고자 하면 메소드의 내용만 변경
        obj.disp();

        System.out.println("Hello Python");

        //메소드 호출
        obj.disp();
    }
}

6.Argument(매개변수)

  • 메소드를 호출할 때 넘겨주는 데이터
  • 메소드를 실행하는데 필요한 데이터
  • 없을 수도 있고 여러 개 일 수 있습니다.
  • 매개변수가 있으면 함수의 활용범위가 높아지게 됩니다.

1) MethodClass에 매개변수가 있는 메소드를 추가

// 매개변수가 정수 1개이고 리턴 타입이 void 메소드
// 이 메소드는 호출할려면 반드시 정수 1개를 넘겨주어야 합니다.

    public void print(int n) {
        // 메소드의 내용
        for (int i = 0; i < n; i = i + 1) {
            System.out.println("Hello Java");
        }
    }

2) main 메소드에서 호출

//매개변수가 있는 메소드 호출
System.out.println("========================");
obj.print(5);
System.out.println("========================");
obj.print(2);

3) 메소드를 만들 때 매개변수의 개수 제한은 없지만 매개변수의 개수가 많으면 함수를 호출할 때 코드가 길어지고 매개변수의 순서대로 데이터를 대입하는 것이 어렵습니다.

  • 이 문제를 해결하기 위해서 매개변수가 여러 개 일 때는 별도의 클래스를 만들거나 Map 을 이용하는 것을 권장합니다.

  • Eclipse에서는 적용이 안되지만 Intelli J 나 Android Studio에서는 매개변수 앞에 이름을 붙이는 구조를 지원을 합니다.

4) Method Overloading(메소드 중복 정의)

  • 대부분의 객체 지향 언어에서는 하나의 클래스에 동일한 이름의 메소드를 여러 개 만드는 것을 지원

  • 이 때 매개변수의 개수나 매개변수의 자료형은 달라야 합니다.

  • 하나의 클래스에 메소드의 이름은 같고 매개변수의 개수나 자료형이 다른 경우를 메소드 오버로딩이라고 합니다.

  • 동일한 알고리즘을 사용하는데 매개변수의 개수나 자료형이 다른 이유때문에 메소드 이름을 다르게 하면 메소드 이름을 기억하기도 어렵고 메소드 이름이 너무 많이 필요합니다. - C언어

  • 정수 2개 덧셈하는 메소드: add(int, int)

  • 실수 2개 덧셈하는 메소드: add(double, double)

  • 객체 지향 언어 면접 보러 가면 반드시 기억

5) Method Overloading 구현을 위해서 MethodClass 수정

public class MethodClass {
    // 매개변수가 없고 리턴 타입이 void 메소드
    public void disp() {
        // 메소드의 내용
        for (int i = 0; i < 3; i = i + 1) {
            System.out.println("Hello Java");
        }
    }
    // 매개변수가 정수 1개이고 리턴 타입이 void 메소드
    // 이 메소드는 호출할려면 반드시 정수 1개를 넘겨주어야 합니다.
    // 동일한 이름의 메소드가 하나의 클래스에 존재하는 경우를 Method Overloading 이라고 합니다.
    public void disp(int n) {
        // 메소드의 내용
        for (int i = 0; i < n; i = i + 1) {
            System.out.println("Hello Java");
        }
    }
}

6) main 메소드에서 print 호출하는 부분을 disp로 수정

7.매개변수 전달 방법

  • value type(scala, 기본형): 변수가 데이터 자체를 의미
int a = 10;
int b = a + 5;
  • reference type(vector, 참조형): 변수가 데이터 전체의 시작 위치를 가리키는 참조

int [] ar = {100, 300, 200};

  • ar 은 데이터가 아니고 데이터가 저장된 곳의 참조
  • 데이터를 찾아갈려면 ar[인덱스]를 해주어야 합니다.

1) call by value

  • 매개변수의 자료형이 value 형인 경우로 메소드가 전달되는 데이터를 변경할 수 없습니다.

2) call by reference

  • 매개변수의 자료형이 reference 형인 경우로 메소드가 전달되는 데이터를 변경할 수 도 있습니다.

3) 실습

  • MethodClass 클래스에 2개의 메소드를 생성
  • 하나는 정수를 받아서 1증가시키고 출력하는 메소드
  • 다른 하나는 정수 배열을 받아서 첫번째 데이터를 1감소시키고 출력하는 메소드
    //정수 1개를 매개변수로 받아서 1증가시키고 출력하는 메소드 : Call By Value
    public void inc(int n) {
        n = n + 1;
        System.out.println("n:" + n); 
    }

    //배열 1개를 매개변수로 받아서 첫번째 데이터를 1감소시키고 출력하는 메소드 : Call By Reference
    public void dec(int [] ar) {
        ar[0] = ar[0] - 1;
        System.out.println("ar[0]:" + ar[0]);
    }
  • main 메소드에 확인하기 위한 코드를 작성하고 실행
        int x = 100;
        int [] br = {100,200,300};
        obj.inc(x);
        //x의 값은 직접 호출해서 변경하지 않는 이상 절대로 변경되지 않음
        System.out.println("x:" + x);

        obj.dec(br);
        //참조형의 경우 메소드의 매개변수로 대입되면 데이터가 변경되어 있을 수도 있음
        System.out.println("br[0]:" + br[0]);

4) 참조형 데이터를 받아서 작업을 하는 메소드 중에서 return을 하지 않는다면 이 메소드는 매개변수로 받은 데이터를 변경을 할 가능성이 높습니다.

  • 단 예외적인 메소드는 화면에 무엇인가를 출력하는 메소드들입니다.
  • print 나 그래프 등을 그리는 메소드 등

8.varargs

  • 매개변수의 개수를 지정하지 않고 대입 가능하도록 한 방식
  • java 1.5에서부터 지원
  • 매개변수를 만들 때 (자료형 ... 매개변수이름) 의 형태로 작성하면 자료형의 데이터를 몇 개를 대입하던지 메소드 내에서는 매개변수이름의 배열로 취급
  • 파이썬에서는 *이름 의 형태로 만들어져 있는 것과 동일
  • 이 방식을 취하는 대표적인 메소드는 printf 메소드 입니다.
    //정수 데이터가 몇 개 가 오던지 합계를 구해서 출력해주는 메소드
    public void sum(int ... ar) {
        //... 이름을 이용하면 내부에서는 배열로 취급
        int sum = 0;
        //배열의 모든 데이터를 순서대로 접근해서 sum에 추가
        for(int data : ar) {
            sum = sum + data;
        }
        System.out.println("합계:" + sum);
    }
  • main 메소드에서 위의 메소드 호출
    obj.sum(10, 30);
    obj.sum(20, 30, 10, 50);

9.return

  • return은 메소드 수행 중에 메소드를 호출한 곳으로 제어권을 이동시키는 명령어
  • return을 할 때 1개의 데이터를 호출한 곳으로 가져 갈 수 있습니다.
    • 이렇게 데이터를 가져갈 때는 메소드 이름앞에 가져갈 데이터의 자료형을 기재해야 합니다.
  • return 할 데이터가 없으면 void 라고 기재해야 합니다.
  • return 이후에 작성한 코드는 수행될 수 없기 때문에 return 이후에 실행되는 코드는 작성하면 안됩니다.
  • return 이 없는 메소드는 메소드의 결과를 가지고 다음 작업을 이어서 할 수 없지만 return이 있으면 그 결과를 가지고 다음 작업을 이어서 수행할 수 있습니다.
  • 되도록이면 메소드를 만들 때 set 하는 메소드가 아니면 return을 하는 것이 좋습니다.

1) MethodClass에 리턴을 하는 메소드를 생성

    //2개의 정수를 매개변수로 받아서 더한 후 결과를 리턴하는 메소드
    //메소드 이름 앞의 자료형과 return 하는 데이터의 자료형은 일치해야 합니다.
    public int addReturn(int a, int b) {
        return (a+b);
    }

2) main 메소드에서 위의 메소드 사용

        //return 이 있는 메소드
        //메소드의 수행 결과를 r에 저장
        int r = obj.addReturn(200, 300);
        System.out.println("결과:" + r);
        //이전 작업 결과를 가지고 다음 작업을 수행
        r = obj.addReturn(r, 700);
        System.out.println("결과:" + r);

        //return 값이 메소드는 다른 메소드의 매개변수가 될 수 있습니다.
        r = obj.addReturn(300, obj.addReturn(300, 700));
        System.out.println("결과:" + r);

10.static 메소드

  • 메소드의 자료형 앞에 static을 추가한 메소드
  • static이 붙은 메소드는 클래스가 호출해도 되고 인스턴스가 호출해도 됩니다.
    • static이 없는 메소드는 반드시 인스턴스가 호출해야 합니다.
  • static 메소드는 인스턴스 변수 사용이 안됩니다.
  • static 변수와 자신의 메소드 안에서 만든 지역 변수만 사용이 가능
  • 클래스 이름으로 호출할 때 인스턴스가 하나도 없을 수 있고 static 메소드에는 this가 없습니다.
  • 이 메소드는 인스턴스 변수와 무관한 메소드를 인스턴스 생성없이 호출하기 위한 목적이나 디자인 패턴을 적용해서 인스턴스를 생성하는 용도로 만듭니다.
  • static 메소드는 특별한 경우가 아니면 클래스로 호출하는 것을 권장합니다.

11.this

  • 인스턴스 메소드의 숨겨진 매개변수
  • 인스턴스 메소드의 첫번째 매개변수로 우리가 생성하지 않아도 자동으로 생성됩니다.
  • 인스턴스를 이용해서 메소드를 호출할 때 인스턴스의 참조가 자동으로 대입됩니다.
  • 인스턴스 메소드 안에서 지역변수가 아닌 변수나 메소드를 호출할 때 앞에 자동으로 대입됩니다.
  • 실제 사용은 인스턴스 메소드 안에서 지역변수와 인스턴스 변수의 이름이 같을 때 인스턴스 변수를 명시하기 위해서 사용을 합니다.

Property 와 getter & setter

1.접근자 메소드

  • 인스턴스 변수에 접근하기 위한 메소드
  • 객체 지향 프로그래밍에서는 인스턴스 변수에 인스턴스(객체)가 직접 접근하는 것을 권장하지 않습니다.
    • 인스턴스가 인스턴스 변수에 직접 접근하게 되면 예기치 않은 상황이 발생할 수 있기 때문입니다.
    • 변수는 일반적으로 동기화(Synchronized)의 대상이 아닙니다.
    • 대다수의 프로그래밍 언어가 동기화의 단위가 메소드 또는 인스턴스입니다.

1) getter

  • 인스턴스 변수의 데이터를 리턴해주는 메소드
  • 메소드의 리턴 타입은 인스턴스 변수의 리턴 타입과 동일하게 만듭니다.
  • 메소드의 이름은 get변수명 으로 하는데 변수명의 첫글자는 대문자로 하고 변수의 자료형이 boolean 인 경우는 get 대신에 is를 사용하는 것이 관례
  • 메소드의 내용은 인스턴스 변수를 리턴하는 것만 하는 것이 보통입니다.

2) setter

  • 인스턴스 변수의 값을 설정하는 메소드
  • 메소드의 리턴 타입은 void
  • 메소드의 이름은 set변수명으로 하는데 변수명의 첫글자는 대문자
  • 인스턴스 변수와 동일한 자료형의 매개변수를 받아서 인스턴스 변수에 그 값을 저장하는 내용을 소유
  • 저장을 할 때는 다른 내용을 추가하기도 하는데 저장하기 전에 유효성 검사를 해서 저장 가능한 데이터인지 확인하는 작업이나 값이 변경된다는 내용을 다른 곳에 알려주기도 합니다.
  • Key - Value Observing 이라고 합니다.
class T{
    private int age;    //private 은 클래스 내부에서만 사용이 가능
    private String name;

    //setter 메소드
    public void setAge(int n){
        age = n;
    }

    public void setName(String n){
        name = n;
    }

    //getter 메소드
    public int getAge(){
        return age;
    }

    public String getName(){
        return name;
    }
}

T ob = new T(); //인스턴스 생성
ob.setAge(50);
ob.setName("park");
System.out.println("이름:" + ob.getName());

3) 최근에 등장한 IDE 들은 대부분 접근자 메소드를 자동으로 만들어주는 기능을 제공

4) 인스턴스 변수가 scala data 가 아닌 배열이나 List 인 경우 인덱스를 받아서 하나만 가져오거나 하나만 수정하는 메소드도 만드는 것을 권장합니다.

2.Property(속성)

  • 인스턴스가 변수를 호출하는 것처럼 사용하지만 실제로는 getter 나 setter 와 같은 접근자 메소드를 호출하는 것
  • VB, VC#, Python, Kotlin, Swift 등에서는 프로퍼티를 지원
  • Java에서는 지원을 하지 않지만 Java Web Programming에서 EL을 이용해서 이 프로퍼티를 지원합니다.

3.DTO(Data Transfer Object, Variable Object, Domain Class)

  • 여러 개의 정보를 묶어서 하나로 만들기 위한 클래스

4.실습 - DTO 클래스를 만들고 main에서 클래스의 인스턴스를 만들고 내부 데이터 사용

1) DTO 클래스

public class Student {
    //인스턴스 변수 선언
    private int num;
    private String name;
    private String major;

    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        //this 가 붙으면 메소드 내부에서는 찾지 않고 
        //메소드 외부에서 먼저 찾습니다.
        //this.num 은 메소드 외부에 있는 인스턴스 변수 num 이고
        //num은 메소드의 매개변수 num이 됩니다.
        this.num = num;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMajor() {
        return major;
    }
    public void setMajor(String major) {
        this.major = major;
    }

}

2) main 메소드를 소유한 클래스

public class Main {

    public static void main(String[] args) {
        //Student 클래스의 인스턴스 생성
        Student student = new Student();
        //인스턴스 변수에 값을 설정
        student.setNum(1);
        student.setName("park");
        student.setMajor("CS");

        //인스턴스 변수의 값 가져오기
        System.out.println("번호:" + student.getNum());
        System.out.println("이름:" + student.getName());
        System.out.println("전공:" + student.getMajor());
    }
}

Constructor(생성자)

  • 인스턴스를 만들 때 호출하는 메소드
  • 생성자는 반드시 new 라는 예약어와 함께 호출

1.자바에서의 생성자

1) 클래스를 만들면 매개변수가 없는 기본 생성자가 제공되는데 클래스 안에 생성자를 만들면 이 생성자는 소멸됩니다.

2) 생성자의 이름은 클래스이름으로 만들어야 합니다.

3) 생성자 오버로딩(메소드 이름은 같고 매개변수의 개수나 자료형이 다른 경우)이 가능합니다.

2.생성자를 만드는 목적

  • 인스턴스 변수의 값을 초기화할 목적으로 많이 생성
  • 인스턴스가 생성될 때 다른 작업을 같이 수행하고자 하는 경우에도 생성

3.생성자를 만들때 주의할 점

  • 매개변수가 없는 생성자를 default constructor 라고 하는데 이 생성자가 없는 경우 생성자를 호출할 때 반드시 매개변수를 대입해야 합니다.
  • default constructor 가 없는 클래스로 부터 상속받는 경우에는 반드시 생성자를 만들어서 상위 클래스의 생성자를 호출하는 구문을 만들어 주어야 합니다.
  • 이 경우는 Android에서 많이 발생

4.실습

1) id 와 pw를 문자열로 저장할 수 있는 클래스 생성 - Member

public class Member {
    private String id;
    private String pw;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPw() {
        return pw;
    }
    public void setPw(String pw) {
        this.pw = pw;
    }    
}

2) main 메소드를 소유한 실행 클래스를 만들고 main 메소드 안에서 인스턴스를 만들고 값을 저장한 후 값을 출력

public class Main {

    public static void main(String[] args) {
        //Member 클래스의 인스턴스를 생성
        //자바 개발자의 대부분은 인스턴스를 1개만 만드는 경우 클래스 이름의 첫글자만
        //소문자로 변환해서 이름을 생성을 합니다.
        //자바 개발을 할 때는 인스턴스를 자동으로 생성해주는 스프링 프레임워크를 많이 사용하는데
        //스프링이 이름을 만들 때 이 규칙을 적용
        Member mem1 = new Member();

        System.out.println("id:" + mem1.getId() + " pw:" + mem1.getPw());
    }
}

5.생성자를 별도로 만들지 않으면 인스턴스 변수의 값들은 기본값으로 채워집니다.

1) 기본값

boolean -> false
정수 -> 0
실수 -> 0.0
나머지 -> null

2) 위의 실습 결과는 id는 null 그리고 pw는 null이 출력

3) 모든 인스턴스들이 id는 root pw는 1234로 초기화된 상태에서 시작하도록 하고자 함

  • 인스턴스를 만들고 setter 메소드를 호출해서 id 와 pw 값을 변경해서 해결 가능

  • 인스턴스를 1개만 생성한다면 위의 방법을 이용하는 것이 나쁘지 않지만 여러 개를 생성해야 하는 경우 매번 위와 같은 작업을 하는 것은 비효율적입니다.

  • 위와 같은 경우는 생성자를 만들어서 생성자에서 값을 설정하는 것이 효율적입니다.

4) Member 클래스에 id에 root를 pw에 1234를 설정하는 생성자를 만듬

//Member 클래스의 생성자
//생성자는 리턴 타입없이 클래스 이름을 그대로 사용
//매개변수가 없는 생성자를 Default Constructor 라고 합니다.
public Member() {
    id = "root";
    pw = "1234";
}

5) main을 실행해보면 setter 를 호출하지 않아도 root 에 1234로 출력

6.매개변수가 있는 생성자

  • 생성자는 오버로딩이 가능하기 때문에 기본 생성자가 있는 경우에도 매개변수가 있는 생성자를 만들 수 있습니다.
  • 매개변수가 있는 생성자는 매개변수로 데이터를 대입받아서 인스턴스 변수를 초기화 할 목적으로 만듭니다.
  • 외부에서 데이터를 주입받아서 인스턴스 변수를 초기화 할 수 있다면 setter 메소드의 호출횟수가 줄어들고 다양한 방법으로 인스턴스를 생성할 수 있게 됩니다.
  • 객체 지향 언어에서는 생성자의 종류만큼 인스턴스를 생성할 수 있는 방법이 있습니다.

7.this() & super()

  • 생성자에서 자신의 클래스의 다른 생성자를 호출할 때는 this(매개변수)를 이용할 수 있습니다.

  • super()는 상위 클래스의 생성자를 호출할 때 이용

    • 생성자를 만들면 우리가 작성하지 않아도 가장 위에 super() 구문이 포함됩니다.
    • 상위 클래스의 매개변수가 없는 생성자를 호출하는 구문입니다.
  • 상위 클래스에 매개변수가 없는 생성자(Default Constructor)가 없는 경우 클래스를 상속받으면 에러가 발생합니다.

  • 생성자를 만들지 않으면 이런 생성자가 자동으로 포함됨

public 클래스이름(){
    super();
}
  • 상위 클래스의 매개변수가 없는 생성자를 호출하는 구문이 자동으로 포함되기 때문에 에러 발생

  • 이런 경우에는 생성자를 만들고 super(매개변수)를 직접 호출해 주어야 합니다.

  • super()는 가장 위에 나와야 합니다.

  • this()는 super()를 제외하고 가장 위에 나와야 합니다.

8.인스턴스 배열에서의 생성자

  • 인스턴스 배열을 만들 때 크기만 설정한 경우에는 각각의 인덱스에서 생성자를 호출해서 대입해 주어야 합니다.

클래스이름 [ ] 배열이름 = new 생성자이름[개수];

  • 개수 만큼의 인스턴스를 저장할 수 있는 공간이 생성된 것입니다.
    • 위의 경우는 인스턴스는 만들어지지 않았습니다.

배열이름[인덱스] = new 생성자(); 를 호출해서 각각에 대입을 해주어야 합니다.

  • main 메소드에 작성하고 실행
        //Member 클래스의 인스턴스 배열을 생성
        //Member 인스턴스의 참조를 저장할 수 있는 공간 2개를 생성
        Member [] ar = new Member[2];

        //공간에 인스턴스를 생성해서 대입
        //이 구문을 생략하면 모두 null
        ar[0] = new Member();
        ar[1] = new Member();

        for(Member imsi : ar) {
            System.out.println(imsi);
        }

9.인스턴스 필드 이니셜라이저

  • 클래스 안에 { }를 만들고 괄호 안에 내용을 작성하면 생성자를 호출할 때 { }안의 내용이 자동으로 수행됩니다.

  • Member 클래스에 작성하고 main을 실행해서 생성자가 호출될 때 마다 코드가 실행되는지 확인

//클래스 안에 { }를 만들고 작성하면 생성자를 호출할 때
//생성자보다 먼저 호출되서 내용을 수행
{
    System.out.println("객체를 생성합니다.");
}

10.참조형 변수 사이의 대입

  • 참조형 데이터는 실제 데이터가 아니라 참조를 대입해주기 때문에 참조형 변수끼리 대입을 하면 동일한 영역을 가리키게 됩니다.
  • 하나의 변경이 다른 하나에 영향을 주게 됩니다.
  • 특별한 경우가 아니면 참조형 변수 사이의 대입은 하지 않는 것이 좋습니다.
  • 참조형 변수의 데이터는 되도록이면 복제를 해서 다른 곳에 대입하는 것이 좋습니다.
    • 복제를 하는 방법은 보통 2가지를 권장하는데 하나는 복사 생성자를 이용하는 것이고 다른 하나는 clone 이라는 메소드를 만들어서 넘겨주는 것 입니다.
  • 생성자 중에서 자신의 자료형을 매개변수로 받는 생성자가 있으면 이것은 복사 생성자이며 java에서 clone 메소드는 현재 인스턴스를 복제해서 새로운 인스턴스를 만들어서 리턴하는 메소드입니다.

1) main 메소드에 작성해서 참조형 변수 사이의 대입 확인

        //하나의 인스턴스를 생성하고 내부 데이터 설정
        Member origin = new Member();
        origin.setId("ggangpae1");
        origin.setPw("100100100");

        //참조형 사이의 대입
        //origin이 가리키고 있는 인스턴스를 weak도 가리킵니다.
        Member weak = origin;

        //weak가 id를 변경했는데 origin 것도 변경
        weak.setId("itggangpae");
        System.out.println(weak.getId());
        System.out.println(origin.getId());

2) 동일한 값을 갖는 인스턴스를 사용하고자 할 때 복제해서 사용하는 것을 권장

  • 이 복제하는 것을 다른 말로 Deep Copy 라고 합니다.

3) Member 클래스에 복사 생성자를 추가하거나 clone 메소드 추가

  • 복사 생성자는 자신과 동일한 자료형의 매개변수를 갖는 생성자를 만들고 그 안에서 데이터를 전부 복사해서 리턴하도록 만들어주면 됩니다.

  • 이러한 일을 해주는 메소드를 만들 때는 이름을 clone으로 만드는 것을 권장

  • Member 클래스에 추가

    //인스턴스를 복제해주는 메소드
    public Member clone() {
        //인스턴스를 생성
        Member other = new Member();
        //데이터를 복제
        //원래 참조형 데이터도 clone 해 주어야 하지만 String 은 예외
        other.id = this.id;
        other.pw = this.pw;

        //복제된 데이터를 갖는 객체를 리턴
        return other;
    }
  • main 메소드에 코드를 작성하고 확인
System.out.println("============================");
        //origin을 복제해서 대입
        Member deep = origin.clone();
        //현재는 내용이 같습니다.
        System.out.println(deep.getId());
        System.out.println(origin.getId());

        //복제를 해서 deep 에 대입해주었기 때문에 변경하기 전에는 같은 내용을 같지만
        //한쪽에서 내용을 변경해도 다른쪽에는 영향이 없기 때문에 deep의 내용을 변경해도 origin은 그대로
        System.out.println("============================");
        deep.setId("choongang");
        System.out.println(deep.getId());
        System.out.println(origin.getId());

11.Java 에서의 메모리 정리

  • heap 에 만들어진 데이터는 프로그램 실행 도중 메모리 정리를 할 수 있는데 Java에서는 가리키고 있는 변수가 없으면 정리 대상이 되고 시스템이 필요한 시점에 Garbage Collection을 호출해서 정리를 합니다.
  • 강제로 메모리 정리를 시키고 싶다면 참조형 변수에 null을 대입해서 정리 대상이 되도록 할 수 있습니다.
  • 참조형 사이의 변수 대입을 하게되면 변수에 null을 대입해도 메모리 정리가 안 될 수 있습니다.
Member origin = new Member();
Member weak = origin;
origin = null; //null을 대입해도 메모리 정리 대상이 안됩니다.
weak = null; //이것까지 해주어야만 메모리 정리가 됩니다.
  • 참조형 변수의 데이터를 다른 참조형에 대입하는 경우는 메소드 안에서 만들어진 참조형 데이터를 외부에서 사용하기 위해서 외부변수에 대입하는 경우가 대부분
반응형