Android 2011. 7. 14. 23:18
 

간만에 포스팅을 합니다. 바쁜척하느라 매일 오긴오는데

와서 제 블로그를 제가 눈팅하는 그런..짓을 합니다 -_-; 



무튼, Activity와 Context 는 비슷해 보이면서도 다릅니다. 저도 아직 두 가지 명확하게 설명을 할

수준은 못되지만, 명확한 개념을 알고싶으시면 조금만 수고를 하셔서 검색을 하시면

다른 훌륭하신분들의 글이 많이 올라와 있습니다.

먼저 Activity 는 안드로이드 어플리케이션의 가장 기본적인 블록으로 전체적으로 한 화면 이라고

보시면 됩니다. 한 화면의 View와 UI 를 뿌리고 관리하며 터치 등 사용자의 입력을 감지합니다.

한 화면이기 때문에 다음 화면으로 넘어가면 거기서 새로운 액티비티가 생성되고 관리하게 됩니다.

반면 Context는 핵심 부품같은 존재로 여러 액티비티의 리소스를 접근하거나 공유할 수 있게 

해줍니다. 설명이 많이 부족하네요 이거 -_-.. 

현재 Activity와 Context를 얻어서 사용해야 할 때가 있습니다. 다이얼로그나 팝업등을 띄울 때인데요

팝업을 예로들면 어느 앱에 로그인을 하려는데 그 로그인창이 팝업창으로 되어 있다면 컴퓨터는

멍청해서 알아서 메인화면 위로 로그인창을 띄우지 못하고 코드상으로 꼭 메인화면 위에서 띄워라

라고 써줘야 합니다. 

popupview = View.inflate(getApplicationContext(), R.layout.sidepopup, null);

이게 그 예인데요 팝업뷰에 파라미터로 Context, int, ViewGroup 이 들어갑니다.

다른거는 넘어가고 Context를 보면 getApplicationContext() 이게 현재 화면의 context를

지정하는 것으로, 저 popupview는 이제 메인화면 위에 뜬다는 소리입니다. 메인화면의 

Context를 받았기 때문이죠.

안드로이드 입문하는 소스들을 보면 대부분 한 클래스에서 모든걸 끝내어 기능만 알아보고 넘어가는

식이 많은데, 이제 그보다 큰 것을 하다보면 위와같이 현재 화면, 또는 현재 클래스에서 모든

작업을 하기란 불가능합니다.

Activity를 예로들어보면 많이 보시는 간단한 Toast를 봐도

Toast.makeText(act,"와이파이에 접속중이 아닙니다.", Toast.LENGTH_LONG).show(); 


세개의 파라미터 중에 첫번째가 액티비티 입니다. 짧은 예제에는 여기에 대부분 this나 

클래스명.this 이런식으로 사용하시는데요. 이게 이 토스트가 뜰 화면을 지정하는 것입니다.

위에 예제의 경우 액티비티가 있는 클래스가 아닌 곳에서 띄우려니, 띄울곳에서 액티비티를 얻어

넘겨주어 그 액티비티를 받아 사용하는 것입니다. 그럼 넘겨준 액티비티에서 뜨겠죠? 


이와같이 넘기거나 사용할 때 현재 액티비티나 Context를 받아야합니다. 받는 방법은

Activity 는
Activity act;
                                                            act = 현재클래스명.this;
이고 

Context는 

Context mContext;
                           mContext =  getApplicationContext();
 
이런식으로 담아두고, 이 변수로 다른 클래스에 넘기기도하고 가져다 쓰기도 하고 그러시면 됩니다

솔직히 100% 아는 내용이 아니라 횡설수설했는데.. 암튼 도움이되셨길 바랍니다. 
posted by 젊은쎄오
:
Android 2011. 6. 27. 22:46
안드로이드를 하다보면 액티비티가 계속 쌓이는 경우가 있다. 이 경우는 시스템 적으로 아무래도

부담이되고, 물론 눈에 보일정도로 그런다기보다 계속 그렇게 쌓다보면 뒤로가기를 한참을 눌러야

밖으로 빠져나가게 되는 불상사가 생긴다.

이럴 경우 현재 액티비티나 현재액티비티가 아닌 다른 액티비티를 종료시켜서 액티비티를 줄이는

방법이있는데, 우선 현재 액티비티를 죽이는 방법은 간단하다.

어떠한 작업을 완료하고 액티비티를 종료하기를 원한다면 작업 완료 다음줄에

finish();

이것만 적어주면 된다. 이렇게 되면 저 함수를 만나는 즉시 현재 액티비티가 종료된다. 

하지만 A 액티비티에서 B액티비티를 갔는데 A액티비티를 죽이고 싶다면 이렇게 하면된다.

우선 A 클래스에 

public static Activity AActivity;

라고 스테틱으로 액티비티를 선언한다. 그리고 onCreate 안에 

AActivity = Aclass.this;

이렇게, 액티비티 객체에 현재 클래스를 담아준다. 그럼 이제 B클래스로가서

Aclass aActivity = (Aclass)Aclass.AActivity;

이렇게 aActivity 라는 객체를 만드는데 그 객체는 Aclass의 스테틱변수인 AActivity를

넣어 둔다는 의미이다 보면 복잡해 보이는데 글로 쓰면 이렇다 .

A클래스  A클래스객체  =  (A클래스)A클래스.A클래스에서 스태틱 액티비티 변수

이정도 순서이다. 헷갈리기 쉬울 것 같다. 

그 다음 아래에 이렇게 만든 객체를 피니시하면된다

aActivity.finish();

이렇게 써주면 B클래스에서 아까 앞에 A액티비티를 종료 시킬 수 있다.



 
posted by 젊은쎄오
:
Android 2011. 6. 25. 20:54
안드로이드뿐만아니라 작은 스마트폰에서 여러개를 나타내는 방법은 리스트만큼 좋은 것이

없을 것이다. 그만큼 자주쓰는 것이라, 스마트폰 쪽 개발을 한다면 리스트뷰를 안쓸수가없다.

이번 포스팅에는 리스트 사용방법의 개념을 알아보기로 한다. 

먼저 리스트는 기본 리스트가 있고 사용자가 모양이나 구성등을 이쁘게 꾸며서 만드는 

커스텀 리스트가 있다. 

기본 리스트 예제부터 보자

public class ListExamActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        ListView lv = (ListView)findViewById(R.id.list);
        
        ArrayList al = new ArrayList();
        al.add("어레이리스트에");
        al.add("add를 이용하여");
        al.add("리스트에 들어가는 ");
        al.add("값들을 써줍니다.");
        
        ArrayAdapter aa =
        	new ArrayAdapter(this,   android.R.layout.simple_list_item_1, al);
        
        lv.setAdapter(aa);
    }
}

먼저 리스트를 만드려면 세가지의 구성이 필요하다, 각 항목의 객체가 들어있는 ArrayList와

그것을 뿌릴 ListView가 두번째 그리고 ArrayList의 내용을 ListView에 붙여줄 연결고리

역할을 하는 ArrayAdapter 라는 것이 필요하다.

위에서 보면 일단 ArrayList<String> 에 값들을 넣어야 하는데 문자형을 넣기 때문에 String을

써 주었다. 그리고 ArrayList 객체인 al 에 add 매소드를 이용하여 문자들을 넣어준다.

저 add하나가 한 항목을 나타낸다고 보면 된다.  


그리고 ArrayAdapter<String> 를 생성하는데 문자열을 붙여줌으로 똑같이 String으로 써주고 

() 안에 세가지가 들어간다, 처음엔 어디다 뿌리는건지 Context , 그리고 리스트의 타입 , 마지막으로

리스트뷰에 실질적으로 붙일 어레이 리스트객체를 써준다. Context는 나도 개념적으로 부족하여 

이것이 뿌려질 화면 정도로 알고 있다. 현재는 현재 화면에 뿌려지기 떄문에 this라고 썼다. 

두번째는 리스트 타입인데 지금 쓴 android.R.layout.simple_list_item_1 이것은

리스트 한 칸에 기본적으로 한 줄로 나타낸 다는 의미이다. 

기본적으로 자주쓰는 몇개를 예로들면

simple_list_item_2   > 리스트 한 항목이 두 줄로 이루어 진다.

simple_list_item_checked    >  리스트 오른쪽으로 체크박스가 달린다

simple_list_item_single_choice    > 리스트 오른쪽으로 라디오버튼이 달린다

simple_list_item_multiple_choice     >  리스트 오른쪽으로 체크박스가 달리는데 중복 체크가 가능하다.


이정도가 있다. 

그 다음 리스트뷰 객체인 lv 에 setAdapter() 메소드를 쓰고 파라미터로 ArrayAdapter 객체인

aa를 넣어준다. 그럼 리스트뷰에 아답터가 리스트어레이 객체들을 붙여준다 그럼 화면에 

뿌려지게 되는 것이다. 



이렇게 붙게 된다.




 
posted by 젊은쎄오
:
IT Info/신기술 용어 2011. 6. 23. 16:48

객체지향프로그래밍에서, MVC란 사용자 인터페이스를 성공적이며 효과적으로 데이터 모형에 관련 시키기 위한 방법론 또는 설계 방식중 하나이다. MVC 방식은 자바SmalltalkC 및 C++ 등과 같은 프로그래밍 언어를 쓰는 개발 환경에서 널리 사용된다. MVC 형식은 목적 코드의 재사용에 유용한 것은 물론, 사용자 인터페이스와 응용프로그램 개발에 소요되는 시간을 현저하게 줄여주는 형식이라고 많은 개발자들이 평가하고 있다.

MVC 형식은 소프트웨어 개발에 사용될 세 가지 구성요소 또는 객체를 제안한다.

  • 모형 : 소프트웨어 응용과 그와 관련된 고급 클래스 내의 논리적 데이터 기반 구조를 표현. 이 목적 모형은 사용자 인터페이스에 관한 어떠한 정보도 가지고 있지 않다.
  • 뷰 : 사용자 인터페이스 내의 구성요소들을 표현하는 클래스들의 집합 (누름단추, 표시 상자 등과 같이 사용자가 화면상에서 보고 응답할 수 있는 모든 것들)
  • 제어기 : 모형과 뷰를 연결하고 있는 클래스들을 대표하며, 모형과 뷰 내의 클래스들 간에 통신하는데 사용됨  - 출처 http://www.terms.co.kr/MVC.htm


      음,, 클래스 구조 쪽 질문을 올렸다가 MVC라는 것을 공부해보길 권유하는 분이 있어서 

    한 번 검색하여 보았다. 아직 정확히 이해는 안가지만 객체지향언어에 가장 효율적인 관리

    또는 연동 등 을 정의해놓은 것 같다. 근데 이것이 이상적인 것인지 아님 대부분의 실무자가

    이대로 잡고 코딩을 하는지는 더 알아봐야겠다. 개념만 나와있지 실무자들이 쓰는 글은 아직

    못 봤다. 
posted by 젊은쎄오
:
IT Info/신기술 용어 2011. 6. 23. 10:46
N스크린은 TV나 PC, 태블릿PC, 스마트폰 등 다양한 기기에서 하나의 콘텐츠를 끊김없이 이용할 수 있게 해주는 서비스를 말한다. 사용자가 구입한 콘텐츠가 단말기가 아니라 서버에 저장되어 있기 때문에 언제 어디서나 다양한 단말기로 불러와 이용할 수 있다는 장점이 있다. 국내외 이동통신사들은 N스크린을 통해 사용자들이 자사 서비스를 이용하는 시간이 늘어날수록 영화, 드라마 등 콘텐츠를 구입할 가능성이 높아져 궁극적으로 콘텐츠 매출을 늘릴 수 있기 때문에 미래 핵심서비스로 인지해 시장 선점을 위해 경쟁하고 있다. - 출처 네이버 백과사전


N스크린의  N은 흔히 수학에서 다수를 표현할 때 '1부터 N개 까지 '  이 때 사용하는 N의 

의미이다. 한 컨텐츠를 가지고 예를 들어 동영상이 하나있다면 그것을 폰에서도보고 TV에서도

보고 아이패드에서도보고 컴퓨터에서도 볼 수 있는 것이다. 처음엔 N스크린의 개념을 별도의

컨버팅없이 여러 기기에서 동영상을 재생할 수 있는 편리한 것이구나 했는데, 단순히

컨버팅 과정없이 컨텐츠를 다수의 기기가 공유 할 수 있다가 아니라 그 데이터를 넣어 두는

공간이 더 큰 의미였다. 출시를 앞둔 Icloud 가 그 예 이고  한국의 대표적인 N스크린엔

먼저 LG의 U+Box 가 있다.  가입을 하여 쉽게 서버상에 파일들을 올려놓고 PC에서건 폰에서건

컨버팅없이 받아서 올려놨던 영상을 볼 수 있다.

두번째로는 SK  ' 호핀' 이 있다. 호핀도 비슷한 개념이지만 이는 SK측에서 서비스 할 영상

컨텐츠를 올려놓고 그것을 볼 수 만 있다. 현재는 5000여 편의 영상이 있고 올 해 안에

10000 여 편의 영상컨텐츠를 올려 놓을 거라고 한다. 그리고 호핀을 지원하는 기기도 늘릴

계획이다.

마지막으로 KT의 U cloud이다. U Box와 마찬가지로 개인의 사진, 영상, 정보등을 서버에 

올려놓을 수 있으며 여러 기기로 사용 할 수 있다. KT는 앱도 N스크린 화 를 추진하고 있다는데

쉽게 말해 안드로이드앱이건 아이폰앱이건 구분없이 쓰게 된다는 이야기이다. 좋은 소식같다. 




 
posted by 젊은쎄오
:
IT Info/신기술 용어 2011. 6. 23. 10:24

SNS란 온라인에서 친구들을 만들어 주는 서비스이다, 한국에는 대표적으로 싸이월드가

시작을 하여 현재에는 트위터, 페이스북, 미투데이 등등 여러종류가 있고 각각 특징을

모아보면, 쉽게 친구를 사귈수 있고 친구가 하는 말들, 생각들을 공유 할 수 있다.

나는 페이스 북 밖에 안하여 페이스북을 예로들면 담벼락이라는 공간이 있고 거기다

오늘 있었던 일이나 뭐 하고싶은 말들을 쓰면 나에게 친구 추가되있는 모든이에게

그 내용이 노출된다. 또한 내 친구에게 추가된 친구중에 중복되는 사람이 있으면 내가

알수도 있는 사람일지도 모른다는 것으로 인지를 하고 친구 추천에 뜨기도 한다.

싸이월드 때만해도 Web에 한정되어있었지만 스마트폰이 생기며

SNS는 힘을 받기 시작하고, 실시간으로 내가 있는 공간을 사진 또는 동영상으로 찍어

올릴 수 도 있게 되었다.  일반 블로그나 카페가 그룹의 목적으로 폐쇠적이었다면 SNS는

개인적인 면이 강하며 정보공유가아닌 자기 있는 그대로의 느낌이내 생각을 전달하는 것이

주가 되었다. 

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 젊은쎄오
:
JAVA 2011. 6. 14. 00:44
이번에는 객체의 데이터 필드의 선언방법과 사용방법을 알아본다.

[이름]

[데이터]
반지름  --------------> 필드로 선언되야 할 부분

[기능]
면적을 구한다


이렇게 정의된 클래스를 소스로 나타내 보자.

public class Circle {
double radius;                         -------- > 필드 
Circle(double radius){
this.radius = radius;         -------- > 생성자
}
double getArea(){                    -------- > 매소드
double area;
area = radius * radius * 3.14;
return area;
}
}

이렇게 나뉘어 진다. 이런식으로 필드를 선언한다. 필드 뿐만아니라 다른 종류의 

변수들도 있다. 생성자의 radius라는 파라미터 변수, getArea 메소드안에 area라는 

로컬 변수가 있다. 이렇듯 변수는 선언 위치에 따라 변수 이름도 다르지만 사용할 수 

있는 범위도 서로 다르다.

필드의 사용 범위

파라미터 변수는 해당 생성자나 매소드 안에서만 사용 가능 하고 로컬변수는 선언 된

위치부터 매소드의 끝 또는 선언된 블록의 끝까지 사용할 수 있지만 필드는 같은

클래스 내에서라면 순서에 상관없이 생성자나 매소드 안에서 얼마든지 사용 할 수있다.

필드는 클래스 외부에서도 사용 할 수있는데 다음을 보자.

public class Cirtest {
public static void main(String args[]){
Circle obj = new Circle(0.0);
obj.radius = 5.0;
double area = obj.getArea();
System.out.println(obj.radius);
System.out.println(area);
}
}
이런식으로 필드를 선언한 클래스 외부의 다른 클래스에서도 사용가능하다.

하지만 이런식으로 외부에서 접근하는 것을 막을 수도있다.

바로 접근 제어 수식어(access control modifier) 인 private 을 쓰면된다.

필드를 선언 할 때 private double radius;  라고 선언하면 외부에서 접근을 할 수 없다.

자바에서는 이런식으로 객체의 구성요소를 외부로부터 감추는 정보 은닉(infomation hiding) 

기술을 제공하고 있는데 이 기술은 객체들이 복잡하게 얽히는 것을 방지한다.











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



 

'JAVA' 카테고리의 다른 글

JAVA] 20. 클래스의 정적 구성 요소  (0) 2011.06.17
JAVA] 19. 메소드  (0) 2011.06.15
자바에서의 인스턴스란?  (1) 2011.06.13
JAVA] 17. 생성자  (0) 2011.06.13
JAVA] 16. 객체와 클래스  (0) 2011.06.09
posted by 젊은쎄오
: