살군의 보조기억 장치

Another memory device…

Archive for January 2011

팩토리메소드 패턴

leave a comment »

이번에는 가장 많이 사용하는 패턴 중 하나인 FactoryMethod 패턴에 대해 살펴본다.

정의를 내려보자면 생성될 객체의 정확한 클래스를 명시하지 않고 특정 메소드에서 결정한다.
역시 와닿지 않는다….

Observer 때와 마찬가지로 스타크래프트를 예로 들어본다.
테란의 메카닉 유닛을 생산하는 건물이 마침 Factory 니까… 그걸로 설명 한다.

사용자 삽입 이미지

FactoryMethod 는 말 그대로 생산, 생성의 의미를 가지고 있다.
생산될 대상은 Product 이고 이는 스타크래프트의 팩토리가 생산하는 유닛들이다.
이 유닛들은 SiegeTank, Vulture 같은 유닛들로 구체화된다.
그리고 이들 유닛을 생성하는 처리를 담당하는 Creator 를 사용함으로써 FactoryMethod 패턴이 구성된다.
위의 그림과 같이 SiegeTank 란 유닛을 생산하기 위한 SiegeTankCreator 로써 존재하는데.
Creator 에서 유닛을 생성하여 반환하는 메소드를 factoryMethod 라 했다.
그렇다면 Creator 가 곧 스타크래프트의 팩토리 일까?
아니다 Creator 는 각각의 유닛별로 고유한 생산 로직을 담은 모듈에 해당된다.
스타크래프트의 팩토리는 그 Creator 를 모아놓은 것이다. (이는 좀 더 뒤에 다른 패턴에서 다루게 된다.)
Creator 는 게이머가 팩토리를 선택하고 시즈탱크를 생산하겠다라고 명령을 내릴때 동작한다.
유닛 생산시 필요한 시간을 소비시키고 적합한 애니메이션이나 소리를 들려주는 등의 처리가 Creator 에서 일어나는 일이 될 것이다.

예제 소스를 통해 살펴보자..
나름 재미가 있길래 조금 오바를 했다. FactoryMethod 패턴을 설명하기 위한 핵심은 진하게 표시된 부분이다.

public abstract class Unit {
protected final String name;
protected Unit(String name) {
this.name = name;
}
public String getName() { return this.name; }
public void command1() { System.out.println(name + “:이동”); }
public abstract void command2();
public abstract void command3();
}

유닛은 공통적인 처리나 로직등을 담을 필요가 있다 판단해서 인터페이스를 사용하지 않고 추상 객체로 작성했다.
유닛의 이름이나 command1 에서 일어나는 이동 같은 것들이 이런 이에 해당한다.
이 유닛을 상속하여 SiegeTank와 Vulture 를 만들수 있다.

public class Vulture extends Unit {
private int countSpiderMine;
Vulture() {
super(“벌처”);
this.countSpiderMine = 3;
}
public void command2() { System.out.println(name + “:수류탄”); }
public void command3() {
if ( this.countSpiderMine > 0 ) {
this.countSpiderMine–;
System.out.println(name + “:마인심기”);
} else {
System.out.println(name + “:마인없음”);
}
}
}
public class SiegeTank extends Unit {
private boolean siegeMode;
SiegeTank() {
super(“탱크”);
this.siegeMode = false;
}
public void command1() {
if ( !this.siegeMode ) {
super.command1();
} else {
System.out.println(name + “:이동못함”);  // 시즈모드일때는 이동하지 못한다.
}
}
public void command2() {
if ( this.siegeMode ) {
System.out.println(name + “:시즈포”);
} else {
System.out.println(name + “:통통포”);
}
}
public void command3() {
if ( this.siegeMode ) {
this.siegeMode = false;
System.out.println(name + “:탱크모드”);
} else {
this.siegeMode = true;
System.out.println(name + “:시즈모드”);
}
}
}

나름  SiegeTank와 Vulture 의 특성을 구현해 보았다.
이렇게 해서 만들어야 할 대상 Product 가 준비되었다. 이제 Creator 를 만들어본다.

public abstract class Creator {
protected Creator() {}
public abstract Unit createUnit();
}

위의 경우는 인터페이스로 작성해도 되지만 추상 객체로 만든 이유는 어떠한 공통 로직이 나중에라도 필요하지 않을까 해서이다. 이제 SiegeTank와 Vulture 를 만드는 각각의 Creator 를 작성한다.

public class SiegeTankCreator extends Creator {
public Unit createUnit() {
Unit unit = new SiegeTank();
System.out.println(unit.getName() + ” 생산”);
return unit;
}
}
public class VultureCreator extends Creator {
public Unit createUnit() {
Unit unit = new Vulture();
System.out.println(unit.getName() + ” 생산”);
return unit;
}
}

각각의 Creator 가 Unit 이라는 추상 객체로 반환하지만, 내부에서 각각 new SiegeTank(), new Vulture() 했다.
다시 한번 SiegeTank, Vulture 의 소스를 보면 Constructor 이 package private 이기 때문에 package 밖에서는 생성할 수 없다. 오로지 createUnit 으로만 생산할 수 있다. FactoryMethod 패턴을 사용하는 의미를 바로 안다면 SiegeTank, Vulture 는 결코 밖에서 보이면 안되고, 오로지 Unit 으로만 핸들링 되어야 한다. 그렇지 않다면 구지 FactoryMethod 패턴을 사용할 이유는 없다.
이제 이들 Creator 들을 모아놓은 팩토리를 만들고 테스트 해본다.

public class Factory {
private Creator creator1;
private Creator creator2;
public Factory() {
this.creator1 = new SiegeTankCreator();
this.creator2 = new VultureCreator();
}
public Unit createUnit1() { return this.creator1.createUnit(); }
public Unit createUnit2() { return this.creator2.createUnit(); }
}
public static void main(String[] args) {
Factory factory = new Factory();
Unit unit1 = factory.createUnit1();
unit1.command1();
unit1.command2();
unit1.command3();
unit1.command2();
unit1.command1();
unit1.command3();
unit1.command1(); 

Unit unit2 = factory.createUnit2();
unit2.command1();
unit2.command2();
unit2.command3();
unit2.command3();
unit2.command3();
unit2.command3();
unit2.command1();
}

사용자 삽입 이미지실행된 모습 

그런데 왜 객체를 직접 생성하지 않고, FactoryMethod 패턴을 사용하여 생성할까..?
이유는 간단하다. ExtentionPack Blood War 를 만들기 위해서다.
스타크래프트 오리지날에 골리앗이란 유닛이 없었다고 가정하고…
확장팩에 골리앗이라는 새로운 유닛을 만들어 추가로 넣고자 한다…
FactoryMethod 패턴이 적용되어 있지 않다면 꽤나 많은 수정이 일어날 것이다.
FactoryMethod 패턴을 바탕으로 설계되어 있다면
먼저 Unit 을 상속해 특화된 기술 요소를 넣은 골리앗을 만든다.
그리고 이를 생성하는 Creator 를 만들고, 그곳에 빌드 타임이나 제한 요소등을 넣을 수 있다.
지금까지 새로운 객체를 추가만 했지 기존 소스의 수정은 없었다는 점이 중요 포인트다…
앞서의 예에서 팩토리에 골리앗을 만드는 Creator 를 넣는 부분은 팩토리를 수정해야 하지만…
차후 이 부분은 다른 패턴을 가지고 설명할 기회가 있을 것이다.

참고 삼아서 스타크래프트의 사용자 인터페이스를 잠시 말한다.
게이머가 유닛을 선택하고 그 유닛에 내리는 명령의 가짓수는 몇가지 일까?
한 유닛에 한번에 선택할 수 있는 명령은 우측 하단의 최대 9개 버튼뿐이다.
마우스 왼쪽버튼, 오른쪽버튼으로 맵을 찍거나, 키보드로 단축키를 넣는 것은
Observer 패턴에 의해 9개 버튼중의 하나인 명령을 실행하는 것뿐이다.
건물짖기를 누르면 지을 수 있는 건물로 버튼이 바뀌는 것은 Shift 일 뿐이다.
예제 소스에서 유닛의 명령메쏘드 이름을 move, attack 으로 하지 않고, command1, command2 로 한건 이 때문이다.
이렇게 해서 각각의 개성넘치는 유닛들의 기능이 한 곳에서 단순한 구성으로 제어가 가능해진다.
여기서 이 얘기를 하는 것은 FactoryMethod 패턴에서 모든 유닛이 Unit 이란 슈퍼 클래스하나로 사용될 수 있어야 함을 이야기 하고자 한 것이다. 이것은 FactoryMethod 패턴의 활용 가치를 높여주는 핵심적 사항이다.
결국 제일 어려운 것은 FactoryMethod 가 아니라 Product 를 결정하는 것이다.

스타크레프트 예제도 어려우면 다음을 보자..

public class creator1 {
public Number createNumber() {  return new Integer(1234); }
}
public class creator2 {
public Number createNumber() {  return new Long(1234); }
}

이 예제도 객체(Integer, Long)의 생성이 메쏘드 내에서 이루어 지고,
그렇게 생성된 객체의 슈퍼클래스 형태(Number)로 리턴되는 FactoryMethod 패턴이다.
즉, createNumber() 란 메쏘드가 객체를 생성해서 반환하는 공장 메소드란 것이다.
그리고…
지금 필요한 건 Integer 와 Long 이었지만, 혹시 나중에 new Double 을 붙일 필요가 있다면…
그것만 쉽게 만들어 붙일 수 있도록 공통적인 부분을 인터페이스나 추상 객체로 만들어 놓은 것일 뿐이다.

아마 객체를 상속해서 쓰기 좋아했던 개발자라면…
실제 이게 팩토리메소드 패턴이야라고 알지 못하고도 그간 사용하고 있었을 수도 있다.

retrieved from: http://bum20.springnote.com/pages/2117622?print=1 (2011.01.10)

Advertisements

Written by gomiski

2011/01/10 at 7:30 am

Posted in Java, Lecture

[Java] Static keyword

leave a comment »

자바를 한번쯤 공부해본사람이라면 static키워드를 모르지는 않을 것입니다.

하지만, 바르게 알고 있는 사람들은 그리 많지 않습니다.
자바경력자를 면접볼 때 static키워드에 대해서 질문하곤 합니다.

 

면접관 : static키워드에 대해서 설명해보세요.
응시자 : static키워드를 쓰면, 객체를 생성하지 않고도 변수나 함수를 사용할 수 있습니다.

 

면접관 : 왜 static키워드를 쓰나요?
응시자 : 객체를 생성하지 않아도 되니까 편리하고 속도도 빠릅니다.

 

면접관 : 그렇다면 모든 변수와 함수에 static을 붙이는 것이 좋겠네요?
응시자 : 가능한한 static을 붙이는 것이 좋다고 생각합니다.

 

면접관 : 어떤 경우에 static을 붙일 수 있고, 어떤 경우에 static을 붙일 수 없습니까?
응시자 : …

 

면접관 : 만일 당신이 새로운 클래스를 작성한다고 할 때, 어떤 경우에 static키워드를
사용해야한다고 생각합니까?

응시자 : …
대부분의 경우 위와 같은 내용으로 문답이 진행됩니다.

사실 응시자의 대답은 다 맞는 얘기입니다. 하지만, static의 핵심적인 개념을 모르기 때문에
어떤 경우에 왜 static을 사용해야하는지는 잘모르는 것 같습니다.

 

먼저 결론부터 간단히 정리하면 다음과 같습니다.

 

1.클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용해야하는 것에 static을 붙인다.
– 인스턴스를 생성하면, 각 인스턴스들은 서로 독립적기 때문에 서로 다른 값을 유지한다.
경우에 따라서는 각 인스턴스들이 공통적으로 같은 값이 유지되어야 하는 경우 static을
붙인다.

 

2. static이 붙은 멤버변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
– static이 붙은 멤버변수(클래스변수)는 클래스가 메모리에 올라갈때 이미 자동적으로
생성되기 때문이다.

 

3. static이 붙은 메서드(함수)에서는 인스턴스 변수를 사용할 수 없다.
– static이 메서드는 인스턴스 생성 없이 호출가능한 반면, 인스턴스 변수는 인스턴스를
생성해야만 존재하기 때문에… static이 붙은 메서드(클래스메서드)를 호출할 때
인스턴스가 생성되어있을수도 그렇지 않을 수도 있어서 static이 붙은 메서드에서
인스턴스변수의 사용을 허용하지 않는다.
(반대로, 인스턴스변수나 인스턴스메서드에서는 static이 붙은 멤버들을 사용하는 것이
언제나 가능하다. 인스턴스변수가 존재한다는 것은 static이 붙은 변수가 이미 메모리에
존재한다는 것을 의미하기 때문이다.)

 

4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
– 메서드의 작업내용중에서 인스턴스 변수를 필요로 한다면, static을 붙일 수 없다.
반대로 인스턴스변수를 필요로 하지 않는다면, 가능하면 static을 붙이는 것이 좋다.
메서드 호출시간이 짧아지기 때문에 효율이 높아진다.
(static을 안붙인 메서드는 실행시 호출되어야할 메서드를 찾는 과정이 추가적으로
필요하기 때문에 시간이 더 걸린다.)

 

5. 클래스 설계시 static의 사용지침
– 먼저 클래스의 멤버변수중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지
살펴보고 있으면, static을 붙여준다.
– 작성한 메서드 중에서 인스턴스 변수를 사용하지 않는 메서드에 대해서 static을
붙일 것을 고려한다.

일반적으로 인스턴스변수와 관련된 작업을 하는 메서드는 인스턴스메서드(static이 안붙은
메서드)이고 static변수(클래스변수)와 관련된 작업을 하는 메서드는 클래스메서드(static이 붙은 메서드)라고 보면 된다.
다음은 static에 대한 자세한 설명과 예제입니다.
static은 객체지향개념을 이해하는 가장 중요한 첫걸음이니 확실히 알아두셔야합니다.

 

==================================================================

 

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

클래스변수와 인스턴스변수의 차이를 이해하기 위한 예로 카드 게임에 사용되는 카드를 클래스로 정의해보자.

카드 클래스를 작성하기 위해서는 먼저 카드를 분석해서 속성과 기능을 알아 내야한다. 속성으로는 카드의 무늬, 숫자, 폭, 높이 정도를 생각할 수 있을 것이다.
이 중에서 어떤 속성을 클래스 변수로 선언할 것이며, 또 어떤 속성들을 인스턴스 변수로 선언할 것인지 생각해보자.

 

class Card {
String kind ;                         // 카드의 무늬 – 인스턴스 변수
int number;                         // 카드의 숫자 – 인스턴스 변수
static int width = 100 ;             // 카드의 폭 – 클래스 변수
static int height = 250 ;            // 카드의 높이 – 클래스 변수
}

각 Card인스턴스는 자신만의 무늬(kind)와 숫자(number)를 유지하고 있어야 하므로 이들을 인스턴스변수로 선언하였고, 각 카드들의 폭(width)과 높이(height)는 모든 인스턴스가 공통적으로 같은 값을 유지해야하므로 클래스변수로 선언하였다.

만일 카드의 폭을 변경해야할 필요가 있을 때는 모든 카드의 width값을 변경하지 않고, 한 카드의 width값만 변경해도 모든 카드의 width값이 변경되는 셈이다.

 

[예제6-4] CardTest.java
class CardTest{
public static void main(String args[]) {
// 클래스변수(static 변수)는 객체생성없이 ‘클래스이름.클래스변수’로 직접 사용 가능하다.
System.out.println(“Card.width = ” + Card.width);
System.out.println(“Card.height = ” + 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.width = 100
Card.height = 250
c1은 Heart, 7이며, 크기는 (100, 250)
c2는 Spade, 4이며, 크기는 (100, 250)
이제 c1의 width와 height를 각각 50, 80으로 변경합니다.
c1은 Heart, 7이며, 크기는 (50, 80)
c2는 Spade, 4이며, 크기는 (50, 80)

Card클래스의 클래스변수(static변수)인 width, height 그리고 color는 Card클래스의 인스턴스를 생성하지 않고도 ‘클래스이름.클래스변수’와 같은 방식으로 사용할 수 있다.
Card인스턴스인 c1과 c2는 클래스 변수인 width와 height를 공유하기 때문에, c1의 width와 height를 변경하면 c2의 width와 height값도 바뀐 것과 같은 결과를 얻는다.
Card.width, c1.width, c2.width는 모두 같은 저장공간을 참조하므로 항상 같은 값을 갖게 된다.
인스턴스 변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.
[플래시동영상]자료실의 플래시동영상 MemberVar.swf을 꼭 보도록하자.

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

변수에서 그랬던 것과 같이, 메서드 앞에 static이 붙어 있으면 클래스메서드이고 붙어 있지 않으면 인스턴스메서드이다.
클래스 메서드는 호출방법 역시 클래스변수처럼, 객체를 생성하지 않고도 ‘클래스이름.메서드이름(매개변수)’와 같은 식으로 호출이 가능하다.
그렇다면 어느 경우에 static을 사용해서 클래스메서드로 정의해야하는 것일까?

클래스는 ‘데이터(변수)와 데이터에 관련된 메서드의 집합’이라고 할 수 있다. 같은 클래스 내에 있는 메서드와 멤버변수는 아주 밀접한 관계가 있다. 인스턴스메서드는 인스턴스변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스변수를 필요로 하는 메서드이다.
그래서 인스턴스변수와 관계없거나(메서드 내에서 인스턴스변수를 사용하지 않거나), 클래스변수만을 사용하는 메서드들은 클래스메서드로 정의한다.

물론 인스턴스변수를 사용하지 않는다고 해서 반드시 클래스 메서드로 정의해야하는 것은 아니지만, 그렇게 하는 것이 일반적이다.
참 고로 Math클래스의 모든 메서드는 클래스메서드임을 알 수 있다. Math클래스에는 인스턴스변수가 하나도 없거니와 Math클래스의 함수들은 작업을 수행하는데 필요한 값들을 모두 매개변수로 받아서 처리 하기 때문이다. 이처럼, 단순히 함수들만의 집합인 경우에는 클래스메서드로 선언한다.

[참고]인스턴스 변수 뿐만 아니라 인스턴스 메서드를 호출하는 경우에도 인스턴스 메서드로 선언되어야 한다. 인스턴스 메서드를 호출하는 것 역시 인스턴스 변수를 간접적으로 사용하는 것이기 때문이다.

[예제6-12] MyMathTest2.java
class MyMath2 {
long a, b;

// 인스턴스변수 a, b를 이용한 작업을 하므로 매개변수가 필요없다.
long add() {       return 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; }
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());

}

[실행결과]
300
100
20000
2.0
300
100
20000
2.0

인 스턴스메서드인 add(), subtract(), multiply(), divide()는 인스턴스변수인 a와 b만으로도 충분히 원하는 작업이 가능하기 때문에, 매개변수를 필요로 하지 않으므로 괄호()에 매개변수를 선언하지 않았다.
반면에 add(long a, long b), subtract(long a, long b) 등은 인스턴스변수 없이 매개변수만으로 작업을 수행하기 때문에 static을 붙여서 클래스메서드로 선언하였다. MyMathTest2의 main메서드에서 보면, 클래스메서드는 객체생성없이 바로 호출이 가능했고, 인스턴스메서드는 MyMath2클래스의 인스턴스를 생성한 후에야 호출이 가능했다.
이 예제를 통해서 어떤 경우 인스턴스메서드로, 또는 클래스메서드로 선언해야하는지, 그리고 그 차이를 이해하는 것은 매우 중요하다.

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


같은 클래스에 속한 멤버들간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단, 클래스멤버가 인스턴스멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.
그 이유는
인스턴스멤버가 존재하는 시점에 클래스멤버는 항상 존재하지만, 클래스멤버가 존재하는 시점에 인스턴스멤버가 항상 존재한다는 것을 보장할 수 없기 때문이다.

[예제6-] ArrayEx.java
class MemberCall {
int iv = 10;
static int cv = 20;

int iv2 = cv;
//   static int cv2 = iv;                   에러. 클래스변수는 인스턴스 변수를 사용할 수 없음.
static int cv2 = new MemberCall().iv;   // 굳이 사용하려면 이처럼 객체를 생성해야함.

static void classMethod1() {
System.out.println(cv);
//         System.out.println(iv);       에러. 클래스메서드에서 인스턴스변수를 바로 사용할 수 없음.
MemberCall c = new MemberCall();
System.out.println(c.iv);   // 객체를 생성한 후에야 인스턴스변수의 참조가 가능함.
}

void instanceMethod1() {
System.out.println(cv);
System.out.println(iv);  // 인스턴스메서드에서는 인스턴스변수를 바로 사용가능.
}

static void classMethod2() {
classMethod1();
//         instanceMethod1(); 에러. 클래스메서드에서는 인스턴스메서드를 바로 호출할 수 없음.
MemberCall c = new MemberCall();
c.instanceMethod1(); // 인스턴스를 생성한 후에야 인스턴스메서드를 호출할 수 있음.
}

void instanceMethod2() { // 인스턴스메서드에서는 인스턴스메서드와 클래스메서드
classMethod1();         // 모두 인스턴스생성없이 바로 호출이 가능하다.
instanceMethod1();
}
}


클래스멤버(클래스변수와 클래스메서드)는 언제나 참조 또는 호출이 가능하다.
그렇기 때문에 인스턴스멤버가 클래스멤버를 참조, 호출하는 것은 아무런 문제가 안 된다.
클래스멤버간의 참조 또는 호출 역시 아무런 문제가 없다.

그러나, 인스턴스멤버(인스턴스변수와 인스턴스메서드)는 반드시 객체를 생성한 후에만 참조 또는 호출이 가능하기 때문에 클래스멤버가 인스턴스멤버를 참조, 호출하기 위해서는 객체를 생성하여야 한다.

하지만, 인스턴스멤버간의 호출에는 아무런 문제가 없다. 하나의 인스턴스멤버가 존재한다는 것은 인스턴스가 이미 생성되어있다는 것을 의미하며, 즉 다른 인스턴스멤버들도 모두 존재하기 때문이다.

실제로는 같은 클래스 내에서 클래스멤버가 인스턴스멤버를 참조 또는 호출해야하는 경우는 드물다. 만일 그런 경우가 발생한다면, 인스턴스메서드로 작성해야할 메서드를 클래스메서드로 한 것은 아닌지 한번 더 생각해봐야 한다.

[알아두면 좋아요]
수학에서의 대입법처럼, c = new MemberCall()이므로 c.instanceMethod1();에서 c대신 new MemberCall()을 대입하여 사용할 수 있다.

MemberCall c = new MemberCall();
int result = c.instanceMethod1();

위의 두 줄을 다음과 같이 한 줄로 할 수 있다.

int result = new MemberCall().instanceMethod1();

대신 참조변수를 사용하지 않았기 때문에 생성된 MemeberCall인스턴스는 더 이상 사용할 수 없다

retrieved from: http://rockdrumy.tistory.com/entry/JAVA-static%ED%82%A4%EC%9B%8C%EB%93%9C-%EB%B0%94%EB%A1%9C%EC%95%8C%EA%B8%B0

 

Read the rest of this entry »

Written by gomiski

2011/01/10 at 4:35 am

Posted in Java, Lecture