JAVA 2014. 2. 9. 23:31

* 상속 

class Color{

     protected abstract void setAlpha();

     public void setColor(){
          setAlpha();
          setDrawColor();
     }

    private void setDrawColor(){
         // something
    }
}

라는 클래스가 있다. 이 Color 클래스를 상속받는다면 

추상매소드 setAlpha()를 반드시 override 해야 하고 부모(Color)에있는 

변수를사용할 수 있고  setDrawColor()를 오버라이드 받아 

수정하여 쓸 수 있다. 그럼 자식 setDrawColor()만 수행하고 부모껀 무시한다.

이 Color 클래스를 상속받는 Red 클래스가 있다.

Class Red extends Color{
     @override
     private void setAlpha(){
          // alpha = 70%; 
     }
}


이걸 사용 하는 방법은 사용할 class에서 

Color redColor = new Red();
redColor.setColor();

이렇게 사용한다.

실행 순서는 Color setColor()를 들어가 Red의 setAlpha() 매소드를 수행하고 부모(Color)클래스의
setDrawColor();를 수행한다. 

이런식으로 공통으로 사용하는 매소드가 필요할 때 그 매소드만 따로모아
클래스를 만들어놓고 상속받아 쓰면 효율적이다.


'JAVA' 카테고리의 다른 글

JAVA] Singleton 패턴  (0) 2013.02.07
JAVA] 현재 날짜, 시간 구하기  (1) 2011.11.30
JAVA] split으로 문자열 나누기  (0) 2011.10.17
JAVA] 22. 인터페이스 - 1  (0) 2011.08.19
JAVA] drawRect 속성 알아보기  (1) 2011.08.18
posted by 젊은쎄오
:
JAVA 2013. 2. 7. 11:10

사용이유 

- 로그인 정보와 같이 고유한 값이 필요할 때 여기저기서 new 로 생성하지않고 

A a = new A.getInstance(); 로 호출하여 고유값을 공유한다.


이렇게 호출 시 최초 호출에  A클래스의 인스턴스 공간이 생성되고 

이 후 호출 시에는 최초 호출한 인스턴스를 가져온다. 


지정한 클래스 인스턴스가 절대로 한개밖에 존재하지 않는것을 보증하고 싶을경우.


데이터 공유용으로는 잘못된사용. 



http://underclub.tistory.com/436

'JAVA' 카테고리의 다른 글

JAVA] 간단한 상속 개념 정리  (0) 2014.02.09
JAVA] 현재 날짜, 시간 구하기  (1) 2011.11.30
JAVA] split으로 문자열 나누기  (0) 2011.10.17
JAVA] 22. 인터페이스 - 1  (0) 2011.08.19
JAVA] drawRect 속성 알아보기  (1) 2011.08.18
posted by 젊은쎄오
:
JAVA 2011. 11. 30. 10:28
자바 또는 안드로이드에서 현재 날짜와 시간을 구하는 코드입니다.
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat ( "yyyy.MM.dd HH:mm:ss", Locale.KOREA );
Date currentTime = new Date ( );
String mTime = mSimpleDateFormat.format ( currentTime );
System.out.println ( mTime );

결과는 이렇게 년.월.일 시:분:초 로 나옵니다.

 


'JAVA' 카테고리의 다른 글

JAVA] 간단한 상속 개념 정리  (0) 2014.02.09
JAVA] Singleton 패턴  (0) 2013.02.07
JAVA] split으로 문자열 나누기  (0) 2011.10.17
JAVA] 22. 인터페이스 - 1  (0) 2011.08.19
JAVA] drawRect 속성 알아보기  (1) 2011.08.18
posted by 젊은쎄오
:
JAVA 2011. 10. 17. 13:10
문자열이 일정한 패턴으로 길게 들어있다면 , split 이란 매소드로 끊어 담을 수 있습니다. 

저 같은 경우 , 이미지 패스 세개가 쭉 붙여서 한 String 배열로 담겨서 받은 적이있는데 

이 이미지를 받아 뿌리려면 각각 패스마다 잘라서 담아야했어서 split을 사용했습니다.

 

예제는 간단합니다, 위에 String name 변수에 " " 스페이스 공백을 사이에 둔 first , second, third 가 있습니다,

이렇게 일정한 패턴이라면 뽑아 낼 수 있는데요,

/* 각자 자르기 */ 를 보시면 값이 있는 name 변수에 .split(" ") 이렇게 붙이는데 이게 " "  이 공백으로

문자열을 나누겠다는 의미입니다. 만약 예제 문자열이  first=second=third  이런식이었다면 ("=") 이런식으로

사용하면 됩니다.

뒤에 []  는 배열의 의미인데 (" ") 이렇게 자르고 난 뒤 그림과 같이 왼쪽부터 0번,1번 ,2번 배열로 사용할 수 있습니다.



이렇게 하나 씩 잘라서 안쓰고 아예 배열에 넣고 싶다하시면 /* 잘라서 배열에 넣기 */  와 같이 

아예 String[] 배열 객체에 담을수도 있습니다, 사용방법은 위와 같이 [0] ,[1] 이런 배열 인덱스를 뽑아서

사용하구요 , 결과값은 이렇습니다



 

'JAVA' 카테고리의 다른 글

JAVA] Singleton 패턴  (0) 2013.02.07
JAVA] 현재 날짜, 시간 구하기  (1) 2011.11.30
JAVA] 22. 인터페이스 - 1  (0) 2011.08.19
JAVA] drawRect 속성 알아보기  (1) 2011.08.18
JAVA] String 원하는 만큼 잘라내기  (0) 2011.08.04
posted by 젊은쎄오
:
JAVA 2011. 8. 19. 00:35
자바에서는 다중 상속을 허용하지 않습니다. 하지만 간혹 이미 다른 클래스를 상속받은 

서브클래스들의 필요한 부분을 모아 따로 슈퍼 클래스를 선언해야 할 상황이 있습니다.



그림과 같이 단행본 클래스와 부록 CD 클래스의 공통적인 기능을 추출하여 인터페이스로 만들 수 

있습니다. 다만 주의 할 점은 공통적인 기능(매소드)은 추출 할 수 있지만 , 공통적인 데이터는 

표현 할 수 없다는 제약이 있습니다. 

저렇게 추출한 인터페이스를 소스로 옮겨보면 


이렇게 됩니다, 클래스 선언과 비슷하지만 class 대신 interface 를 써서 선언합니다. 매소드의 로직은 

구상할 필요가 없는데 인터페이스에 속하는 매소드들은 무조건 추상 매소드로 선언해야 하기 

때문입니다.

이제 이걸 자세히 알아보기 위해 책 대여 클래스와 CD대여 클래스를 만들어 이 둘이 공통으로 쓰는 

기능을 인터페이스하여 어떻게 오버라이딩하는지 알아보겠습니다 


먼저 책 대여 클래스인데요, 번호, 책이름, 저자, 대출인, 대출일, 대출 상태등이 있습니다 

생성자로 먼저 번호와 책이름 , 저자를 받아놓고 checkOut 매소드를 오버라이딩하여 

여기에 실려 넘어오는 대출인과 대출일, 대출 상태등을 담아놓은 후 누가 언제 뭘 빌려갔다라고 

찍습니다.  반대로 checkIn 을 호출하면 대출인과 대출일을 null로 바꾸고 대출상태도 0으로 바꿉니다


이제 시디 대여 클래스인데 얘는 CDInfo 라는 클래스를  이미 상속 받고 있습니다 .


CDInfo는 별거 없고 , 단지 시디 관련 번호와 시디 제목을 담아 놓습니다.

다시 시디 대여 클래스로 가보면 생성자로 시디 번호와 시디 타이틀을 받아 슈퍼클래스인 

CDInfo에 담아 놓습니다. checkOut 과 checkIn은 책 대여 클래스와 기능이 동일합니다. 

단지 책 제목이냐 시디 제목이냐가 다른데요,



 

이제 이것을 실행 해 보면



이렇게 찍히게 됩니다. 

이처럼 라이브러리는 이미 다른 상속을 받고있는 서브 클래스라 하더라도 비슷한 기능을 추출하여

안에 그 기능을 추상 매소드로 만들어 놓음으로써 필요한 클래스들이 얼마든지 implements 하여

오버라이딩 할 수 있다는 장점이 있습니다. 









출판사 : 한빛미디어 , 저자 : 김윤명 님의 뇌를 자극하는 Java프로그래밍에서 공부한 내용입니다. 

'JAVA' 카테고리의 다른 글

JAVA] 현재 날짜, 시간 구하기  (1) 2011.11.30
JAVA] split으로 문자열 나누기  (0) 2011.10.17
JAVA] drawRect 속성 알아보기  (1) 2011.08.18
JAVA] String 원하는 만큼 잘라내기  (0) 2011.08.04
JAVA] 21. 클래스의 상속  (0) 2011.06.22
posted by 젊은쎄오
:
JAVA 2011. 8. 18. 18:11



아 생각보다 헷갈리네요 ..ㅠ 

중요한건 두가지가 모여서 점하나를 찍는거고 right 와 bottom은 left와 top 값 까지 더해서

값을 주셔야 합니다. 그림과 같이 시작점은 같거든요,

마지막 Paint는 저보다 더 잘 아시겠지만 paint.setColor(Color.RED) 나 paint.setTextSize등 

그릴 것의 속성입니다.  paint.setColor(Color.RED) 로 윗줄에 써넣고 drawRect 을 실행했다면

빨간 사각형이 나오겠죠 ! 

'JAVA' 카테고리의 다른 글

JAVA] split으로 문자열 나누기  (0) 2011.10.17
JAVA] 22. 인터페이스 - 1  (0) 2011.08.19
JAVA] String 원하는 만큼 잘라내기  (0) 2011.08.04
JAVA] 21. 클래스의 상속  (0) 2011.06.22
JAVA] 20. 클래스의 정적 구성 요소  (0) 2011.06.17
posted by 젊은쎄오
:
JAVA 2011. 8. 4. 10:32
코딩 하다보면 String형의 텍스트를 잘라내야 될 경우가 있습니다. 

예를 들어 이미지를 파싱해 왔는데 mainImage:http://www.mainImage.com/124313.jpg

이렇게 왔다면 http부터 이미지의 패스기 때문에 앞에 mainImage :  여기는 필요 없습니다. 

그럼 http 부터 끝까지 잘라내서 새로 String 변수에 담아야 하는데 그 때는 subString이란

놈을 사용합니다.

String imgPath = "mainImage:http://www.mainImage.com/124313.jpg";
      String newPath = imgPath.substring( imgPath.indexOf(":")+1, imgPath.length);

 처음에 imgPath에 풀패스를 담고, 그 다음 새로 담을 newPath를 만든후에 거기 담는데 

담는 부분을 잘보시면 substring( 시작 , 끝 ); 입니다.  시작을 보시면 :에 한 칸 +1 해서

http에 h 부터 잘라서 끝은 .length() 니까 끝까지죠 .

그렇게 딱 패스 부분만 담는 것 입니다.

imgPath.substring ( 0 , 10 ) ;

이런식으로 왼쪽부터 0,1,2,3 식으로 칸을 세어 담을 수 도 있구요

 

'JAVA' 카테고리의 다른 글

JAVA] 22. 인터페이스 - 1  (0) 2011.08.19
JAVA] drawRect 속성 알아보기  (1) 2011.08.18
JAVA] 21. 클래스의 상속  (0) 2011.06.22
JAVA] 20. 클래스의 정적 구성 요소  (0) 2011.06.17
JAVA] 19. 메소드  (0) 2011.06.15
posted by 젊은쎄오
:
JAVA 2011. 6. 22. 22:36
객체지향 프로그램은 상호 작용하는 객체들로 이루어지고, 객체 생성에 필요한 클래스를 만드는 일은

프로그래머의 몫이다. 그러므로 프로그래머는 새로운 유형의 객체가 필요하면 클래스를 만들게 되는데

이 때 만들 객체가 기존의 객체와 비슷한 유형을 가지는 클래스를 만들어야 할 경우도 있다. 예를들어 

[이름]
은행 계좌 클래스

[데이터]
계좌번호
예금주 이름
잔액

[기능]
예금한다  
인출한다


전에 만들어 봤던 은행 계좌 메소드를 사용하여 

계좌번호 : 111-111-111111
예금주 : 김이박
잔액 : 2100000
-----------------------------
예금한다
인출한다

의 객체를 만들어 보았었다. 허나 직불카드번호와 직불카드 사용액을 지불하는 메소드를 추가한다면  

계좌번호 : 111-111-111111
예금주 : 김이박
잔액 : 2100000
직불 카드번호 : 1111222233334444
-------------------------------
예금한다
인출한다
직불카드 사용액을 지불한다. 
 
이렇게 된다면, 저 두 줄때문에 새로운 클래스를 제작하기 보다 이미 존재하는 유사한 클래스를

가져다 필요한 부분을 추가하여 가져올 수 있는 방법을 사용하는 것이 훨씬 바람직한 코딩이다.

위와같이 클래스를 가져다가 확장하여 새로운 클래스를 만드는 기술을 객체지향 프로그래밍에서는 

상속(inheritance) 라 하고 상속받아 만들어진 클래스는 상속받은 클래스의 기능을 모두 사용 할 수

있고 더 확장 할 수도 있다. 

* 클래스 상속의 기초문법

아까 예로 든 것처럼 아래와 같이 만들어야 한다고 치자

계좌번호 : 111-111-111111
예금주 : 김이박
잔액 : 2100000
직불 카드번호 : 1111222233334444
-------------------------------
예금한다 
인출한다
직불카드 사용액을 지불한다. 

일단 기본틀이 되는 은행계좌 클래스는 이렇다.


public
class Account {

String accountNo;

String ownerName;

int balance;

void deposit(int amount){

balance += amount;

}

int withdraw(int amount) throws Exception{

if(balance < amount)

throw new Exception("잔액이 부족 합니다.");

balance -= amount;

return amount;

}

}


이제 이 클래스를 가져다 직불 계좌 클래스를 만들어야 하는데 우선 직불 계좌 클래스의 이름은

"CheckingAccount" , 직불카드 번호는 "cardNo" ,  직불카드 사용액지불 메소드명은 "pay" 라고 

정해 놓고 시작하자.

우선 클래스를 상속하려면 선언이 필요한데 형식은 다음과 같다

class 상속받아새로만들어질클래스명 extends 상속되어질클래스{}
class CheckingAccount extends Account {} 

이다.  앞엣놈이 뒤엣놈을 상속받는다고 생각하면 된다. 자바에서는 이 때 상속을 해주는 

Account 클래스를 슈퍼클래스(superclass) 라 하고 상속 받는 CheckingAccount를

서브클래스(subclass) 라고 한다. 이제 이렇게 클래스를 상속받았으니 추가되는 필드와

메소드를 작성하여 보자.

public class Account {

String accountNo;

String ownerName;

int balance;

void deposit(int amount){

balance += amount;

}

int withdraw(int amount) throws Exception{

if(balance < amount)

throw new Exception("잔액이 부족 합니다.");

balance -= amount;

return amount;

}

}


class CheckingAccount extends Account{

String cardNo;

int pay(String cardNo, int amount) throws Exception{

if(!cardNo.equals(this.cardNo) || (balance < amount))

throw new Exception("지불이 불가능합니다");

return withdraw(amount);

}

}

 
자, 잘보면 위의 Account 클래스를 상속받은 CheckingAccount 클래스가 있다. 

이 클래스는 상속을 받았기 때문에 위에서 상속한 계좌번호, 예금주이름, 잔액 을 따로 또 

선언하지 않고 , 추가된 직불카드 번호 필드만 생성한다. 그리고 직불카드 사용액 지불 메소드만

만든다. 그 메소드인 pay 메소드를 보자, 파라미터로 직불카드번호와 금액을 받는다. 그리고 if문에서

!cardNo.equals(this.cardNo)  이것부터 보면 파라미터로 넘어온 카드번호(cardNo) 와 이미 저장되어

있는 내 카드번호(this.cardNo)가 같지 않다면 (!)  이란 의미이다 즉 내가 카드를 긁었는데 

카드 번호가 맞지 않거나 중간에 || 이것은

피연산자1 || 피연산자2            >   두 값이 모두 false면 false, 그렇지 않으면 true이다.

이 의미이다, 그리고 피연산자2에 해당하는 balance < amount 는 잔액보다 긁으려는 금액이 크다면,

이 의미이다, 즉 앞에 카드번호가 틀리거나 , 잔액보다 큰 금액을 파라미터로 넘겼다면 아래 지불이 

불가능하다고 뜬다. 그리고 둘다 해당되지않는다면 withdraw 메소드에 파라미터로 넘어온 금액을 

넘겨서 잔액 - 파라미터금액을 하고 다시 잔액을 리턴하게 된다. 아까 연산기호 기억이 안난다면
 
 여기 를 다시보면 된다. 참고로 CheckingAccount 클래스를 상속받는 또다른 클래스가 있다면 

그 클래스는 CheckingAccount 와 더불어 Account 까지 상속받아 안에 필드와 메소드를 사용할 수 

있게 된다. 

class Exam {

public static void main(String ar[]){

CheckingAccount obj = new CheckingAccount();

obj.accountNo = "111-111-111111";

obj.ownerName = "송동수";

obj.cardNo = "1111-2222-1111-2222";

obj.deposit(1000000);

try{

int paidAmount = obj.pay("1111-2222-1111-2222", 890000);

System.out.println("지불액 : "+paidAmount);

System.out.println("액 : "+obj.balance);

}catch(Exception e){

}

}

}
 

이런식으로 지불하는 프로그램을 만들어보았다. 우선 계좌번호와, 예금주, 카드번호, 잔액을 넣고

직불카드 지불 메소드에 해당 직불카드 번호와 89만원을 긁으라고 넘겼다. 그럼 위 

CheckingAccount 메소드를 타고 지불액과 잔액이 떨어진다. 

지불액 : 890000

액 : 110000  이렇게 말이다. 만약 잔액보다 많은 금액을 넣는다면 직불이 불가능하다고 뜬다,


*상속과 생성자

앞에선 초기 값을 프로그램을 실행 시키고 대입시켰지만 이같은 방법은 좋은 방법이아니다.

앞에서 배운 생성자를 활용하는 것이 좋은데 알아보자.

class CheckingAccount extends Account{

String cardNo;

CheckingAccount(String accountNo, String ownerName, 

int balance, String cardNo){

this.accountNo = accountNo;

this.ownerName = ownerName;

this.balance = balance;

this.cardNo = cardNo;

}

int pay(String cardNo, int amount) throws Exception{

if(!cardNo.equals(this.cardNo) || (balance < amount))

throw new Exception("지불이 불가능합니다");

return withdraw(amount);

}

}

요렇게 생성자를 만들어 둔다. 이제 이 클래스를 실행하는 프로그램에서 초기에 생성자에

파라미터를 담아 호출하면 시작하자마자 값이 담기고 시작을 하여 효율적이다. 

class Exam {

public static void main(String ar[]){

CheckingAccount obj = new CheckingAccount("111-111-111111",
 "송동수", 0 "1111-2222-1111-2222");

obj.deposit(1000000);

try{

int paidAmount = obj.pay("1111-2222-1111-2222", 890000);

System.out.println("지불액 : "+paidAmount);

System.out.println("액 : "+obj.balance);

}catch(Exception e){

String msg= e.getMessage();

System.out.println(msg);

}

}

}

이렇게 아예 클래스객체를 만들 때 값을 넘겨 초기 값을 담아 두고 그것을 이용하는 편이 좋다.



와오, 점점 복잡해진다.. 






출판사 : 한빛미디어 , 저자 : 김윤명 님의 뇌를 자극하는 Java프로그래밍에서 공부한 내용입니다. 

'JAVA' 카테고리의 다른 글

JAVA] drawRect 속성 알아보기  (1) 2011.08.18
JAVA] String 원하는 만큼 잘라내기  (0) 2011.08.04
JAVA] 20. 클래스의 정적 구성 요소  (0) 2011.06.17
JAVA] 19. 메소드  (0) 2011.06.15
JAVA] 18. 필드  (0) 2011.06.14
posted by 젊은쎄오
:
JAVA 2011. 6. 17. 00:58
클래스의 기본적인 용도는 객체를 생성하는 것이고 , 클래스에 선언된 필드와 메소드는 객체를

생성하고나면 생성된 객체에 속하게 된다. 하지만 때로는 클래스 자체에 속하는 구성요소를 

선언해야 될 때도 있는데 그런 구성요소를 클래스의 정적(static) 구성요소라고 부른다.

정적 필드

일반적으로 필드는 객체의 고유한 데이터 값을 저장하기 위해 사용하지만 경우에 따라서는

클래스 자체에 속하는 데이터를 지정할 변수도 필요하다, 이럴 때 사용하는 것이 

정적 필드 (static field)  이다. 이 필드는 클래스 전체에서 사용가능하므로 클래스 내부

어디든 이 필드에 값을 넣을 수있지만, 일단 넣으면 그 값을 썻던 모든 곳이 새 값으로 교체된다.

public class staticExam {
int total = 0;
static int grandTotal = 0;
void staticExam(int value){
total += value;
grandTotal += value;
}
}

위 빨간 부분이 정적필드의 생성과 사용부분이다. 

total  필드는 객체마다 따로 생기지만 grandTotal 필드는 특정 객체에 상관없이 클래스 자체에 

하나만 생기는 정적 필드이다. 다음 소스로 정적필드의 특성을 알아보자.

class StaticFieldExam{
public static void main(String args[]){
staticExam se1 = new staticExam();
staticExam se2 = new staticExam();
se1.staticExam(10);
se2.staticExam(20);
System.out.println("se1.total :"+se1.total); 
System.out.println("se1.grandTotal :"+se1.grandTotal); 
System.out.println("se2.total :"+se2.total); 
System.out.println("se2.grandTotal :"+se2.grandTotal); 
}
}

이 프로그램을 보자, 우선 앞 소스인 staticExam을 인스턴스화하여 두가지 객체를 만들었다.

se1에는 staticExam 매소드에 10을 파라미터로 넘겼고, 그럼 

void staticExam(int value){
total += value;
        grandTotal += value;
}
 이 구문이 수행되어 total과 grandTotal에 10이 들어갈 것이다. 그리고 다시 제자리로 돌아가

다음줄인 se2에 20을 실어 메소드에 보내면 total은 인스턴스 필드기 때문에 20이란 새로운

필드가 만들어졌고 grandTotal은 클래스자체에 속하는 정적 필드기 때문에 아까 10과 지금의

20을 더하여 가지고 있는다. 결과를 보자

se1.total :10
se1.grandTotal :30
se2.total :20
se2.grandTotal :30

이렇게 나온다. total은 se1과 se2의 필드에 각각 들어가 있는 반면 grandTotal 필드에는 값이

누적되있다. 정적 필드는 클래스 자체에 속하기 때문에 앞에 객체 이름 대신 클래스 이름을 붙여서 

사용 할 수도있다.  staticExam.grandTotal; 이렇게 말이다

상수의 선언

정적필드에 final 키워드 까지 붙이면 크 필드는 소스 코드에서 주어진 초기값을 프로그램 실행중에

절대 바꿀 수 없게 된다. 그래서 자바에서는 상수를 사용하고 싶을 때는 final과 static을 모두 붙여

필드를 만들고 이를 상수 변수(constant variable) 라고 부른다. 상수는 변하지 않는 값을 말한다. 

public class staticfinal {
final static int LIMIT = 1000;
int value;
void setValue(int value){
if(value < LIMIT)
this.value = value;
else
this.value = LIMIT;
}
}

이런식으로 상수 변수를 만들었다.

class staticfinalExam2{
public static void main(String args[]){
staticfinal sf = new staticfinal();
sf.setValue(1010);
System.out.println("sf.value :"+sf.value); 
System.out.println("상한값  :"+staticfinal.LIMIT); 
}
}

이런식으로 1010을 파라미터로 넘기면 위 소스에서 1010 < 1000 이기 때문에

else로 빠지고 this.value엔 1000이 들어간다 . 결과값은

sf.value :1000
상한값  :1000

이렇다.

정적 메소드 

static을 붙여 만든 메소드를 정적 메소드(static method) 라고 한다. 예를 보자

public class staticMethod {
int total = 0;
static int grandTotal = 0;
void Method(int value){
total += value;
grandTotal += value;
}
static int getGrandTotal(){
return grandTotal;
}
이런식으로 정적 메소드를 선언 할 수 있다. 

class StaticMethodExam{
public static void main(String args[]){
staticMethod sm1 = new staticMethod();
staticMethod sm2 = new staticMethod();
sm1.Method(10);
sm2.Method(20);
int grandTotal = staticMethod.getGrandTotal();  //정적 메소드 호출
System.out.println("sm1.total :"+sm1.total); 
System.out.println("sm2.total :"+sm2.total); 
System.out.println("총계 :"+grandTotal); 
}
}
프로그램 소스를 보자, 우선 staticMethod클래스의 객체를 각각 sm1,sm2를 만들고

Method 메소드의 파라미터에 sm1은 10, sm2는 20을 넣었다. 그럼 우선 total에는

인스턴스 필드이기 때문에 sm1에는 10이 sm2에는 20이 들어 갈 것이다. 그리고 

그 값들은 차례로 정적 필드인 grandTotal에 쌓인다, 그리고 정적 메소드 getGrandTotal()

에서 grandTotal을 리턴하기 때문에 프로그램상에서 이 정적 메소드를 호출하면 

grandTotal이 리턴 값으로온다 , 즉 30이 리턴된다. 결과는 이렇다.

sm1.total :10
sm2.total :20
총계 :30


기능적인 메소드 선언에 유용한 정적 메소드

특정 객체에 종속되지 않고 기능을 수행하는 메소드를 기능적인 메소드라 할 수 있다. 그런 메소드는

정적 메소드로 선언하는 것이 좋다.

정적 초기화 블록

정적 필드는 특정 객체에 속하지 않기 떄문에, 생성자에서 초기값을 대입하면 안된다. 그렇기에

정적 필드의 초기값을 필드 선언문에서 대입할 수 없을 때에는  

정적 초기화 블록( static initialization 또는 static initializer)을 사용하여야 한다.


public class staticBlock {
static int arr[];
static{
arr = new int[100];
for(int i = 0; i < 100; i++){
arr[i] = i;
}
}
}

이런식으로 정적 초기화 블록을 선언해두면 자바 가상 기계는 이 클래스가 사용되기전에 한 번

이 블록 안의 명령문을 실행 한다. 그렇기 때문에 위 arr을 사용하기전에 이미 0~99를 채워 놓는다.

class staticExam{
public static void main(String args[]){
System.out.println(staticBlock.arr[20]); 
System.out.println(staticBlock.arr[15]); 
System.out.println(staticBlock.arr[67]); 
}
}

이렇게 하면 이미 채워 놓기 때문에 바로 찍혀나온다.

둘 이상의 정적 초기화 블록을 갖는 클래스 

한 클래스 안에 둘 이상의  정적 초기화 블록을 선언 할 수도 있는데 그러면 클래스 내에 쓰여진 

순서대로 수행을 하게 된다.

public class staticinit {
static int arr1[];
static{
arr1 = new int[10];
for(int i = 0; i < 10; i++){
arr1[i] = i+1;
}
}
static int arr2[];
static{
arr2 = new int[10];
for(int i = 0; i < 10; i++){
arr2[i] = (i+1) * 10000;
}
}
static int arr3[];
static{
arr3 = new int[10];
for(int i = 0; i < 10; i++){
arr3[i] = arr1[i] + arr2[i];
}
}
}

이런식으로 세가지 정적 초기화 블록이 있다면 

class staticExam{
public static void main(String args[]){
for(int i = 0; i < 10; i++){
System.out.println(staticinit.arr3[i]); 
}
}
}
이것을 실행 시켰을 때

10001
20002
30003
40004
50005
60006
70007
80008
90009
100010

이렇게 나온다. 이유는 첫번째 arr1이 1부터 10까지를, 두번째 arr2이 1000부터 10000까지를,

세번째 arr3이 이 둘을 더한 것을 출력한다. 마지막 arr3만 찍었는데 저렇게 나왔다는 것은,

이미 arr1과 arr2 가 수행 되었을 거란 것이고, 이는 정적 초기화 블록이 여러개 있다면 위에서부터

쓰여진 순서대로 계산이 된다라는 것을 알 수 있다.



static이 붙으면 클래스 모든 곳에서 넣는 값이 다 들어가서 뭣도 모를 때 자주 썼지만, 아마 이놈이

메모리를 많이 차지하는 것으로 알고 있다.. 쉽게말해 남용하면 안되는 놈이다 , 그래서 static을

한동안 안썼다.. 안쓰면 좋은거니까. 하지만 일을 하다보니 static없이 하면 코드가 더러워지는

경우가 있다.. 결과적으로 필요할 때 딱 써야되는데 그 '필요할 때'만 쓰기가 참 어렵다. 










출판사 : 한빛미디어 , 저자 : 김윤명 님의 뇌를 자극하는 Java프로그래밍에서 공부한 내용입니다.

'JAVA' 카테고리의 다른 글

JAVA] String 원하는 만큼 잘라내기  (0) 2011.08.04
JAVA] 21. 클래스의 상속  (0) 2011.06.22
JAVA] 19. 메소드  (0) 2011.06.15
JAVA] 18. 필드  (0) 2011.06.14
자바에서의 인스턴스란?  (1) 2011.06.13
posted by 젊은쎄오
:
JAVA 2011. 6. 15. 00:26
오늘은 메소드에 관하여 알아보자, 클래스에 정의된 기능은 자바 클래스의 메소드로 선언해야 한다.

다음을 보자

[이름]
은행 계좌 클래스

[데이터]
계좌번호
예금주 이름
잔액

[기능]
예금한다   ----------  > 메소드로 선언되야 할 부분
인출한다


위 클래스의 기능 부분이 메소드로 선언되어야 할 부분이다.

메소드를 만들 때는 먼저 메소드에 들어갈 로직을 구상하고, 그 로직을 실행하는데 필요한 데이터가

무엇인지와 로직의 실행 결과를 어떤 타입의 데이터로 산출해야 하는지 파악을 해야한다.

메소드의 로직은 메소드 본체안에 써야하고 메소드가 필요로하는 데이터는 파라미터로 표현,

로직의 결과는 return 으로 돌려준다.


public class MethodTest {
String accountNo;
String name;
int balance;

MethodTest(String account, String name, int balance){
this.accountNo = account;
this.name = name;
this.balance = balance;
}
void deposit(int cash){
balance += cash;
}

int withdraw(int cash){
if(balance < cash)
return 0;
balance -= cash;
return cash;
}

}

이런식으로 예금하기와 인출하기의 매소드를 만들어 보았다.

예금하기는 파라미터로 실려온 예금하는 금액을 잔액에 + 시켜버린다.

인출하기는 뽑을 금액이 파라미터로 넘어온 후, 먼저 잔액보다 큰가를 확인한다. 

만약 크다면 0을 리턴하고 작다면 잔액 - 인출액을 한다음 결과값을 리턴한다.

이제 클래스에서 선언되있는 메소드를 호출하는 프로그램을 작성하자.

public class MethodExam {
public static void main(String args[]){
MethodTest obj1 = new MethodTest("111-111-111111", "김이박", 2000000);
MethodTest obj2 = new MethodTest("222-222-111111", "송정임", 12000000);
obj1.deposit(100000);
obj2.withdraw(150000);
printMethod(obj1);
printMethod(obj2);
}

private static void printMethod(MethodTest obj) {
System.out.println("계좌번호 : "+obj.accountNo);
System.out.println("예금주 : "+obj.name);
System.out.println("잔액 : "+obj.balance);
System.out.println();
}

}

위 부분이 obj1 에는 입금을, obj2엔 인출을 수행하고 파라미터에 각각 금액을 적어 넘겼다.

결과는

계좌번호 : 111-111-111111
예금주 : 김이박
잔액 : 2100000

계좌번호 : 222-222-111111
예금주 : 송정임
잔액 : 1185000

이렇게 잘 계산 되어 나온다. 

이렇듯 클래스 외부에서 매소드 호출 방법을 배워보았다. 하지만 클래스 내부에서도 메소드를

호출해야 할 경우가 있는데 보자.


public class Numbers {
int num[];
Numbers(int num[]){
this.num = num;
}
int getTotal(){
int total = 0;
for ( int i = 0; i < num.length; i++){
total += num[i];
}
return total;
}
}

이 메소드에 평균을 구하는 메소드를 추가하려한다. 앞에서는 클래스 객체.매소드명() 이렇게

호출했지만, 지금은 같은 클래스 안이기 때문에 따로 클래스 객체는 필요하지 않고 매소드의

리턴값을 담을 변수하나만 놓으면 된다

total   =  getTotal(); 

이렇게 하면 간단하게 그 메소드를 호출한다. 

public class Numbers {
int num[];
Numbers(int num[]){
this.num = num;
}
int getTotal(){
int total = 0;
for ( int i = 0; i < num.length; i++){
total += num[i];
}
return total;
}
int getAverage(){
int total;
total = getTotal();
int average = total / num.length;
return average;
}
}

이렇게 추가해준다. 그럼 저 메소드 호출부를 만나면 해당 메소드를 가서 메소드 전체를

한번 훑고 다시 돌아와 다음줄을 실행한다. 이걸 실행하는 프로그램을 짜보자.

public class MethodExam2 {
public static void main(String args[]){
int arr[] = {10,20,30,40,50,60,70,80,90,100};
Numbers obj = new Numbers(arr);
int total = obj.getTotal();
int average = obj.getAverage();
System.out.println("합계 : "+total);
System.out.println("평균 : "+average);
}
}

요렇게 짜주면, 일단 Numbers obj = new Numbers(arr); 이 구문으로 위의 배열이

num[] 배열에 쭈르륵 쌓인다. 이 후에  int total = obj.getTotal(); 를 호출하면 

 for ( int i = 0; i < num.length; i++){
total += num[i];
}

이 구문 때문에 num.length 즉, 배열의 갯수니 10부터 100까지 열개니까 num.length는 10을

의미하고 포문은 열 번 돈다는 이야기이다. 그러면서 들어오는 값을 차곡차곡 total변수에

합산한다.  그러고 int average = obj.getAverage(); 를 호출한다. 그럼

 int getAverage(){
int total;
total = getTotal();
int average = total / num.length;
return average;
}
total = getTotal(); 이번에 배운 클래스 안의 매소드 호출로 전부 합산된 550을 가져와 total에

넣는다 그리고 그걸 num.length로 나누니 550 / 10 이 되는 것이고 그 몫을 average에 담고

리턴한다. 그러고 그 리턴값들을 담은 변수를 출력하니

합계 : 550
평균 : 55

라고 찍히게 된다.

하지만 이런 연산을 하는 메소드는 얼마든지 익셉션이 발생할 수 있다 . 당장

int arr[] = new int[0];
Numbers obj = new Numbers(arr);
int total = obj.getTotal();
int average = obj.getAverage(); 

이렇게 배열갯수를 0을 주고 평균을 구하라 한다면, 말이 안되기 때문에 익셉션이 나며 

오류메시지를 뿌린다. 이러한 예외가 있을 수 있으므로 예외처리를 해주어야 한다.

public class MethodExam2 {
public static void main(String args[]){
int arr[] = new int[0];
Numbers obj = new Numbers(arr);
int total = obj.getTotal();
System.out.println("합계 : "+total);
try{
int average = obj.getAverage();
System.out.println("평균 : "+average);
}catch(java.lang.ArithmeticException e){
System.out.println("평균값을 계산하는 도중에 에러발생");
}
}
}
이렇게 예외처리를 했다면 오류없이

합계 : 0
평균값을 계산하는 도중에 에러발생
 
이렇게 뿌려준다. 코드에서는 얼마든지 문제가 일어날 수 있다. 그걸 완벽히 막아내면

좋겠지만 났을 때의 대처방안도 매우 중요하다..

매소드 오버로딩 

자바에서는 메소드 호출문에서 사용한 파라미터의 수, 타입, 순서와 메소드에 선언된

파라미터 변수의 수, 타입, 순서가 맞지 않으면 메소드를 호출할 수 없다. 이걸 이용하면

한 클래스에 같은 이름의 메소드를 파라미터를 다르게 여러개를 선언 할 수 있다는 소리고

이것을 메소드 오버로딩(overloading) 이라고 부른다. 

public class overloading {
String name;
int age;
float height, weight;
overloading(String name, int age, float height, float weight){
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}
void update(int age){
this.age = age;
}
void update(int age, float height){
this.age = age;
this.height = height;
}
void update(int age, float height,  float weight){
this.age = age;
this.height = height;
this.weight = weight;
}
}
이렇게 update 라는 메소드 이름이 세번이나 중복 되었지만 파라미터가 다르기 때문에

문제없이 코드 작성이 된다.  자바에서는 이렇게 메소드 구분에 사용되는 메소드 이름, 

파라미터 변수의 수, 타입, 순서를 묶어서 메소드 시그니쳐(signature, 서명) 라고 부른다. 

위 update 메소드의 시그니쳐는 update(int),update(int, float), update(int,float,float) 이다.

프로그램을 짜보면

 public class Exam {
public static void main(String args[]){
overloading obj = new overloading("동수", 24, 170.0f, 55.0f);
printMethod(obj);
obj.update(25, 175.0f, 57.0f);
printMethod(obj);
obj.update(26, 180.0f);
printMethod(obj);
obj.update(27);
printMethod(obj);
}

private static void printMethod(overloading obj) {
System.out.println("이름 : "+obj.name);
System.out.println("나이 : "+obj.age);
System.out.println("키 : "+obj.height);
System.out.println("몸무게 : "+obj.weight);
System.out.println();
}
}

이런식으로 각각 같은이름의 메소드를 호출한다.

이름 : 동수
나이 : 24
키 : 170.0
몸무게 : 55.0

이름 : 동수
나이 : 25
키 : 175.0
몸무게 : 57.0

이름 : 동수
나이 : 26
키 : 180.0
몸무게 : 57.0

이름 : 동수
나이 : 27
키 : 180.0
몸무게 : 57.0

그럼 이렇게 쭉쭉 갱신된다. 

매소드를 잘다뤄야 프로그램 그래도 어느정도 안다라고 생각한다 개인적으로..

이렇게 메소드를 이리저리 호출하는 것이 지금에서야 제대로 안게 음.. 부끄러우면서도

다행인거 같다. 100% 활용하도록 연습좀 해야겠다.. 







출판사 : 한빛미디어 , 저자 : 김윤명 님의 뇌를 자극하는 Java프로그래밍에서 공부한 내용입니다.


'JAVA' 카테고리의 다른 글

JAVA] 21. 클래스의 상속  (0) 2011.06.22
JAVA] 20. 클래스의 정적 구성 요소  (0) 2011.06.17
JAVA] 18. 필드  (0) 2011.06.14
자바에서의 인스턴스란?  (1) 2011.06.13
JAVA] 17. 생성자  (0) 2011.06.13
posted by 젊은쎄오
: