<AMain>
package collec.basic;
import java.util.ArrayList;
import java.util.List;
class A {
// Integer: int의 wrapper클래스
List<Integer> nums = new ArrayList<>();
int ival;
String s = null;
String s1 = new String();
// A클래스에는 3개의 생성자가 있다
A() { // 기본 생성자
s = new String("나신입"); // s에 "나신입" 문자열 할당
}
A(int ival) { // int 파라미터를 받는 생성자 A
s = new String("나초보");
}
A(String name) {
s = new String(name); // 인자로 받은 문자열을 's'에 할당
}
}
public class AMain {
public static void main(String[] args) {
System.out.println("main 호출");
// A클래스의 전역변수들은 읽혀졌을까? 인스턴스화(A클래스)를 안했기 때문에 안읽혔다.
String s = null;
// System.out.println(s); // null
// System.out.println(s.length()); // 0이 아니라 NullPointerException
// s = "";
// System.out.println(s); // 공백
// System.out.println(s.length()); // 0
// "나신입" 출력하기
// 1.
A a = new A();
System.out.println(a.s);
// 2.
A a1 = new A(0);
a1.s = "나신입";
System.out.println(a1.s);
// 3. 생성자의 파라미터 자리(메소드 오버로딩)를 활용
A a2 = new A("나신입");
System.out.println(a2.s);
s = "나신입"; // Q.이게 어느 s에 값이 들어간거지?
a2 = new A(s);
System.out.println(a2.s);
}
}
*추가 설명*
List<Integer> nums = new ArrayList<>();
- List<Integer>: Integer 형식의 요소를 보유하는 리스트 타입을 선언
- nums: ArrayList 인스턴스에 대한 참조를 저장하는 변수
--------------------------------------------------
- ArrayList 클래스의 인스턴스를 생성
- ArrayList 인스턴스: Integer 객체를 저장하는 동적 배열 형태의 리스트
- ArrayList: Java에서 제공하는 동적 배열
=> 제네릭에서 ArrayList<> 구문을 사용하여
ArrayList를 Integer 타입으로 매개변수화
wrapper class
기본 타입의 값을 객체로 취급해야 하는 경우가 있는데 기본 타입의 값을 그대로 사용할 수 없어 변환을 해야 함.
이때 기본 타입의 값을 감싸는 클래스를 wrapper class라고 한다
동적배열: 크기가 자동으로 조절되며 요소를 추가, 삭제, 삽입, 액세스할 수 있는 효율적인 데이터 구조
<Try-catch문>
try {
// 예외가 발생할 수 있는 코드
} catch (예외타입 변수) {
// 예외타입1에 대한 처리 코드
} finally {
// 항상 실행되어야 하는 코드 (선택 사항)
}
<BMain>
package collec.basic;
import java.util.ArrayList;
import java.util.List;
class B {
List<Integer> nums = new ArrayList<>();
int ival;
String s = null; // 초기값으로 null 설정
String s1 = new String();
B() {}
B(int ival) {
s = new String("나초보");
}
}
public class BMain {
public static void main(String[] args) {
System.out.println("main 호출");
B b = new B();
try {
// b의 s 변수에 접근 시도
System.out.println(b.s.length());
} catch (Exception e) {
System.out.println("NullPointerException");
}
b = new B(1);
System.out.println(b.s.length()); // 나초보
}
}
b.s.length()
- 문자열 s의 길이를 나타내는 메소드 호출
→ 문자열의 길이 즉, 포함된 문자(문자열) 개수 반환
NullPointerException 발생 이유
: 디폴트 생성자에서 s에 대한 인스턴스화가 안 됨
('s' 변수가 'null'로 초기화되어 있기 때문)
Q. 발생 이유 다시 한 번 확인해보자
List<Integer> 변수 = new ArrayList<>();
- List<Integer> 변수
: Integer 타입의 요소를 저장하는 리스트를 선언
: 이 리스트는 정수(Integer) 값들을 저장할 수 있는 리스트
- new ArrayList<>();
: ArrayList라는 리스트 타입의 객체를 생성하는 코드
- ArrayList<>();
: 제네릭(Generic)을 사용하여 요소의 타입을 지정하지 않고,
나중에 사용될 때 타입이 자동으로 추론
- ArrayList
: Java 컬렉션 프레임워크에서 제공하는 동적 배열
: 요소를 추가하고 제거하는 데 유용한 자료구조
<ListMain1>
package collec.list;
import java.util.ArrayList;
import java.util.List;
class List1{
// 아래 전역변수(nums)는 인스턴스화(생성자 호출) 할 때 읽혀진다
List<Integer> nums = null; // 선언만
List1() { // List1 클래스의 생성자 List1()
// 생성자에서 지역 변수 nums을 새 ArrayList<Integer> 객체로 초기화
// 전역 변수 nums가 아니라 생성자 내의 지역 변수
List<Integer> nums = new ArrayList<>();
// 이 지역 변수 nums는 생성자를 빠져나갈 때 제거되므로 아무런 영향을 미치지 않음
// nums = new ArrayList<>();
// nums 타입을 적지 않았기 때문에 선언을 하지 않고 생성하기만 한 것 (전역변수 초기화)
}
}
public class ListMain1 {
public static void main(String[] args) {
// List1 클래스의 인스턴스를 생성
List1 list1 = new List1();
// list1은 Null이 아니다.
// List1 list1 = new List1(); 을 보면 알 수 있다.
// 인스턴스의 nums(전역)변수를 참조하여 ArrayList 객체를 새로 생성하고 초기화
// 이제 nums 변수가 ArrayList<Integer> 객체를 참조
list1.nums = new ArrayList<>();
// 이와같은 방법은 전역변수일 때만 가능하다.
// 지역변수일 때는 리턴타입으로 해결 (Q. 어떻게 해결?)
// ArrayList 객체에는 아무 요소가 없으므로 size() 메소드는 0을 반환
System.out.println(list1.nums.size());
}
}
<ListMain2-문제>
package collec.list;
import java.util.ArrayList;
import java.util.List;
class List2 {
List<Integer> li = new ArrayList<>();
List<String> names = null;
List2() {
// insert here - names를 인스턴스화 하는 문장을 작성하시오
// 생성자 내부에서 List<String> names를 ArrayList 객체로 초기화
names = new ArrayList<>();
// insert here - li에 숫자 1을 담는 코드를 작성하시오
// li에 숫자 1을 인덱스 0 위치에 추가
li.add(0, 1);
// names에 "나신입"을 인덱스 0 위치에 추가
names.add(0, "나신입");
}
}
public class ListMain2 {
public static void main(String[] args) {
List2 list2 = new List2();
// insert here -> [1]을 출력하는 문장을 적으시오
// li 리스트에서 0번 인덱스에 있는 요소인 1을 출력
System.out.println(list2.li.get(0)); // 출력: 1
// insert here -> [나신입] 을 출력하는 문장을 적으시오
// names 리스트에서 0번 인덱스에 있는 요소인 "나신입"을 출력
System.out.println(list2.names.get(0)); // 출력: 나신입
}
}
<ListMain2-답>
package collec.list;
import java.util.ArrayList;
import java.util.List;
class List2 {
List<Integer> li = new ArrayList<>();
List<String> names = null;
boolean isOk = false;
List2() {
names = new ArrayList<>();
// insert here - li에 숫자 1을 담는 코드를 작성하시오. - boolean isOk = add(Object obj)
// 논리에러를 찾는 건 어렵다. (조건문과 반복문 섞어쓰기) - 런타임 에러이다. - 디버깅 어렵다.
// html과 Java(List와 Map -> JSON으로 뽑고 그 데이터셋을 <td>나신입{자바자리-Map, XXXXVO}</td> 섞어쓰기
// li 리스트에 숫자 1을 추가
boolean isOk = li.add(1); // li.size()=1 , List의 기호는 [1] - Front-End와 Back-End만나는 부분 처리.(List-[], Map-{})
// isOk는 add 메소드의 처리 결과를 가지고 있는 변수
// this.isOk를 초기화하여 데이터 추가가 성공했는지 나타냅니다.
this.isOk = isOk;
System.out.println("isOk가 true이면 데이터 추가를 성공했다는 것이다."); // 사용자(업무담당자)에 대한 응답처리의 기준값으로 사용됨
// 사용자 정의 메소드를 구현할 때 리턴타입에 대해서 신중하게 결정한다.
// names 리스트에 "나신입"을 추가
names.add("나신입");
System.out.println(names); // names 리스트 출력
// 이 코드는 인스턴스화 없이도 출력이 가능하다.
// 왜냐면 내 안에 정의된 전역변수 이니까.
// 아래 코드가 실행되면 나신입이 나초보로 덮어씌어진다
// names 리스트에서 0번 인덱스의 값을 "나초보"로 변경
Object obj = names. set(0, "나초보");
// add로 하면 size - 2, set으로 하면 size는 늘 1이다.
// set 메소드는 특정 위치에 값을 대체하고, 이전 값은 obj 변수에 저장
}
}
public class ListMain2 {
public static void main(String[] args) {
// insert here -> [1]을 출력하는 문장을 적으시오. - 인스턴스화
List2 li2 = new List2();
System.out.println(li2.li); // [1] - 생성자를 경유 하기 때문에 boolean isOk = li.add(1); 를 만났다.
//insert here -> [나신입] 을 출력하는 문장을 적으시오.
System.out.println(li2.names); // [나초보]
// boolean isOk = li.add(1); 라인에서 처리된 결과를 여기에서 확인받고 싶다. 어떡하지? - 어? isOk가 지역변수네! -> 전역변수로 해결하기 -> 초기화
// this.isOk = isOk; 라인에서 전역변수에 초기화를 다시 하면 한 번 생성된 인스턴스 변수에 대해서 isOk값은 하나의 값만 가진다. - 유지문제
System.out.println(li2.isOk); // true가 출력됨 -> li2.size() 했을 때 1이 출력된다면 확인된 것이다.
}
}
boolean 메소드 사용하는 이유
add 메소드가 성공적으로 요소를 리스트에 추가한 경우 true를 반환하며, 실패한 경우에는 false를 반환
→ 데이터 추가 작업의 성공 여부를 확인 가능
(처리 결과를 받을 수 있다)if(isOk) System.out.println("처리성공"); else System.out.println("처리실패");
<ListMain3>
package collec.list;
// 컬렉션 프레임워크에는 Object만 담을 수 있다. -> 원시형은 불가능 하다.
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
class List3 {
// 생성자에서 li에 3.14를 담고 싶어 한다. 적절한 제네릭 타입은?
List<Double> li = new ArrayList<>();
List<Boolean> isOk = null;
List3() {
li.add(3.14);
//insert here - 아래 코드에서 NullPointerException의 원인이 발견되었다
//이 문제를 해결하는 코드를 작성하시오.
isOk = new ArrayList<>(); // 싱글 스레드에서 안전
isOk = new Vector<>(); // 멀티 스레드에서 안전
isOk.add(true); // isOk 리스트에 true 저장
}
} /////////// end of List3
public class ListMain3 {
public static void main(String[] args) {
List3 l1 = new List3();
System.out.println(l1.li); //3.14가 출력된다
System.out.println(l1.isOk); //true가 출력된다
System.out.println("List1에 선언된 자료구조 초기화해보기");
} ///////////////// end of main
} /////////////////// end of ListMain3
CRUD: "Create, Read, Update, Delete"를 나타내는 데이터 조작 작업
- Create(생성): 데이터를 추가할 때 어떤 타입의 데이터를 생성할 것인지
- Read(읽기): 어떤 타입의 데이터를 읽을 것인지
- Update(갱신): 어떤 타입의 데이터를 갱신할 것인지
- Delete(삭제): 어떤 타입의 데이터를 삭제할 것인지
이를 위해 제네릭 타입을 사용하면 다양한 데이터 타입에 대해 동일한 CRUD 작업을 수행할 수 있는 유연성을 제공합니다. 일반적으로 제네릭 타입은 데이터 구조(예: 리스트, 맵) 또는 클래스를 정의할 때 사용됩니다.
- <입력>
- add(element): boolean
: 응답처리시에 선택해야하는 메소드
: 리턴타입이 boolean이라서 처리 결과에 대한 응답을 받아볼 수 있다(보이지 않는것을 확인해 줌)- add(int, element): void
: 응답처리시에는 부적합하다.
→ 메소드 선택 시 기준이 될 수 있다(리턴타입이 있고 없고가 기준에 영향이 있다). 안전한 코드를 작성하기 위해 사용자 정의 메소드를 설계할 때 리턴타입을 반드시 고려하기
- <수정>
- set(int, element):Element(=Object)
: 내가 추리한 것을 그대로 반환해준다.
: 입력은 새로운 정보를 추가, 수정은 기존에 있는 정보를 변경
<ListMain4-CRUD 수정>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List4 {
List<Integer> rank = new ArrayList<>();
void init() {
// 초기 순위 데이터를 목록에 추가
rank.add(1);
rank.add(2);
rank.add(3);
}
// 리스트에 등록된 순위를 수정하는 메소드 구현
// 사용자로부터 두 개의 정보를 입력받기(UI, UX, View계층에서)
boolean rankUpdate(int index, int value) { // Q. 여기서 말하는 index가 뭐지?
boolean isOk = false;
// index 위치의 값을 value로 설정(수정)
Integer it = rank.set(index, value);
// isOk = true; 라인을 경유하는지 아니면 스킵하게 되는건지 짐작 가능함
int x = it; // 오토박싱
System.out.println(x + "," + value);
// 수정 결과 값 it와 사용자로부터 입력받은 값 value를 비교
System.out.println(it == value);
// 사용자로부터 받아온 값과 set메소드의 리턴값으로 받아온 값을 비교
Q. 사용자로부터 받아온 값이 value->it에 담겼다는 것까지는 이해했어. set메소드의 리턴값이 어디에 있지? 언제 리턴했지?
if (it != null) { // it가 null이 아니면 수정 성공
System.out.println("받아온 값과 수정된 값이 같니??");
isOk = true;
}
return isOk;
}
}
public class ListMain4 {
public static void main(String[] args) {
System.out.println("수정하고자 하는 위치값과 숫자를 입력 하시오. 예) 위치값 | 변경할값 ");
Scanner sc = new Scanner(System.in);
// 사용자로부터 "위치값 | 변경할 값" 형식의 입력 받기
String user = sc.nextLine();
// StringTokenizer를 사용하여 입력값을 파싱하여 index와 value로 분리
StringTokenizer st = new StringTokenizer(user, "|");
String imsi = st.nextToken();
int index = Integer.parseInt(imsi);
String value = st.nextToken();
int ivalue = Integer.parseInt(value);
// List4 클래스의 인스턴스 생성
List4 l4 = new List4();
l4.init(); // 초기 순위 데이터 설정
// rankUpdate 메소드 호출하여 수정 작업 수행
boolean isOk = l4.rankUpdate(index, ivalue);
if (isOk) {
System.out.println("수정 처리되었습니다.");
// 수정된 목록 출력
// [1,2,3] --> 1|3 -> [1,3,3]
System.out.println(l4.rank);
} else {
System.out.println("수정 실패하였습니다.");
}
}
}
오토박싱(Auto Boxing)
: 자바에서 제공되는 자동 형 변환 기능 중 하나로, 기본 자료형과 해당 래퍼(wrapper) 클래스 사이의 변환을 자동으로 수행int x = it;
- it: Integer 클래스의 객체 / x: 기본 자료형인 int 변수
- 오토박싱이 제공되고 있어서 Integer 객체와 int 자료형 사이의 변환을 자동으로 처리
- 따라서 it 객체의 내부 값(정수)을 추출하여 int 변수 x에 저장하는 것이 가능하며, 이 과정에서 오토박싱이 자동으로 수행
StringTokenizer
: 자바에서 문자열을 구분자(delimiter)를 기준으로 토큰(token)으로 나누는 데 사용되는 클래스. 주로 CSV 파일 또는 텍스트 데이터를 파싱할 때 유용하게 쓰임
StringTokenizer를 사용하려면 문자열과 구분자를 지정하고, 이를 토큰으로 분리합니다. 기본적으로 공백(whitespace)을 포함한 여러 구분자(탭, 쉼표, 세미콜론 등)를 사용할 수 있습니다. 여러 개의 토큰을 생성하고 각 토큰에 순차적으로 접근할 수 있습니다.
*파싱(Parsing): 데이터를 의미 있는 조각으로 분해하고, 이러한 조각을 읽고 이해하여 데이터를 추출하거나 조작하는 작업을 포함
<StringTokenizer 예제>
import java.util.StringTokenizer;
public class StringTokenizerExample {
public static void main(String[] args) {
String data = "apple,banana,cherry,dates";
StringTokenizer tokenizer = new StringTokenizer(data, ",");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
System.out.println(token);
}
}
}
쉼표(,)를 구분자로 사용하여 문자열 "apple,banana,cherry,dates"를 토큰으로 분리하고, 각 토큰을 출력
<결과>
apple
banana
cherry
dates
Integer.parseInt() 메소드
int index = Integer.parseInt(imsi); int ivalue = Integer.parseInt(value);
- 사용자로부터 입력받은 문자열(imsi,value)을 정수(int)로 변환
→ 문자열이 반드시 숫자(ex."2")여야 하며, 음수 기호나 실수 부분 등은 정수로 변환되지 않음
만약 imsi(value)에 저장된 문자열이 정수로 변환할 수 없는 경우(예: "abc"와 같이 숫자가 아닌 문자가 들어있는 경우), Integer.parseInt는 NumberFormatException 예외를 발생시킵니다. 이 경우, 프로그램 실행이 중단될 수 있으므로 예외 처리를 통해 이러한 상황에 대비하는 것이 좋습니다.
if문에서 (it != null) 로 조건을 준 이유
만약 index 위치에 값을 설정하지 못한 경우, set 메소드는 null을 반환합니다. 따라서 if (it != null)은 set 메소드가 값의 설정을 성공했는지를 확인하기 위한 조건입니다.Integer it = rank.set(index, value);
<ListMain5-1. CRUD 수정2>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List5 {
// 제네릭을 원시형 타입에서 참조형(xxxVO, Map)으로 바꾸었다.
List<String> rank = new ArrayList<>();
void init() {
// 초기화 메소드를 호출하면 rank 리스트에 세 가지 등수를 초기화
rank.add(0, "나신입");
rank.add(1, "나초보");
rank.add(2, "나일등");
}
boolean rankUpdate(int index, String newValue) {
boolean isOk = false;
// oldValue : 기존에 들어있던 값을 담는 변수 선언
// newValue : 새로 들어갈 값을 담을 변수 (사용자가 입력한 이름으로 담음
// rank 리스트에서 기존 값(oldValue)을 새 값(newValue)으로 수정
String oldValue = rank.set(index,newValue);
// 기존 값(oldValue)과 새 값(newValue)을 출력
System.out.println(oldValue + ", " + newValue);
// 기존 값(oldValue)과 새 값(newValue)이 동일한지 확인
System.out.println(oldValue.equals(newValue));
// 문제 - 기존의 값과 같은 값이면 수정처리 하지 않도록 코드를 수정하시오
if (oldValue != null) {
System.out.println("받아온 값과 수정된 값이 같니??");
// 수정 작업이 성공했으면 "isOk"를 true로 설정
isOk = true;
}
return isOk;
}
}
public class ListMain5 {
public static void main(String[] args) {
System.out.println("수정하고자 하는 위치값과 숫자를 입력 하시오. 예) 위치값 | 변경할값 ");
Scanner sc = new Scanner(System.in);
// 사용자로부터 위치값과 변경할 값을 입력받아서 처리
String user = sc.nextLine();
StringTokenizer st = new StringTokenizer(user, "|");
// 위치값과 변경할 값을 추출
String imsi = st.nextToken();
int index = Integer.parseInt(imsi);
String value = st.nextToken();
List5 l5 = new List5();
l5.init(); // 초기화 메소드를 호출하여 초기값을 설정
boolean isOk = l5.rankUpdate(index, value);
if (isOk) {
System.out.println("수정 처리되었습니다.");
// 수정된 결과 출력: [1,2,3] --> 1|3 -> [1,3,3]
System.out.println(l5.rank);
} else {
System.out.println("수정 실패하였습니다.");
}
}
}
<ListMain5-2>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List5{
List<String> rank = new ArrayList<>(); //rank.size()=0
void init() { // 전역변수의 선언된 깡통에 3가지 정보를 추가하기
rank.add(0,"나신입");
rank.add(1,"나초보");
rank.add(2,"나일등");
}
boolean rankUpdate(int index, String newValue) {
boolean isOk = false;
boolean isEqual = false;
for(int i=0;i<rank.size();i++) {
//사용자가 입력한 인덱스의 위치값과 rank리스트의 인덱스 값이 같으면 그 자리가 변경할 위치이다.
if(i==index) {
String oldValue = rank.get(index); //그 때 그 위치값이 우리가 비교할 기존에 이름값이다.
if(oldValue.equals(newValue)) {
isEqual = true;
}
} ////////// end of if
} /////////////end of for
// 문제 - 기존 값과 같은 값이면 수정처리 하지 않도록 코드를 수정하시오.
if(isEqual) {
System.out.println("기존 이름과 같은 이름을 입력하셨습니다. 다시 확인하세요.");
return false;
}else {
System.out.println("기존 이름과 다른 이름을 입력하셨습니다. 수정을 진행합니다.");
String oldValue = rank.set(index, newValue);
isOk = true;
}
return isOk;
}
}
public class ListMain5 {
public static void main(String[] args) {
System.out.println("수정하고자 하는 위치값과 이름을 입력하시오. 예)위치값|변경할값");
Scanner sc = new Scanner(System.in);
String user = sc.nextLine();
StringTokenizer st = new StringTokenizer(user, "|");
String imsi = st.nextToken();
int index = Integer.parseInt(imsi);
String value = st.nextToken();
List5 l5 = new List5();
l5.init();
boolean isOk = l5.rankUpdate(index, value);
if(isOk) {
System.out.println("수정 처리되었습니다.");
System.out.println(l5.rank);
}
else System.out.println("수정 실패하였습니다.");
}
}
<ListMain6-CRUD 삭제>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List6 {
List<String> rank = new ArrayList<>();
void init() {
rank.add(0,"나신입");
rank.add(1,"나초보");
rank.add(2,"나일등");
}
boolean rankDelete(String delValue) {
boolean isOk = false;
// insert here
isOk = rank.remove(delValue);
return isOk;
}
}
public class ListMain6 {
public static void main(String[] args) {
System.out.println("삭제하고자 하는 이름을 입력하시오.");
Scanner sc = new Scanner(System.in);
String value = sc.nextLine();
List6 l6 = new List6();
l6.init();
boolean isOk = l6.rankDelete(value);
if(isOk) {
System.out.println("삭제 처리되었습니다.");
System.out.println(l6.rank);
}
else System.out.println("삭제 실패하였습니다.");
}
}
<ListMain7-CRUD 입력>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List7{
List<String> rank = new ArrayList<>();//rank.size()=0
void init() {
rank.add(0,"나신입");
rank.add(1,"나초보");
rank.add(2,"나일등");
}
// 아래코드가 실행이 되면
boolean rankInsert(String newValue) {
boolean isOk = false;
// insert here
isOk = rank.add(newValue);
return isOk;
}
}
public class ListMain7 {
public static void main(String[] args) {
System.out.println("추가하고자 하는 이름을 입력하시오.");
Scanner sc = new Scanner(System.in);
String value = sc.nextLine();
List7 l7 = new List7();
l7.init();
boolean isOk = l7.rankInsert(value);
if(isOk) {
System.out.println("추가 처리되었습니다.");
System.out.println(l7.rank);
}
else System.out.println("추가 실패하였습니다.");
}
}
<ListMain8-CRUD (전체)조회>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List8{
List<String> rank = new ArrayList<>();
void init() {
rank.add(0,"나신입");
rank.add(1,"나초보");
rank.add(2,"나일등");
}
// 아래코드가 실행이 되면
// 전역변수이면 어차피 동기화가 된다 - 하나이다. - static
// 단 최초에는 빈 깡통 이니까, 3명의 명단을 출력하려면 init()메소드를 경유 시킬 것. - 전처리
void rankSelect() { // 왜 리턴타입을 void 로 바꾸는 건가요?? -> 전역변수이기 때문에.
System.out.println(rank);
}
// 자료구조에 들어있는 값을 순회하는데 get(int)메소드의 리턴타입이 Element인 것을
// 사용자 정의 메소드를 구현하여서 굳이 리턴타입을 boolean으로 바꾸어 본다. (if문 복습)
// 한 건 조회하기. -> 조건식이 필요하니까 파라미터가 필요하고 전체조회는 있는거 모두 출력이니까 파라미터가 필요 없다
boolean rankDetail(int index) {
boolean isOk = false;
String name = null;
// insert here
name = rank.get(index);
if(name != null) {
isOk = true;
System.out.println(name);
}
return isOk;
}
}
public class ListMain8 {
public static void main(String[] args) {
System.out.println(" 전체조회 1번을 입력하고 상세조회이면 2번을 입력하세요");
Scanner sc = new Scanner(System.in);
String value = sc.nextLine();
List8 l8 = new List8();
l8.init();
if ("1".equals(value)) {
// 나 전체 목록 볼거야
l8.rankSelect();
} else if ("2".equals(value)) {
System.out.println("조회하실 번호를 입력하세요.");
value = sc.nextLine();
int ivalue = Integer.parseInt(value);
l8.rankDetail(ivalue);
}
} ////////////// end of main
} //////////////// end of ListMain8
<ListMain9-CRUD 조회 직접 해보기>
package collec.list;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
class List9{
List<String> rank = new ArrayList<>();//rank.size()=0
void init() {
rank.add(0,"나신입");
rank.add(1,"나초보");
rank.add(2,"나일등");
//rank.add(3,"입력한 이름");
}
void rankSelect() {
System.out.println(rank);
}
boolean rankDetail(int index) {
boolean isOk = false;
String name = null;
//insert here
name = rank.get(index);
System.out.println("찾는 이름은 "+name+" 입니다.");
if(name!=null) {
isOk = true;
}
return isOk;
}
}
public class ListMain9 {
public static void main(String[] args) {
System.out.println("전체조회 1번을 입력하고 상세조회이면 2번을 입력하시오.");
Scanner sc = new Scanner(System.in);
List9 l9 = new List9();
l9.init();
// for(int i=0;i<5;i++) {
while(true) {
String menu = "-1";//-1 : End of file
menu = sc.nextLine();
if("1".equals(menu)) {
System.out.println("1번 전체조회를 선택하셨습니다.");
l9.rankSelect();
//return;//메인메소드를 빠져나간다.
continue;
}
else if("2".equals(menu)) {
System.out.println("2번 상세조회를 선택하셨습니다.");
System.out.println("상세조회를 원하는 번호를 입력하세요.");
String user = sc.nextLine();
System.out.println("상세보기를 원하는 번호는 "+user + " 입니다.");
int index = Integer.parseInt(user);
if(index>=0) {
l4.rankDetail(index);
}
//return;
continue;
}
else if("q".equals(menu)) {
//return;
System.out.println("프로그램을 종료합니다.\\n");
System.exit(0);
}
}
} //////////// end of main
} /////////////// end of ListMain9
package collec.list;
public class Powder {
@Override
public String toString() {
return "나는 파우더 입니다.";
}
}
package collec.list;
public class Plastic {
@Override
public String toString() {
return "나는 플라스틱 입니다.";
}
}
<Powder타입>
package collec.list;
public class ThreeDPrinter1 {
private Powder material;
// Getter 메서드: material 필드의 값을 반환
public Powder getMaterial() {
return material;
}
// Setter 메서드: material 필드의 값을 설정
public void setMaterial(Powder material) {
this.material = material;
}
}
<Plastic 타입>
package collec.list;
// List<Object> -> List<Element> -> List<T> type parameter -> 개발자 자유도를 높인다.
public class ThreeDPrinter2 {
private Plastic material;
// Plastic과 타입이 다르다
// private Powder material;
// 타입이 너무 포괄적/직관적이지 않다→ 유지보수 어려움
// private Object material;
public Plastic getMaterial() {
return material;
}
public void setMaterial(Plastic material) {
this.material = material;
}
}
<Object 타입-이렇게 하지 말 것>
package collec.list;
public class ThreeDPrinter3 {
private Object material;
public Object getMaterial() {
return material;
}
public void setMaterial(Object material) {
this.material = material;
}
}
package collec.list;
public class MaterialTest {
public static void main(String[] args) {
Plastic p = new Plastic();
System.out.println(p);
// 위와 같은 값 출력. 우리가 주소번지를 출력할 때는 toString이 생략되어 있는 것이다
// Q. 이게 무슨 말이지?
System.out.println(p.toString());
}
}
출력: 나는 플라스틱 입니다.
나는 플라스틱 입니다.
package collec.list;
public class ThreeDPrinterTest {
public static void main(String[] args) {
Powder p = new Powder();
// ThreeDPrinter3 클래스의 객체 tp3를 생성
ThreeDPrinter3 tp3 = new ThreeDPrinter3();
// 아래 코드에서 파라미터 이슈가 발생되지 않는건, Object이기 때문이다.
// Q. 어떤 파라미터 이슈인지?
// 3D 프린터에 Powder 객체 p를 설정
tp3.setMaterial(p);
// 3D 프린터에서 재료를 가져와 Powder 타입으로 형변환→ p1에 저장
Powder p1 = (Powder)tp3.getMaterial();
}
}
<사용자 정의 제네릭 구현하기>
package collec.list;
public class GenericMaterial<T> {
// 제네릭 타입 T로 선언된 material 필드
private T material;
// material 필드의 값을 반환하는 메소드
public T getMaterial() {
return material;
}
// material 필드의 값을 설정하는 메소드
public void setMaterial(T material) {
this.material = material;
}
}