'대학생 졸업하기 전 레벨/Java'에 해당되는 글 11건

Java Advanced Imaging (JAI)

 

import javax.media.jai.*;



이 API를 이용하여 이미지 파일을 변경하거나 저장할 수 있다.

JAI 다운로드 페이지 : https://jai.dev.java.net/binary-builds.html

API : http://download.java.net/media/jai/javadoc/1.1.3/jai-apidocs/index.html


jai-1_1_3-lib.zip 파일 다운로드

압축 해제후 jar 파일들을 C:\j2sdk1.4.2_12\jre\lib\ext 로 복사

출처 : Tong - Popsicle님의 Java통

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

자바 소스를 컴파일한 class 파일을 디컴파일할 수 있는 툴은 여러가지가 있다.

개인적으론 Jad 라는 프로그램과 Decafe Pro 라는 프로그램을 즐겨 쓰는 편인데...

Decafe Pro 의 장점이라면 GUI 방식의 윈도우 지원 툴이라는 것이고

Jad 의 장점이라면 다양한 플랫폼을 지원하고

폴더내에 있는 모든 class 파일을 동시에 디컴파일 할 수 있다는 것이다.


여기서는 Jad의 간단한 사용법을 적어보겠다.

첨부된 파일은 Jad v1.5.8g 버전으로

class 파일들이 있는 폴더에 넣고


한 파일 디컴파일시에는 :

jad -sjava sample.class



폴더내 모든 class 파일 디컴파일시에는 :

jad -sjava *.class


하면 휘릭 하고 java 파일들이 생성된다.


Jad Homepage : http://www.kpdus.com/jad.html

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

자바에서 Random값을 구하는 방법으로는 크게 다음 두가지가 있다.

  1) java.lang.math.Random

  2) java.util.Random


이때 첫번째 방법은 seed값을 변환할 수 없기 때문에 고르게 분포하지 않는다.

그래서 seed값을 변환해 고른 난수추출을 할 수 있는 방법이 필요한데 이때,

두번째 방법을 사용한다. 아래의 예제는 아주 간단히 정규분포(Normal / Gaussian)에서

난수를 추출하는 방법을 보여주고 있다.

---------------------------------------------------------------------------------------

import java.util.Random;


public class RandomNumber {

    public static void main(String[] args) {
        Random rand = new Random(System.currentTimeMillis()); // seed값을 배정하여 생성
        System.out.println(Math.abs(rand.nextGaussian()));         // 난수값 출력

    }

}

----------------------------------------------------------------------------------------


아래의 예제는 다양한 범위에서 난수를 추출하는 방법을 보여주고 있다.

---------------------------------------------------------------------------------------

import java.util.Random;


public class RandomNumber {

    public static void main(String[] args) {
        Random rand = new Random(System.currentTimeMillis()); // seed값을 배정하여 생성
        System.out.println(Math.abs(rand.nextInt(10)));                //0~10사이의 난수값생성
        System.out.println(Math.abs(rand.nextInt(9)+1));               //1~10사이의 난수값생성
        System.out.println(Math.abs(rand.nextInt(990)+10));           //10-100사이의 난수값생성

    }

}

----------------------------------------------------------------------------------------

nextInt([숫자])를 사용할경우 0~[숫자]까지의 범위에서 난수가 추출되므로 예로 0~9까지 난수를

추출한후 1을 더해주면 1~10까지의 난수가 추출됨.



** 참고사항 : 컴퓨터상에서 난수추출과 Seed값 배정법(출처 : 네이버 지식검색 자료모음)


컴퓨터는 생각을 할 수 없습니다. 그래서 무작위로 수를 뽑는 것 역시 불가능합니다.
단, 엄청나게 긴 수열을 만들어 내어서 "난수"로 보이는 숫자를 만들어 낼 수 있는데
그것이 유사 난수(Pseudo random)이라고 합니다.
단, 이 수열의 집합은 Seed라는 지정번호에 좌우되는데(Seed가 같을 경우, random을

해도 같은 수열만 나온단 말이 되겠죠) Seed의 숫자에 따라서 생성되는 수열이 달라집니다.

프로그래머들은 Seed 번호를 대개 현재의 시각에 대응시킵니다. 그래서 한번의 Random

호출시마다 다른 난수가 생성됩니다. 즉 명령을 실행하라고 인간이 엔터키나 클릭을 한

시점의 시간을 1000분의 1초를 단위로 추출해서 그 수를 기본으로 난수를 만들기 때문에

언제나 실행 할때마다 전혀 다른 난수가 나오게 되는것입니다.


최종적으로는, seed를 and or xor 등등을 여러번 섞고 왼쪽 오른쪽으로 돌렸다가 비트단위로

반정도로 잘라서 뒤섞고 하는방식으로 만듭니다.

출처 : http://blog.naver.com/echris7/140012818525
이거 C언어랑 달라서.. (C언어는 int 리턴.. Java는 double 리턴..).. 쩝..

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

Tag Java

Java Press (http://www.gihyo.co.jp/magazines/javapress) 라는 일본의 Java전문 서적(2003 2월판)에서 발췌한 Java performance tips입니다.

 

그중 Java 일반적사항에 관련하여 7, String 관련2, Collection관련 8, IO관련2,

등 총 4개 분야 19여개의 Tips에 대해 설명하겠습니다.

 

1. 일반적사항 관련 Tips

 

    ① 쓸데없이 Cast를 남발하면 바람직하지 않음.

   

     Loop구조에서 쓸데없이 cast를 남발하면 performance를 현저히 저하시킵니다.

 

      ) 쓸데없이 cast를 남발한 바람직하지 않은 코드예

 

      for(int i=0; i<list.size(); i++)

      {

        if ( ((String)list.get(i)).indexOf('a') ! =-1)  {

        } else if(((String)list.get(i)).indexOf('b') ! =-1)  {

        } else if(((String)list.get(i)).indexOf('c') ! =-1)  {

        } else if(((String)list.get(i)).indexOf('d') ! =-1)  {

        } ...

      }

 

      ) 쓸데없는 cast를 제거한 좋은 코드예

 

      for (int i=0; i<list.size(); i++)

      {

        String value = (String)list.get(i);

        if(value.indexOf('a') ! = -1) {

        } else if ((value.indexOf('b') != -1){

        } else if ((value.indexOf('c') != -1){

        } else if ((value.indexOf('d') != -1){

        } ...

      }

 

    ② 쓸데없이 동기화를 행하면 바람직하지 않음

   

        同期化(Synchronized)은 높은 cost입니다. 필요가 없을 시에는 사용하지 마십시요.

 

 

    ③ 쓸데없는 인스턴스생성은 바람직하지 않음

 

        인스턴스수가 많지 않은 경우에는 별 문제가 되지 않겠지만, 많은 인스턴스를 생성

하는 경우에는 performance를 현저히 저하 시키므로 주의하십시요.

 

        ) String 인스턴스를 2번생성한 바람직 하지 않은 코드예

 

          String value = new String("문자열");

 

        ) 개량 후 코드예

 

          String value = "문자열";

 

 

    ④ 필요이상으로 Wrapper클래스를 사용하면 바람직하지 않음

 

        Wrapper클래스(Integer, Boolean )을 클래스멤버로 사용하는 경우 인스턴스생성

이 필요하게 되므로, 기본적으로 Primitive형을 사용하는 편이 performance를 높

입니다.

 

        ) Wrapper클래스를 사용한 코드예

 

        public class Person {

 

          private Integer id;

          private Boolean isValid;

        };

 

        ) primitive형으로 치환한 코드예

 

        public class Person {

 

          private int id;

          private boolean isValid;

        };  

 

        또한 Wrapper클래스에는 없지만 java.math.BigDecimal 클래스는 Double 클래스

보다 정확한 부동소수연산이 가능하지만 performance를 저하시키므로 유의바랍니

.

 

    primitive형의 default값을 이용

 

int boolean형등의 primitive형은 선언시 default값이 초기화 됩니다. 이것을 이용하면 초기화처리를 생략할 수 있습니다. 덧붙여 말하면 int형은 0, float 0.0, boolean형은 false로 선언시에 초기화 됩니다.

 

        ) primitive형의 초기화처리를 행한 코드예

 

        public class Person {

 

          private int id;

          private boolean isValid;

 

          public Person() {

 

            id = 0;

            isValid = false;

          }

        }

 

        ) primitive형의 default값을 이용한 코드예

 

        public class Person {

 

            private int id;

            private boolean isValid;

 

            public Person() {

 

            }

          }

 

 

    ⑥ 문자열을 숫자형으로 변환하는 방법

 

        문자열을 숫자형으로 변환시에 각 Wrapper클래스(Integer,Double ) static

소드인 parseXXX()를 이용합니다.

        valueOf()를 경유해서 XXXValue()를 실행하면 한번의 인스턴스를 생성하게 되어

불필요한 cost를 들게 합니다.

 

        ) valueOf()를 이용하여 문자열을 숫자형으로 변환한 코드예

 

          double doubleValue = Double.valueOf("1234.56").doubleValue();

          int intValue = Integer.valueOf("123456").intValue();

 

        ) 개량한 코드예

 

          double doubleValue = Double.parseDouble("1234.56");

          int intValue = Integer.parseInt("123456");

 

 

    ⑦ 필요이상으로 System.gc()를 사용하면 바람직하지 않음

     

        필요이상으로 System.gc()를 이용하면 프로그램실행 performance가 저하됩니다.

2. String 관련 Tips

 

    ① 문자열 연결방법

        +연산자를 이용하여 문자열을 연결하게 되면 심하게 performance가 저하됩니다.

        StringBuffer클래스를 사용하면 performance가 향상됩니다.

   

        ) + 연산자에 의한 문자열연결 코드예

 

          String result = "";         

for (int i=0; i  {

result + =i;

          }

        ) StringBuffer클래스에 의한 문자열연결 코드예

 

          StringBuffer buf = new StringBuffer();

          for(int i=0; i

            buf.append(i);

          }

          String result = buf.toString();

 

        더욱이, 연결후의 문자열의 길이를 알고 있을 경우,  StringBuffer클래스 생성시에

적당한 초기값을 주면 더욱더 performance가 향상됩니다.

        StringBuffer클래스는 용량이 부족하게 되면 내부적으로 버퍼사이즈가 자동으로 변

경되나 연결후의 사이즈를  알고 있는 경우에는 초기값으로 사이즈를 주면 그러한

처리과정을 생략할 수 있습니다.

 

      ) StringBuffer buf = new StringBuffer(length);

 

       ) 문자열연결에 관한 performance 측정

                                                                                         

 

연결수: 1000

연결수 : 500

+연산자

250(ms)

7500(ms)

StringBuffer

15(ms)

20(ms)

StringBuffer(초기값有)

2(ms)

10(ms)

          CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1

                                                                               

    StringTokenizer클래스

      

문자열을 자를 때,StringTokenizer클래스를 이용하는 것이 편하기는 하지만 문자열

이 고정되어 있는 경우에는 독자적인 Tokenizer를 사용하는것이 효율적입니다.

 

StringTokenizer클래스가 token을 반복할때, 매번 자를문자가 변경되어 있는지를

체크하기 때문입니다.

 

       ) StringTokenizer클래스를 취하는 코드예

 

         String word = "aaa,bbb,ccc,ddd,eee,fff";

 

         StringTokenizer token = new StringTokenizer(word,",");

 

         List list = new ArrayList();

        

         while(token.hasMoreTokens()) {

           list.add(token.nextToken());

         }

       

       ) 자를문자를 ,로 고정한후 token을 추출한 코드예

 

          String word = "aaa,bbb,ccc,ddd,eee,fff";

         

          List list = new ArrayList();

 

          int now=0;

          int next=0;

 

          while ( (next = word.indexOf(",",now)) > 0 )

          {

            list.add(word.substring(now,next));

            now = next + 1;

          }

       

 

        또한 StringTokenizer클래스에는 hasMoreElements() hasMoreTokens() 두개의

메소드가 있는데,  hasMoreElements()가 내부적으로 hasMoreTokens()를 호출하

므로 통상적으로 hasMoreTokens()를 이용 하도록 합니다.

 

        참고) J2SE 1.4부터 새로운 메소드가 추가된것이 있는데, SringTokenizer 클래스의

token 추출과 같은 기능의 메소드로 java.lang.String 클래스의 split()메소드를 소

개합니다.

 

          String word = "aaa,bbb,ccc,ddd,eee,fff";

          String [] result = word.split(",");

3. Collection관련 Tips

   

    ① 배열의 이용

       

데이타의 개수나 사이즈가 변동하는 경우에만 Collection계통의 클라스를 사용하며,

그외에는 배열을 사용합니다.

      

    J2SE1.2이상에서의 Collection이용

 

JDK1.1까지는 Vector클래스나 Hashtable클래스가 편리했으나, 이러한 클래스는 메소드가 동기화(synchronized)

되어 있습니다. 따라서 동기화가 필요없는 경우에는 비효율적입니다.

J2SE1.2이상에서는 메소드가 동기화되어있지 않은 ArrayList클라스나 HashMap

래스를 이용합니다.

       Vector클래스는 ArrayList Hashtable HashMap클래스로 바꿔이용합니다.

 

        ) Collection클래스 이용예

          

           Vector vector = new Vector();

           Hashtable table = new Hashtable();

 

        ) J2SE1.2이상 Collection클래스 이용예

         

           List list = new ArrayList();

           Map  map  = new HashMap();

 

        또한, J2SE1.2이상에서 Collection의 동기화가 필요한 경우에는

 

           List list = Collection.synchronizedList(new ArrayList(..));

       

        위와 같이 사용합니다.           

   

    Collection size 초기화

 

Collection default 사이즈로 만들면, 필요시 자동적으로 사이즈가 확장되나 명확히 예측이 가능한 경우에는 사이즈를 초기화 하는 편이 훨씬 효율적입니다.

 

        ) 사이즈를 지정하지 않고 Collection을 생성한 코드예

 

          List list = new ArrayList();

          HashMap map = new HashMap();

 

        ) 사이즈를 지정한 Collection 생성 코드예

           

          List list = new ArrayList(num);

          HashMap map = new HashMap(num);

 

 

    Iterator클래스보다 빠른 요소검사

 

       Collection 사이즈를 명확히 알 경우에는 Iterator클래스의 next()와 비교하여,

       Iterator클래스의 hasNext()에 의한 요소종료 체크가 필요없으며 내부처리가 간단한

       List클래스의 get()메소드를 추천합니다.

 

       ) Iterator클래스의  next()에 의한 요소조사

 

         Iterator iterator = array.iterator();

         while (iterator.hasNext())

         {

           Object object = iterator.next();

         }

 

       ) List클래스의 get()에 의한 요소조사

 

          int size =array.size();

          for (int i=0; i

          {

            Object object = array.get(i);

          }

         

    ⑤ 요소삽입/삭제시 주의점

 

        List도중에 요소를 추가/삭제할 경우에 내부적으로 배열의 copy가 행해집니다.

따라서 요소의 수가 많으면 많을 수록 copy하는 요소수도 많아져 결과적

으로 performance의 저하를 초래합니다.

내부적처리로써 [ (전체사이즈) - (삽입/삭제대상요소의 index)] 만큼의 요소가 copy되므로 아래의 예를 참조바랍니다.

 

        ) List의 맨앞에 요소를 추가/삭제하는 경우 --  속도가 느림.

 

         list.add(0, new Object());

         list.remove(0);

 

        ) List의 맨 뒤에 요소를 추가/삭제하는 경우 -- 속도가 빠름.

 

         list.add(new Object());

         list.remove(list.size() - 1);

 

 

    List요소 전체삭제

 

List요소를 전체삭제 할때, 통상 쓰는 clear()을 이용하지말고, 새롭게 List를 생성(초기화)하는 편이 효율적입니다. 왜냐하면, clear()는 내부적으로 보유하고 있는 배열의 전체요소에 null을 셋팅함으로써 전체삭제를 실현하기 때문입니다.

 

        ) clear()에 의한 요소 전체삭제

 

          List list = new ArrayList();

         

          for(int i=0; i< num; i++) {

            list.add(new Integer(i));

          }

 

          list.clear();

 

        ) List재작성에 의한 요소 전체삭제

 

          List list = new ArrayList();

 

          for(int i=0; i< num; i++) {

            list.add(new Integer(i));

          }

 

          list = new ArrayList();

 

    ⑦ 배열요소 copy방법

   

루프를 돌며 배열요소를 하나씩 copy할 경우에는 System.arraycopy(Object src,int srcPos,Object dest,int destPos,int length)를 이용합니다.

        메소드의 인자는 아래와 같습니다.

 

          src - the source array.

          srcPos - starting position in the source array.

          dest - the destination array.

          destPos - starting position in the destination data.

          length - the number of array elements to be copied.

       

        ) 루프를 돌며 배열소소를 copy하는 예

 

           int[] buf = new int[num];

           int[] copy = new int[num];

 

           for (int i=0; i

           {

              copy[i] = buf[i];

           }

       

        ) System.arraycopy()에 의한 신속한 copy

 

           int[] buf = new int[num];

           int[] copy = new int[num];

 

           System.arraycopy(buf,0, copy,0, num);

 

     List에 보존되어 있는 object 요소를 배열에 넣는 방법

 

List클래스의 toArray()를 이용하여 List에 보존되어 있는 Object요소를 배열에 넣습니다.

 

          ) 루프에 의한 object요소 copy

             

            int size = list.size();

            Integer[] result = new Integer[size];

 

            for (int i=0; i

            {

              result[i] = (Integer) list.get(i);

            }

 

          ) toArray()에 의한 신속한 copy

 

            int size = list.size();

            Integer[] result = new Integer[size];

 

            list.toArray(result);

4. IO관련 Tips

 

     ① 통상적으로 Stream계의 클래스를 사용함

 

        java.io패키지에서 문자데이터 입출력시에는 Reader/Writer 클래스를

        바이트단위 데이터 입출력시에는 InputStream/OutputStream 을 이용합니다.

        다만, 아스키캐릭터의 경우에는 1문자가 1바이트이므로

InputStream/OutputStream 클래스를 이용할 수 있습니다.

       

        100K 정도의 영문자로 이루어져 있는 텍스트파일을 가지고 예를 들겠습니다.

 

        ) Reader계 클래스을 이용한 파일 입출력 예

 

            FileReader in = new FileReader("test.txt");

            int buf;

 

            while ( buf = in.read() != -1)

            {

              .......

            }

            in.close();

 

        ) InputStream계 클래스를 이용한 파일 입출력 예

 

            FileInputStream in = new FileInputStream("test.txt");

            int buf;

 

            while ( buf = in.read() != -1)

            {

              .......

            }

 

            in.close();

 

          위의 2가지 예를 비교한 performance 비교표는 아래와 같습니다.

             

사용클래스

처리시간(ms)

FileReader

18000

FileInputStream

800

CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1

 

InputStream계 클래스를 이용한 파일 입출력이 월등히 빠른 처리속도를 보임을 알 수 있습니다.

            

     Buffering을 이용

 

        ) Buffering을 한 Reader계 클래스을 이용한 파일 입출력 예

 

            FileReader in = new FileReader("test.txt");

            BufferedReader bin = new BufferedReader(in);

            int buf;

 

            while ( buf = bin.read() != -1)

            {

              .......

            }

 

            bin.close();

 

        ) Buffering을 한 InputStream계 클래스를 이용한 파일 입출력 예

 

            FileInputStream in = new FileInputStream("test.txt");

            BufferedInputStream bin = new BufferedInputStream(in);

            int buf;

 

            while ( buf = bin.read() != -1)

            {

              .......

            }

            bin.close();

 

위의 2가지 예를 비교한 performance 비교표는 아래와 같습니다.

 

사용클래스

처리시간(ms)

BufferedReader

150

BufferedInutStream

80

 

CPU : Pentium 300MHz/ Memory :128M / OS : Linux/ J2SE:1.3.1



[펌] .. http://blog.empas.com/poolpiri3/1798925 줄리피님 블로그

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

Tag Java

Source file 구조

  1. 자바 파일의 이름은 반드시 .java 확장자로 끝나야 한다.
  2. source안에 public인 top level class가 있다면 파일이름은 반드시 해당 class의 이름으로 되어야 한다.
    • public인 class가 2개 이상 하나의 파일에 존재 할 수 없으므로 이런 경우는 따로 만들어야 한다.
    • public인 class가 하나도 없다면 파일 이름은 어떤 class의 이름을 사용하여도 상관없다
    • 만약 public인 class가 존재하고 타 클래스가 main method를 가지고 있다면 public인 class의 이름으로 파일을 생성하여 main method를 가진 클래스를 호출해야한다.
  3.  source 파일의 구조는 문장에 따라서 순서가 정해져 있다.
    1. package 선언문
    2. import 문
    3. class 정의문

keyword

  1. 자바의 키워드는 모두 소문자이다.
    • abstract   do   implements   private   throw
      boolean   double   import   protected   throws
      break   else   instanceof   public   transient
      byte   extends   int   return   true
      case   false   interface   short   try
      catch   final   long   static   void
      char   finally   native   super   volatile
      class   float   new   switch   while
      continue   for   null   synchronized
      default   if   package   this
  2. C에서 많이 쓰이던 sizeof operator가 없다.
  3. NULL, TRUE, FALSE와 같이 에서 keyword는 아니지만 #define 문으로 정의해서 사용하던 단어들도 소문자이다.
  4. goto, const는 실제 구현은 되어있지 않으나 keyword로 등록되어 있다.

identifier

  1. java identifier는 class name, method name, variable name, label등에 사용된다.
  2. 첫번째 문저는 숫자가 아닌 단어로 시작해야 한다.
    • 특수 문자도 첫번째 문자로 올 수 있다.
  3. 자바 keyword는 identifier로 사용할 수 없다.
    • keyword를 포함하는 단어는 사용할 수 있다.
  4. 공백을  포함할 수 없다.
  5. unicode를 지원하기 때문에 한글도 사용은 가능하다.
  6. maximum length에 대한  제한이 없다.

coding convention

  1. class & interface
    • 첫번째 문자 : 대문자
    • 단어와 단어의 연결 : 뒷 단어가 대문자로 시작
    • 명사
  2. method & variable
    • 첫번째 문자 : 소문자
    • 단어와 단어의 연결 : 뒷 단어가 대문자로 시작
    • method는 동사, variable는 명사
  3. constant
    • Primitive Data Type constant
      • 모두 대문자
      • 단어와 단어의 연결 : _(underscore)로 연결
    • Reference Data Type constant
      • 대소문자 다같이 사용

Data type

  1. Primitive Data Type
    • boolean, char, byte, short, int, long, float, double등 8개가 있다.
      • byte : 8bit (-128[-2^7]~127[2^7-1])
      • short : 16bit ( -2^15 ~ 2^15-1 )
      • int : 32bit (-2^31 ~ 2^31-1 )
      • long : 64bit (-2^63 ~ 2^63-1 )
      • float : 32bit 크기의 실수
      • double : 64bit 크기의 실수
      • boolean : true, false
      • char
        1. single quotes에 둘러쌓인 문자로 표현됨 (ex: 'e', 'g', '1'... )
        2. '\n', '\r', '\t', \u88ab' 형식 지원 (마지막은 유니코드 표현)
    • 실제 값을 갖는다.
    • 위의 Data Type은 이에 대한 정보가 Compiler에 내장되어 있어 선언과 함께 정의된 만큼의 메모리를 생성하게 된다.
  2. Reference Data Type
    • 값이 저장되어 있는 메모리의 주소를 갖는다.
    • Type : Array, class, interface
    • 그때 그때마다의 정의에 따라 메모리 할당에 필요한 정보가 달라지기 때문에 선언과 생성이 분리되어 있다.
      • new operator를 사용하여 heap으로 부터 할당해서 사용할 수 있다
import java.util.*;

class TestVar {

    public static void main(String[] args) {

        String msg;   //라인 1
        msg = new String("sample 1"); //라인 2

    }

}

      • 1번은 선언을 한 경우이며 이 경우는 메모리가 할당되지 않는다. 2의 라인에서 메모리가 할당된다.
      • 위의 선언은 new를 생략하고 간단히  "sample 1"이라고 해도 생성이 된다. 내부적으로는 new 연산이 적용이 된다.
    • array의 경우 [] 기로를 통해 해당 변수가 arrayType이라는 것을 알려주어야 하며, array는 특정 타입의 element들을 연속적으로 갖는 것이기 때문에 반드기 그 element의 type이 무엇인지 알려주어야 한다. 
int intArray[];

String msgArray[], str;

      • []안에 절대 size 정보를 주면 안된다. 선언은 단지 어떤 타입의 array라는 것을 알려주는 것이므로 메모리가 할당되지 않는다.
      • String의 변수를 갖는 msgArray는 배열로 선언되었으나 str은 단지 String class type 변수이다.
      • array에 실질적인 메모리를 할당하기 위해서는 new 연산자가 사용되게 되며 이 때 size도 지정을 한다.
int intArray[] = new int[100]

double [] dArray, otherArray;
dArray = new double[100];
otherArray = new double[200]

      • []가 변수 선언시 앞에 있으면 그 뒤에 나오는 변수들은 모두 배열이다.
      • 선언 후 size 지정을 통한 생성에 대한 명시를 하지않고 바로 변수를 할당 할 수 있다. 이 경우 배열의 갯수는 할당된 수 만큼 생성된다.
int intArray[] = {100, 200, 300};
    • 다차원 배열의 경우 2차 이상의 배열들은 각각 dynamic하게 size를 가질 수 있다.
    • 초기값
      • byte : 0
      • short : 0
      • int : 0
      • long : 0L
      • float : 0.0f
      • double : 0.0d
      • char : '\u0000'
      • boolean : false
      • Reference Data Type : null

멤버변수와 지역변수

  • 멤버변수
    1. 해당 class 내에 method와 동등한 위치에 선언된 변수
    2. 해당 class 내 어디서든 참조 가능하고 한 class 안에서는 global하게 값이 유지된다.
    3. 단. static으로 선언된 method에서는 non static인 멤버 변수를 access 할 수 없다.
    4. 멤버 변수의 경우 선언된 후 별도로 초기값이 지정되지 않으면 선언한 에따라 default 값을 초기값으로 갖게 된다.
  • 지역변수
    1. 해당 Class의 method 내에 선연된 변수
    2. 해당 method가 호출되었을 때 stack에 생성되었다가 수행이 완료되면 없어진다.
    3. 지역변수는 초기값이 자동적으로 주어지지 않는다. 따라서 초기화를 하지 않고 호출하면 지역 변수는 전부 error로 처리합니다.

위와 같은 차이가 나는 이유는 {}로 싸여진 변수의 범위가 다르기 때문이다.

{} 내에서 선언된 지역 변수는 {} 지역을 벗어나면 자동으로 삭제된다.


매개변수 전달방식

매개변수란?

  1. method를 호출할 때 메소드 내로 값을 전달하기 위한 매개로 선언된 변수.
  2. 무제한으로 매개변수를 선언 할 수 있다.
  3. 매개 변수의 데이터 형을 맞추지 않으면 method는 호출할 수 없다.
  • Primitive Data Type의 변수를 매개변수로 이용하는 경우
    1. call by value방식으로 전달이 된다.
    2. 변수에 할당된 메모리의 주소를 전달하는 것이 아니라 이와 똑같은 정보의 메모리 복사본이 새롭게 만들어져 호출되는 쪽에서 사용하도록 하는 것
  • Reference Data Type의 변수를 매개변수로 이용하는 경우
    1. call by ref 방식으로 전달이 된다. (주소값이 복사되므로 실제적인 메모리에 대한 정보가 전달이 됨.)

연산자

연산자의 우선순위

saparatop

. [] () ; ,

...


R to L

++ -- + - ~ !(data type)

L to R

* / %

L to R

+ -

L to R

<< >> >>>

L to R

< > <= >= instanceof

L to R

== !=

L to R

&

L to R

^

L to R

|

L to R

&&

L to R

||

R to L 

?;

R to L 

= *= /= %= += -= <<=
>>= >>>= &= ^= ┃=


a++, ++a

아래와 같은 예제가 있다.

int a = 1;

int b, c;
b = ++a;
c = a++;


위의 경우

b는 2,  a에도 2

c는 2, a는 3이 저장이 된다.

++이 앞에 있으면 그 뒤의 변수에 대해 우선 연산이 이루어진다.

++이 뒤에 있으면 그 앞부분의 연산이 먼저 이루어진다.


연산식

  • int type보다 크기가 작은 숫자 type들은 연산식을 처리할 때 int로 Type Conversion을 하고 연산식을 처리한다.

따라서 아래의 경우는 compile error가 발생한다.

byte b1 = 64;

byte b2 = 4;
byte b3 = b1 * b2;

이유는 b1 * b2의 결과가 int값의 결과값을 리턴하게 되는데 이 결과값을 byte type인 b3에 대입하려고 하기 때문이다.

이런경우 type Conversion을 해주어야 한다.

byte b1 = 64;

byte b2 = 4;
byte b3 = byte(b1 * b2);

그러나 위의 경우는 b1과 b2의 곱이 byte의 값을 over했기 때문에 올바른 값이 b3에 들어가지 않게 된다.

  • + 연산자는, 만약 한 operand만 Stirng이고 나머지가 String이 아닌 모든 경우(Primitive Data Type, Reference Data Type 모두), String이 아닌 다른 쪽이 무조건 String으로 conversion 된다.

instanceof 연산자

Reference Data Type에만 적용해서 쓸 수 있는 연산자로 그 object의 run-time type을 알아낼 수 있게 해준다.


&, |, &&, || 연산자

두 쌍의 연산자는 각각 같은 역할을 한다.

다만 &&와 ||는 해당 연산자의 왼쪽 조건이 부합되지 않는 조건이면 연산을 끝낸다.

따라서 일반적으로는 &&와 ||의 연산이 좀더 효율적이다.

Type Conversion

서로 다른 Data Type을 사용한 연산식은 연산을 실행하기 전, 둘 중 하나를 다른 하나의 Data Type에 맞게 전환한다.

이는 컴파일 때 뿐만이 아니라 run-time일 때에도 올바르게 되었는지 check를 한다.

강제 변환(Explicit Type Conversion)과 수동 변환 (Implicit Type Conversion)이 있다.

강제 변환은 변환될 type을 지정해주어 형을 변환하는 것이다.


수동변환

  1. Primitive  Data Type은 컴파일할 때에 이미 Type Conversion이 일어난다.
  2. int type보다 크기가 작은 숫자 type들은 연산식을 처리 할 때 int로 Type Conversion을 하고 연산식을 처리한다.
  3. Primitive Data Type 중 boolean type을 제외한 모든 다른 type (char, byte, short, int, long, float, double)들은 boolean type으로의 전환이 불가능, (자바에서는 1=true라는 공식이 성립하지 않는다.)
  4. 서로 다른 Data Type에 있어 Type Conversion은 보다 더 넓은 Data Type으로 전환이 자동으로 일어난다.
  5. Primitive Data Type 간에 있어 자신보다 좁은 type으로의 Implicit Type Conversion은 절대 일어나지 않는다.
  6. 위와 같은 크기 관계이지만 char와 short타입은 둘다 16bit로 크기는 같으나 char type은 unsigned인 관계로, 둘 사이는 Implicit Type Conversion이 일어나지 않는다.

Class의 Type Conversion

Class 간의 Type Conversion이 일어나기 위해서는 상위 클래스 중에 공통인 클래스가 존재해야 한다.

derived(sub) class의 type으로 선언된 변수가 base class의 type으로 생성된 object를 참조(포인트) 하도록 하는 문장은 일단 컴파일시 무사히 통과가 된다.

그러나 run-time일 때 유요한 Type Conversion인지 확인할 때에는 경우에 따라 다르다.

이를 통과하기 위한 조건은 base class type의 변수가 전환될 type의 class나 전환될 type의 class로부터 파생된 class의 instance를 정확히 갖고 있어야 한다.

instanceof 연산자

해당 클래스가 해당 object 타입인지 결과를 true, false로 리턴해준다.

[object] instanceof [object type]

Java에서의 modifier들

선언을 통해 identifier를 compiler에게 알려주는 역할을 할 때 단순히 type 정보뿐만 아니라 그 이외에 좀 더 다양한 정보를 modfier를 통해 알려 줄 수 있다.


자바에서 제공하는 modifier는 크게 access modifier와 그 외 modifier로 나뉘어진다.

  • access modifier
    • public, private, friendly, protected
  • 그 외 modifier
    • final, static, abstract, native, synchronized, volatile, transient

modifier는 선언문에 쓰여지는데, 반드시 Data Type 앞 쪽에 와야 한다.

 

access modifier

주로 method나 member variables 선언시 사용하는 modifier


class 내부

같은 package의 다른 class

다른 package의 상속 class

다른 package의 다른 class

public

O

O

O

O

protected

O

O

O

X

(friendly)

O

O

X

X

private

O

X

X

X


가장 헷갈리기 쉬운 것이 friendly와 private의 관계인데 friendly는 modifier의 명명자가 아닌 modifier를 지정하지 않았을 경우 기본적으로 적용되는 범위 지정을 뜻한다.

friendly와 private 둘다 다른 package의 상속된 class에서는 사용할 수 없으나

friendly는 같은 package내의 상속된 class는 사용할 수 있다.

그 외의 modifier들

  • final
    1. class : class를 상속하는 것은 불가능
    2. method : 해당 method가 존재하는 class를 상속받은 class 내에 해당 method의 verride 불가
    3. member variable : 상수 선언
  • abstract
    • abstract로 정의 해야하는경우
      • class가 한 개 이상의 abstract 메소드를 갖고 있을 때
      • abstract class로부터 파생된 base class에 있는 abstract 메소드를 override로 구현하지 않았을 때
      • class가 interface로부터 파생되었는데 interface에 있는 전체 메소드를 구현하지 않았을 때
      • 해당 class를 상속받은 sub class에서는 객체를 생성할 수 있지만 기존의 class는 객체를 생성하지 않으려는 경우
  • static
    1. member variable
      • class의 일반 멤버 변수는 new 연산자를 통해 instance를 만들 때 마다 (즉, object를 생성할 때 마다) 각각 메모리가 할당되어진다.
      • 그러나 class의 어떤 멤버 변수가 static으로 선언되어 있다면 그 멤버 변수는 정의된 class가 load되는 시점에 이미 유일한 메모리를 할당받게 된다.
      • 즉, 하나의 class에 대해 new 연산자를 이용하여 아무리 많은 instance를 생성한다고 해도 static으로 선언된 멤버 변수는 new 연산을 수행하기 전에 이미 메모리를 할당 받았으므로 static으로 선언된 멤버 변수에 대해 object 생성시 추가적인 메모리 할당은 없는 것이다.
      • 이러한 변수를 class 변수라고 한다.
      • 이렇게 static으로 정의된  멤버 변수는, instance와 상관없이 만들어지고 유지되기 때문에 자바에서 class wide global 변수로서의 역할을 한다.
    2. method
      • 해당 메소드가 각 클래스마다 새로운 메소드 호출이 아닌 동일한 메소드가 호출되게 되어진다.
      • 따라서 static으로 선언된 method는 instance를 생성하지 않아도 사용이 가능하다.
      • 이와 같은 특성상 주의해야 할 사항이 있다.
        1. static으로 선언된 메소드에서는 non static인 멤버 변수를 access할 수 없다. 일반적인 멤버 변수는 new 연산자에 의해 instance가 생성될 때에야 비로소 메모리에 할당 받기 때문이다.
        2. this란 class안에서 자신의 reference를 의미하는 keyword이다. 따라서 this는 생성된 instance가 없으면 존재할 수 없으므로 static으로 선언된 method에서는 this라는 keyword를 사용할 수 없다.
        3. static으로 선언된 메소드를 파생된 class에서 override를 통해 일반 메소드로 바꿀 수 없다.
    3. static initializer block
      • block  '{' 와 '}' 앞에 static modifier를 붙인 형태를 말한다.
      • class 내에 위치하며 method 외에 위치한다.
      • method처럼 호출될 수 있는 형태가 아니며 class가 load되는 시점에 한번 실행되게 되어있다. 즉 instance 생성과 무관하다.
      • static initializer block이 여러 개 존재한다면 class가 load되는 시점에 나타나는 순서대로 차례로 실행이 된다.
      • 실행 순서
        1. 멤버 변수
        2. static initializer block
        3. main method 호출
          1. main method에서 자신의 instance 생성시 또는 외부 class에서 해당 class의 instance 생성시 constructor 호출
    4. native modifier
      • method를 선언할 때 사용
      • native로 선언된 메소드는 abstract처럼 선언부만 가지며 이 메소드의 body 부분은 통상 자바가 아닌 다른 언어(주로 C언어)로 만들어진다.
      • 이러한 개념은 platform dependent한 코드 부분을 자바와 연결시키는 방법으로 많이 이용되고 있다.
    5. transient modifier
      •  Java에는 serialize를 하게 해주는 ObjectInputStream과 ObjectOutputStream 같은 특별한 stream이 있다. 만약 어떤 메소드가 serializable 하다면, ObjectOutputStream이 제공하고 있는 writeObject 메소드를 이용하여 이 class의 object 상태를 persistent한 위치에 object 단위로 저장할 수 있다. transient modifier는 이러한 과정중에 serializable한 변수에서 제외 시키는 기능을 한다.

class Account implements Serializable {

    String name;

    int balance;

    transient String passwd;

}

      • 위와 같은 경우 name과 balance 변수는 멤버변수로서 그 변수가 직렬화(serializable) 과정에 저장이 되지만 passwd는 저장이 되지 않는다.


class

method

member variable

local variable

public

O

O

O

X

protected

X

O

O

X

(friendly)

O

O

O

X

priavte

X

O

O

X

final

O

O

O

O

abstract

O

O

X

X

static

X

O

O

X

native

X

O

X

X

transient

X

X

O

X

synchronized

X

O

X

X

modifier 사용대상


조건 분기문

자바에서는 if구문을 사용할 때 true = 1, false = 0으로 인식을 하지 않으므로 true와 false에 대한 결과값에 대해 명시를 해주어야 한다. 따라서 다음과 같은 구문은 오류가 발생한다.

int count = 0;

if (count) {

    System.out.println("true state");

}

위와 같은 구문은 아래와 같이 수정해주어야 한다.

int count = 0;

if (count != 0) {

    System.out.println("true state");

}


switch 구문은 다음과 같다.

switch (expression) {

    case value1 : 문장(들);

        break;

    case value2 : 문장(들);

        break;

    case valueN : 문장(들);

        break;

    default : 문장(들);

        break;

}


for 구문은 다음과 같다.

for (init_expr; boolean expr; alter_expr)

    문장 or block (중괄호{}로 감싸인 여러 문장들);


whlie 구문은 다음과 같다.

while (boolean_exp)

    문장 or block (중괄호{}로 감싸인 여러 문장들);

do whlie 구문은 다음과 같다.

do 문장 or block (중괄호{}로 감싸인 여러 문장들);

    while (boolean_exp);   

while 문과 do while문의 차이는 while 문은 boolean_exp의 조건에 따라 한번도 실행되지 않을 수 있는 반면 do while문은 무조건 실행이 된 후 조건을 비교하게 된다는 점이다.


이외의 구문으로

break문은 현재 위치에서 가장 가까운 block을 벗어나기 위해 사용되는 문장이며

continnue 문은 자신이 포함된 반복문의 시작위치로 jump하여 새롭게 조건을 비교하도록 하고자 할 때 사용된다.


예외처리

자바에서는 프로그래밍에서 발생할 수 있는 문제를 두가지로 구분하여 처리를 한다.

  1. 화면에 잘못된 메세지를 보내주소 실행을 멈출 만큼 프로그램 자체에 문제가 있는 것은 error로 분류.
    • Error class에서 파생된 class 형태로 error를 처리. (OutOfMemoryError, StackOverflowError 등)
    • error에 대한 처리코드가 명확하게 정의되어 있지 않아도 컴파일 할 때 문제삼지 않음
  2. 문제가 발생될 것이 예측되어 프로그램 과정 중에 잡아낼 수 있는 문제들은 exception(예외)로 간주
    • exception또한 class로 다루어진다.
    • 자바의 모든 예외 class들은 java.lang package의 Exception class에서 파생되며 java.lang package가 자동으로 import되며 Exception class도 자동 import 된다.

Exception의 종류

  1. RuntimeException class에서 파생된 예외들
    • 주로 프로그래머의 부주의로 발생되는 예외 (array bound를 벗어나거나 null pointer를 사용하거나 등등...)
  2. Exception class에서 파생된 예외들
    • 주로 사용자가 잘못 사용할 수도 있기 때문에 발생하는 예외 (파일명을 잘못 입력하는 식의 오류)

Exception의 처리

  1. try-catch구문에 의해 처리되거나
  2. 발생된 메소드의 밖으로 처리를 던질수 있다.
    • 예외 처리를 던진다는 것은 곧 인위적 예외 발생도 가능하다는 말이다.
    • 또한 던질 대상이 될 예외 클래스를 지정할 수 있으므로 사용자 지정 예외 처리 클래스도 존재한다는 말이다.

try, catch, finally 구문

try {

    구문;

}

catch (ExceptionType1 e) {

    복구 routine1;

}

catch (ExceptionType2 e) {

    복구 routine2;

}

catch (ExceptionType3 e) {

    복구 routine3;

}

finally {

    구문;

}

    • try 블럭 안쪽의 구문을 실행하는 동안 아무런 예외(exception)이 발생하지 않았다면, catch 블럭은 실행되지 않는다.
    • try 블럭 안쪽의 구문에서 예외가 발생되면 catch문 중 해당 발생된 예외를 잡는 블럭 안으로 흐름이 이동되며 해당 catch 블럭의 구문이 수행이 된 후 다시 흐름이 외부로 이동된다.
    • 예외가 catch에서 중복 해당하는 경우 가장 순서가 위쪽에 나열된 catch 블럭을 수행하며 더이상의 catch 블럭의 처리는 없다. (하나의 예외에 대해서 수행되는 catch 블럭은 하나이다.)
    • finally 블럭은 생략가능하며, 존재하는 경우 예외 발생 여부와 상관없이 무조건 실행이 된다.
      • 혹 발생하지 않는 경우가 있을 수는 있다.
        1. try 블럭을 실행시키는 thread가 dead상태가 되었을 때
        2. try 블럭에서 System.exit()가 호출되어 프로그램이 종료될 때
        3. CPU 전원이 끊겼을 때
        4. finally 블럭이 끝나기 전에 안에서 또 다른 예외가 발생했을 때

인위적으로 예외 발생하기.

위에서 언급한 방법은 프로그램 실행중 try 블럭 내에서 예외가 발생시 catch로 예외 상황에 대한 처리를 맡기는 것인데 객체를 생성한 대상 클래스 내의 메소드에서 예외가 발생한 경우 해당 예외에 대한 처리를 해당 객체를 생성한 클래스와 같은 상위 클래스로 던질 수 있다.

이때 사용하는 구문이 throws, throw 이다.

throw는 인위적으로 예외를 발생시키는 keyword이며 만약 throw문이 try문 안에서 사용되었다면 당연히 이에 매칭되는 catch 문에서 throw에 의해 던져진 예외를 잡을 것이다.

그러나 호출된 메소드에서 try, catch구문의 사용없이 throw를 통해 예외를 던졌다면 그 순간 수행이 중단되며, 어디선가 이 예외를 잡아(catch) 처리하는 루틴, 즉 try, catch문이 있는 곳까지 (호출관계가 누적된 stack의 정보를 참조하여) 예외는 상위로 전달이 될 것이다.

이 경우 throws는 컴파일러에게 "이 메소드에서는 이런 예외가 throw를 이용하여 던져질 수 있다."는 것을 알려주는 keyword로, 메소드의 선언부에 사용된다.

구문은 다음과 같이 사용한다.


class {

    method() throws 예외이름 {

        throw new 예외이름();

    }

}

위와 같이 사용하면 해당 예외이름의 예외를 상위 클래스에서 찾아서 처리를 하게 되며 상위 클래스에도 해당 예외처리가 없다면 그 상위로 다시 던지게 된다.

이 경우 만약 중간에 있는 메소드 내에서 실행중 오류가 발생되고 상위로 해당 오류에 대한 exception처리를 던지는 경우 상위 메소드의 exception처리 후 finally가 실행되며 중간에 있는 메소드의 오류 발생 이후의 연산은 처리가 되지 않는다.

객체지향의 개념

객체가 가지는 구성요소는 2가지가 있다.

  1. 상태 (state, attribute)
    • 객체가 가지고 있는 속성 또는 특성. 객체의 정적인 부분
  2. 행동 (behavior, action)
    • 객체가 가지고 있는 기능 또는 행동, 객체의 동적인 부분

이러한 객체를 소프트웨어적으로 표현하기 위한 방법 중의 하나가 객체지향방법이며, 이 객체지향방법에서 나타내는 몇가지 특징들을 살펴보면 다음과 같다.

  • 캡슐화 (Encapsulation)
    • 상태 정보를 저장하고 있는 변수와 상태를 변경하거나 서비스를 수행하는 메소드를 하나의 소프트웨어 묶음으로 캡슐화한다.
      캡슐화는 소프트웨어의 개발자에게 높은 모듈성(modulatiry)과 정보은닉(information hiding) 등 두가지 이득을 제공해 준다.
    • 모듈성이 높아지면 다른 객체의 내용 변경과 연관이 적어져서 재사용성과 유지보수성을 높일 수 있다.
    • 이러한 캡슐화된 부분은 접근 권한을 어떻게 부여하느냐에 따라서 다른 객체가 접근할 수 있는지를 결정하게 된다.
  • 다형성 (Polymorphism)
    • 하나의 객체가 여러 형태로 나타날 수 있거나 여러개의 class가 같은 메세지에 대해서 각자의 방법으로 작용함을 의미한다.
      즉, 같은 이름을 갖는 여러가지 형태가 존재한다는 것이다.
    • 자바에서는 연산자 overloading이 없으며 메소드 overloading과 메소드 overriding을 제공한다.
    • 자바에서는 아직 형태가 결정되지 않은 interface를 두고 이 interface를 상속받아 다른 형태가 나타나도록 하고 있다.
  • 상속 (Inheritance)
    • 하나의 class로 캡슐화된 정보가 다른 class에서도 사용되어야 한다면 새롭게 정의할 class는 기존의 class에 포함된 정보와 중복된다.
      이렇게 중복되는 정보는 새롭게 정의하는 class에서 기존의 정의된 class에 포함된 정보를 이용함으로써 그 정보를 가지게 되는데 이것을 상속이라 한다.
    • 즉 상속은 새롭게 정의할 class에서 이미 존재하는 class의 속성을 그대로 가질 수 있으며 이를 바탕으로 필요한 속성만 추가하여 정의하는 방법이다.
      이 때 새로 정의되는 class를 sub class, 기존의 클래스를 super class라고 한다.

class의 개념

class란 어떤 특정 종류의 모든 객체들에 대해 일반적으로 적용할 수 있는 변수와 메소드를 정의하고 있는 소프트웨어적인 설계도 (blueprint) 또는 프로토타입 (prototype)이라 할 수 있다.

다시 말해서, 실세계에 존재하는 객체들이 가질 수 있는 상태와 행동들에 대해 소프트웨어적으로 추상화 (abstraction) 해 놓은 것이 class 이다.

객체가 갖는 상태를 변수로 정의하고, 행동을 메소드로 정의할 수 있다.

그리고 이를 하나의 묶음으로 캡술화 하기 위해 "class { }"와 같이 정의할 수 있다.

이렇게 정의된 class르르 실제 객체로 생성할 수 있고, 객체를 선언하는 방법은 기본 데이터 형에 대한 변수를 선언하는 것과 같다.

다시 말해서 class형에 대한 변수를 선언한다고 생각할 수 있다.

자바에서 객체생성은 다음과 같다.

class이름 객체이름 = new class이름();

또는


class이름 객체이름;

객체이름 = new class이름();

자바에서 class에 대한 객체 (인스턴스)를 선언하고 생성하기 위해

  1. class에 대한 변수를 선언함과 동시에 생성하는 방법
  2. class에 대한 변수를 선언하고 나중에 필요할 때 객체 (인스턴스)를 생성하는 방법

두가지 방법이 있다.


자바에서는 이러한 class에 대한 변수를 참조형 변수라 하고, 참조형은 반드시 new 연산자를 이용하여 메모리 공간을 할당해 주어야 한다.

자바에서 말하는 class란 object를 만들어내기 위한 틀이다.

class는 element의 집합을 정의(선언)한 것이고, 이러한 정의에 근거하여 메모리를 할당받은 것이 object이다. 틀이 아니고 틀에 의해 만들어진 실체가 object인 것이다.


보통 class를 표현하는 명사나 형용사(attribute)는 멤버 변수로, 동사(behavior)는 메소드로 class 내에 표현이 된다.


class들 간의 관계

  1. 상속의 관계 ("is a" 관계)
    • 상속의 관계인 두 class에 있어, sub class의 object를 생성하면 extends 된 super class의 object도 함께 생성되는 것이다.
  2. 포함의 관계 ("has a" 관계)
    • 포함의 관계인 경우 포함을 하고 있는 클래스의 객체가 생성이 된다고 하더라도 이에 포함된 class의 object가 만들어지는 것은 아니다.
    • 포함의 관계에서는 상위 클래스가 호출시 포함을 시킬 클래스의 object를 생성하는 형식으로 객체 내부에 포함되는 객체를 생성해준다.

this와 super

this는 object 안에서 자신을 참조할 때 사용

super는 상위 class의 object를 참조할 때 사용


위의 두 keyword는 생성된  object 내에서 사용되는 것이기 때문에 static으로 선언된 메소드에서는 사용될 수 없다.

  1. this는 객체 자신에 대한 참조값을 가지고 super는 객체를 상속해준 super class 타입의 객체에 대한 참조값을 가진다.
  2. 메소드 내에서만 사용된다.
  3. 매개변수와 객체 자신이 가지고 있는 변수의 이름이 같을 경우 또는 객체 자신의 변수 이름과 객체의 superclass로부터 상속받아 가진 변수의 이름이 같을 때, 이를 구분하기 위해 자신이 가지고 있는 변수앞에 this나 super를 사용한다.
  4. 객체 자신이나 super class 타입의 객체에 대한 참조값을 ㅡ메소드에 전달하거나 리턴해주기 위해 사용하기도 한다.
  5. this나 super를 사용함으로써, 모호하지 않고 좀더 명확한 프로그램을 작성할 수 있다.

package 선언

  1. class들을 하나의 묶음(그룹) 단위로 구성한다.
  2. class들을 묶음 단위로 제공하여, 필요할 때만 사용할 수 있게 한다.
  3. class 이름의 혼란을 막아서 충돌을 방지한다.
  4. package 이름과 함께 class 이름을 사용함으로써 class를 효율적으로 관리할 수 있다.
  5. class를 관련이 있는 것끼리 묶어놓음으로써, 필요한 class의 식별이 용이하게 한다.
  6. package 단위의 접근 권한을 지정할 수 있고, 이를 통하여 class만 있는 경우보다 더욱 다양한 접근 권한을 제어할 수 있다.
  7. 하나의 class는 하나의 package에 속해야 한다.

자바표준 패키지 : 자바 API

자바는 J2SDK에서 정의된 많은 연관된 class들을 package로 묶어 제공하여, 필요에 따라 사용자가 import하여 사용할 수 있다.

이러한 미리 제공된 class package들을 자바 API (Java Application Programming Interface)라 한다.

자주 사용하는 자바 API Package는 다음과 같다.

  • java.applet
    • Java Applet Package. 애플릿 제작 및 브라우저와 애플릿의 상호작용 등을 제공하는 Applet class와 interface를 포함하고 있다.
  • java.awt
    • Java Abstract Windowing Toolkit Package. 그래픽 사용자 인터페이스의 제작과 관리에 필요한 모든 class와 interface를 포함하고 있다.
  • java.awt.event
    • Java AWT Event Package. 이벤트 처리를 해주는 class와 interface를 포함하고 있다.
  • java.io
    • Java Input/Output Package. 데이터를 입력받고 출력할 수 있도록 하는 class를 포함하고 있다.
  • java.lang
    • Java Language Package. 이 package는 특별히 지정하지 않아도 자동으로 import된다. 자바 프로그램들이 기본적이니 언어차원에서 필요로 하는 class와 interface를 포함하고 있다.
  • java.sql
    • Java Structured Query Language Package. 프로그램이 데이터베이스와 정보를 교환하기 위한 class와 interface를 포함하고 있다.
  • java.util
    • Java Utilities Package. 날짜/시간 조작, 난수 발생, 문자열의 토큰화 등과 관련된 각종 유틸리티 class와 interface를 포함하고 있다.

Method overloading

Method overloading은 매개변수의 type이나 개수를 다르게 하여, method 이름이 같은 또다른 메소드를 정의할 수 있는 개념이다.

실제로 method 이름이란 프로그래머에게 보여지는 것이고, 내부적으로는 package명, class명, 매개변수 type, 매개변수 개수 등의 정보들이 method를 구별짓는데 영향을 주게 되어있다.

따라서 엄밀히 말하면 단순히 이름이 똑같다고 똑같은 함수는 아닌 것이다.

하지만 return type이나 modifier의 종류, exception 선언등과 같은 것들은 method를 구별짓는데 아무 영향도 줄 수 없기에, 다른 것은 다 똑같으며 이것들이 달라진다는 것은 overloading라고 할 수 없다.


method overloading의 규칙은 다음과 같다.

  1. overloading이 된 메소드를 호출할 때 넘겨주는 매개변수 값에 의해 widen promotion이 일어난다.
  2. return type, access modifier, exception 선언은 overloading에 전혀 영향을 미치지 않는다.

Method overriding

파생된 class는 이미 super (base) class가 가지고 있는 method들을 상속받아서 가지고 있게 된다.

이러한 상황에서, super (base) class에 정의된 method와 동일한 이름의 method를 파생된 class에서 재정의할 수 있게 하는 것이 바로 메소드 overriding이다.


이 때 재정의되는 method는 (overloading과는 달리) return type과 매개변수 갯수, type들의 선언부를 완전히 똑같이 만들어야만 한다.

이 개념은 super class에서 정의해놓은 method의 body(구현) 부분으르 파생된 class에서 다시 정의하여 사용하겠다는 것이다. 즉, super class 코드를 바탕으로 새로운 기능을 추가하거나, 수정할 수 있게 해주는 것이다.


method overriding의 규칙은 다음과 같다.

  1. access modifier는 파생된 class에서 access 범위가 넓어지는 쪽으로는 변경이 가능하다. 하지만 좁혀지게는 재정의 할 수 없다.
    • private < (friendly) < protected < public
  2. 더 많은 예외(exception)을 던질 수 없다. 즉 줄이거나 같게만 가능하다.

Constructor (생성자)

생성자는 이미 method 이름이 정해져 있는 method(class 명과 동일)이며, 다른 method처럼 class의 object가 만들어진 후 필요에 따라 언제든지 호출할 수 있는 것이 아니라, object가 만들어지는 순간 딱 한번만 수행되는 method이다.

주로 object 멤버 변수들의 초기화에 관련된 작업을 수행한다.


constructor를 선언하지 않은 경우 default constructor가 수행이 되며 이 default constructor는 아무런 동작을 하지 않는다.


constructor overriding

만약 constructor가 선언이 되어있고 해당 constructor의 매개변수와 호출한 object의 매개변수의 type이나 개수가 다른 경우 error가 발생된다.

이런 경우 constructor도 overloading이 가능하므로 this()로 다른 constructor를 호출하는 것이 가능하다. 이에 대한 예제는 아래와 같다.

class Employee {

    String name;

    float salary;


    Employee(String name, float f) { //constructor

        this.name = name;

        this.salary = f;

    }

    Employee() { //constructor

        this("unknown", 0.0f);

    }

    //...

}

위와 같이 Employee class를 정의한 경우

 Employee someone = new Employee();

와 같은 문장에 의해

 Employee("unknown", 0.0f);

가 호출이 된다. 이 때, this()는 항상 첫번째 문장으로 불려져야 한다.


부모 클래스의 constructor 호출

파생된 object가 생성될 때 base class의 object도 같이 생성이 된다. 이러한 작업에 사용되는 것이 super()이다.

super는 원래 참조형 상수이지만 constructor를 호출하는 메소드처럼 사용할 수 있다.

파생된 object가 생성될 때, 파생된 class의 constructor에서 특별한 지정이 없었다면, base class의 object를 생성하기 위한 base class의 default constructor가 호출되어진다.

이 때에도 상위 클래스의 constructor의 호출에 대한 언급이 없다면 기본적으로 상위클래스의 default constructor(매개 변수가 없는 constructor)를 호출하게 되므로 해당 constructor가 있는지, 또는 원하는 상위 클래스의 constructor를 호출하였는지에 대한 확인이 필요하다.

이때 상위 constructor를 호출할 때 사용하는 것이 super(); 이다.

member 변수의 초기화 순서

new 연산자에 의해 어떤 class의 object가 만들어 질 때

  1. object 크기 만큼 memory가 할당된다.
  2. 할당되면서 멤버변수들에게 초기값을 주지 않았을 때 갖는 default 값이 대입된다.
    • 만약 이 object가 파생된 class에 대한 것이었다면, base class의 object도 만들어지며 위 1, 2번과 같은 진행을 거친 후, base class 부터 다음과 같은 방식으로 초기화가 진행이 된다.
      • 맴버 변수를 선언하면서 지정한 초기값이 있을 경우 이 값이 대입된다.
      • 지정된 constructor에 의해 초기화가 발생된다.
  3. 멤버 변수를 선언하면서 지정한 초기값이 있을 경우 이 값이 대입된다.
  4. 지정된 constructor에 의해 초기화가 발생된다.

즉, 최종적으로는 constructor에 의해 초기값이 영향을 받게 된다.

Inheritance (상속)

모든 객체지향 기반의 환경에서는 class를 기반으로 하는 프로그래밍이 이루어지며 각 class간의 관계는 상속과 포함으로 이루어진다고 하였다.


전혀 새로운 독립적인 class를 무조건 만들어내기보다는 기존에 존재하는 class 중 상속("is a") 관계를 갖는 class를 찾아서, 그것을 바탕으로 기본속성은 상속받고 새로운 기능만 파생된 class에 추가해서 넣는다면, 보다 효율적으로 system을 구축할 수 있다.

즉, 상속은 객체지향에서 주장하는 code의 재사용성을 제공해준다.

자바의 class들은 run-time에 동적으로 binding 되기 때문에 (base class와 derived class가 다른 파일에 저장되어 있을 경우) bass class에 새로운 멤버 변수나 메소드를 추가하거나 기존 코드를 변경시킨다 해도, 이미 컴파일 되어 있던 파생 class를 다시 컴파일 시키지 않아도 된다. (왜냐하면 run-time에 파생된 class들이 메모리를 할당받을 때 변경된 base class도 메모리를 할당받게 되므로 변경된 정보를 그대로 상속받을 수 있는 것이다.)

이것은 maintenance와 reliability라는 측면에서도 커다란 개선 효과를 가져다 준다.


자바에서 상속을 명시하는 keyword는 'extends' 이다.

자바는 single inheritance (단일 상속) 만을 허용한다.

Polymorphism (다형성)

같은 class type의 object가 동일한 이름의 method를 호출했음에도 불구하고, (상속과 overriding된 method로 인해) 경우에 따라 서로 다른 기능의 method가 동작되는 것을 다형성이라 한다.


이에 관련이 있는 것이 바로 binding 시점인데

  • C++, Java와 같은 객체 지향 언어의 경우 run-time binding이 발생
  • C의 경우 compile time binding이 발생

위와 같은 시점의 차이가 있다.

만약 아래와 같은 선언이 있다고 하자.

A test = new B();

test.method();

C의 경우 compile 단계에서 binding이 일어나므로 선언된 type인 A라는 type으로 메모리가 할당이 되어 A에 존재하는 method()가 호출이 된다.

그러나 C++, Java의 경우 run-time 단계에서 binding이 일어나므로 선언은 A로 되어 있어도 new로 정의된 정보에 대하여 메모리 할당이 발생이 되어 B에 존재하는 method()가 호출이 된다.


결국 종속된 class을 new를 통해 지정해 주게 되면 해당 class의 method가 호출이 되어 다형성이 이루어지게 된다.


다형성은 method에 대해 동작되므로 멤버변수에 발생하지는 않는다.

결국 instance 변수와 class 변수는 재정의가 되어 다형성이 이루어지지 않는 것이다.

또한 instance 변수와 class 변수, class method가 은닉된 경우는 재정의 될 수 없다.

Heterogeneous collection class

array 배열을 이용해 class의 선언도 가능하다.

이는 다형성이 가능하기 때문에 가능한 것이기도 하다.

GeoShape list[] = new GeoShape[5];

list[0] = new Rectangle();

list[1] = new GeoShape();

list[2] = new Circle();

list[3] = new Rectangle();

list[4] = new GeoShape();

위와 같이 배열로 부모 class 객체에 대해 선언을 하고 각 배열을 해당 class의 자식 class로 생성을 해줄 수 있다.

마찬가지로 배열의 특성을 이용해 해당 class들의 method를 호출 할 수 있다.

for(int i=0; i < list.length; i++) {

    list[i].method();

}

만약 자식 class 내에 해당 method()가 존재하지 않는 경우 에러가 발생하게 된다. 이런 경우를 부모 class에서 해당 method()를 abstract method로 선언을 하고 자식 class에서 구현을 하는 식으로 정해놓으면 이러한 문제가 발생할 염려가 없다.


이것처럼 불특정한 대상들을 묶어서 관리하기 위한 interface를 자바에서는 제공해주고 있다.


interface

특징

구현 class

Set

데이터 순서와 무관

데이터의 중복 불허

HashSet, TreeSet

List

데이터의 순서 관리

데이터의 중복 허용

ArrayList, LinkedList, Vector

Map

키(key)와 값을 묶어서 관리

키(key)의 중복 불허

HashMap, TreeMap, Hashtable


각 interface에 정의되어 있는 주요 method는 다음과 같다.


Set

size()

Set의 요소 개수를 리턴

isEmpty()

Set이 비어있는지 여부 리턴

contains()

Set에 특정 원소가 포함되어 있는지 여부 리턴

add()

Set에 특정 원소를 추가

remove()

Set에서 특정 원소를 제거


List

get()

지정한 위치에 있는 데이터를 리턴

set()

지정한 위치에 있는 데이터를 변경

add()

지정한 위치에 데이터를 추가

remove()

지정한 위치에서 데이터를 제거

indexOf()

지정한 데이터가 있는 처음 위치를 리턴

lastIndexOf()

지정한 데이터가 있는 마지막 위치를 리턴

subList()

지정된 범위에 해당하는 부분 List를 리턴


Map

put()

키(key)와 값으로 구성된 새로운 데이터를 추가

get()

지정한 키(key)에 해당하는 데이터를 리턴

remove()

지정한 키(key)에 해당하는 데이터를 삭제

containsKey()

지정한 키(key)가 존재하는지 여부를 리턴

containsValue()

지정한 값이 존재하는지 여부를 리턴

size()

Map의 요소 개수를 리턴

isEmpty()

Map이 비어있는지 여부를 리턴


Vector class

array를 생성할 때, 그 길이가 정해지고, 저장하려는 원소(element)의 형태가 같아야 한다는 단점이 있다.

vector는 다양한 형의 원소를 저장 가능하며, 그 길이 또한 가변적이라는 장점을 가지고 있다.


vector의 주요 method는 다음과 같다.

  • void add(int index, Object element): 객체를 해당 index에 추가합니다.
  • boolean add(Object o): 객체를 현재 Vector의 끝에 추가합니다.
  • boolean addAll(Collection c): 주어진 Collection의 모든 객체를 추가합니다.
  • boolean addAll(int index, Collection c) : 주어진 Collection의 모든 객체를 index 위치에 추가합니다.
  • void addElement(Object obj): 객체를 추가합니다.
  • int capacity(): 이 객체의 용량을 얻습니다.
  • void clear(): Vector 내의 모든 객체를 제거합니다.
  • boolean contains(Object elem): 객체를 포함하고 있는지를 얻습니다.
  • boolean containsAll(Collection c) : Collection 내의 객체들을 포함하고 있는지를 알아봅니다.
  • Object elementAt(int index): 해당 index에 있는 객체를 얻습니다.
  • Enumeration elements(): 이 Vector에 대한 Enumeration 객체를 가져옵니다.
  • Object firstElement(): 첫 번째 객체를 가져옵니다.
  • Object get(int index): 해당 index 위치에 있는 객체를 가져옵니다.
  • int indexOf(Object elem): 객체의 위치를 가져옵니다.
  • int indexOf(Object elem, int index) : 해당 index 위치에서로부터 해당 객체가 처음 나오는 index를 가져옵니다.
  • void insertElementAt(Object obj, int index): 해당 index에 객체를 삽입합니다.
  • boolean isEmpty(): Vector가 비어있는지를 알 수 있습니다.
  • Object lastElement(): Vector내의 마지막 객체를 가져옵니다.
  • int lastIndexOf(Object elem): Vector 내에서 객체의 마지막 index를 얻습니다.
  • int lastIndexOf(Object elem, int index) : 해당 index로부터 마지막의 객체 index를 가져옵니다.
  • Object remove(int index): 해당 index의 객체를 제거합니다.
  • boolean remove(Object o): 객체를 제거합니다.
  • boolean removeAll(Collection c): Collection에 있는 모든 객체를 제거합니다.
  • void removeAllElements(): Vector 내의 모든 객체를 제거합니다.
  • boolean removeElement(Object obj): 객체를 제거합니다.
  • void removeElementAt(int index): 해당 index의 객체를 제거합니다.
  • boolean retainAll(Collection c): Collection에 있는 객체들을 보존합니다.
  • Object set(int index, Object element): 해당 index의 객체를 대체합니다.

Stack class

Stack은 LIFO(Last In First Out) 방식으로 객체를 추가, 삭제하는 자료구조이다.

Vector 클래스를 상속하는 class로서, stack의 고유 기능인 push, pop, top, empty등과 같은 연산기능을 가진 method를 제공해준다.


stack의 주요 method는 다음과 같다.

  • boolean empty(): Stack이 현재 아무 것도 저장되어 있지 않은지를 검사합니다.
  • Object peek(): Stack의 top에 있는 원소를 가져옵니다.
  • Object pop() : Stack의 top에 있는 원소를 가져오고 top의 위치를 하나 감소시킵니다.
  • Object push(Object item): Stack에 새로운 원소를 저장합니다.
  • int search(Object o): 원소의 위치를 가져옵니다.

Enumeration Interface

여러개의 원소들을 포함하는 객체에 대해 정의하고 있는 interface이다. Vector에서 처럼 각 원소에 접근할 때 그 원소의 데이터 형으로 전환하는 코드가 없어도 된다.


Enumeration interface에서 제공하는 주요 method는 다음과 같다.

  • boolean hasMoreElements() : 더 이상 원소가 존재하는지를 검사한다.
  • Object nextElement() : Enumeration 내의 현재 원소 다음의 원소를 가져온다.

다음과 같이 사용한다.

for (Enumeration e = v.elements() ; e.hasMoreElements(); ) {

    System.out.println(e.nextElement());

}

Iterator interface

Enumeration interface를 대체하기 위한 것으로 주요 method는 다음과 같다.

  • boolean hasNext() : 더 이상의 원소가 존재하는지를 얻는다.
  • Object next() : 현재 위치 다음에 있는 원소를 가져온다.
  • void remove() : Iterator 내의 마지막 원소를 제거한다.

다음과 같이 사용한다.

for (Iterator i = v.iterator(); i.hasNext(); ) {

    System.out.println(i.next());

}

Interface

프로그래밍 과정중에 만들어지는 method들의 정의를 표준화 시키기 위한 툴

class와 동일하게 멤버 변수와 메소드를 갖는 구조로 선언이 된다.


class와의 차이점

  1. 모든 member variable은 public static final로 선언되어야만 한다.
    • interface의 member variable은 단지 상수로만 사용이 된다.
    • 선언을 해주지 않아도 자동으로 public static final로 선언이 된다.
  2. 모든 method는 public abstract로 선언되어야만한다.
    • 선언을 해주지 않아도 자동으로 public abstract로 선언이 된다.

이렇게 선언된 interface는 (abstract로 선언된 class처럼)

  1. 생성문을 통해 object를 만들 수 없으며, 단지 base class처럼 상속을 시켜주는 역할만 한다.
  2. 일단 선언되고 나면 class들처럼 data type으로 사용할 수 있다.
    즉, 일반 변수, 매개 변수, return 값 등의 type으로 사용할 수 있다.
  3. interface도 interface로부터 상속되어질 수 있다.
  4. implements라는 keyword로 상속을 선언한다.

interface는 선언된 method를 가지고 base class와 같이 상속을 시켜줌으로써, 관계없는 class간에 method를 overriding 하여 사용할 수 있게 해준다.


interface는 abstract로 선언된 class가 제공하지 못하는 다중 상속(multiple inheritance)를 지원한다.

inner class

inner class는 크게

  • 멤버의 속성을 갖는 inner member class
  • method 안에 정의하는 inner area class
  • 이름을 생략할 수 있는 anonymous inner class

로 나누어 볼 수 있다.


inner member class

class 내부에 member와 같은 level로정의되는 class를 말한다.

예제는 다음과 같다.

class MyOuter {
    private int   outVar = 1;
   
    class MyInner {
        int      inVar = 2;
        static int  s1 = 3;       // 라인 1.  error !!

        int innerMethod() {
            inVar = outVar;       // 라인 2.
                    
            if (this.inVar == MyOuter.this.outVar) // 라인 3.
            inVar = 0;

            return inVar;
        }
    }
 
    int outerMethod() {
        MyInner inobj = new MyInner(); // 라인 4.

        return inobj.innerMethod(); 
    }

    public static void main( String   arg[]) {
        MyInner tobj = new MyInner();  // 라인 5.  error!!
        MyOuter mobj = new MyOuter();

       mobj.outerMethod();
    }
}

위의 코드를 compile하는 경우 생성되는 파일

    1. MyOuter.class : inner member class를 포함하는 class
    2. MyOuter$MyInner.class : inner member class

주의해야할 부분

    • inner member class 내부 member variable나 method는 static으로 선언될 수 없다. 따라서 라인1은 error이다.
    • inner member class에서는 outer class의 모든 member variable이나 method를 access를 할 수 있다.
      outer class 입장에서 본다면 inner member class 또한 내부에 정의된 구성원이므로, 라인2 와 같이 outer class의 private로 선언된 멤버변수도 access할 수 있다.
    • inner member class 내부의 this는 inner member class를 의미한다.
      만약 outer class를 참조해야 한다면 super를 사용하는 것이 아니라 OuterclassName.this를 사용한다.
      라인 3이 이러한 예이다. (그냥 outVar도 가능하지만, 설명을 위해 이렇게 사용했다.)
    • outer class내에서 inner member class의 object를 생성할 수 있는 곳은 outer clas를 가리키는 this가 존재하는 곳이다. (라인 4)
      즉 this를 사용할 수 없는, static으로 선언된 method에서는 inner member class를 생성할 수 없다. 따라서 라인 5와 같은 static method에서는 에러가 발생한다.
    • 만약 outer class 내에서가 아닌 다른 class에서 inner member class를 생성하고자 한다면, 반드시 outer class의 object를 먼저 생성하고 이 object를 통해서 inner member class를 생성해야만 한다.
      이런 속성 때문에 inner member class가 Event Listener로 많이 사용된다.
MyOuter myout = new MyOuter();

MyInner myin = myout.new MyInner();


또는


MyInner myin = new MyOuter().new MyInner();

    • inner member class는 top level class와 달리 static, private, protected가 될 수 있다.
      만약 inner member class가 static으로 선언되었다면 이 inner member class안에서는 outer class의 instance member(즉 모든 method와 variable)를 access할 수 없다.
      static으로 선언된 inner class를 중첩 class라고 한다. 중첩 class가 포함하고 있는 method에서는 class의 method에서처럼 non-static variable 또는 non-static method에 접근할 수 없지만, class variable 또는 class method에는 접근할 수 있다.

inner area class

method 안에 정의되는 class를 말한다.

inner area class에서는 자신이 속한 method의 지역변수가 final로 선언된 것만 access할 수 있다.

예제는 다음과 같다.

public class MyOuter {
   int   oVal = 0;

   Runnable  oMethod() {   
      int         지역Val = 200;
      final int  fval= 100;

      class My지역 implements Runnable { 
         int  mem지역;

          public void run() {
             mem지역 = fval;         // 라인 1.    
             oVal = 400;              // 라인 2.        
             지역Val = 400;          // 라인 3.  error!!
          }
      }
                
      My지역 runobj = new My지역(); // 라인 4.
     
      return runobj;
   }
}

inner area class는

  • 라인1과 같이 자신의 내부에서, 자신을 둘러싸고 있는 method의 final로 선언된 area variable을 access 할 수 있다.
  • 라인2와 같이, 자신을 둘러싸는 method가 속한 class의 member variable을 access 할 수 있다.
  • 라인3과 같이 자신의 내부에서, 자신을 둘러싸는 method의 area variable을 access 할 수 없다.
    왜냐하면 일반 area variable은 method가 return 되면서 사라져 버리기 때문에, method 종료 후에도 살아있을 수 있는 지역 class의 object에서 참조하는 것은 위험하기 때문이다.
  • 라인4와 같이 area class를 둘러싸고 있는 method 내에서 area class의 object를 생성할 수 있다.

anonymous inner class

이 형식의 class는 inner area class의 일종으로, clas의 이름이 없는 class이다.

anonymous inner class의 생성과 선언은 다음과 같이 한번에 이루어진다.

new 상속받을class또는 interface이름 () {

    //body ...

}

따라서, anonymous inner class는 constructor가 없다.

예제는 다음과 같다.

class MainGUI {
    Button b = new Button( "ok" );
      
    void registHandler() {
        b.addActionListener(         // 라인 1.
            new ActionListener() {    // 라인 2.
                public void actionPerformed(ActionEvent e) {
                    System.out.println("pressed ok");  
                }
            }
        );           // end of 메소드 call
    }               // end of registHandler

                   // ...
}
   
interface ActionListener {
    public void actionPerformed(ActionEvent e );
}



출처 : http://blog.naver.com/luversof/50026428239
신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

Tag Java

티스토리 툴바