자바 객체제향에 대해 알아보자

Updated:

ch6. 객체지향 프로그래밍1

Created: Apr 13, 2020 4:42 PM

1. 객체 지향 언어

  1. 객체지향 언어의 역사
    → 실제 세계는 객체로 이루어져 있고 발생하는 모든 사건들은 객체간의 상호작용이라고 정의
    → 1960년대 중반에는 주로 절차적 언어들이 주를 이루었지만 프로그램의 규모가 점점 커지고 사용자들의 요구가 빠르게 변화해가는 상황을 극복하기 어렵다는 한계를 느끼고 그에 대한 대안으로 객체지향언어가 선택됨

  2. 객체지향 언어의 특징
  3. 코드의 재사용성
  4. 코드의 관리가 용이
  5. 신뢰성이 높은 프로그래밍이 가능하도록 함 ← 중복된 코드의 제거

—> 너무 객체지향 개념에 얽매이지 말고 일단 프로그램을 기능적으로 완성한 후에 어떻게 하면 보다 객체지향적으로 코드를 개선해나갈지 고민하여 점차 개선해나가는 것이 좋다

2. 클래스와 객체

  1. 클래스와 객체의 정의와 용도
    → 객체는 실제로 존재하는 어떤 사물을 의미하고 이것을 클래스라는 틀(?)에 정의한 내용대로 생성한다

  2. 객체와 인스턴스
    → 클래스의 내용대로 생성된 객체를 그 클래스의 인스턴스 라고 하고 만드는 과정을 인스턴스화 라고 한다
    → 어찌됐든 인스턴스도 객체의 개념이기 때문에 엄격히 구분할 필요는 없지만 알아두긴하자

  3. 객체의 구성요소 - 속성 & 기능
    → 어떤 객체든 클래스에서 다양한 속성과 기능이 정의되어 생성된다
    → 속성=맴버 변수=필드
    → 기능=메소드=함수

  4. 인스턴스의 생성과 사용
    → 클래스를 만들기만 해서는 객체를 사용할 수 없다. 객체를 사용하려면 아래 같이 인스턴스를 생성해야 된다
    → 클래스명 참조변수명=new 클래스명(); —> 이것을 참조변수가 해당 객체를 참조하고 있다고 함
    → 위와 같이 작성하면 new 클래스명()에 의해서 메모리에 클래스의 인스턴스가 생성되고 그 메모리의 주소값이 참조변수에 저장된다. 이 참조변수를 통해 해당 인스턴스에 접근할 수 있다
    → new 클래스명()이 일어날때 해당 클래스의 필드들은 기본값으로 초기화 된다(int → 0, String → null, boolean → false …)
    tip) 참조변수의 참조를 받지 못하는 인스턴스는 가비지 컬렉터에 의해서 자동적으로 메모리에서 제거된다

  5. 객체 배열
    → 많은 수의 객체를 다뤄야 할때 객체를 배열 형식으로 다룰수 있게 도와준다
    → Demo[] demoArr=new Demo[2] 라고 선언하면 demoArr[0], demoArr[1]이 생성된다. 하지만 객체를 다루기 위한 참조변수가 만들어진 것일 뿐 아직 객체가 저장되지 않았다. 각각의 참조변수에 new Demo()를 통해 인스턴스를 생성해주어야 한다

  6. 클래스의 또다른 정의
  7. 데이터와 함수의 결합
  8. 사용자 정의 타입(프로그래밍 언어에서 제공하는 자료형외에 프로그래머가 서로 관련된 변수들을 묶어서 하나의 타입(=클래스)으로 새로 추가하는 것)

3. 변수와 메서드

  1. 선언위치에 따른 변수의 종류
    → 크게는 2가지로 나뉜다. 바로 맴버 변수와 지역 변수이다. 메소드 내에서 선언되어 있는 변수를 지역 변수라 하고 그 외는 모두 맴버 변수이다. 맴버 변수 중에서도 static이 붙은 것을 클래스 변수, 붙지 않은 것을 인스턴스 변수라고 한다

-인스턴스 변수
→ 인스턴스가 생성될 때 만들어지며 그렇기 때문에 인스턴스를 생성한 이후에나 사용가능하다
→ 생성한 인스턴스들마다 서로 다른 속성값을 가질 수 있으므로 인스턴스마다 다른 값을 가져야하는 속성의 경우에 사용한다
-클래스 변수
→ 클래스가 메모리에 올라갈 때 만들어지며 그렇기 때문에 인스턴스를 생성하기 전에도 사용가능하다
→ 모든 인스턴스가 공통된 저장공간(변수)를 공유하게 되므로 모든 인스턴스들이 공통적인 값을 유지해야 하는 속성의 경우에 사용한다
-지역 변수
→메서드 내에 선언되어 메서드 내에서만 사용 가능하며 메서드가 종료되면 사용할 수 없게 된다

  1. 클래스 변수와 인스턴스 변수
    → 인스턴스 변수는 인스턴스가 생성될 때마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로 항상 공통된 값을 가진다
    → 인스턴스 변수는 ‘ 참조변수명.인스턴스변수명 ‘ 의 형식으로 사용하면 되고 클래스 변수는 ‘ 클래스명.클래스변수명 ‘ 의 형식으로 사용하면 된다

  2. 메서드
    → 메서드는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다
    → 높은 재사용성, 중복된 코드의 제거, 프로그램의 구조화 등의 장점이 있다

  3. 메서드의 선언과 구현
    → 메서드는 크게 선언부와 구현부로 나누어져 있다
    → 선언부는 반환타입, 메서드의 이름, 매개변수 선언으로 구성되어 있다
    → 구현부는 메서드를 호출했을 때 수행할 문장들을 적는다
    → 선언부에서 선언한 반환타입이 void인 경우를 제외하고는 모두 구현부에서 return으로 반환값을 정해줘야 한다. 또한, 반환값은 하나 이상이 될 수 없다
    tip) 메서드 선언 시에 괄호안의 값은 매개변수라고 부르고 메서드 호출 시에 괄호안의 값은 인자라고 불린다

  4. 메서드의 호출
    → 메서드의 호출 없이 선언만으로는 메서드를 실행시킬 수 없다. ‘ 메서드이름(인자값1, 인자갑2 …) ‘ 의 형식으로 메서드를 호출한다
    → 같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능하지만 static 메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없다

  5. return 문
    → return 문은 현재 실행 중인 메서드를 종료하고 호출한 메서드로 되돌아간다
    → 모든 메서드에는 적어도 하나의 return문이 있어야 한다(반환값이 void인 메서드도 사실은 return; 이 생략되어있는 것임)

  6. JVM의 메모리 구조
    → 응용프로그램이 실행되면 JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다
    → 3가지 주요 영역에 대해 설명해보자면 메서드 영역(method area), 힙(heap), 호출스택(call stack)이 있다
    -메서드 영역: 프로그램 실행 중 어떤 클래스가 사용될 때 JVM이 해당 클래스의 클래스 파일을 읽어서 정보를 이곳에 저장한다
    -힙: 프로그램 실행 중 생성되는 인스턴스들을 이곳에 저장한다
    -호출스택: 메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면 호출스택에 그 메서드를 위한 저장공간이 할당되며 메서드가 종료되면 그 공간은 반환되어 비워진다. 여러 메서드를 사용할 경우 나중에 호출한 메서드들이 먼저 호출한 메서드 위에 쌓여 위부터 차례차례 반환되어 비워지는 구조이다

  7. 기본형 매개변수와 참조형 매개변수
    → 기본형 매개변수를 값을 읽기만 할 수 있을 뿐 변경할 수 없지만 참조형 매개변수는 값을 읽고 변경까지 할 수 있다(참조 변수는 따른 기본형 변수들과 달리 생성한 인스턴스의 주소값을 저장하기 때문이다)
    → 아래의 2종류의 코드를 참고해보자

     public class PrimitiveParam {
         public static void main(String[] args) {
             Data d=new Data();
             d.x=10;
             System.out.println("x="+d.x);
        
             change(d.x);
             System.out.println("x="+d.x);
         }
        
         private static void change(int x) {
             x=100;
             System.out.println("x="+x);
         }
     }
    
     public class ReferenceParam {
         public static void main(String[] args) {
             Data d=new Data();
             d.x=10;
             System.out.println("x="+d.x);
        
             change(d);
             System.out.println("x="+d.x);
         }
        
         private static void change(Data d) {
             d.x=100;
             System.out.println("x="+d.x);
         }
     }
    
  8. 참조형 반환타입
    → 매개변수뿐만 아니라 반환타입 또한 참조형이 될 수 있는데 결국 객체의 주소를 반환한다는 의미이다
    → 이 역시 아래의 코드를 참고하자

     public class ReferenceReturn {
         public static void main(String[] args) {
             Data d=new Data();
             d.x=10;
        
             Data d2=copy(d);
             System.out.println("d.x="+d.x);
             System.out.println("d2.x="+d2.x);
         }
        
         private static Data copy(Data d) {
             Data tmp=new Data();
             tmp.x=d.x;
        
             return tmp;
         }
     }
    
  9. 재귀호출
    → 메서드의 내부에서 자신을 다시 호출하는 것을 재귀호출이라고 한다
    → 개발자의 입장에서는 메서드가 다시 자신을 호출하는 것이 어색하게 느껴질 수 있겠지만 메서드의 입장에서는 그저 특정 위치에 있는 명령을 수행할 뿐 그 이상도 이하도 아니다
    → 호출된 메서드는 값에 의한 호출을 통해 원래의 값이 아닌 복사된 값으로 작업하기 때문에 호출한 메서드와 관계없이 독립적인 작업수행이 가능하다
    → 다만 잘못 쓴다면 무한반복문 처럼 되서 오버플로가 발생할 수 있으니 꼭 조건문을 넣어주어야 하고 매개변수의 유효성 검사는 필수로 해야 한다

  10. 클래스 메서드와 인스턴스 메서드
    → 변수에서도 그랬듯이 메서드 앞에 static이 붙어있으면 클래스 메서드, 그렇지 않으면 인스턴스 메서드이다
    → 즉, 클래스의 맴버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있다면 static을 붙여주고 또한, 작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에 static을 붙인다
    → 아래 코드를 참조하자

    class MyMath{
        long a,b;
        
        long add(){return a+b;}
        long substract(){return a-b;}
        long multiply(){return a*b;}
        double divide(){return a/b;}
        
        static long add(long a, long b){
            return a+b;
        }
        static long substract(long a, long b){
            return a-b;
        }
        static long multiply(long a, long b){
            return a*b;
        }
        static double divide(double a, double b){
            return a/b;
        }
    }
        
    class MyMathTest {
        public static void main(String[] args) {
            System.out.println(MyMath.add(4,2));
            System.out.println(MyMath.substract(4,2));
            System.out.println(MyMath.multiply(4,2));
            System.out.println(MyMath.divide(4,2));
        
            MyMath myMath=new MyMath();
            myMath.a=4;
            myMath.b=2;
        
            System.out.println(myMath.add());
            System.out.println(myMath.substract());
            System.out.println(myMath.multiply());
            System.out.println(myMath.divide());
        }
    }
    
  11. 클래스 맴버와 인스턴스 맴버간의 참조와 호출
    → 클래스 메서드에서는 인스턴스 변수와 인스턴스 메서드를 사용할 수 없다(인스턴스 맴버나 메서드가 존재하는 시점에 클래스 맴버나 메서드는 반드시 존재하지만 역은 성립하지 않을 수도 있기 때문이다)

4. 오버로딩(overloading)

Leave a comment