2016년 1월 28일 목요일

[JAVA 교육] 접근제한자 / 다형성 - 실습예제2

[ Class Diagram ]



[소스코드 : PolyApplication.java]
package sk.didimdol.oop.polymorphism;

public class PolyApplication {
    public static void main(String[] args) {
        Shape s = null;// = new Shape(10,20);  //abstract으로 만들어버려서 에러남
        s = new Circle(3,5,10);
        Shape s2 = new Circle(20,30,50);
        Rectangle r1 = new Rectangle(3,5,10,20);
        Shape s3 = r1;//다형적 객체

        Shape[] shapeList = new Shape[3];
        shapeList[0] = s;
        shapeList[1] = new Circle(4,5,10);//가능하다. is-a 관계이므로
        shapeList[2] = r1;

        for(Shape shape : shapeList){
            shape.draw();
        }

        Shape s4 = new Circle(6,7,20);
        s4.draw();      //Circle(자식)의 draw 호출
        Object obj = new Rectangle(3,4,10,20);
        Rectangle r3 = (Rectangle)obj;
        r3.draw();
        System.out.println(r3.calcArea());
        System.out.println(s4.calcArea());
        //Shape에 calcArea()가 없어서 에러
        //그래서 Shape에 abstract calcArea만들어주고 클래스명 앞에도 abstract붙여야한다.

        System.out.println();
    }
}

abstract class Shape {
    int x;
    int y;

    public Shape(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }

    public void draw() {
        System.out.println(x+", "+y+" 위치에 도형을 그립니다.");
    }

    public abstract double calcArea();
}

class Circle extends Shape{
    int radius;

    public Circle(int x, int y, int radius) {
        super(x, y);
        this.radius = radius;
    }

    @Override
    public void draw() {
        super.draw();
        System.out.println("원을 그립니다.");
    }

    public double calcArea() {
        return radius * radius * 3.141592;
    }
}

class Rectangle extends Shape{
    int width;
    int height;

    public Rectangle(int x, int y, int width, int height) {
        super(x, y);
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        super.draw();
        System.out.println("사각형을 그립니다.");
    }

    public double calcArea() {
        return width * height;
    }
}

[JAVA 교육] 접근제한자 / 다형성 - 실습예제

[JAVA 교육] 접근제한자 / 다형성 - 실습예제


[ Class Diagram ]



[소스코드 : NameCardCLIApplication.java]

/********************************************************************
 * <고객관리 프로그램, Customer Management Program>
고객관리 프로그램을 만들어야 합니다.
고객정보는 이름, 이메일, 나이를 저장합니다.
최대 100명의 정보를 저장할 수 있어야 합니다.
메모리에 정보를 저장/관리합니다.
배열을 이용합니다.

기능적 요구사항
 - 고객정보 입력(Insert)
 - 고객정보 수정(Update)
 - 고객정보 삭제(Delete)
 - 고객정보 리스트 출력(List)
 - 고객정보 조회(Previous, Next)
 - 수정 또는 삭제는 조회를 한 다음에 사용할 수 있습니다.

비기능적 요구사항
 - 언어는 자바
 - CLI 환경 어플리케이션
 - 기능들은 모듈단위로 작성되야 합니다.
    메서드를 작성하란 의미입니다.
    메서드는 기능을 실행하는 별도의 블록
        메서드 이름
        메서드 파라미터 변수 선언
        리턴 타입
    public 리턴타입 메서드이름(변수타입 변수명,...) {
        //To Do
    }
    public void insertData() {
        //To Do
    }
 ********************************************************************/

package namecard.prj3;

import java.util.Scanner;

public class NameCardCLIApplication {
    static final int MAX = 100;
    static NameCard[] nameCardList = new NameCard[MAX];
    static int count = 0;
    static int index = -1;
    static Scanner scan = new Scanner(System.in);

    public static void main(String[] args) {
        boolean key = true;
        System.out.println("******************************************");
        System.out.println("************고객 관리 프로그램************");
        System.out.println("******************************************");

        String menu;
        while(key){
            System.out.println("");
            System.out.println(">>메뉴를 선택하세요.");
            System.out.println("(L)ist, (I)nsert, (S)earch, (Q)uit");
            menu = scan.next();
            switch(menu.toUpperCase().charAt(0)){
            case 'L':
                System.out.println("모든 정보를 출력합니다.");
                listData();
                break;
            case 'I':
                System.out.println("새로운 정보를 추가합니다.");
                insertData();
                break;
            case 'S':
                if(count == 0) {
                    System.out.println("입력된 데이터가 없습니다.");
                } else {
                    System.out.println("정보를 조회합니다.");
                    searchData();
                }
                break;
            case 'Q':
                System.out.println("프로그램을 종료합니다.");
                key = false;
                break;
            }//end switch
        }//end while
    }//end main

    public static void insertData() {
        if(count < MAX) {
            System.out.println("회원구분(0:비회원, 1:회원, 2:VIP)");
            int gubun = scan.nextInt();

            System.out.print("이름을 입력하세요. : ");
            String name = scan.next();
            System.out.print("이메일을 입력하세요. : ");
            String email = scan.next();
            System.out.print("나이를 입력하세요. : ");
            int age = scan.nextInt();

            NameCard card = null;
            if(gubun == 0){
                card = new NameCard(name, email, age);
            } else if(gubun == 1) {
                System.out.print("ID를 입력하세요. : ");
                String id = scan.next();
                card = new MemberNameCard(name, email, age, id);
            } else if(gubun == 2) {
                System.out.print("회원 ID를 입력하세요. : ");
                String id = scan.next();
                System.out.print("권한을 입력하세요. : ");
                String permission = scan.next();
                card = new VipNameCard(name, email, age, id, permission);
            } else {
                System.out.println("잘못된 회원 구분입니다. 추가가 취소됩니다.");
            }

            if(card != null){
                nameCardList[count] = card;
            }

            System.out.println("새로운 정보가 추가되었습니다.");
            count++;
        } else {
            System.out.println("더이상 추가 할 수 없습니다.");
        }
    }

    public static void listData() {
        if(count == 0){
            System.out.println("현재 입력된 정보가 없습니다.");
        }else {
            System.out.printf("|\t이름\t\t|\t이메일\t\t\t\t|\t나이\t|\n");
            for(int i=0; i<count ; i++) {
                System.out.printf("|\t"+nameCardList[i].getName()+"\t\t|\t"
                            +nameCardList[i].getEmail()+"\t\t|\t"
                            +nameCardList[i].getAge()+"\t|\n");
            }
        }
    }

    public static void searchData() {
        boolean key=true;
        String smenu;
        while(key) {
            System.out.print("세부메뉴를 선택하세요. (P)revious/(N)ext/(U)pdate/(D)elete/(M)ain : ");
            smenu = scan.next();
            switch(smenu.toUpperCase().charAt(0)) {
            case 'P':
                previousData();
                break;
            case 'N':
                nextData();
                break;
            case 'U':
                updateData();
                break;
            case 'D':
                deleteData();
                break;
            case 'M':
                System.out.println("메인 메뉴로 돌아갑니다.");
                index = -1;
                key = false;
                break;
            default:
                System.out.println("잘못된 입력입니다.");
            }
        }

    }

    public static void previousData() {
        if(index == -1){
            System.out.println("(N)ext를 선택해주세요.");
        } else if(index > 0) {
            index--;
            printData(index);
        } else {
            System.out.println("처음 데이터입니다.");
            printData(index);
        }
    }

    public static void nextData() {
        if(index < count-1) {
            index++;
            printData(index);
        } else {
            System.out.println("마지막 데이터입니다.");
            printData(index);
        }
    }

    public static void updateData() {
        if(index != -1) {
            NameCard card = nameCardList[index];

            System.out.println("선택된 정보를 수정합니다.");
            System.out.print("이름을 입력하세요. : ");
            card.setName(scan.next());
            System.out.print("이메일을 입력하세요. : ");
            card.setEmail(scan.next());
            System.out.print("나이를 입력하세요. : ");
            card.setAge(scan.nextInt());

            if(card instanceof VipNameCard) {
                System.out.print("회원 ID를 입력하세요. : ");
                ((VipNameCard) card).setId(scan.next());
                System.out.print("권한을 입력하세요. : ");
                ((VipNameCard) card).setPermission(scan.next());

            } else if (card instanceof MemberNameCard){
                System.out.print("회원 ID를 입력하세요. : ");
                ((MemberNameCard) card).setId(scan.next());
            }

            System.out.println("정보가 수정되었습니다.");
            printData(index);
        }
    }

    public static void deleteData() {
        if(index != -1) {
            System.out.println("선택된 정보를 삭제합니다.");
            for(int i=index ; i<count ; i++) {
                nameCardList[i] = nameCardList[i+1];
            }
            nameCardList[count-1]=null;

            if(!((count > 1) && (index == 0))) {
                index--;
            }
            count--;
        }
    }

    public static void printData(int pos) {
        System.out.println("======================================");
        System.out.println("현재 Index : "+pos+" ");
        nameCardList[pos].printNameCardInfo();
        System.out.println("======================================");
        System.out.println("");
    }
}

[소스코드 : NameCard.java]
package namecard.prj3;

public class NameCard {
    private String name;
    private String email;
    private int age;

    public NameCard(String nameString emailint age) {
        super();
        this.name = name;
        this.email = email;
        this.age = age;
        System.out.println("1");
    }

    public NameCard(String nameint age) {
        this(name,null,age);
        //this.name = name;
        //this.age = age;
        //위의 2줄로 쓰는거 보다. 첫번째줄 처럼 쓰는게 좋다.
        System.out.println("2");
    }

    public NameCard() {
        //this("무명씨", "없음", 0);   //첫번째 생성자 호출
        this("무명씨"0);   //두번째 생성자 호출
        System.out.println("3");
    }

    //NameCard card = new NameCard();를 실행했을 때 실행 순서.
    // 3번째 생성자->2번째 생성자->1번째 생성자.

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void printNameCardInfo(){
        System.out.println("[이름: "+name+"\t"+
                            "이메일:"+email+"\t"+
                            "나이: "+age+"]");
    }

}

/*1사람 고객 정보를 저장하려면

//////////////NameCard card = new NameCard();card.name = "홍길동";card.email = "hong@hong.com";card.age = 30;-------------vs-------------NameCard card = new NameCard("홍길동","hong@hong.com",30);/////////////*/

[소스코드 : MemberNameCard.java]
package namecard.prj3;

public class MemberNameCard extends NameCard{
    private String id;

    public MemberNameCard(String nameString emailint ageString id) {
        super(name, email, age);
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public void printNameCardInfo() {
        // TODO Auto-generated method stub
        super.printNameCardInfo();
        System.out.println("[ ID : "+id+"]");
    }

}

[소스코드 : VipNameCard.java]

package namecard.prj3;

public class VipNameCard extends MemberNameCard{
    private String permission;

    public VipNameCard(String nameString emailint ageString idString permission) {
        super(name, email, age, id);
        this.permission = permission;
    }

    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    @Override
    public void printNameCardInfo() {
        // TODO Auto-generated method stub
        super.printNameCardInfo();
        System.out.println("[ 권한 : "+permission+"]");
    }
}

[JAVA 교육] 접근제한자 / 다형성

[JAVA 교육] 접근제한자 / 다형성
(*본 게시물은 본인이 교육을 통해서 배우는 내용을 정리하는 글입니다. 부족한 부분이 많으니 참고해주시기 바랍니다. 혹시 정확한 의미를 알고 싶으시거나, 틀린 내용에 대해 조언해주시고 싶은 분들께서는 댓글을 남겨주시면 최대한 빠르게 답변하겠습니다. 감사합니다.


  1. Modifier(제한자)
    1. access 접근제한자 (아래로 갈수록 접근 제한이 강화)
      1. public
        • 클래스, 변수, 생성자, 메서드
        • 어디서든 접근 가능
        • 표기: '+'
      2. protected
        • 변수, 생성자, 메서드, 내부클래스(Inner Class, 클래스 바로 안쪽 클래스, 메소드 안의 내부클래스는 로컬내부클래스)
        • 동일 패키지안에서 접근 가능
        • but, 상속 관계에 있다면 다른 패키지여도 접근 가능
        • 표기: '#'
      3. package friendly(or default 강사님은 default라는 것은 없다고 함.)(키워드는 아님)
        • 접근제한자를 표시하지 않는것.
        • 동일 패키지 안에서 접근 가능(protected와 공통점)
        • 클래스, 변수, 메서드, 내부클래스
        • 표기: '~' or 공백
      4. private
        • 변수, 메서드, 생성자, 내부클래스
        • 동일 클래스 안에서만 접근 가능
        • 표기: '-'
    2. usage
      1. static
      2. final
      3. abstract
      4. transient
      5. native
  2. OOP 특징
    1. Encapsulation
      1. 접근제한자
      2. 변수는 private, 메소드는 public
      3. 이유 : 입력 data 검증(변수에 직접 넣으면 if문으로 확인 불가하지만 setter로 넣으면 if문으로 검증가능), 권한 체크
    2. 상속 Inheritance
      1. 단일 상속
      2. extends 키워드를 이용한다.
      3. is-a 관계
      4. Object를 상속
      5. 필드, 메서드만 상속
      6. 부모객체를 참조할 때는 "super."
      7. 일반화(Generalization) - 분석/설계할 때 사용하는 상속 용어
    3. 재정의 Override
      1. 부모가 가진 메서드를 자식이 다시 재정의한 메서드를 만드는 것.
      2. 이름이 동일해야한다.
      3. 파라미터도 동일해야한다.
      4. 리턴타임도 동일해야한다.
      5. access modifier는 부모의 접근제한레벨보다 자식의 접근제한레벨이 더 public해야한다.
      6. 부모가 static이면 자식도 static이어야 한다.
      7. final 변수는 재정의 불가능(final 붙인거는 '상속은 해줄건데 고치지는 못한다~' 라는것)
      8. 부모에서 throws하지 않는 새로운 예외는 throws할 수 없다.
  3. Polymorphism (다형성)
    1. 상속 관계(is-a) 전제되야 한다.
    2. 다형적 객체
      1. 부모타입으로 선언
      2. 자식객체참조
      3. ex. Shape s = new Circle();
    3. 이종모음 Heterogeneous Collection
      1. 배열의 다형성이 적용되어서 여러 타입의 객체를 저장하는 것
    4. wrapper class
      1. 기본타입을 객체로 사용할 수 있도록 만들어 놓은 클래스
      2. Byte, Short, Integer, Long / Float, Double / Boolean / Character(문자)
      3. jdk 1.4.6에 생겼다.
      4. java SE 5(jdk 1.5)부터는 Auto Boxing을 지원한다.(=자동으로 wapper 적용, 자동으로 푸는것(unwrap)도 지원)
    5. Virtual Method Invocation
      1. 컴파일 타임때는 선언한 클래스(new로 만든 객체의 타입이 아니라 변수의 타입)의 메서드 참조
        추상메서드(abstract method = body가 없이 이름만 있는 메소드)도 참조 가능.
        (!중요! 추상메서드를 구현한 클래스는 반드시 abstract여야 한다. 하지만 그 역은 그럴 필요 없다. 그리고 추상클래스는 객체 생성은 안되지만 상속은 된다.)
      2. 런타임시 생성한 클래스(new로 생성한 객체)의 메서드 실행
      3. 선언한 클래스에 없는 메서드 호출하고 싶으면 형변환을 해야한다.
    6. instanceof (자바의 키워드 중 하나)
      1. 객체가 어떤 클래스의  instance인지를 알려주는 키워드
  4. Tip
    1. Singleton 디자인 패턴 : 생성되는 객체의 수를 제한, 1개로 제한자바의 API같은게 아니고 개발방법같은 것. 패턴.stateless에 적합, stateful 부적합

[JAVA 교육] OOP / 클래스 / 변수 / this & super

[JAVA 교육] OOP / 클래스 / 변수 / this & super

(*본 게시물은 본인이 교육을 통해서 배우는 내용을 정리하는 글입니다. 부족한 부분이 많으니 참고해주시기 바랍니다. 혹시 정확한 의미를 알고 싶으시거나, 틀린 내용에 대해 조언해주시고 싶은 분들께서는 댓글을 남겨주시면 최대한 빠르게 답변하겠습니다. 감사합니다.)


1. Review - 제어문
(1) 조건문
     1) if(조건식)
     2) switch(표현식)
(2) 반복문 레이블을 지정할 수 있다.
     1) for : 반복횟수가 정해져 있을 때
    2) while : 반복횟수가 정해져 있지 않을 때
     3) do-while : 1회 이상 실행할 때
(3) 탈출문 break와 continue는 레이블과 함께 사용하여 흐름을 제어할 수 있다.
   1) break : 진행중인 반복문을 완전히 탈출
   2) continue : 진행중인 반복문을 1회 skip
   3) return : 메소드 탈출
(4) 배열
   1) 특징 : 동종, 크기 불변
   2) 순서
          a. 선언
         b. 생성
          c. 초기화
   3) 객체배열
          a. 선언(ex. Person[] customers; )
          b. 생성(ex. customers = new Person[10]; )
       c. 초기화. 기본형 배열처럼 {}를 이용한 직접 초기화가 안된다.
                  new를 이용한 객체 생성 후 할당해야 한다. (ex. customers[0] = new Person(); )



2. OOP

1) 객체 지향 프로그래밍
   * OOP : Object Oriented Programming
   * '부품 객체를 먼저 만들고 이것들을 하나씩 조립해 완성된 프로그램을 만드는 기법' 이 의미는 좀 아니다.
   이 의미는 '컴포넌트 기반 개발'을 의미한다.
   * 실제 현실의 객체를 프로그램에 그대로 적용시키는 것을 객체 지향 프로그래밍이라고 한다.

2) 장점
   * 재사용성이 높다.
   * 그래서 개발 생산성이 높다.
   * 'CBD(컴포넌트 기반 개발)'이 가능하다.

3) 클래스와 객체
   (1) 클래스 : [책 설명]객체를 만들기 위한 틀(Templete, Blueprint, 설계도)
   (2) 객체 : 클래스의 인스턴스, 유형 또는 무형 사물

4) 객체추상화 : 현실 객체를 프로그램에 클래스(가상)로 가져오는 것.
   (1) 클래스를 만드는 과정
   (2) 객체의 특징을 분석
        a. 명사적 특징 (ex. 보드마카 - 색깔) : Data. 정보. Field(변수). Attribute(분석/설계에서 주로 쓰는 단어)
        b. 동사적 특징 (ex. 보드마카 - 쓰다) : method. behavior, operation(분석/설계에서 주로 쓰는 단어)
        c. 예시(Pen)
             1. 명사 : color
             2. 동사 : write

5) 객체간의 관계(네모박스는 클래스)
   (1) Association(연관)

   (2) Aggregation(복합연관)(집합관계) : B가 공유

   (3) Composition(집합연관)(집합관계) : B는 A의 전유
        A has a B

   (4) Generalization(일반화)
        B is a A, inheritance

   (5) Realization(실체화)
        implementation

   (6) Dependency(의존)

6)  특징
   (1) Encapsulation
        1. 접근제한자
        2. 변수는 private, 메소드는 public
        3. 이유 : 입력 data 검증(변수에 직접 넣으면 if문으로 확인 불가하지만 setter로 넣으면 if문으로 검증가능), 권한 체크

   (2) 상속 Inheritance
        1. 단일 상속
        2. extends 키워드를 이용한다.
        3. is-a 관계
        4. Object를 상속
        5. 필드, 메서드만 상속
        6. 부모객체를 참조할 때는 "super."
        7. 일반화(Generalization) - 분석/설계할 때 사용하는 상속 용어

   (3) 재정의 Override
        1. 부모가 가진 메서드를 자식이 다시 재정의한 메서드를 만드는 것.
        2. 이름이 동일해야한다.
        3. 파라미터도 동일해야한다.
        4. 리턴타임도 동일해야한다.
        5. access modifier는 부모의 접근제한레벨보다 자식의 접근제한레벨이 더 public해야한다.
        6. 부모가 static이면 자식도 static이어야 한다.
        7. final 변수는 재정의 불가능(final 붙인거는 '상속은 해줄건데 고치지는 못한다~' 라는것)
        8. 부모에서 throws하지 않는 새로운 예외는 throws할 수 없다.
   (4) Polymorphism 다형성



3. 클래스

1) 정의 : class 클래스 이름 {}

2) 구성요소
   (1) 변수(Field)
        a. instance 변수
        b. class변수 = static 변수
   (2) 메서드
   (3) 생성자(Constructor)
        a. 용도 : 인스턴스 변수 초기화, 객체 생성시 new와 함께 사용
        b. 기본 생성자 : 인자 없음. 컴파일러가 추가(생성자가 없을때)
        c. 규칙
             1. 클래스명과 동일해야한다.
             2. 메서드처럼 생겼지만 메서드는 아님. so, 리턴타입 없음.
             3. Overloading이 가능하다.(중복, 인자가 다를때).
             4. 첫줄에는 super() 또는 this()가 와야 한다. 없으면 super()자동으로 온다.
                  1. super() : 부모클래스의 생성자를 호출(참조)할 때 사용
                  2. this() : 동일 클래스 내의 다른 생성자를 호출(참조)할 때 사용
   (4) static {}, static initializer
   (5) {}, instance initializer
   (6) 내부클래스

3) 예시
class Pen {
   //변수=데이터=속성
   //변수 : 고유 데이터, 상태 값, 다른클래스의 객체
   String color;
   void write() {

   }
   Pen() {
        //생성자. 리턴타입이 없다. 이름은 클래스 이름과 똑같다.
   }
   static {
        //static 변수 초기화
    }
   {
        //instance 변수 초기화
    }
}

4) 객체 생성
   (1) 선언 ex. Pen mypen;
   (2) 생성 ex. mypen = new Pen();



4. 변수
1) 멤버(Member)변수 - 클래스 안, 초기화 하지 않아도 default값으로 초기화 된다.
   (1) instance 변수
      * 반드시 객체를 생성화하고 호출해야한다.
        * 객체마다 각각의 값을 가진다.
        * 생성자, {} 에서 초기화
   (2) class 변수 = static 변수
        * class 이름만으로 참조가능
        * 모든 객체가 같은 값을 공유한다.
        * static {} 에서 초기화

2) 지역변수 - 메소드 안
   (1) 매게변수=Parameter
   (2) Local 변수 : 반드시 초기화 한 후에 참조해야한다.

3) 상수 - fianl
   (1) 멤버변수 : 상수로 사용하기 위해 final상수 사용.
   (2) 지역변수 : 로컬클래스(Local Class)에서 변수를 참조하기 위해서 final 상수 사용.
        * 메서드안에서 내부클래스를 만들고 그 안의 메서드에서 바깥 메소드의 지역변수를 참조하는게 안된다. 이유는 스택에 바깥 메서드 위에 내부 클래스의 메서드가 올라가는데 스택은 메모리 주소로 값을 참조하는게 아니라 stack point를 옮겨서 참조하기 때문에 바깥 메서드의 지역변수를 참조하려면 내부 클래스의 메서드가 종료되어야하기 때문이다. 값을 사용해서 메서드를 진행하려 하는데 메서드를 종료해야한다는건 역설이다. 그렇기 때문에 바깥 메서드의 지역변수를 final로 지정해서 그 지역변수를 heap에 저장해놓고 내부 클래스의 메서드가 사용할 수 있게 한다.



5. this & super
1) this. , super. - 멤버 참조
   (1) this. : 현재 객체의 멤버
   (2) super. : 부모 객체의 멤버
   (3) 위치 : 매서드, 생성자 안에서 사용

2) this(), super() - 생성자 참조
   (1) this() : 현재 클래스의 다른 생성자 호출
   (2) super() : 부모 클래스의 생성자 호출

3) 위치
   (1) 생성자 첫 라인 : 여기에는 this()나 super()만 사용할 수 있다.



6. Tip
1. 이클립스에서 Export해서 jar로 실행파일 만들기 
   1. 순서 
        1. 원하는 package 우클릭 - Export 선택
        2. Java - JAR file 선택 - Next
        3. 원하는 소스 선택하고 밑에 'Select the export destination'에 저장할 위치\파일 선택(Browse 선택해서) - Next
        4. 'Export class files with compile errors'와 'Export class files with compile warnings' 체크 - Next
        5. 밑에 'Select the class of the application entry point'에서 메인이 있는 메인클래스를 선택한다. - Finish
   2. cmd에서 실행은 'java -jar [filename.jar]'
     하지만 매번 이렇게 입력하기 귀찮으니깐 bat파일 만들어서 bat파일을 실행한다.
        >>@echo off
        >>java -jar [filename.jar]
   이렇게 두줄 입력하고 cmd에서 [이름.bat]만 입력하면 실행된다.
   echo off를 안하면 java -jar 입력줄까지 cmd에 표시가 된다.
2. Object vs Instants = 유일 vs 무한
3. Class 생성자를 만들때 이클립스에서 편리한 기능을 제공해준다.
   우클릭->Source->Generate Constructor using Fields->OK
4. initializer(static, instance)=초기화자에서는 프로그램 수행간 처음 한번만 수행 되는 동작(드라이버 로드 등)을 수행할 때 좋다.
5. static {} 블럭 안에서 non-static 멤버를 "직접" 참조할 수 없다.
   그래서 main에서 사용할 멤버들은 static이 붙는다.
   참조하고 싶으면 non-static멤버를 가지고 있는 클래스를 객체화하여 사용해야한다.
6. cmd에서 패키지 컴파일 할때는 javac -d 옵션이 중요하다.