이클립스 에서 copy&paste 했기때문에 소스가 깔끔하지 않을수도 있지만 주석으로
설명하겟다.
package net.bitacademy.java41.step07;
import java.util.ArrayList; //Member class 에서 초기화된 객체의 주소값을 저장할
import java.util.Date; //가변적인 배열 LIst를 위한 Import 작업
import java.util.Scanner;
public class RedApp {
protected Scanner scanner;
protected ArrayList<Member> list = new ArrayList<Member>(); //list선언
private int no; //데이터 삭제와 업데이트시 메소드에 list에 인덱스번호
//를 전달할 변수
// * 생성자
// - 인스턴스가 사용되기 전에 역할을 수행하는데 필요한
// 최소한의 것을 준비하는 메서드
// * default constructor
// - 파라미터가 없는 생성자.
// - 클래스에 명시적으로 선언된 생성자가 없다면,
// 컴파일러가 자동으로 기본 생성자를 추가한다.
// public RedApp() {}
public RedApp() {
scanner = new Scanner(System.in); //스캐너 객체를 생성자를 통해 생성
list.add(new Member() //어려워 보일수 있지만 Member 클래스에 set메소드의
.setName("홍길동") //리턴타입을 그 객체에 주소값으로
.setPhone("111-2222") //하였기때문에 타입이Member인 list
.setEmail("hong@test.com") //에 담을수 있다.
.setBlog("hong.blogspot.com")
.setAge(20)
.setRegDate(new Date()));
list.add(new Member() //add메소드를 이용 list에 각각의 Member
.setName("임꺽정") //객체 를 추가
.setPhone("111-3333")
.setEmail("leem@test.com")
.setBlog("leem.blogspot.com")
.setAge(30)
.setRegDate(new Date()));
list.add(new Member() //add메소드는 사이즈를 자동증가
.setName("일지매") //각각의 인덱스에 객체를 담는다.
.setPhone("111-4444")
.setEmail("ill@test.com")
.setBlog("ill.blogspot.com")
.setAge(40)
.setRegDate(new Date())); //위와같이 생성자를 만들어주는 이유는 입력은 사용자로부
//입력 받지만 중간 테스트를 위해서 매번 데이터를 입력해야
//하는 불편함을 없애기 위해 만들었다.
//입력 받지만 중간 테스트를 위해서 매번 데이터를 입력해야
//하는 불편함을 없애기 위해 만들었다.
}
private void add(){ //데이터를 추가하기위한 메소드
Member m = new Member(); //Member 객체 생성후 그 객체의 인스턴스변수를
System.out.print("이름 : "); //사용자로부터 입력받아 초기화한후
m.setName(scanner.nextLine());
System.out.print("전화번호 : ");
m.setPhone(scanner.nextLine());
System.out.print("이메일 : ");
m.setEmail(scanner.nextLine());
System.out.print("블로그 : ");
m.setBlog(scanner.nextLine());
System.out.print("나이 : ");
m.setAge( Integer.parseInt( scanner.nextLine() ) );//나이변수는 타입이 인트이
//이기때문에 Integer.parseInt 를이용 정수를 반환하여 초기화한다.
System.out.print("등록하시겠습니까?(y/n)"); //사용자의 선택을 통해
if(scanner.nextLine().toLowerCase().equals("y")){
m.setRegDate(new Date()); //Date객체는 생성자로 현재시간을 반환
list.add(m); //list에 추가한다.
System.out.println("등록되었습니다!");
} else {
System.out.println("등록 취소하였습니다!");//list.add를 하지 않으면
} //등록이 되지 않음
}
private void list() {
System.out.printf("%1$3s %2$10s %3$15s %4$30s\n", //printf메소드를 이용
"번호", "이름", "전화", "이메일"); //간편 문자열처리 %1은 문자열순서
/* //$3은 표현할 문자의 최대글자수 s는 String
//타입의 변수를 뜻한다.
for(int i = 0; i < list.size(); i++) {
Member m = list.get(i); //for루프를 이용 list에 get메소드를 이용할수있지
} //인스턴스에 접근하려면 코드가 길어지고 지저분
*/ //하기 때문에. 밑에방식을 쓰겟다.
// 위의 for문 보다 간결한 표현식
int no = 1;
for(Member m : list) { //list 배열의 사이즈만큼 Member 객체 에서 인스턴스변수
System.out.printf("%1$3d %2$10s %3$15s %4$30s\n", //를 화면에 출력
no++, m.getName(), m.getPhone(), m.getEmail()); // 반복이아니라
} //인덱스를 이동하면서!!
} //선언된 no변수는 no++로 출력되는데 회원번호를
//의미한다.
public void execute() { //메인메소드에서 처음 호출되는 메소드로 사용자입력에따라
while(true) { //각각의 메소드를 호출한다.
System.out.print("명령>");
String command = scanner.nextLine();
if (command.equals("add")) { //문자열은 equals메소드를 이용해비교
no = 0; //no 변수를 주는 이유는 밑에서 설명하겟다.
add(); //add();호출 추가기능
} else if (command.equals("list")) {
no = 0; //출력기능 역시 no변수를 0으로 초기화 하고있다.
list(); //도대체 왜!!!!!!!
} else if (command.startsWith("view")) {//startsWith메소는는 파라미터로
//전달된 "view"같을경우 조건을 만족한다.
//명령>view 2 //<<이런식으로 입력을 받게되는데
String[] values = command.split(" ");//split메소드를 이용 " "공백을 기 //기준으로 String 값을 반환하기때문에 두개의 view와숫자하나를
//모두 String 값으로 반환하게된다. 따라서!!! String 에 배열에
//순차적으로 들어가게된다.
no = Integer.parseInt(values[1]);// 드디어 나왔다 왜 no 변수가
view( no ); //각각의 추가,조회 모드에선 0으로 초기화되고
//view메소드에서만 입력된 값을 받는지.....
//이유인 즉슨!! 업데이트와 삭제기능을 게시물을 보고있는
//상태에서만 기능을 수행하고 list의 위치값을 전달하기위한것이다
} else if (command.equals("update")) {
if (no > 0) { //이부분 ! view를 호출하지
update(); //않으면 업데이트와 삭제를 할수 없다.!
} else { //왜
System.out.println("먼저 멤버를 조회하세요!");
}
} else if (command.equals("delete")) {
if (no > 0) { //view를 메소드가 호출되다면 조건을 만족
detele(); //업데이트와 삭제 메소드 호출된다.
} else {
System.out.println("먼저 멤버를 조회하세요!");
}
} else if (command.equals("quit")) {
System.out.println("안녕!"); //프로그램 종료부분
break;
}
}
}
private void detele() {
list.remove(no - 1); //-1을 해준이유!! 글번호는 3번이라면 list에 위치는 0
no = 0; //부터 시작하기 때문에 -1해줘야한다. 역시 다시 0으로~
System.out.println("삭제되었습니다!");
}
private void update() {
Member m = list.get(no - 1); //일단 입력받은 위치에 인덱스에 접근. 역시-1
Member copy = m.clone(); //변경을 취소할수도 있기때문에 일단 객체의 카피본생성
System.out.printf("번호(%1$d):", no); //no값은 직접세팅! 입력을 받지 않기때문에.
System.out.printf("이름(%1$s):", m.getName());//Member 클래스에 정의된 clone메소드
String value = scanner.nextLine(); //를이용 다른 Member객체를 생성 인스턴스변수를
if (value.length() > 0) { //list에 no에 위치객체에 접근 인스턴스를 복사한다.
copy.setName(value); //수정할 데이타가 없다면 변경하지 않는다.
}
System.out.printf("전화(%1$s):", m.getPhone());
value = scanner.nextLine();
if (value.length() > 0) { // 위와동일
copy.setPhone(value);
}
System.out.printf("이메일(%1$s):", m.getEmail());
value = scanner.nextLine();
if (value.length() > 0) { // 역시 동일
copy.setEmail(value);
}
System.out.printf("블로그(%1$s):", m.getBlog());
value = scanner.nextLine();
if (value.length() > 0) { // 또 동일
copy.setBlog(value);
}
System.out.printf("나이(%1$d):", m.getAge());
value = scanner.nextLine();
if (value.length() > 0) { //인트타입 마춰주는거빼고 동일
copy.setAge( Integer.parseInt(value) );
}
System.out.print("변경하시겠습니까?(y/n)");
if(scanner.nextLine().toLowerCase().equals("y")){ //역시 대소문자를 가리지않게
copy.setRegDate(new Date()); //셋팅하고 Date객체정보도 가져온다
list.set(no-1, copy); //set메소드를 원레 위치값에 복사된
System.out.println("변경되었습니다!"); //인스턴스의 주소값을 전달(copy)
} else {
System.out.println("변경 취소하였습니다!"); //취소할경우 복사된 객체는 메소드가
} //끝남과동시에 소멸 list에 Member 타입의
} //배열의 요소는 변하지 않는다.
//역시 no = 0;초기화를 해주어야한다.
//(소스엔 빠짐)
//역시 no = 0;초기화를 해주어야한다.
//(소스엔 빠짐)
private void view(int no) { //list에 담긴 객체정보를 전부 출력하는
if (no > 0 && no <= list.size()) { //메소드
Member m = list.get(no - 1); //굳이 Member 객체를 선언하지 않아도
System.out.println("번호:" + no); //되지만 소스의 간결함과 가독성을 위해
System.out.println("이름:" + m.getName()); //객체 m 을 생성 접근하였다.
System.out.println("전화:" + m.getPhone());
System.out.println("이메일:" + m.getEmail());
System.out.println("블로그:" + m.getBlog());
System.out.println("나이:" + m.getAge());
System.out.printf("등록일:%1$tY-%1$tm-%1$td \n", m.getRegDate());
} else { //Date 인스턴스에 접근하고 출력시
//printf메소드를 사용 (API)참조
//printf메소드를 사용 (API)참조
System.out.println("존재하지 않는 멤버의 번호입니다.");
}
}
public static void main(String[] args) {
// * 인스턴스 생성
// - 개별적으로 값을 다루기 위해, 클래스에 선언된
// 인스턴스 변수를 준비
// - 인스턴스가 사용되기 전에 필요한 작업을 수행하도록
// 생성자 메서드를 호출한다.
RedApp app = new RedApp();
app.execute();
}
}
(1)RedApp class
메인메소드를 포함한 RedApp 클래스 밑의 Member 클래스와의
관계를 눈여겨보라.
(1)RedApp class
메인메소드를 포함한 RedApp 클래스 밑의 Member 클래스와의
관계를 눈여겨보라.
package net.bitacademy.java41.step07;
import java.util.Date;
// * Value Object = Data Transfer Object
// - 여러 속성의 값을 관련된 것 끼리 하나로 묶어서 다루는 클래스
// - 예) Member, Project, Task
public class Member {
private String name;
private String phone; //InCapsulation(캡슐화) 접근제한자가 private
private String email; // 다른 클래스에선 직접 엑세스가 불가능하다.
private String blog;
private int age;
private Date regDate;
//getter and setter 를 통한 인스턴트 접근
public String getName() {
return name;
}
public Member setName(String name) {
this.name = name;
return this; //this 키워드는 현재 객체의 주고값 즉 Member class 에 주소값을 뜻한다.
}
public String getPhone() {
return phone;
}
public Member setPhone(String phone) {
this.phone = phone;
return this; //왜 모든 setter메소드가 현재객체를 반환하고 있을까?
}
public String getEmail() {
return email;
}
public Member setEmail(String email) {
this.email = email;
return this; // 위에서 언급했듯이 미리 데이타를 입력하기위해 현재 객체를 반환
// RedApp 클래스 생성자를통한 인스턴스 변수의 셋팅을 위함이다.
//프로그램 취지상 않해도 되긴하지만 test 할때 매번 데이타를 직접 입력
//해야하는 번거로움을 없애기위해서!!!
// RedApp 클래스 생성자를통한 인스턴스 변수의 셋팅을 위함이다.
//프로그램 취지상 않해도 되긴하지만 test 할때 매번 데이타를 직접 입력
//해야하는 번거로움을 없애기위해서!!!
}
public String getBlog() {
return blog;
}
public Member setBlog(String blog) {
this.blog = blog;
return this;
}
public int getAge() {
return age;
}
public Member setAge(int age) {
if (age > 0 && age < 120) { //혹시라도 말도 안되는 나이값이 설정되지 않기위한 조건
this.age = age; //나이가 중요시되는 병원 기타등등 데이터의 오류입력을
} //원천봉쇄 하고자함.
return this;
}
public Date getRegDate() {
return regDate;
}
public Member setRegDate(Date regDate) {
this.regDate = regDate;
return this;
}
public Member clone() { //RedApp클래스에 update 때문에 만들어진 메소드
Member m = new Member();// 새로운 멤버 객체를 만들고 그객체에 현재 객체의
m.name = this.name; //인스턴스변수 값을 복사하고
m.phone = this.phone; //복사된 인스턴스 변수값을 가지고있는 새로운 m객체를
m.email = this.email; //반환 RedApp 에서 명령에따라 list에 set 하게된다.
m.blog = this.blog;
m.age = this.age;
m.regDate = this.regDate;
return m; // 이부분
}
}
각각의 데이터 초기화를 위한 Value Object 클래스
자, 그렇다면 결과물을 확인할때다.
1.사용자 입력은 생략하겟다 생성자로 셋팅했기때문에.
2.list 입력시 현제 저장된 데이터가 출력된다. 물론 프로그램종료시 다 날라감...
3.add 입력시 데이터를 입력받는다. 단 한글입력시 콘솔창에서 깨지는 현상이
나타나는데 일단은 데이터의 이동에 집중 하자 편집도 엉망이지만...
4다시 list 입력시 추가된 4번 리스트를 확인할수있다. 단 등록확인란에서 꼭y를
입력해야한다 n 입력시 등록이 되지 않는다.
5.view 2 를 입력하면 번호 2번에 데이터가 출력된다.임꺽정이네.
6.2번데이터 출력과 동시에 2-1한 값이 RedApp 클래스에 전역변수에 값이 들어감으로
7.delete 메소드를 호출할수 있다. delete 메소드는 전역변수에 값이 0보다커야만 호출되
므로....
8 역시 아직 delete 메소드는 호출 하지 않았기 때문에 전역변수 no의 값은 1을 가지고 있
어서 update가 가능 하다 update 부터 하겟다.
9.update 입력을 하면 view 명령어로 볼수있던 임꺽정의 정보가 올라오고
: 옆에 새로운 데이터를 입력할수있다.xxx로 통일했음.
10.y를 입력하여 변경을 완료한후 다시 list를 입력하면 기존에 임꺽정은 없어지고
xxx가 입력된걸 확인할수 있다.
11.다시 xxx를 지우기 위해 view 2를 입력하여 열람한후 delete 명령어를 입력하면
삭제되었습니다. 는 문구가 나온다.
12.다시 list를 입력해서 확인해보면 xxx 의 데이타는 없어졌다. 이로인해 모든기능완성!!
여기까지 봐주신분이 계시다면 쌩유..
잘봤습니다 감사합니다~
답글삭제잘봤습니다 감사합니다~
답글삭제