무작정 개발.Vlog

자바의 정석 | Ch 06 - 객체지향프로그래밍1-1

by 무작정 개발
반응형

1. 객체지향 언어

 

객체지향 언어의 주요 특징

1. 코드의 재사용성이 높다.
    - 새로운 코드를 작성할 때 기존의 코드를 이용하여 쉽게 작성할 수 있다.

2. 코드의 관리가 용이하다.
    - 코드 간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경할 수 있다.

3. 신뢰성이 높은 프로그래밍을 가능하게 한다.
    - 제어자와 메서드를 이용해서 데이터를 보호하고 올바른 값을 유지하도록 하며,
      코드의 중복을 제거하여 코드의 불일치로 인한 오동작을 방지할 수 있다.

객체지향 개념을 학습할 때 재사용성과 유지보수 그리고 중복된 코드의 제거, 이 3가지 관점에서 보면 보다 쉽게 이해할 수 있다.

 

책에서는 너무 객체지향 개념에 얽매여서 고민하기보다는 일단 프로그램을 기능적으로 완성한 다음 어떻게 하면 보다 객체지향적으로

코드를 개선할 수 있는지를 고민하여 점차 개선해나가는 것이 좋다고 적혀 있다.

 

2. 클래스와 객체

2.1 클래스와 객체의 정의와 용도

 

(1) 클래스(Class)

  • 클래스란 객체를 정의해 놓은 것 or 객체를 정의해 놓은 설계도
  • 객체를 생성하는 데 사용되며, 객체는 클래스에 정의된 대로 생성됨

(2) 객체(Object)

  • 객체란 실제로 존재하는 것. 용도는 기능(변수)과 속성(메서드)에 따라 다름.
  • 눈으로 볼 수 있는 형태가 있는 것뿐만 아니라 개념이나 논리와 같은 형태가 없는 것도 객체로 간주함.

 

2.2 객체와 인스턴스

 

클래스(Class)로부터 객체(Object)를 만드는 과정을 클래스의 인스턴스화(instantiate)라고 하며, 어떤 클래스로부터 만들어진

객체를 그 클래스의 인스턴스(instancd)라고 한다.

 

클래스로 부터 객체를 만드는 과정
클래스 -> 객체

객체와 인스턴스는 같은 의미이지만, 객체는 모든 인스턴스를 대표하는 포괄적인 의미이다. 인스턴스는 설계도를 바탕으로 소프트웨어 

세계에 구현된 구체적인 실체 혹은 어떤 클래스로부터 만들어진 것인지를 강조하는 보다 구체적인 의미이다.

 

ex)

// 클래스
public class Human {
   ......
}
// 객체와 인스턴스
public class Main {
    public static void main(String[] args) {
       Human child, adult; //객체
       
       // 인스턴스화
       child = new Human(); // child는 Human 클래스의 인스턴스(객체를 메모리에 할당)
       adult = new Human(); // adult는 Human 클래스의 인스턴스(객체를 메모리에 할당)
    }
}

 

클래스, 객체, 인스턴스의 차이점

 

  • 클래스(Class) vs 객체(Object)

       클래스는 '설계도' , 객체는 '설계도로 구현한 모든 대상'

  • 객체(Object) vs 인스턴스(Instance)

       클래스의 타입으로 선언되었을 때는 객체, 그 객체가 메모리에 할당되어 실제 사용될 때는 인스턴스

       

       객체는 현실 세계에 가깝고 인스턴스는 소프트웨어 세계에 가깝다.

       객체는 '실체' , 인스턴스는 '관계'   /    객체를 '클래스의 인스턴스'라고도 부른다.

 

 

2.3 객체의 구성요소 - 속성과 기능

 

객체는 속성과 기능, 2가지 종류의 구성요소로 이루어져 있으며, 일반적으로 객체는 다수의 속성과 다수의 기능을 갖는다. 즉, 객체는 속성과 기능의 집합이라고 할 수 있다. 그리고 객체가 가지고 있는 속성과 기능을 그 객체의 멤버(구성원, member)라 한다.

 

클래스란 객체를 정의한 것이므로 클래스에는 객체의 모든 속성과 기능이 정의되어있다. 클래스로부터 객체를 생성하면, 클래스에 정의된 속성과 기능을 가진 객체가 만들어지는 것이다.

속성과 기능은 아래와 같이 같은 뜻의 여러 가지 용어가 있다.

속성(property) - 멤버 변수(member variable), 특성(attribute), 필드(field), 상태(state)
기능(function) - 메서드(method), gkatn(function), 행위(behavior)

 

2.4 인스턴스의 생성과 사용

클래스로부터 인스턴스를 생성하는 방법은 여러 가지가 있지만 일반적으로 다음과 같이 한다.

클래스명 변수명;  //   클래스의 객체를 참조하기 위한 참조 변수를 선언
변수명 = new 클래스명(); //   클래스의 객체를 생성 후, 객체의 주소를 참조 변수에 저장

Tv t;   //   Tv클래스 타입의 참조변수 t를 선언
t = new Tv();   // Tv인스턴스를 생선 한 후, 생성된 Tv인스턴스의 주소를 t에 저장

이제 하단 예제를 풀어보자!

//예제 6-1/ch6/TvTest.java
package Chapter06;

class Tv {
    //Tv의 속성(멤버변수)
    String color;
    boolean power;
    int channel;

    //Tv의 기능(메서드)
    void power()   {power = !power;} // TV를 켜거나 끄는 기능을 하는 메서드
    void channelUp()   { ++channel;} // TV의 채널을 높이는 기능을 하는 메서드
    void channelDown()   {--channel;} // TV의 채널을 낮추는 기능을 하는 메서드
}

public class TvTest {
    public static void main(String[] args) {
        Tv t;             //Tv인스턴스를 참조하기 위한 변수 t를 선언
        t = new Tv();     //Tv인스턴스를 생성
        t.channel = 7;    //Tv인스턴스의 멤버변수 channel의 값을 7로 한다.
        t.channelDown();  //Tv인스턴스의 메서드 channelDown()을 호출한다.
        System.out.println("현재 채널은 " + t.channel + " 입니다.");
    }
}

위의 예제는 Tv클래스로부터 인스턴스를 생성하고 인스턴스의 속성(channel)과 메서드(channelDown())를 사용하는 방법을

보여주는 것이다.

인스턴스는 참조 변수를 통해서만 다룰 수 있으며, 참조 변수의 타입은 인스턴스의 타입과 일치해야 한다.

 

package Chapter06;

class Tv {
    //Tv의 속성(멤버변수)
    String color;
    boolean power;
    int channel;

    //Tv의 기능(메서드)
    void power()   {power = !power;} // TV를 켜거나 끄는 기능을 하는 메서드
    void channelUp()   { ++channel;} // TV의 채널을 높이는 기능을 하는 메서드
    void channelDown()   {--channel;} // TV의 채널을 낮추는 기능을 하는 메서드
}

public class TvTest {
    public static void main(String[] args) {
        Tv t1 = new Tv();
        Tv t2 = new Tv();
        System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
        System.out.println("t2의 channel값은 " + t2.channel + "입니다.");

        t1.channel = 7;
        System.out.println("t1의 channel값을 7로 변경하였습니다.");

        System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
        System.out.println("t2의 channel값은 " + t2.channel + "입니다.");
    }
}

위의 예제는 Tv클래스의 인스턴스 t1과 t2를 생성한 후에, 인스턴스 t1의 멤버 변수인 channel의 값을 변경하였다.

같은 클래스로부터 생성되었을지라도 각 인스턴스의 속성(멤버 변수)은 서로 다른 값을 유지할 수 있으며, 메서드의 내용은 모든 

인스턴스에 대해 동일하다. 이제 하단 3번째 예제를 풀어보자!

 

package Chapter06;

class Tv {
    //Tv의 속성(멤버변수)
    String color;
    boolean power;
    int channel;

    //Tv의 기능(메서드)
    void power()   {power = !power;} // TV를 켜거나 끄는 기능을 하는 메서드
    void channelUp()   { ++channel;} // TV의 채널을 높이는 기능을 하는 메서드
    void channelDown()   {--channel;} // TV의 채널을 낮추는 기능을 하는 메서드
}

public class TvTest {
    public static void main(String[] args) {
        Tv t1 = new Tv();
        Tv t2 = new Tv();
        System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
        System.out.println("t2의 channel값은 " + t2.channel + "입니다.");
 
        t2 = t1;  // t1이 저장하고 있는 값(주소)을 t2에 저장한다.
        t1.channel = 7; // channel 값을 7로 한다.
        System.out.println("t1의 channel값을 7로 변경하였습니다.");

        System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
        System.out.println("t2의 channel값은 " + t2.channel + "입니다.");
    }
}

위의 예제를 보면 알 수 있듯이, 참조 변수에는 하나의 값(주소)만이 저장될 수 있으므로 둘 이상의 참조 변수가 하나의 인스턴스를 

가리키는(참조하는) 것은 가능하지만 하나의 참조 변수로 여러 개의 인스턴스를 가리키는 것은 가능하지 않다.

 

2.5 객체 배열

객체 역시 배열로 다루는 것이 가능하며, 이를 '객체 배열'이라고 한다. 그렇다고 객체 배열 안에 객체가 저장되는 것은 아니고, 

객체의 주소가 저장된다. 사실 객체 배열은 참조 변수들을 하나로 묶은 참조변수 배열인 것이다.

Tv tv1, tv2, tv3;              -->           Tv [ ] tvArr = new Tv [3];

길이가 3인 객체 배열 tvArr을 아래와 같이 생성하면, 각 요소는 참조 변수의 기본값인 null로 자동 초기화된다. 그리고 이 객체 배열은 3개의 객체, 정확히는 객체의 주소, 를 저장할 수 있다.

 

객체 배열(참조 변수의 배열) -> 타입 [ ] 배열 이름 = new 타입[n];

@객체 배열 생성 후 반드시 객체를 생성해야 한다.@

 

3. 변수와 메서드

 

3.1 선언 위치에 따른 변수의 종류

변수는 클래스 변수, 인스턴스변수, 지역번수 모두 3종류가 있다. 변수의 종류를 결정짓는 중요한 요소는 '변수의 선언된 위치'이므로 변수의 종류를 파악하기 위해서는 변수가 어느 영역에 선언되었는지를 확인하는 것이 중요하다. 멤버변수를 제외한 나머지 변수들은 모두 지역변수이며, 멤버변수 중 static이 붙은 것은 클래스변수, 붙지 않은 것은 인스턴스 변수이다.

 

class Variables
{
	int iv;           //인스턴스변수                            --> 클래스영역
    static int cv;    //클래스변수(static변수, 공유변수)           --> 클래스영역
    
    void method()
    {                 //                       --> 메서드영역
    	int lv = 0;   //지역변수                 -->메서드영역
    }
}

<변수의 종류와 특징>

변수의 종류 선언위치(영역) 생성시기& 특징
클래스 변수
(class variable)
클래스영역 클래스가 메모리에 올라갈 때, 자동생성
객체생성필요x, 아무때나사용가능, 
인스턴스변수
(instance variable)
인스턴스가 생성되었을 때
객체를 생성해야 사용가능, 객체생성필요
지역변수
(local variable)
클래스 영역 이외의 영역
(메서드, 생성자, 초기화 블럭 내부)
변수 선언문이 수행되었을 때
클래스 이외의 영역(메서드, 생성자, 초기화블럭내부)에서
선언되며 메서드 종료시 자동제거됨

(1) 인스턴스 변수(instance variable)

  • 클래스의 인스턴스를 생성할 때 생성
  • 인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다.
  • 인스턴스마다 고유한 상태를 유지해야 하는 속성의 경우, 인스턴스 변수로 선언

(2) 클래스 변수(class variable)

  • 클래스가 메모리에 올라갈 때 생성
  • 선언하는 방법은 인스턴스 변수 앞에 static을 붙이면 된다.
  • 모든 인스턴스가 공통된 저장공간(변수)을 공유하게 된다.

      ( 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야 하는 속성의 경우, 클래스 변수로 선언해야 함)

  • 객체(인스턴스)를 생성하지 않고도 바로 사용 가능

(3) 지역변수(local variable)

  • 변수 선언문이 수행되었을 때 생성됨.
  • 메서드 내에 선언되어 메서드 내에서만 사용 가능
  • 메서드가 종료되면 소멸되어 사용 못함
  • for문 or while문의 블록 내에 선언된 지역변수는, 지역변수가 선언된 블럭 { } 내에서만 사용 가능, 블록{ }을 벗어나면 소멸

 

3.2 클래스 변수와 인스턴스 변수

객체의 속성

 

숫자, 무늬. -> 개별속성(인스턴스 변수(iv)) 참조 변수, 변수 이름

폭, 높이.    -> 공통 속성(클래스 변수(cv)) cv는 사용할 때 클래스 이름. 변수 이름

 

이제 하단 예제를 풀어보자!

//예제6-5/ch6/CardTest.java
package Chapter06;

class CardTest {
    public static void main(String[] args) {
        System.out.println("Card.width = " + Card.width);
        System.out.println("Card.heigh = " + Card.height);

        Card c1 = new Card();
        c1.kind = "Heart";
        c1.number = 7;

        Card c2 = new Card();
        c2.kind = "Spade";
        c2.number = 4;

        System.out.println("c1은 " + c1.kind + ", " + c1.number
                + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
        System.out.println("c2은 " + c2.kind + ", " + c2.number
                + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );

        System.out.println("c1의 width와 height를 각각 50, 80으로 변경합니다.");
        c1.width = 50;
        c1.height = 80;

        System.out.println("c1은 " + c1.kind + ", " + c1.number
                + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
        System.out.println("c2은 " + c2.kind + ", " + c2.number
                + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );

    }
}

class Card {
    String kind;
    int number;
    static int width = 100;
    static int height = 250;
}

위의 예제는 Card클래스의 클래스 변수(static변수)인 width, height는 Card클래스의 인스턴스를 생성하지 않고도 '클래스 이름. 클래스 변수'와 같은 방식으로 사용할 수 있다. Card인스턴스인 c1과 c2는 클래스 변수인 width와 height를 공유하기 때문에, c1의 width와

height를 변경하면 c2의 width와 height값도 바뀐 것과 같은 결과를 얻는다.

Card.width, c1.width, c2.width는 모두 같은 저장공간을 참조하므로 항상 같은 값을 갖게 된다.

 

인스턴스 변수(iv)는 인스턴스가 생성될 때마다 생성되므로 각기 다른값응로 유지할 수 있지만,
클래스 변수(cv)는 하나의 저장공간을 공유하므로 항상 공통된 값을 갖는다.

 

3.3 메서드

 

<지역변수>

메서드 내에 선언된 변수. 메서드 영역이 서로 다른 지역변수들(x, y, 등)은 이름이 중복되어도 관계없다.

<메서드>

문장들을 작업 단위로 묶어서 이름을 붙인 것. 
값(입력)을 받아서 처리하고, 결과를 반환(출력)

장점
1. 높은 재사용성
2. 중복된 코드의 제거
3. (한 곳에서 수행하기 때문에) 관리가 쉽다.
4. 코드가 간결해서 이해하기 쉬움
메서드 작성 : 반복되는 여러 문장을 메서드로 작성. / 하나의 메서드는 한 가지 기능만 수행하도록 작성

 

3.4 메서드의 선언과 구현

메서드 = 선언부 + 구현부

 

메서드 구조
Method 구조

 

3.5 메서드의 호출

메서드를 정의했어도 호출되지 않으면 아무 일도 일어나지 않는다. 메서드를 호출해야만 구현부 { } 문장들이 수행된다.

메서드 호출 : 메서드 이름(값 1, 값 2,...); // 메서드를 호출하는 방법

 

메서드의 실행 흐름

 

1. 객체 생성 -> 2. 메서드 호출 -> 3. 메서드 안 수행문 수행 -> 4. 호출한 곳으로 반환

 

이제 하단 예제를 풀어보자!

//예제6-6/ch6/CardTest.java
package Chapter06;

public class MyMathTest {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        long result1 = mm.add(5L, 3L);
        long result2 = mm.subtract(5L, 3L);
        long result3 = mm.multiply(5L, 3L);
        double result4 = mm.divide(5L, 3L);

        System.out.println("add(5L, 3L) = " + result1);
        System.out.println("subtract(5L, 3L) = " + result2);
        System.out.println("multiply(5L, 3L) = " + result3);
        System.out.println("divide(5L. 3L) = " + result4);
    }
}

class MyMath {
    long add(long a, long b) {
        long result = a + b;
        return result;
    }

    long subtract(long a, long b) { return a - b;}
    long multiply(long a, long b) { return a * b;}
    double divide(double a, double b) {
        return a / b;
    }
}

위의 예제는 사칙연산을 위한 4개의 메서드가 정의되어 있는 MyMath클래스를 이용한 예제이다. divide(double a, double b)를 호출하는 부분을 보자. divide메서드에 선언된 매개변수 타입은 double형인데, 이와 다른 long형의 값인 5L 와 3L을 사용해서 

호출하는 것이 가능하다. 호출 시에 입력된 값은 메서드의 매개변수에 대입되는 값이므로, long형의 값을 double형 변수에 저장하는 것과

같아 'double a = 5L;'을 수행했을 때와 같이 long형의 값인 5L은 double형 값인 5.0으로 자동 형 변환되어 divide의 매개변수 a에

저장된다. 그래서 divide메서드에 두 개의 정수 값(5L, 3L)을 입력하여 호출하였음에도 불구하고 연산 결과가 double형의 값이 된다.

add(long a, long b) 메서드에서도 매개변수 a, b에 int형의 값을 넣어 add(5,3)과 같이 호출하는 것이 가능하다.

 

 

3.6 return 문

 

return문

  • 샐 행중인 메서드를 종료하고 호출한 곳으로 되돌아간다.
  • 반환 타입이 void가 아닌 경우, 반드시 return문 필요!
  • 조건식을 쓸 때(메서드 내에서) return문이 거짓일 경우에도 쓰여있는지 확인할 것

반환 값

반환 타입이 void가 아닌 경우, 반환 타입을 일치시켜야 한다. 아니면 자동형 변환 가능한 타입(int인 경우 byte, short, char)

 

매개변수의 유효성 검사

적절하지 않은 값이 들어오면 매개변수의 값을 보정하거나, return문으로 작업을 중단하고 호출한 메서드로

되돌아가게 하는 코드를 반드시 넣어야 한다.

 

3.8 기본형 매개변수와 참조형 매개변수

java에서는 메서드를 호출할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사해서 넘겨준다. 매개변수의 타입이

기본형(primitive type) 일 때는 기본형 값이 복사되겠지만, 참조형(reference type)이면 인스턴스의 주소가 복사된다.

 

기본형 매개변수(8개) : 변수의 값을 읽기만 가능(read only)
참조형 매개변수 : 변수의 값을 읽고 변경할 수 있음(read & write)

이제 하단 예제를 풀어보자!

 

//예제6-9/ch6/CardTest.java
package Chapter06;

class Data { int x;}

public class PrimitiveParamEx {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;
        System.out.println("main() : x = " + d.x);

        change(d.x);
        System.out.println("After change(d.x)");
        System.out.println("main() : x = " + d.x);
    }

    static void change(int x) {   // 기본형 매개변수
        x = 1000;
        System.out.println("change() : x = " + x);
    }
}

위의 예제를 보면 change메서드에서 main메서드로부터 넘겨받은 d.x의 값을 1000으로 변경했는데도 main메서드에서는

d.x의 값이 그대로이다. 왜 이런 결과가 나오는지 단계별로 그림을 그려보면 아래와 같다.

자바의 정석 3판 p265
출처 : 자바의 정석3판 p265

  1. change메서드가 호출되면서 'd.x'가 change메서드의 매개변수 x에 복사됨
  2. change메서드에서 x의 값을 1000으로 변경
  3. change메서드가 종료되면서 매개변수 x는 스택에서 제거됨

'd.x'의 값이 변경된 것이 아니라, change메서드의 매개변수 x의 값이 변경된 것이다. 즉, 원본이 아닌 복사본이 변경된 것이라 원본에는 

아무런 영향을 미치지 못한다. 이처럼 기본형 매개변수는 변수에 저장된 값만 읽을 수만 있을 뿐 변경할 수는 없다.

이제 다음 예제를 풀어보자!

 

//예제6-9/ch6/ReferenceParamEx.java

package Chapter06;

class Data {int x;}

class ReferenceParamEx {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;
        System.out.println("main() : x = " + d.x);
        
        change(d);
        System.out.println("After change(d)");
        System.out.println("main() : x = " + d.x);
    }
    
    static void change(Data d) {   // 참조형 매개변수
        d.x = 1000;
        System.out.println("change() : x = " + d.x);
    }
}

위의 예제는 이전과 달리 change메서드를 호출한 후에 d.x의 값이 변경되었다. change메서드의 매개변수가 참 조형이라서 값이 아니라

'값이 저장된 주소'를 change메서드에게 넘겨주었기 때문에 값을 읽어오는 것뿐만 아니라 변경하는 것도 가능하다.

 

3.9 참조형 반환 타입

 

매개변수뿐만 아니라 반환 타입도 참조형이 될 수 있다. 반환 타입이 참 조형이라는 것은 반환하는 값의 타입이 참조형이라는 얘긴데, 

모든 참조형 타입의 값은 '객체의 주소'이므로 그저 정수 값이 반환되는 것일 뿐 특별할 것이 없다. 먼저 하단 예제를 풀어보자!

//예제6-14/ch6/ReferenceParamEx2.java
package Chapter06;

class Data {int x;}

class ReferenceReturnEx2 {
    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);
    }

    static Data copy(Data d) {
        Data tmp = new Data();
        tmp.x = d.x;
        
        return tmp;
    }
}

copy메서드는 새로운 객체를 생성한 다음에, 매개변수로 넘겨받은 객체에 저장된 값을 복사해서 반환한다. 반환하는 값이 Data객체의

주소이므로 반환 타입이 'Data'인 것이다.

 

참조형 반환 타입

  • 객체 주소를 반환
  • 객체 주소를 줬기 때문에(리모컨 토스) 객체를 다룰 수 있게 됨

 

3.10 재귀 호출(recursive call)

 

재귀호출

메서드의 내부에서 메서드 자신을 다시 호출하는 것

void method() {
        method();   //   재귀 호출. 메서드 자신을 호출
}

하단 예제를 풀어보자!

//예제6-15/ch6/FactorialTest.java
package Chapter06;

class FactorialTest {
    public static void main(String[] args) {
        int result = factorial(4);

        System.out.println(result);
    }
    static int factorial(int n) {
        int result = 0;

        if(n==1)
            result = 1;
        else
            result = n * factorial(n-1); // 다시 메서드 자신을 호출
        return result;
    }
}

위의 예제는 팩토리얼을 계산하는 메서드를 구현하고 테스트하는 것이다.

 

 

3.11 클래스 메서드(static메서드)와 인스턴스 메서드

 

메서드 앞에 static이 붙어 있으면 클래스 메서드이고, 붙어 있지 않으면 인스턴스 메서드이다. 

 

 

인스턴스 메서드

  • 객체를 생성해야만 호출 가능
  • 인스턴스 생성 후 [참조 변수. 메서드 이름 () ]으로 호출
  • 인스턴스 멤버(iv, im)와 관련된 작업을 하는 메서드
  • 메서드에서 인스턴스 변수 사용 가능

클래스 메서드(static메서드)

  • 객체 생성 없이 [ 클래스 이름. 메서드 이름() 호출
  • 인스턴스 멤버(iv, im)와 관련 없는 작업을 하는 메서드
  • 메서드 내에서 인스턴스 변수 사용불가(iv를 사용하지 않으면 static를 붙이자)
클래스의 멤버 변수 중 모든 인스턴스에 공통된 값을 유지해야 하는 것이 있는지 살펴보고 있으면, static을 붙인다.

작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에 static을 붙일 것을 고려한다.

이제 하단 예제를 풀어보자!

//예제6-19/ch6/MyMathTest2.java
package Chapter06;

class MyMath2 {
    long a, b;
    // 인스턴스변수 a, b만을 이용해서 작업하므로 매개변수가 필요없다.
    long add()      {return  a+b;} // a, b는 인스턴스변수
    long subtract() {return  a-b;}
    long multiply() {return  a*b;}
    double divide() {return  a/b;}

    // 인스턴스변수와 관계없이 매개변수만으로 작업이 가능하다.
    static long add(long a, long b)          {return a+b;} // a, b는 지역변수
    static long subtract(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 MyMathTest2 {
    public static void main(String[] args) {
        //클래스 메서드 호출. 인스턴스 생성없이 호출가능
        System.out.println(MyMath2.add(200L, 100L));
        System.out.println(MyMath2.subtract(200L, 100L));
        System.out.println(MyMath2.multiply(200L, 100L));
        System.out.println(MyMath2.divide(200.0,  100.0));

        MyMath2 mm = new MyMath2(); //인스턴스를 생성
        mm.a = 200L;
        mm.b = 100L;
        //인스턴스메서드는 객체생성 후에만 호출이 가능함.
        System.out.println(mm.add());
        System.out.println(mm.subtract());
        System.out.println(mm.multiply());
        System.out.println(mm.divide());

    }
}

 

3.12 클래스 멤버와 인스턴스 멤버 간의 참조와 호출

같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단, 클래스멤버가 인스턴스 멤버를

참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.

그 이유는 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하지만, 클래스멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 

않을 수도 있기 때문이다.

메서드 간 호출 참조

  • 인스턴스메서드가 호출 되었으면 이미 객체 생성(iv가 이미 존재)
  • static메서드는 iv 사용불가. why? 객체가 있을지 없을지 몰라서
반응형

블로그의 정보

무작정 개발

무작정 개발

활동하기