(21)-23.10.23[JAVA]

DANA·2023년 10월 25일

KDT-구디아카데미

목록 보기
21/56

AMain

  • 메소드 오버로딩(Method Overloading): 한 클래스에 이름이 동일한 메서드가 중복 정의되어 있는 경우. 파라미터(매개변수)의 타입이나 개수가 달라야 한다
<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 타입으로 매개변수화
  • int: 변수의 타입(기본형)
  • Integer: int의 래퍼 클래스(wrapper class)

    wrapper class
    기본 타입의 값을 객체로 취급해야 하는 경우가 있는데 기본 타입의 값을 그대로 사용할 수 없어 변환을 해야 함.
    이때 기본 타입의 값을 감싸는 클래스를 wrapper class라고 한다

동적배열: 크기가 자동으로 조절되며 요소를 추가, 삭제, 삽입, 액세스할 수 있는 효율적인 데이터 구조

BMain

<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. 발생 이유 다시 한 번 확인해보자

ListMain1

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

  • add(int, element) : void - 리턴타입이 void라서 대입연산자로 받을 수 없다.
<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

<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

ListMain4

  • CRUD 제네릭 타입에 VO 또는 Map을 넣어서 연습해보자

CRUD: "Create, Read, Update, Delete"를 나타내는 데이터 조작 작업
- Create(생성): 데이터를 추가할 때 어떤 타입의 데이터를 생성할 것인지
- Read(읽기): 어떤 타입의 데이터를 읽을 것인지
- Update(갱신): 어떤 타입의 데이터를 갱신할 것인지
- Delete(삭제): 어떤 타입의 데이터를 삭제할 것인지

이를 위해 제네릭 타입을 사용하면 다양한 데이터 타입에 대해 동일한 CRUD 작업을 수행할 수 있는 유연성을 제공합니다. 일반적으로 제네릭 타입은 데이터 구조(예: 리스트, 맵) 또는 클래스를 정의할 때 사용됩니다.

  • 제네릭을 VO나 Map으로 선택하는 건 JSON 사전 준비작업
    (일반적으로 타입 안정성과 데이터 일관성이 중요한 경우 VO를 사용하고, 동적 데이터나 다양한 데이터 형식을 다루어야 할 때 Map을 선택)
  • 공공포털이나 회사들이 자신들의 서버를 공개하지 않는대신 요청에 대한 검색 결과를 JSON으로 제공
    ex. List(VO) -> JSON, JSON -> List<|VO>, List<|Map>
  • <입력>
    • 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

<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

<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

<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

<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

<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

Powder

package collec.list;

public class Powder {
	@Override
	public String toString() {
		return "나는 파우더 입니다.";
	}
}
  • 이 클래스는 toString 메소드를 오버라이딩하여 객체를 문자열로 표현할 때 "나는 파우더 입니다."라는 문자열을 반환하도록 설정

Plastic

package collec.list;

public class Plastic {
	@Override
	public String toString() {
		return "나는 플라스틱 입니다.";
	}
}
  • 이 클래스는 toString 메소드를 오버라이딩하여 객체를 문자열로 표현할 때 "나는 플라스틱 입니다."라는 문자열을 반환하도록 설정
  • @Override 어노테이션: 컴파일러에게 해당 메소드가 슈퍼 클래스에서 상속받은 메소드를 오버라이딩한다는 것을 알려줌
  • toString(): Object 클래스에 정의된 메소드 중 하나. 이 메소드는 객체를 문자열로 표현하는 데 사용되며, 기본적으로는 클래스 이름과 해시 코드를 문자열로 반환

ThreeDPrinter1

  • 제네릭을 사용한다는 건 주소번지를 두번 접근해야 값에 도달함
  • 데이터셋 역할을 하는 클래스 설계에 대한 이해가 필요하다
  • Spring Boot: DB연동을 직접하지 않는다(DML을 사용하지 않는다.) - 그런데 DB연동은 된다
  • 자동으로 해준다 - Hibernate사용 - 데이터베이스의 테이블 관계를 클래스 설계로 처리하기 때문에 쿼리문이 없이도 DB연동이 가능하다
<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;
	}
}
  • Getter 메서드: 다른 클래스에서 이 메서드를 호출하여 3D 프린터의 재료를 얻을 수 있음
  • Setter 메서드: 이 메서드를 호출하여 3D 프린터의 재료를 변경할 수 있음. 새로운 Powder 객체를 전달하여 설정할 수 있음

ThreeDPrinter2

<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;
	}
}

ThreeDPrinter3

<Object 타입-이렇게 하지 말 것>
package collec.list;

public class ThreeDPrinter3 {
	private Object material;

	public Object getMaterial() {
		return material;
	}

	public void setMaterial(Object material) {
		this.material = material;
	}
}
  • Object 타입은 포괄적인 대신 직관적이지 않기 때문에 타입을 맞춰야 한다.
  • ClassCastingException(형변환 오류)이 발동될 수 있으며, 서버가 다운되기도 하기 때문에 포괄적인 타입은 위험함

MaterialTest

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());
	}
}
출력: 나는 플라스틱 입니다.
     나는 플라스틱 입니다.
  • Plastic 클래스에서 toString()가 재정의(오버라이딩)되지 않았다면 주소번지가 출력되는데, 재정의가 되어있기 때문에 주소번지가 출력되지 않는다
  • UI솔루션을 사용하여 자바와 연동시에 인터페이스 되는 부분들을 toString()재정의해서 사용할 수 있다
    : 공통코드 만드는 사람 => 공통팀(백엔드로 국한되지 않음 - 프론트도 포함)

ThreeDPrinterTest

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();
	}
}
  • 타입을 잘못 맞추면 ClassCastingException이 발동할 수 있다(멈춘다)

GenericMaterial

<사용자 정의 제네릭 구현하기>
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;
	}
}
  • 제네릭 타입 자료형 매개변수 'T'(type parameter) : 이 클래스를 사용되는 시점에서 실제 사용할 자료형이 결정된다. (컴파일 타임에 JVM이 바꿔치기를 해준다.)
  • 단 static변수형은 사용 불가함(컨벤션)
  • GenericMaterial클래스: 제네릭 자료형을 사용하는 클래스
  • T는 보통 Type의 약자로 사용되며, T 말고 다른 이름으로 대체 가능함

0개의 댓글