728x90
반응형
SMALL
package miniprj.model;

import lombok.Data;

@Data
public class Book {
	// 예약자성함
	   String name;
	   // 체크인날짜
	   String checkIn;
	   // 체크아웃 날짜
	   String checkOut;
	   // 예약한 객실(standard, superior, suite 셋 중 하나)
	   String room;
	   // 예약 비밀번호
	   String password;
}
package miniprj.model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class BookDAO implements IBookDAO{

	@Override
	public int deleteBook(String name, String password) {
		int rowCount=0;
		String sql="delete from book where cust_name=? and pwd=?";
		Connection con=null;
		try {
			con=BookDataSource.getConnection();
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setString(1, name);
			stmt.setString(2, password);
			rowCount=stmt.executeUpdate();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			BookDataSource.closeConnection(con);
		}
		return rowCount;
	}

	@Override
	public int insertBook(Book book) {
		int rowCount=0;
		String sql="insert into book "
				+ "(cust_name, checkin, checkout, room, pwd) values(?,?,?,?,?)";
		Connection con=null;
		try {
			con=BookDataSource.getConnection();
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setString(1, book.getName());
			stmt.setString(2, book.getCheckIn());
			stmt.setString(3, book.getCheckOut());
			stmt.setString(4, book.getRoom());
			stmt.setString(5, book.getPassword());
			rowCount=stmt.executeUpdate();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			BookDataSource.closeConnection(con);
		}
		return rowCount;
	}

	@Override
	public int updateBook(Book book) {
		String sql="update book set checkin=?, checkout=?, room=? "
				+ "where cust_name=? and pwd=?";
		int rowCount=0;
		Connection con=null;
		System.out.println(book);
		try {
			con=BookDataSource.getConnection();
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setString(1, book.getCheckIn());
			stmt.setString(2, book.getCheckOut());
			stmt.setString(3, book.getRoom());
			stmt.setString(4, book.getName());
			stmt.setString(5, book.getPassword());
			rowCount=stmt.executeUpdate();
			
		} catch (Exception e) {
			throw new RuntimeException();
		}finally {
			BookDataSource.closeConnection(con);
		}

		return rowCount;
	}
	public boolean login(String name, String password) {
		String sql="select * from book where cust_name=? and pwd=?";
		int rowCount=0;
		Connection con=null;
		try {
			con=BookDataSource.getConnection();
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setString(1, name);
			stmt.setString(2, password);
			ResultSet rs=stmt.executeQuery();
			if (rs.next()) {
				return true;
			}else{
				System.out.println("일치하는 정보가 없습니다.");
				return false;
			}
		}catch (Exception e) {
			return false;
		}
	}

	@Override
	public int getBookCount() {
		String sql="select count(*) from book";
		int rowCount=0;
		Connection con=null;
		try {
			con=BookDataSource.getConnection();
			PreparedStatement stmt=con.prepareStatement(sql);
			ResultSet rs=stmt.executeQuery();
			rs.next();
			rowCount=rs.getInt(1);
		} catch (Exception e) {
			throw new RuntimeException();
		}finally {
			BookDataSource.closeConnection(con);
		}
		return rowCount;
	}

	@Override
	public Book getOne(String name, String password) {
		String sql="select * from book where cust_name=? and pwd=?";
		Connection con=null;
		Book book=new Book();
		try {
			con=BookDataSource.getConnection();
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setString(1, name);
			stmt.setString(2, password);

			ResultSet rs=stmt.executeQuery();
			while(rs.next()) {
				book.setName(rs.getString("cust_name"));
				book.setCheckIn(rs.getString("checkin"));
				book.setCheckOut(rs.getString("checkout"));
				book.setRoom(rs.getString("room"));
				book.setPassword(rs.getString("pwd"));
			}
		} catch (Exception e) {
			throw new RuntimeException();
		}finally {
			BookDataSource.closeConnection(con);
		}
		return book;
	}

	@Override
	public ArrayList<Book> getAllBooks() {
		// TODO Auto-generated method stub
		ArrayList<Book> list = new ArrayList<>();
		String sql = "select * from book";
		Connection con = null;
		
		try {
			con = BookDataSource.getConnection();
			PreparedStatement stmt = con.prepareStatement(sql);

			ResultSet rs = stmt.executeQuery();

			while(rs.next()) {
				Book book = new Book();
				book.setName(rs.getString("cust_name"));
				book.setRoom(rs.getString("room"));
				book.setPassword(rs.getString("pwd"));
				book.setCheckIn(rs.getString("checkin"));
				book.setCheckOut(rs.getString("checkout"));
				list.add(book);
			}
		}catch(SQLException e) {
			throw new RuntimeException(e);
		} finally {
			BookDataSource.closeConnection(con);
		}

		return list;

	}


}
package miniprj.model;

import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp2.BasicDataSource;

public class BookDataSource {
	private static final String DRIVER = "oracle.jdbc.OracleDriver";
	private static final String URL = "jdbc:oracle:thin:@localhost:1521:xe";
	private static final String USERNAME = "hr";
	private static final String PASSWORD = "hr";
	
	private static BasicDataSource dataSource;
	
	static {
		try {
			dataSource = new BasicDataSource();
			dataSource.setDriverClassName(DRIVER);            
			dataSource.setUrl(URL);
			dataSource.setUsername(USERNAME);                                  
			dataSource.setPassword(PASSWORD);  
			dataSource.setInitialSize(10);
			dataSource.setMaxTotal(10);
			System.out.println("DataSource created");
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
	
	public static Connection getConnection() throws SQLException {
		return dataSource.getConnection();
	}

	public static void closeConnection(Connection con) {
		if(con!=null) {
			try {
				con.close();
			}catch(Exception e) {}
		}
	}
}
package miniprj.model;

import java.util.ArrayList;

public interface IBookDAO {
	public int deleteBook(String name, String password);
	public int insertBook(Book book);
	public int updateBook(Book book);
	
	public int getBookCount();
	public Book getOne(String name, String password);
	public ArrayList<Book> getAllBooks();
}
package miniprj;

import java.util.List;
import java.util.Scanner;

import miniprj.model.Book;
import miniprj.model.BookDAO;

public class BookWin {
	static boolean isCustomer;
	   static boolean isAdmin;
	   private static  Scanner scan = new Scanner(System.in);
	   static BookDAO bookDao = new BookDAO();
	   static String name = null;
	   static String pwd = null;

	   // 호텔 예약 리스트
	   public static void list(Book list) {
	      System.out.printf("%-6s%-12s%-16s%-40s",list.getName(), list.getCheckIn(), list.getCheckOut(), list.getRoom());
	      System.out.println();
	   }

	   public static void mainMenu() {
	      System.out.println();
	      System.out.println("--------------------------------------------------------");
	      System.out.println("메인메뉴: 1.예약 | 2.조회 | 3.수정 | 4.삭제 | 5.로그아웃 | 6.종료");
	      System.out.println("메뉴선택: ");
	      String menuNo = scan.nextLine();
	      System.out.println();

	      switch(menuNo) {
	      case "1" -> {
	         Book book = new Book();

	         System.out.print("예약자: ");
	         book.setName(scan.nextLine());
	         System.out.print("체크인 날짜: ");
	         book.setCheckIn(scan.nextLine());
	         System.out.print("체크아웃 날짜: ");
	         book.setCheckOut(scan.nextLine());
	         System.out.print("객실: ");
	         book.setRoom(scan.nextLine());
	         System.out.println("비밀번호: ");
	         book.setPassword(scan.nextLine());

	         bookDao.insertBook(book);
	         break;
	      }

	      case "2" -> {
	         System.out.println("[호텔 예약관리 시스템]");
	         System.out.println("--------------------------------------------------------");
	         System.out.printf("%-6s%-12s%-16s%-40s", "성함","체크인 날짜","체크아웃 날짜","객실");
	         System.out.println("--------------------------------------------------------");
	         if (isAdmin) {
	            List<Book> list = bookDao.getAllBooks();
//	            System.out.println(list);
	            for(int i=0;i<list.size();i++) {
	               list(list.get(i));
	            }
	         } else if(isCustomer) {
	            Book book = bookDao.getOne(name, pwd);
	            list(book);
	         }
	         break;
	      }

	      case "3" -> {
	         Book book = bookDao.getOne(name, pwd);

	         System.out.print("체크인 날짜: ");
	         book.setCheckIn(scan.nextLine());
	         System.out.print("체크아웃 날짜: ");
	         book.setCheckOut(scan.nextLine());
	         System.out.print("객실: ");
	         book.setRoom(scan.nextLine());

	         bookDao.updateBook(book);
	         break;

	      }
	      case "4" -> {
	         Book onesBook = bookDao.getOne(name, pwd);
	         if(!onesBook.getName().equals(name)) {
	            System.out.println("예약건이 없습니다.");
	            break;
	         } 

	         int rowCount = bookDao.deleteBook(name, pwd);
	         System.out.println(rowCount + "건의 에약이 취소되었습니다.");
	         break;
	      }
	      case "5" -> {
	         isAdmin = false;
	         isCustomer = false;
	         name = null;
	         pwd = null;
	         loginMenu();
	         break;
	      }
	      case "6" -> {
	         System.out.println("프로그램이 종료되었습니다.");
	         System.exit(0);
	      }
	      }
	   }

	   public static boolean loginMenu() {
	      System.out.println();
	      System.out.println("--------------------------------------------------------");
	      System.out.println("성함을 입력하세요: ");
	      name = scan.nextLine();
	      System.out.println("비밀번호를 입력하세요: ");
	      pwd = scan.nextLine();

	      if(name.equals("admin") && pwd.equals("admin")) {
	         isAdmin = true;
	         return true;
	      } else if(bookDao.login(name, pwd)){
	         isCustomer = true;
	         mainMenu();
	         return true;
	      } else {

	         System.out.println("회원정보가 일치하지 않습니다.");
	         return false;
	      }


	   }

	   public static void main(String[] args) {
	      while(true) {
	         if(loginMenu()) {
	        	 while(isAdmin || isCustomer) {
	        		 mainMenu();
	        	 }
	            
	         }

	      }
	   }

}
728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #19 데이터베이스 입출력(게시판 프로그램)  (1) 2023.05.02
[JAVA] #18 입출력 스트림  (0) 2023.05.01
[JAVA] #17 스트림 요소 처리  (0) 2023.05.01
[JAVA] #16 람다식  (0) 2023.04.27
[JAVA] #15 컬렉션 자료구조  (0) 2023.04.27
728x90
반응형
SMALL
package ch20.oracle.sec12;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;


public class BoardExample {
	//매개변수
	private static Scanner scanner = new Scanner(System.in);
	private static Connection con=null;
	private static final String url="jdbc:oracle:thin:@localhost:1521:xe";
	
	
   	//게시물 목록 출력
	public static void list() {
		System.out.println();
		System.out.println("[게시물 목록]");
		System.out.println("--------------------------------------------------");
		System.out.printf("%-6s%-12s%-16s%-40s\n","no","writer","date","title");
		System.out.println("--------------------------------------------------");
		
		try {
			String sql="select * from boards order by bno desc";
			PreparedStatement pstmt=con.prepareStatement(sql);
			ResultSet rs=pstmt.executeQuery();
			
			while(rs.next()) {
				Board board = new Board();
				board.setBno(rs.getInt("bno"));
				board.setBtitle(rs.getString("btitle"));
				board.setBcontent(rs.getString("bcontent"));
				board.setBwriter(rs.getString("bwriter"));
				board.setBDate(rs.getDate("bdate"));
				System.out.printf("%-6s%-12s%-16s%-40s\n", 
						board.getBno(), board.getBwriter(),board.getBDate(),board.getBtitle());
			}
			rs.close();
			pstmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
			exit();
		}
        //메뉴 부르기
		mainMenu();
	}
	
    //메뉴
	public static void mainMenu() {
		System.out.println();
		System.out.println("--------------------------------------------------");
		System.out.println("메인 메뉴 : 1.Create | 2.Read | 3.Clear | 4.Exit");
		System.out.print("메뉴 선택: ");
		int menu = scanner.nextInt();
		scanner.nextLine();
		switch (menu) {
		case 1 -> create();
		case 2 -> read();
		case 3 -> clear();
		case 4 -> exit();
		default -> System.out.println("메뉴를 잘못 입력함.");
		}
	}
	
    //1번 create
    //데이터 생성 insert
	private static void create() {
		Board board = new Board();
		System.out.println("[새 게시물 입력]");
		System.out.print("제목: ");
		board.setBtitle(scanner.nextLine());
		System.out.print("내용: ");
		board.setBcontent(scanner.nextLine());
		System.out.print("작성자: ");
		board.setBwriter(scanner.nextLine());
		
		System.out.println("--------------------------------------------------");
		System.out.println("보조 메뉴: 1.OK | 2.Cancel");
		System.out.print("메뉴 선택: ");
		int menu=scanner.nextInt();

		if(menu==1) {
			try {
				String sql="insert into boards (bno, btitle, bcontent, bwriter, bdate)"
						+ " values(SEQ_BNO.NEXTVAL,?,?,?,sysdate)";
				PreparedStatement pstmt = con.prepareStatement(sql);
				pstmt.setString(1, board.getBtitle());
				pstmt.setString(2, board.getBcontent());
				pstmt.setString(3, board.getBwriter());
				pstmt.executeUpdate();
				pstmt.close();
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
				exit();
			}
		}
		list();
	}
	
    //2번 read
    //데이터 가져오기 select    
	private static void read() {
		System.out.println("[게시물 읽기");
		System.out.print("bno: ");
		int no=scanner.nextInt();
		scanner.nextLine();
		try {
			String sql="select * from boards where bno = ?";
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setInt(1, no);
			ResultSet rs=stmt.executeQuery();
			if(rs.next()) {
				Board board = new Board();
				board.setBno(rs.getInt("bno"));
				board.setBtitle(rs.getString("btitle"));
				board.setBcontent(rs.getString("bcontent"));
				board.setBwriter(rs.getString("bwriter"));
				board.setBDate(rs.getDate("bdate"));
				System.out.println("#############");
				System.out.println("번호: "+board.getBno());
				System.out.println("제목: "+board.getBtitle());
				System.out.println("내용: "+board.getBcontent());
				System.out.println("작성자: "+board.getBwriter());
				System.out.println("날짜: "+board.getBDate());
			
				System.out.println("--------------------------------------------------");
				System.out.println("보조 메뉴: 1.Update | 2.Delete | 3.List");
				System.out.print("메뉴 선택: ");
				int menu=scanner.nextInt();
				scanner.nextLine();

				if(menu==1) {
					update(board);
				}else if(menu==2) {
					delete(board);
				}
			}
			rs.close();
			stmt.close();
		} catch (Exception e) {
			e.printStackTrace();
			exit();
		}
		
		list();
	}
	
    //2-1번 update
    //데이터 수정 update
	public static void update(Board board) {
		System.out.println("[수정 내용 입력]");
		System.out.print("제목: ");
		board.setBtitle(scanner.nextLine());
		System.out.print("내용: ");
		board.setBcontent(scanner.nextLine());
		System.out.print("작성자: ");
		board.setBwriter(scanner.nextLine());
		
		System.out.println("--------------------------------------------------");
		System.out.println("보조 메뉴: 1.OK | 2.Cancel");
		System.out.print("메뉴 선택: ");
		int menu=scanner.nextInt();
		
		if(menu==1) {
			try {
				String sql="update boards set btitle=?, bcontent=?, bwriter=? where bno=?";
				PreparedStatement stmt=con.prepareStatement(sql);
				stmt.setString(1, board.getBtitle());
				stmt.setString(2, board.getBcontent());
				stmt.setString(3, board.getBwriter());
				stmt.setInt(4, board.getBno());
				stmt.executeUpdate();
				stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
				exit();
			}
		}
		list();
	}
    
    //2-2번 delete
    //데이터 삭제 delete
	public static void delete(Board board) {
		try {
			String sql="delete from boards where bno=?";
			PreparedStatement stmt=con.prepareStatement(sql);
			stmt.setInt(1, board.getBno());
			stmt.executeUpdate();
			stmt.close();
		} catch (Exception e) {
			e.printStackTrace();
			exit();
		}
		list();
		
	}
	
    //3번 clear
    //데이터 모두 삭제 truncate
	private static void clear() {
		System.out.println("[게시물 전체 삭제]");
		System.out.println("--------------------------------------------------");
		System.out.println("보조 메뉴: 1.Ok | 2.Cancel");
		System.out.print("메뉴 선택: ");
		int menu=scanner.nextInt();
		scanner.nextLine();
		if(menu==1) {
			try {
				String sql="truncate table boards";
				PreparedStatement stmt=con.prepareStatement(sql);
				stmt.executeUpdate();
				stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
				exit();
			}
		}
		list();
	}
    
    //4번 exit
	private static void exit() {
		if(con!=null) {
			try {
				con.close();
			} catch (SQLException e) {
				// TODO: handle exception
			}
		}
		System.out.println("***게시판 종료***");
		System.exit(0);
	}
    
    //main
	public static void main(String[] args) {
		try {
			Class.forName("oracle.jdbc.OracleDriver");
			con = DriverManager.getConnection(url,"hr","hr");
			
		} catch (Exception e) {
			e.printStackTrace();
			exit();
		} finally {
			list();
		}
		
		
	}
}
728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] 호텔 예약 관리 프로그램  (0) 2023.05.08
[JAVA] #18 입출력 스트림  (0) 2023.05.01
[JAVA] #17 스트림 요소 처리  (0) 2023.05.01
[JAVA] #16 람다식  (0) 2023.04.27
[JAVA] #15 컬렉션 자료구조  (0) 2023.04.27
728x90
반응형
SMALL

입출력 스트림

* 바이트 스트림 : 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 입출력할 때 사용

* 문자 스트림 : 문자만 입출력할 때 사용

=> java.io 패키지 사용

 

구분 바이트 스트림 문자 스트림
입력 스트림 출력 스트림 입력 스트림 출력 스트림
최상위 클래스 InputStream OutputStream Reader Writer
하위 클래스(ex) XxxInputStream
FileInputStream
XxxOutputStream
FileOutputStream
XxxReader
FileReader
XxxWriter
FilreWriter

바이트 출력 스트림

OutputStream은 바이트 출력 스트림의 최상위 클래스로 추상 클래스이다.

리턴 타입 메소드 설명
void write(int b) 1byte를 출력
void write(byte[] b) 매개값으로 주어진 배열b의 모든 바이트를 출력
void write(byte[] b, int off, int len) 매개값으로 주어진 배열b[off]부터 len개의 바이트를 출력
void flush() 출력 버퍼에 잔류하는 모든 바이트를 출력
void close() 출력 스트림을 닫고 사용 메모리 해제

1바이트 출력

public class WriteExample{
	public class void main(String[] args){
    	try{
        	OutputStream os = new FileOutputStream("test1.db");
            
            byte a =10;
            byte b =20;
            byte c =30;
            
            os.write(a);
            os.write(b);
            os.write(c);
            
            os.flush();
            os.close();
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

바이트 배열 출력

public class WriteExample{
	public static void main(String[] args){
    	try{
        	OutputStream os = new FileOutputStream("test2.db");
            byte[] array = {'A','B','C'};
            
            os.write(array);
            os.flush();
            os.close();
            
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

바이트 배열 일부분 출력

public class WriteExample{
	public static void main(String[] args){
    	try{
        	OutputStream os = new FileOutputStream("test3.db");
            byte[] array = {'A','B','C','D','E'};
            
            os.write(array,1,3); //B C D 출력
            os.flush();
            os.close();
            
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

바이트 입력 스트림

InputStream은 바이트 입력 스트림의 최상위 클래스로 추상 클래스이다.

리턴 타입 메소드 설명
int read() 1byte 읽은 후 읽은 바이트를 리턴
int read(byte[] b) 읽은 바이트를 매개값으로 주어진 배열에 저장 후 읽은 바이트 수를 리턴
void close() 입력 스트림을 닫고 사용 메모리 해제

 

1바이트 읽기

public class ReadExample{
	public static void main(String[] args){
    	try{
        	InputStream is = new FileInputStream("test1.db");
            
            whie(True){
            	int data = is.read();
                if(data == -1) break;
                System.out.println(data);
            }
            
            is.close();
        }catch(FileNotFoundException e){
        	e.printStrackTrace();
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

바이트 배열로 읽기

public class ReadExample{
	public static void main(String[] args){
    	try{
        	InputStream is = new FileInputStream("test2.db");
            
            byte[] data = new byte[100];
            
            while(true){
            	int num = is.read(data);
                if(num == -1) break;
                for(int i=0; i<num; i++){
                	System.out.println(data[i]);
                }
            }
            
            is.close();
        }catch(FileNotFoundException e){
        	e.printStackTrace();
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

바이트 배열 읽고 바로 출력하기

public class ReadExample{
	public static void main(String[] args){
    	try{
        	InputStream is = new FileInputStream("test.txt");
            OutputStream os = new FileOutputStream("test2.txt");
            
            byte[] data = new byte[100];
            
            while(true){
            	int num = is.read(data);
                if(num == -1) break;
                os.write(data,0,num);
            }
            os.flush();
            os.close();            
            is.close();
            
            System.out.prinln("복사가 되었습니다");
        }catch(FileNotFoundException e){
        	e.printStackTrace();
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

문자 입출력 스트림

InputStream과 OutputSTream에 대응하는 문자 입출력 스트림으로는 Reader와 Writer가 있다.

 

문자 출력

리턴 타입 메소드 설명
void write(int c) 매개값으로 주어진 한 문자를 출력
void write(char[] cbuf) 매개값으로 주어진 배열의 모든 문자를 출력
void write(char[] cbuf, int off, int len) 매개값으로 주어진 배열에서 cbuf[off]부터 len개까지의 문자를 출력
void flush() 버퍼에 잔류하는 모든 문자를 출력
void close() 출력 스트림을 닫고 사용 메모리를 해제

 

public class WriteExample{
	public static void main(String[] args){
    	try{
        	Writer writer = new FileWriter("text.txt");
            
            //한 문자씩 출력
            char a = 'A';
            writer.write(a);
            char b = 'B';
            writer.write(b);
            
            //char 배열 출력
            char[] arr={'C','D','E'};
            writer.write(arr);
            
            //문자열 출력
            writer.write("FGH");
            
            writer.flush();
            writer.close();
        }catch(IOException e){
        	e.printStacTrace();
        }
    }
}

 

문자 읽기

메소드 설명
int read() 1개의 문자를 읽고 리턴
int read(char[] cbuf) 읽은 문자들을 매개값으로 주어진 문자 배열에 저장하고 읽은 수를 리턴
void close() 입력 스트림을 닫고, 사용 메모리 해제
public class ReadExample{
	public static void main(String[] args){
    	try{
        	Reader reader = null;
            
            //한 문자씩
            reader = new FileReader("test.txt");
            while(true){
            	int data = reader.read();
                if(data == -1) break;
                System.out.println((char)data);
            }
            reader.close();
            
            reader = new FileReader("test.txt");
            char[] data = new char[100];
            while(true){
            	int num=reader.read(data);
                if(num==-1) break;
                for(int i=0; i<num; i++){
                	System.out.print(data[i]);
                }
            }
            reader.close();        
        }catch(FileNotFoundException e){
        	e.printStackTrace();
        }catch(IOException e){
        	e.printStackTrace();
        }
    }
}

 

보조 스트림

보조 스트림 기능
InputStreamReader / OutputStreamWriter 바이트 스트림을 문자 스트림으로 변환
BufferdInputStream, BufferedOutputStream
BufferedReader, BufferedWriter
입출력 성능 향상
DataInputStream, DataOutputStream 기본 타입 데이터 입출력
PrintStream, PrintWriter 줄바꿈 처리 및 형식화된 문자열 출력
ObjectInputStream, ObjectOutputStream 객체 입출력

 

문자 변환 스트림

InputStream을 Reader로 변환

InputStream is = new FileInputStream("text.txt");
Reader reader = new InputStreamReader(is);

OutputStream을 Writer로 변환

OutputStream os = new FileOutputStream("text.txt");
Writer writer = new OutputStreamWriter(os);

 

입출력 성능 향상 스트림

BufferedInputStream bis = new BufferedInputStream(바이트 입력 스트림);
BufferedOutputStream bos = new BufferedOutputStream(바이트 출력 스트림);
BufferedReader br=new BufferedReader(문자 입력 스트림);
BufferedWriter bw = new BufferedWriter(문자 출력 스트림);

 

기본 타입 스트림

바이트 스트림에 DataInputStream과 DataOutputStream 보조 스트림을 연결하면 기본 타입인 boolean, char, short, int, long, double 값을 입출력할 수 있다.

DataInputStream dis=new DataInputStream(바이트 입력 스트림);
DataOutputStream dos = new DataOutputStream(바이트출력 스트림);

 

프린트 스트림

프린트 스트림은 print(), println(), prinf() 메소드를 갖고 있는 보조 스트림이다.

PrintStream ps = new PrintStream(바이트 출력 스트림);
PrintWriter pw = new PrintWriter(문자 출력 스트림);

 

객체 스트림

*직렬화 : 객체를 출력하기 위해 필드값을 일렬로 늘어선 바이트로 변경

*역직렬화 : 직렬화된 바이트를 객체의 필드값으로 복원하는 것

ObjectInputStream ois = new ObjectInputStream(바이트 입력 스트림);
ObjectOutputStream oos = new ObjectOutputStream(바이트 출력 스트림);

oos.writeObject(객체);
객체타입 변수 = (객체타입)ois.readObject();

 

728x90
반응형
LIST
728x90
반응형
SMALL

스트림이란?

컬렉션 및 배열에 저장된 요소를 반복 처리하기 위해서 for문 / Iterator(반복자)를 이용했다.

List<String> list = ...;
for(int i =0; i<list.size(); i++){
	String item = list.get(i);
}
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
	String item = iterator.next();
}

Java 8부터 스트림을 사용할 수 있다.

*스트림 : 요소들이 하나씩 흘러가면서 처리된다.

Stream<String> stream = list.stream();
stream.forEach( 
	item -> System.out.println(item)
);

* Stream과 Iterator의 차이점

1) 내부 반복자이므로 처리 속도가 빠르고 병렬 처리에 효율적이다.
2) 람다식으로 다양한 요소 처리를 정의할 수 있다.
3) 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성할 수 있다.

내부 반복자

for문과 Iterator는 컬렉션의 요소를 컬렉션 바깥쪽으로 반복해서 가져와 처리 => 외부 반복자

스트림은 컬렉션 내부에서 요소를 반복하여 처리 => 내부 반복자

중간 처리와 최종 처리

스트림은 하나 이상 연결될 수 있다.  사진을 보면 오리지날->중간 스트림->매핑 중간 스트림으로 연결된다

=> 스트림 파이프라인이라고 한다.

//Student 스트림
Stream<Student> studentStream = list.stream();
//score 스트림
IntStream scoreStream = studentStream.mapToInt(student->student.getScore());
//평균 계산
double age = scoreStream.average().getAsDouble();
//메소드 체이닝 패턴을 이용해 간결하게 작성
double avg = list.stream()
	.mapToInt(student -> student.getScore())
    	.average()
    	.getAsDouble();

 

리소스로부터 스트림 얻기

컬렉션으로부터 스트림 얻기

public class Product{
	private int pno;
    private String name;
    
    public Product(int pno, String name){
		this.pno = pno;
        this.name = name;
	}
    
    @Override
    public String toString(){
    	return new StringBuilder()
        	.append("{")
            .append("pno : " +pno+", ")
            .append("name: " + name + ", ")
            .append("}")
            .toString();

    }
}
public class StreamExample{
	public static void main(String[] args){
    	List<Product> list = new ArrayList<>();
        for( int i =1; i<=5; i++){
        	list.add(new Product(i, "상품"+i);
        }
        
        Stream<Product> stream = list.stream();
        stream.forEach(p->System.out.prinln(p));
    }
}

 

배열로부터 스트림 얻기

java.uti.Arrays 클래스 이용

public class StreamExample{
	public void main(String[] args){
    	String[] strArray = {"홍길동", "김준규", "이다빈"};
        Stream<String> strStream = Arrays.stream(strArray);
        strStream.forEach(item -> System.out.print(item+ ", "));
        System.out.println();
        
        int[] intArr = {1,2,3,4,5};
        IntStream intStream = Arrays.stream(intArr);
        intStream.forEach(item -> System.out.print(item+", "));
    }
}

 

요소 걸러내기(필터링)

리턴 타입 메소드(매개변수) 설명
Stream
IntStream
LongStream
DoubleStream
distinct() - 중복제거
filter() - 조건 필터링
- 매개 타입을 요소 타입에 따른 함수형
인터페이스이므로 람다식으로 작성 가능

 

요소 변환(매핑)

mapXxxx사용.

mapXxx의 매개변수의 타입인 Function은 매개값을 리턴값으로 벼환하는 함수형 인터페이스로 applyXxx() 추상메소드가 있다.

Studentlist.stream()
	.mapToInt(s->s.getScore())
    .forEach(score -> System.out.prinln(score));

 

요소 정렬

Comparable 구현 객체의 정렬

public class Xxx implements Comparable {
	...
}

List<Xxx> list = new ArrayList<>();
Stream<Xxx> stream = list.stream();
Stream<Xxx> orderedStream = stream.sorted();

//객체가 Comparable을 구현하고 있어야 sorted()메소드를 사용해 정렬할 수 있다.
//역으로 정렬
Stream<Xxx> reverseOrderedStream = stream.sorted(Comparator.reverseOrder());

 

Comparator를 이용한 정렬

sorted((o1,o2)-> {...})

- o1이 o2보다 작으면 음수, 같으면 0, 크면 양수를 리턴한다

 

요소를 하나씩 처리(루핑)

리턴 타입 메소드 설명
XxxStream peek 반복
void forEach 반복

 

728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #19 데이터베이스 입출력(게시판 프로그램)  (1) 2023.05.02
[JAVA] #18 입출력 스트림  (0) 2023.05.01
[JAVA] #16 람다식  (0) 2023.04.27
[JAVA] #15 컬렉션 자료구조  (0) 2023.04.27
[JAVA] #14 멀티 스레드  (0) 2023.04.26
728x90
반응형
SMALL

람다식이란?

- 함수형 프로그래밍. 함수 역할을 하는 매개변수를 가진 중괄호 블럭.

//람다식
(매개변수, ...) -> {처리 내용}

* 사용 예시

public interface Calculable{
	//추상메소드
    void calculate(int x, int y);
}
//익명 구현 객체
new Calculable(){
	@Override
    public void calculate(int x, int y){처리 내용}
}
//람다식 표현 방법
(x,y) -> {처리 내용}
public static void main(String[] args){
	action((x,y)->{
		int result = x+y;
        System.out.println(result);
	}
}

public static void action(Calculable calculable){
	int x=10;
    int y=4;
    calculable.calculate(x,y);
}

* 함수형 인터페이스 : 인터페이스가 단 하나의 추상 메소드를 가질 때. => 이를 보장하기 위해 @FunctionalInterface 어노테이션을 추가한다.

 

 

매개변수가 없는 람다식

()->{
	실행문;
        실행문;
}
() -> 실행문

 

매개변수가 있는 람다식

(타입 매개변수, ...)->{
	실행문;
    	실행문;
}
(타입 매개변수, ...)-> 실행문
(var 매개변수, ...) ->{
	실행문;
    	실행문;
}
(var 매개변수,...)->실행문
(매개변수, ...)->{
	실행문;
    	실행문;
}
(매개변수,...)->실행문

 

리턴값이 있는 람다식

(매개변수, ...)->{
	실행문;
    	return 값;
}
(매개변수, ...) -> return 값
(매개변수, ...)->값

 

메소드 참조

*(::)

1. interface method의 매개변수가 같은 메서드가 실행

2. 람다식 실행구문이 1개인 경우만!

3. 반드시 리턴값 가져야함.

(left,right)->Math.max(left,right);

Math :: max;

 

생성자 참조

(a,b) ->{return new Class(a,b);}

Class::new //생성자 참조
728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #18 입출력 스트림  (0) 2023.05.01
[JAVA] #17 스트림 요소 처리  (0) 2023.05.01
[JAVA] #15 컬렉션 자료구조  (0) 2023.04.27
[JAVA] #14 멀티 스레드  (0) 2023.04.26
[JAVA] #13 제네릭  (0) 2023.04.24
728x90
반응형
SMALL

컬렉션 프레임워크

 

인터페이스 분류 특징 구현 클래스
Collection List - 순서를 유지하고 저장
- 중복 저장 가능
ArrayList, Vector,
LinkedList
Set - 순서를 유지하고 저장
- 중복 저장 불가능
HashSet, TreeSet
Map - 키와 값으로 구성된 엔트리 저장
- 키는 중복 저장 안됨
HashMap, Hashtable,
TreeMap, Properties

 

List 컬렉션

List컬렉션은 인덱스로 관리한다.

기능 메소드 설명
객체
추가
boolean add(E e) 주어진 객체를 맨 끝에 추가
void add(int index, E element) 주어진 인덱스에 객체를 추가
set(int index, E element) 주어진 인덱스의 객체를 새로운 객체로 바꿈
객체
검색
boolean contains(Object o) 주어진 객체가 저장되어 있는지 여부
E get(int index) 주어진 인덱스에 저장된 객체 리턴
isEmpty() 컬렉션이 비어있는지 검사
int size() 저장되어 있는 전체 객체 수 리턴
객체
삭제
void clear() 저장된 모든 객체 삭제
E remove(int index) 주어진 인덱스에 저장된 객체 삭제
boolean remove(Object o) 주어진 객체를 삭제

 

ArrayList

- List컬렉션 중 가장 많이 사용

- ArrayList에 add로 객체 추가 시 배열에 객체가 저장되며, 일반 배열과 달리 길이 제한이 없다.

- 객체 자체가 아닌 객체의 번지를 저장한다. 동일한 객체 저장도 가능하며, 동일한 번지가 저장된다.

//생성방법
ArrayList<E> list = new ArrayList<E>(); //지정된 E타입 객체만 저장 가능
ArrayList<E> list = new ArrayList<>(); //지정된 E타입 객체만 저장 가능
ArrayList list = new ArrayList(); //모든 타입 객체 저장 가능

* 특정 index 객체를 제거하면 바로 뒤부터 끝까지 모두 앞으로 한 칸씩 당겨진다.

* 특정 index에 객체를 추가하면 해당 인덱스부터 끝까지 뒤로 한 칸씩 밀려진다.

 

Vector

ArrayList와 동일한 내부 구조를 가졌지만 Vector는 동기화된 메소드로 구성되어 있어 멀티 스레드가 동시에 Vector() 메소드를 실행할 수 없다.

=> 멀티 스레드 환경에서 안전하게 객체 추가/삭제가 가능하다.

//생성 방법
List<E> list = new Vector<E>(); //E타입 객체만 저장
List<E> list = new Vector<>(); //E타입 객체만 저장
List<> list = new Vector<>(); //모든 타입 객체 저장

=>코드에 여러 스레드가 있어 thread1.start(); thread2.start();해도 한 번에 하나의 스레드만 실행시킨다.

 

LinkedList

LinkedList는 ArrayList와 사용 방법은 동일하지만 내부 구조는 완전히 다르다. ArrayList는 배열에 객체를 저장하지만, LinkedList는 인접 객체를 체인처럼 연결해서 관리한다.

- 특정 위치에서 객체를 삽입/삭제하면 바로 앞 뒤 링크만 변경되므로 빈번한 삽입/삭제에서는 ArrayList보다 좋다.

 

//생성 방법
List<E> list = new LinkedList<E>(); //E타입 객체만 저장
List<E> list = new LinkedList<>(); //E타입 객체만 저장
List<> list = new LinkedList<>(); //모든 객체 저장

 

Set 컬렉션

List와 달리 Set은 저장 순서가 유지되지 않는다. 또한 객체를 중복해서 저장할 수 없고, 하나의 null만 저장할 수 있다.

기능 메소드 설명
객체
추가
boolean add(E e) 주어진 객체를 성공적으로 저장하면 true를 리턴하고 중복 객체면 false를 리턴
객체
검색
boolean contains(Object o) 주어진 객체가 저장되어 있는지 여부
isEmpty() 컬렉션이 비어 있는지 조사
Iterator<E> iterator() 저장된 객체를 한 번씩 가져오는 반복자 리턴
int size() 저장된 객체 수 리턴
객체
삭제
void clear() 저장된 모든 객체를 삭제
boolean remove(Object o) 주어진 객체를 삭제

 

HashSet

- Set컬렉션 중 가장 많이 사용되는 것

//생성 방법
Set<E> set = new HashSet<E>(); //E타입 객체만 저장
Set<E> set = new HashSet<>(); //E타입 객체만 저장
Set<> set = new HashSet<>(); //모든 타입 객체 저장

=>HashSet은 hashCode()의 리턴값이 같고 equals()메소드가 true를 리턴하면 동등한 객체로 보고 중복 저장하지 않는다.

 

* Set은 index가 없어 객체를 검색해서 가져오는 방법이 없다. 그래서 2가지 방법을 이용한다.

//Set에서 객체를 가져오는 방법

//1.for문 이용
Set<E> set = new HashSet<>();
for (E e:set){
	...
}

//2.Iterator이용
Set<E> set = new HashSet<>();
Iterator<E> iterator = set.iterator();

 

리턴타입 iterator 메소드명 설명
boolean hasNext() 가져올 객체가 있으면 true, 없으면 false
E next() 컬렉션에서 하나의 객체를 반환
void remove() next()로 가져온 객체를 Set컬렉션에서 제거한다.

 

//사용 방법
while(iterator.hasNext()){
	E e = iterator.next();
}

 

Map 컬렉션

Map 컬렉션은 키(key)와 값(value)으로 구성된 엔트리 객체를 저장한다. 여기서 키와 값은 모두 객체이다.

키 - 중복저장 불가능

값 - 중복저장 가능

기능 메소드 설명
객체 추가 V put(K key, V value) 주어진 키와 값을 추가, 저장되면 값을 리턴
객체 검색 boolean containsKey(Object key) 주어진 키가 있는지 여부
boolean containsValue(Object Value) 주어진 값이 있는지 여부
Set<Map.Entry<K,V>> entrySet() 키,값 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴
V get(Object key) 주어진 키의 값을 리턴
boolean isEmpty() 컬렉션이 비어있는지 여부
Set<K> keySet() 모든 키를 Set객체에 담아 리턴
int size() 저장된 키의 총 수를 리턴
Collection<V> values() 저장된 모든 값 Collection에 담아서 리턴
객체 삭제 void clear() 모든 Map.Entry(키와 값)을 삭제
V remove(Object key) 주어진 키와 일치하는 Map.Entry 삭제.
삭제되면 값을 리턴

 

HashMap

키로 사용할 객체가 hashCode() 메소드의 리턴값이 같고 equals() 메소드가 true를 리턴할 경우, 동일 키로 보고 중복 저장을 허용하지 않는다.

 

//생성 방법
Map<K,V> map = new HashMap<K,V>();
Map<K,V> map = new HashMap<>();

 

Hashtable

Hashtable은 HashMap과 동일한 내부 구조를 갖고 있다. 차이점으로는 Hashtable은 동기화된 메소드로 구성되어 있어 멀티 스레드가 동시에 Hashtable의 메소드들을 실행할 수 없다.

따라서 멀티 스레드 환경에서도 안전하게 객체를 추가, 삭제할 수 있다.

Map<String, Integer> map = new Hashtable<String, Integer>();
Map<String, Integer> map = new Hahtable<>();

 

Properties

Hashtable의 자식 클래스이기 때문에 Hahtable의 특징을 그대로 갖고 있다. Properties는 키와 값을 String으로 제한한 컬렉션이다.

주로 .properties인 프로퍼터 파일을 읽을 때 사용한다.

//database.properties
driver=oracle.jdbc.OracleDirver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=scott
password=tiger
admin=\uD64D\uAE38\uB3D9
Properties properties = new Properties();
properties.load(Xxx.class.getResourceAsStream("database.properties"));

 

검색 기능을 강화시킨 컬렉션

컬렉션 프레임워크는 검색 기능을 강화시킨 TreeSet, TreeMap을 제공한다.

 

TreeSet

- 이진트리를 기반으로 한 Set컬렉션

TreeSet에 객체를 저장할 때는 부모 노드의 객체와 비교해 낮은 것은 왼쪽 자식에, 높은 것은 오른쪽 자식 노드에 저장한다.

//생성 방법
TreeSet<E.=> treeSet = new TreeSet<E>;
TreeSet<E.=> treeSet = new TreeSet<>;

 

TreeMap

이진트리를 기반으로 한 Map 컬렉션. TreeSet과의 차이점은 키와 값이 저장된 Entry를 저장한다는 점이다.

TreeMap에 엔트리를 저장하면 키를 기준으로 자동 정렬되는데 부모 키값보다 낮은건 왼쪽, 큰 건 오른쪽 자식 노드에 Entry객체를 저장한다.

TreeMap<K,V> treeMap = new TreeMap<K,V>();
TreeMap<K,V> treeMap = new TreeMap<>();

 

Comparable과 Comparator

TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체는 저장과 동시에 오름차순으로 정렬되는데,

객체가 Comparable 인터페이스를 구현하고 있어야 가능하다. Comparable인터페이스를 받아 compareTo()를 재정의해야한다.

리턴 타입 메소드 설명
int compareTo(T o) 주어진 객체와 같으면 0,
크면 양수,
작으면 음수 리턴

 

Comparable 비구현 객체를 저장하고 싶다면 TreeSet과 TreeMap을 생성할 때 비교자(Comparator)를 제공하면 된다.

TreeSet<E> treeSet = new TreeSet<E>(new ComparatorImpl));

TreeMap<K,V> treeMap = new TreeMap<K,V>(new ComparatorImpl());

 

LIFO와 FIFO 컬렉션

LIFO(Last In First Out): 후입선출 => 스택

FIFO(First in First Out): 선입선출 => 

Stack

//스택 생성 방법
Stack<E> stack = new Stack<E>();
Stack<E> stack = new Stack<>();
리턴 타입 메소드 설명
E push(E item) 주어진 객체를 스택에 넣는다.
E pop() 스택의 맨 위 객체를 빼낸다

 

Queue

//큐 생성 방법
Queue<E> queue = new LinkedList<E>();
Queue<E> queue = new LinkedList<>();
리턴 타입 메소드 설명
boolean offer(E e) 주어진 객체를 큐에 넣는다.
E poll() 큐에서 객체를 빼낸다.

 

728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #17 스트림 요소 처리  (0) 2023.05.01
[JAVA] #16 람다식  (0) 2023.04.27
[JAVA] #14 멀티 스레드  (0) 2023.04.26
[JAVA] #13 제네릭  (0) 2023.04.24
[JAVA] #12 java.base 모듈  (0) 2023.04.20
728x90
반응형
SMALL

멀티 스레드 개념

- 운영체제는 실행 중인 프로그램을 프로세스로 관리한다. ( 멀티태스킹: 두가지 이상의 작업을 동시에 처리하는 것)

- OS는 멀티 프로세스를 생성해서 처리.

- 하나의 프로세스가 두 가지 이상의 작업을 처리할 수 있는 이유는 멀티 스레드가 있기 때문( 스레드 : 코드의 실행 흐름)

 

 

메인 스레드

- 모든 자바 프로그램은 메인 스레드가 main()메소드를 실행하면서 시작된다.

- 메인 스레드는 main()의 첫 코드부터 순차적 실행하며 마지막 코드를 실행하거나 return문을 만나면 종료한다.

작업 스레드 생성과 실행

 

작업 스레드 생성과 실행

- 멀티 스레드로 실행하는 프로그램을 개발하려면 먼저 몇 개의 작업을 병렬로 실행할지 결정하고 생성해야한다.

- 자바에서는 메인 스레드가 반드시 존재하기 때문에 이외 추가적인 작업 수만큼 스레드 생성하면 된다. 또 스레드도 객체로 관리하므로 클래스가 필요하다.

 

Thread 클래스로 직접 생성

java.lang 패키지에 있는 Thread 클래스로부터 작업 스레드 객체를 직접 생성하려면 다음과 같이 Runnable 구현 객체를 매개값으로 갖는 생성자를 호출하면 된다.

Thread thread = new Thread(Runnable target);

Runnable은 스레드가 작업을 실행할 때 사용하는 인터페이스다. 이 인터페이스에는 run()메소드가 정의되어있다.

구현 클래스는 run()을 재정의해서 스레드가 실행할 코드를 갖고 있어야 한다.

class MyRunnable implements Runnable{
	@Override
    public void run(){
    	//실행할 코드
    }
}

사용 방법

Runnable myRunnable = new MyRunnable();

Thread thread = new Thread(myRunnable);

thread.start();
Thread thread = new Thread(new Runnable(){
	@Override
    public void run(){
    	//스레드가 실행할 코드
    }
});

thread.start();

 

Thread 자식 클래스로 생성

또 다른 방법은 Thread의 자식 객체로 만드는 것이다. Thread를 상속하여 run()메소드를 재정의해 스레드가 실행할 코드를 작성하면 된다.

하지만 이 방법은 Thread를 extends로 상속받기 때문에 다른 부모를 상속받지 못한다는 단점이 있다.

public class WorkerTread extends Thread{
	@Override
    public void run(){
    	//스레드가 실행할 코드
    }
}

//스레드객체 생성
Thread thread = new WorkerTread();
thread.start();

 

스레드 이름

스레드는 각자 자신의 이름을 갖고 있다. 메인 스레드는 'main'이라는 이름을 갖고 있고, 작업 스레드는 자동적으로 'Thread-n'이라는 이름은 가진다. 만약 다른 이름으로 설정하고 싶으면 Thread클래스의 setName() 메소드를 사용한다.

thread.setName("스레드이름");

Thread thread = Thread.currendThread();
System.out.println(thread.getName());

 

스레드 상태

1. 스레드 객체를 생성(NEW)하고, start() 메소드를 호출하면 RUNNABLE상태가 됨. =>실행 대기

2. 실행 대기하는 스레드는 CPU 스케쥴링에 따라 CPU를 점유하고 run()메소드가 실행하면 RUNNING상태가 됨

3. 실행 스레드는 run()메소드의 코드를 모두 실행하기 전에 스케줄링에 의해 RUNNABLE상태로 돌아갈 수 있으며, 그 때 다른 스레드가 실행 상태가 됨

4. 실행상태에서 run() 메소드가 종료되면 더 이상 실행할 코드가 없기 때문에 스레드의 실행은 멈추며 TERMIATED가 됨.

 

주어진 시간 동안 일시 정지

실행 중인 스레드를 일정 시간 멈추게 하고 싶다면 Thread 클래스의 정적 메소드인 sleep()을 이용

try{
	Thread.speep(1000) // 1초 일시정지
} catch(InterruptedException e){
	//interrupt() 메소드가 호출되면 실행
}

 

다른 스레드의 종료를 기다림

스레드는 다른 스레드와 독립적으로 실행하지만 다른 스레드가 종료될 때까지 기다렸다가 실행해야 하는 경우에 join()메소드를 사용한다.

//<Thread A>

threadB.start(); //threadB 시작
threadB.join(); //threadA 일시 정지. =>B가 끝날 때까지 A는 실행하지 않음.

//<Thread B>
run(){

}

 

 

스레드 동기화

멀티 스레드는 하나의 객체를 공유해서 사용할 수도 있다. 한 객체를 여러 스레드가 접근해서 데이터를 변경하거나 가져올 때 원하지 않는 결과가 발생할 수도 있다.

메소드에 synchrosized키워드를 추가해 한 스레드가 끝날 때까지 flag를 가져가지 못하도록 할 수 있다.

 

스레드 안전 종료

스레드는 자신의 run()메소드가 모두 실행되면 자동적으로 종료되지만, 안전하게 사용하던 리소스들을 정리하고 run()메소드를 빨리 종료하는 방법은 조건 이용 방법과 interrupt()메소드 이용 방법이 있다.

 

조건 이용

public class XXXThread extends Thread{
	private boolean stop;
    
    public void run(){
		while(!stop){
			//스레드가 반복 실행하는 코드;
		}
        //스레드가 사용한 리소스 정리
	}
}

 

interrupt()메소드 이용

interrupt() 메소드는 스레드가 일시 정지 상태에 있을 때 InterruptedException 예외를 발생시켜 run()메소드를 정상 종료시킬 수 있다.

XThread thead = new XThread();
thread.start; //---1
...
thread.interrupt(); //---2


public void run(){ //---1로 인해 진행
	try{
    	while(true){
			...
			Thread.sleep(1); //---2로 인해 일시정지
		}
    }catch(InterruptedException e){ //---일시정지로 인해 예외 발생
		
	}
    //스레드가 사용한 리소스 정리
}

 

데몬 스레드

데몬 스레드는 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드이다. 주 스레드가 종료되면 데몬 스레드도 따라서 자동 종료된다.

스레드를 데몬으로 만들기 위해 주 스레드가 데몬이 될 스레드의 setDaemon(true)를 호출한다.

public static void main(String[] args){
	AutoSaveThread thread = new AutoSaveThread();
    thread.setDaemon(true);
    thread.start();
}

=>AutoSaveThread는 데몬 스레드가 된다.

 

스레드풀

병렬 작업 처리가 많아지면 스레드 개수가 폭증하여 CPU가 바빠지고 메모리 사용량이 늘어난다. 따라서 어플리케이션 성능이 저하되기 때문에 스레드 폭증을 막기 위한 스레드풀을 사용하는 것이 좋다.

스레드의 개수를 제한하여 큐에 들어오는 작업들을 스레드가 하나씩 맡아 처리하는 방식이다.

 

스레드풀 생성

메도드명(매개변수) 초기 수 코어 수 최대 수
newCachedThreadPool() 0 0 Integer.MAX_VALUE
newFixedThreadPool(int nThreads) 0 생성된 수 nThreads

 

ExecutorService executorService = Executors.newCachedThreadPool();
// 초기 수와 코어 수는 0개이고, 작업수가 많아지면 새 스레드를 생성시켜 작업을 처리한다.

ExecutorService executorService = Executors.newFixedThreadPool(5);
// 초기 수는 0개이고, 작업 수가 많아지면 최대 5개까지 스레드를 생성시켜 작업을 처리한다.

ExecutorService threadPool = new ThreadPoolExecutor(
	3, //코어 스레드 개수
    100, //최대 스레드 개수
    120L, //놀고 있는 시간
    TimeUnit.SECONDS, //놀고 있는 시간의 단위
    new SynchronousQueue<Runnable>() //작업 큐
);

 

스레드풀 종료

스레드풀의 스레드는 데몬 스렏가 아니기 때문에 main스레드가 종료되더라도 계속 실행 상태로 남아있다. 두 가지 중 하나의 메소드를 실행해야한다.

리턴 타입 메소드명(매개변수) 설명
void shutdown() 현재 처리 중인 작업뿐만 아니라 작업 큐에 대기하고 있는 모든 작업을 처리한 뒤에 스레드풀을 종료시킨다.
List<Runnable> shutdownNow() 현재 작업 처리 중인 스레드를 interrupt해서 작업을 중지시키고 스레드풀을 종료시킨다. 리턴값은 작업 큐에 있는 미처리된 작업(Runnable)의 목록이다.
728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #16 람다식  (0) 2023.04.27
[JAVA] #15 컬렉션 자료구조  (0) 2023.04.27
[JAVA] #13 제네릭  (0) 2023.04.24
[JAVA] #12 java.base 모듈  (0) 2023.04.20
[JAVA] #11 예외 처리  (0) 2023.04.19
728x90
반응형
SMALL

제네릭이란?

public class Box{
	public Object content;
}
Box box = new Box();
box.content = 모든 객체;

String content = (String)box.content;

필드에 다양한 타입으로 받아오고 싶을 때 Object로 선언하게 되면 내용물을 얻을 때 마다 강제 타입 변환을 거쳐야 한다.

=> 제네릭 : 결정되지 않은 타입을 파라미터로 처리하고 실제 사용할 때 파라미터를 구체적인 타입으로 대체시키는 기능

public class Box<T>{
	public T content;
}
Box<String> box1 = new Box();
box1.content ="안녕하세요";
String content = box.content;

Box<Integer> box2 = new Box();
box2.content = 20;
int content = box.content;

=> 강제 타입 변환이 필요없다.

 

제네릭 타입

* 제네릭 타입 : 결정되지 않은 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다. 선언부에 <>가 붙고 그 사이에 타입 파라미터들이 위치한다.

public class 클래스명<A, B, ...> { ... }
public interface 인터페이스명<A, B, ...>{ ... }
public class Product<K,M>{
 	private K kind;
    	private M model;
}
public interface Rentable<P>{
	P rent(); //타입 파라미터 P를 리턴타입으로도 사용
}

 

제네릭 메소드

* 제네릭 메소드 : 타입 파라미터를 갖고 있는 메소드를 말한다.

타입 파라미터가 메소드 선언부에서 정의된다

리턴 타입 앞에 <> 를 추가하고 타입 파라미터를  정의한 뒤, 리턴 타입과 매개변수 타입에서 사용한다.

public <A, B, ...> 리턴타입 메소드명(매개변수,...) { ... }
public <T> Box<T> boxing(T t) { ... }

 

 

제한된 타입 파라미터

경우에 따라 타입 파라미터를 대체하는 구체적인 타입을 제한할 필요가 있다.

ex) 숫자를 연산하는 제네릭 메소드는 대체로 Number또는 그의 자식클래스로 제한할 필요가 있다.

*제한된 타입 파라미터 : 모든 타입으로 대체할 수 없고,특정 타입과 자식 또는 구현 관계에 있는 타입만 대체할 수 있는 타입 파라미터

public <T extends 상위타입> 리턴타입 메소드명(매개변수, ...) { ... }

 

와일드카드 타입 파라미터

리턴타입 메소드명(제네릭타입<? extends Student> 변수) { ... }
//Student와 그 자식클래스만 타입으로 가능함.
리턴타입 메소드명(제네릭타입<? super Worker> 변수){ ... }
//Worker와 그 부모클래스만 매개변수 타입으로 가능함.
리턴타입 메소드명(제네릭타입<?> 변수) { ... }
728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #15 컬렉션 자료구조  (0) 2023.04.27
[JAVA] #14 멀티 스레드  (0) 2023.04.26
[JAVA] #12 java.base 모듈  (0) 2023.04.20
[JAVA] #11 예외 처리  (0) 2023.04.19
[JAVA] #10 라이브러리 모듈  (0) 2023.04.18
728x90
반응형
SMALL

API 도큐먼트

저버 표준 모듈에서 제공하는 라이브러리는 방대하기 때문에 쉽게 찾아서 사용할 수 있도록 도와주는 API가 있다.

https://docs.oracle.com/en/java/javase/20/docs/api/index.html

 

Overview (Java SE 20 & JDK 20)

This document is divided into two sections: Java SE The Java Platform, Standard Edition (Java SE) APIs define the core Java platform for general-purpose computing. These APIs are in modules whose names start with java. JDK The Java Development Kit (JDK) AP

docs.oracle.com

 

java.base 모듈

java.base는 모든 모듈이 의존하는 기본 모듈로, 모듈 중 유일하게 requires하지 않아도 사용할 수 있다.

패키지 용도
java.lang 자바 언어의 기본 클래스를 제공
java.util 자료 구조와 관련된 컬렉션 클래스를 제공
java.text 날짜 및 숫자를 원하는 형태의 문자열로 만들어 주는 포맷 클래스를 제공
java.time 날짜 및 시간을 조작하거나 연산하는 클래스를 제공
java.io 입출력 스트림 클래스를 제공
java.net 네트워크 통신과 관련된 클래스 제공
java.nio 데이터 저장을 위한 Buffer 및 새로운 입출력 클래스 제공

 

Object 클래스

클래스를 선언할 때 extends 키워드로 다른 클래스를 상속하지 않으면 암시적으로 java.lang.Object 클래스를 상속하게 된다.

 

메소드 용도
boolean equals(Object obj) 객체의 번지를 비교하고 결과를 리
int hashCode() 객체의 해시코드를 리턴
String toString() 객체 문자 정보를 리턴

 

객체 동등 비교

Object obj1 = new Object();
Object obj2 = obj2;
boolean result = obj1.equals(obj2);
boolean result = (obj1 == obj2);

 

객체 해시코드

해시코드란 객체를 식별하는 정수

public int hashCode()

 

객체 문자 정보

Object의 toString() 메소드는 객체의 문자 정보를 리턴한다.

Object obj = new Object();
System.out.println(obj.toString());
//java.lang.Object@de6ced 결과

 

레코드 선언

데이터 전달을 위한 DTO(Data Tranfer Object)를 작성할 때 반복 코드를 줄이기 위해 레코드를 사용한다.

public record Person(String name, int age);

 

롬복 사용하기

롬복은 레코드와 마찬가지로 DTO 클래스를 작성할 때 사용한다.

레코드와의 차이점은 필드가 final이 아니며, Getter 대신 getXxx, Setter 대신 setXxx 로 생성된다.

1) https://projectlombok.org/download 접속

2) 설치파일(lombok.jar) 다운로드

3) lombok.jar을 eclipse 폴더로 이동하고 eclipse.ini 에 -javaagent:lombok.jar 추가

4) 프로젝트에서 [BuildPath]->[Add to Build Path]를 이용해 추가

 

어노테이션을 사용.

 

System 클래스

System클래스를 이용하면 운영체제의 일부 기능을 이용할 수 있다.

정적 멤버 용도
필드 out 콘솔(모니터)에 문자 출력
err 콘솔(모니터)에 에러 내용 출력
in 키보드 입력
메소드 exit(int status) 프로세스 종료
currentTimeMillis() 현재 시간을 밀리초 단위 long값으로 리턴
nanoTime() 현재 시간을 나노초 단위의 long값으로 리턴
getProperty() 운영체제와 사용자 정보 제공
getenv() 운영체제의 환경 변수 정보 제공

 

키보드 입력

int KeyCode = System.in.read();

 

프로세스 종료

System.exit(int status);

 

문자열 클래스

클래스 설명
String 문자열을 저장하고 조작할 때 사용
StringBuilder 효율적인 문자열 조작 기능이 필요할 때 사용
StringTokenizer 구분자로 연결된 문자열을 분리할 때 사용

 

String 클래스

//기본 문자셋으로 byte 배열을 디코딩해서 String 객체로 생성
String str = new String(byte[] bytes);

//특정 문자셋으로 byte 배열을 디코딩해서 String 객체로 생성
String str = new String(byte[] bytes, String charsetName);

 

StringBuilder 클래스

리턴 타입 메소드(매개변수) 설명
StringBuilder append(기본값 | 문자열) 문자열을 끝에 추가
StringBuilder insert(위치, 기본값 | 문자열) 문자열을 지정 위치에 추가
StringBuilder delete(시작 위치, 끝 위치) 문자열 일부를 삭제
StringBuilder replace(시작 위치, 끝 위치, 문자열) 문자열 일부를 대체
String toString() 완성된 문자열을 리턴

 

StringTokenizer 클래스

String data = "홍길동&이수홍,박연수,김자바-최명호";
String[] name = data.split("[&|,-]");
String data="홍길동/이수홍/박연수";
StringTokenizer st = new StringTokenizer(data, ",\t/";

 

포장 클래스

기본 타입 포장 클래스
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double
boolean Boolean

 

박싱과 언박싱

* 박싱: 기본 타입의 값을 포장 객체로 만드는 과정

* 언박싱: 반대로 포장 객체에서 기본 타입의 값을 얻어내는 과정

Integer obj = 100; //박싱
int value = obj; //언박싱

 

포장 값 비교

포장 객체는 내부 값을 비교하기 위해 ==, != 사용 불가! 객체의 번지를 비교하기 때문

Integer obj1 = 300;
Integer obj2 = 300;
println(obj1 == obj2); //false

=> .equals() 이용해야 한다.

 

수학 클래스(Math)

구분 코드 리턴값
절대값 int v = Math.abs(-5); v = 5
올림값 double v= Math.ceil(5.3); v = 6.0
내림값 double v = Math.foor(5.3); v = 5.0
최대값 int v = Math.max(5,9); v = 9
최소값 int v = Math.min(5,9); v = 5
랜덤값 double v11 = Math.random(); 0.0<=v11<1.0
반올림값 long v = Math.round(5.3); v = 5

 

날짜와 시간 클래스

클래스 설명
Date 날짜 정보를 전달하기 위해 사용
Calendar 다양한 시간대별로 날짜와 시간을 얻을 때 사용
LocalDateTime 날짜와 시간을 조작할 때 사용

 

Date 클래스

Date now = new Date();
public class DateExample {

	public static void main(String[] args) {
		Date now= new Date();
		String strNow1= now.toString(); 
		System.out.println(strNow1);//Fri Apr 21 11:00:43 KST 2023
		
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
		String strNow2=sdf.format(now);
		System.out.println(strNow2);//2023.04.21 11:00:43
		
		Date date = new Date();
		System.out.println(date);
		System.out.println(date.getTime());//1682042443861밀리초
        
		java.sql.Date date2 = new java.sql.Date(date.getTime());
		System.out.println(date2); //2023-04-21
		System.out.println(System.currentTimeMillis()); //밀리초
		System.out.println(new java.sql.Date(System.currentTimeMillis())); //2023-04-21
		
		
	}

}

 

Calendar 클래스

Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH) + 1; //월은 0부터 시작
int day = now.get(Calendar.DAY_OF_MONTH);
int week = now.get(Calendar.DAY_OF_WEEK);
int amPm = now.get(Calendar.AM_PM);
int hour = now.get(Calendar.HOUR);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);

TimeZone 클래스를 이용해 알고 싶은 다른 시간대의 Calendar을 얻을 수 있다.

TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
Calendar now = Calendar.getInstance(timeZone);

 

날짜와 시간 조작

LocalDateTime now = LocalDateTime.now();
public class DateTimeOperationExample {

	public static void main(String[] args) {
		LocalDateTime now= LocalDateTime.now();
		DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy.MM.dd. a HH:mm:ss");
		System.out.println("현재 시간: "+now.format(dtf));
		
		LocalDateTime result1=now.plusYears(1);
		System.out.println("1년 덧셈: "+result1.format(dtf));
		
		LocalDateTime result2 = now.minusMonths(2);
		System.out.println("2달 뺄셈: "+result2.format(dtf));
		
		LocalDateTime result3 = now.plusDays(7);
		System.out.println("7일 덧셈: "+result3.format(dtf));
	}

}

/*
결과
현재 시간: 2023.04.21. 오전 11:10:22
1년 덧셈: 2024.04.21. 오전 11:10:22
2달 뺄셈: 2023.02.21. 오전 11:10:22
7일 덧셈: 2023.04.28. 오전 11:10:22
*/

 

형식 클래스

Format 클래스 설명
DecimalFormat 숫자를 형식화된 문자열로 변환
SimpleDateFormat 날짜를 형식화된 문자열로 변환

 

정규 표현식 클래스

//이메일 형식
String str="\\w+@\\w+\\.\\W+(\\.\\W+)?";

//전화번호 형식
String phone="(02|010)-\\d{3,4}-\\d{4}";

 

어노테이션

어노테이션

- 코드에서 @으로 작성되는 요소

- 클래스 또는 인터페이스를 컴파일하거나 실행할 때 어떻게 처리해야 할 것인지를 알려주는 설정 정보

용도

1) 컴파일 시 사용하는 정보 전달

2) 빌드 툴이 코드를 자동으로 생성할 때 사용하는 정보 전달

3) 실행 시 특정 기능을 처리할 때 사용하는 정보 전달

 

어노테이션 타입 정의와 적용

- @interface 뒤에 사용할 어노테이션 이름 작성

public @interface AnnotationName{

}
@AnnotationName

 

어노테이션 적용 대상(어디에)

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface AnnotationName{

}

 

어노테이션 유지 정책(언제)

RententionPolicy 열거 상수 어노테이션 적용 시점 어노테이션 제거 시점
SOURCE 컴파일 할 때 적용 컴파일된 후에 제거됨
CLASS 메모리로 로딩할 때 적용 메모리로 로딩된 후에 제거됨
RUNTIME 실행할 때 적용 계속 유지됨
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationName{

}

 

어노테이션 설정 정보 이용

리턴 타입 메소드명(매개변수) 설명
boolean isAnnotationPresent(AnnotationName.class) 지정한 어노테이션이 적용되었는지 여부
Annotation getAnnotation(AnnotationName.class) 지정한 어노테이션이 적용되어 잇으면 어노테이션을 리턴하고, 그렇지 않으면 null리턴
Annotation[] getDeclaredAnnotations() 적용된 모든 어노테이션을 리턴

 

728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #14 멀티 스레드  (0) 2023.04.26
[JAVA] #13 제네릭  (0) 2023.04.24
[JAVA] #11 예외 처리  (0) 2023.04.19
[JAVA] #10 라이브러리 모듈  (0) 2023.04.18
[JAVA] #9 중첩 선언과 익명 객체  (0) 2023.04.17
728x90
반응형
SMALL

예외와 예외 클래스

에러(Error) : 컴퓨터 하드웨어의 고장으로 인해 응용프로그램 실행 오류가 발생하는 것

예외(Exception) : 잘못된 사용 또는 코딩으로 인한 오류

 

예외의 종류

* 일반 예외(Exception) : 컴파일러가 예외 처리 코드 여부를 검사하는 예외를 말한다.

* 실행 예외(Runtime Exception) : 컴파일러가 예외 처리 코드 여부를 검사하지 않는 예외를 말한다.

 

예외 처리 코드

예외 처리 코드는 try-catch-finally 블록으로 구성된다.

try{
	//예외 발생 가능 코드
} catch{
	//예외 처리
} finally{
	//항상 실행;
}

1) try 블록에서 작성한 코드가 예외 없이 정상 실행되면 catch 블록은 실행되지 않는다.

2) try 블록에서 예외가 발생하면 catch 블록이 실행된다.

3) finally 블록은 예외 발생 여부와 상관없이 항상 실행된다.

 

package ch11.sec02.exam01;


public class ExceptionHandlingExampl2 {
	public static void printLength(String data) {
		try{
			int result= data.length();
			System.out.println("문자 수 : "+result);
		}catch (NullPointerException e) {
			System.out.println(e.getMessage());
		}finally {
			System.out.println("[마무리 실행]\n");
		}
		
	}
	
	public static void main(String[] args) {
		System.out.println("[프로그램 시작]\n");
		printLength("ThisIsJava");
		printLength(null);
		System.out.println("[프로그램 종료]");
	}
}

 

예외 종류에 따른 처리

다양한 종류의 예외는 다중 catch를 사용하면 예외에 따라 다르게 작성할 수 있다.

try{

	ArrayIndexOutOfBoundsException 발생 //예외 발생1
    
   	NumberFormatException 발생 //예외 발생2
    
} catch(ArrayIndexOutOfBoundsException e){
	//예외 처리1
} catch(NumberFormatException e){
	//예외 처리2
}

*처리해야 할 예외 클래스들이 상속관계일 때 하위 클래스 catch 블록을 먼저 작성하고 상위 클래스 catch 블록을 나중에 작성해야 한다.

 

리소스 자동 닫기

리소스 : 데이터를 제공하는 객체.

리소스를 사용하기 위해 열어야(open)하며, 사용 끝난 후에는 닫아야(close)한다. 리소스 사용 중 예외가 발생될 경우에도 안전하게 닫아야 한다.

FileInputStream fis = null;
try{
	fis = new FileInputStream("file.txt");
    ...
} catch(IOException e){
	...
} finally{
	fis.close();
}

 

리소스 자동 닫는 코드

try() 괄호에 리소스를 여는 코드를 작성하면 try 블록이 정상적으로 실행을 완료했거나 예외가 발생해도 자동으로 리소스의 close() 메소드가 호출된다.

try(FileInputStream fis = new FileInputStream("file.txt")){
	...
}catch(IOException e){
	...
}

복수 개의 리소스를 사용해야 한다면 try() 괄호 안에 세미콜론(;)으로 구분한다.

try(FileInputStream fis = new FileInputStream("file.txt");
	FileInputStream fis2 = new FileInputStream("file2.txt")){
	...
}catch(IOException e){
	...
}

 

예외 떠넘기기

메소드 내부에서 예외가 발생할 때 try-catch 블록으로 예외를 처리하는 것이 기본이지만, 메소드를 호출한 곳으로 예외를 떠넘길 수 있다.

리턴타입 메소드명(매개변수, ...) throws 예외클래스1, 예외클래스2, ... {
	...
}

 

사용자 정의 예외

표준 라이브러리에 존재하지 않으면 직접 예외 ㅋㄹ래스를 정의해서 사용해야 한다.

public class XXXException extends [ Exception | RuntimeException ] {
	public XXXEcveption(){
    	//기본 생성자
    }
    
    public XXXException(String message){
    	super(message);
    }
}

 

예외 발생 시키기

사용자 정의 예외를 직접 코드에서 발생시키려면 throw 키워드와 함께 예외 객체를 제공한다.

//직접 try-catch 블록으로 예외 처리
void method(){
	try{
    	...
        throw new Ecveption("예외메시지");
        ...
    }catch(Exception e){
    	String message = e.getMessage();
    }
}
//메소드를 호출한 곳에서 예외를 처리하도록 throws로 예외 떠넘기기
void method() throws Exception{
	...
    throw new Exception("예외메시지");
    ...
}
728x90
반응형
LIST

'IT > JAVA' 카테고리의 다른 글

[JAVA] #13 제네릭  (0) 2023.04.24
[JAVA] #12 java.base 모듈  (0) 2023.04.20
[JAVA] #10 라이브러리 모듈  (0) 2023.04.18
[JAVA] #9 중첩 선언과 익명 객체  (0) 2023.04.17
[JAVA] #8 인터페이스  (0) 2023.04.14

+ Recent posts