파일 입, 출력 ( File I/O )

파일 입, 출력 ( File I/O )

 

 

 

 

 

FileOutputStream

 

새로 생성한 테스트 폴더에 파일이 존재하지 않음

 

package file;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Ex01 {
public static void main(String[] args) throws IOException {
	
	// 파일 경로 지정(E:\\0.핀테크\\test) 및 생성할 파일(\\test.txt) 설정
	File path = new File("E:\\0.핀테크\\test\\test.txt");
	
	// 내보내는 통로 OutputStream
	FileOutputStream fos = new FileOutputStream(path); // 위에서 설정한 경로 변수로 설정, 예외처리 throws 로 처리함
	fos.write( 97 ); // 예외처리 thorws 로 처리
	fos.write( 'a' ); // 예외처리 throws 로 처리
	// write() 메소드는 int 자료형과 byte 자료형만 입력할 수 있다
	fos.write("test".getBytes()); // 문자열을 처리하려면 byte 형으로 변환하여 사용해야 한다
	
	// 가져오는 통로 InputStream
	
}
}

파일 스트림 사용

 

위 코드 실행 후 파일이 생성된 모습

 

파일 내용 확인

 

package file;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Ex02 {
public static void main(String[] args) throws Exception {
	
	Scanner sc = new Scanner(System.in);
	// 경로 설정
	String path = "E:\\0.핀테크\\test\\test2.txt";
	// 파일 내보내는 통로인 FileOutputStream 생성
	FileOutputStream fos = new FileOutputStream(path);
	
	// 입력 내용 받기
	System.out.print("출력할 내용 입력 >> ");
	String  name = sc.next();
	
	// byte 형태로 문자열 전달하여 생성
	fos.write(name.getBytes());
	System.out.println("내용이 저장되었습니다!");
	
}
}

텍스트 입력받은 후 생성되는 파일 확인

 

파일이 정상적으로 생성된 모습

 

package file;

import java.io.File;

public class Ex03 {
public static void main(String[] args) {
	// 문자열로 경로를 생성하는 경우 문자열에 존재하는 메소드만 사용할 수 있다
	String sPath = "c:/test/";
	
	// 하지만 경로를 File 자료형으로 선언하면 File 클래스에 존재하는 메소드를 사용할 수 있다
	File fPath = new File("E:\\0.핀테크\\abcd");
	fPath.mkdir(); // abcd 디렉토리 생성
	fPath.delete(); // abcd 디렉토리 삭제
	
	fPath = new File("E:\\0.핀테크");
	// list() 메소드는 반환 형태가 String[] 배열
	String[] s = fPath.list();
	// 존재하는 파일 갯수
	System.out.println(s.length); // 7 출력
	for(String a : s) {
		System.out.println(a);
		// eclipse-java
		// eclipse-java-2023-03-R-win32-x86_64.zip
		// jdk-11.0.22_windows-x64_bin.exe
		// test
		// test-home
		// test_git
		// workspace-java
	}
	
	// 현재 생성된 경로가 존재하는지 확인하는 exists() 메소드
	// 존재하면 : true, 존재하지 않으면 : false
	System.out.println(fPath.exists()); // true 출력
}
}

경로를 파일 객체로 생성하여 사용하는 이유, 파일 자료형의 메소드 종류

 

package file;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Ex04 {
public static void main(String[] args) throws IOException {
	Scanner sc = new Scanner(System.in);
	
	// 파일 경로는 입력받지 않고 미리 설정해두었음
	String path = "E:\\\\0.핀테크\\test";
	
	// 파일명 입력받는 부분
	System.out.print("생성할 파일명 입력 >>> ");
	String fileName = sc.nextLine();
	
	// File 자료형으로 경로를 설정 + 사용자가 입력한 파일명을 내용에 추가
	File filePath = new File(path + "\\" + fileName + ".txt");
	
	// 파일을 전송하기 위해 fileOutputStream 객체 생성
	// FileOutputStream fos = new FileOutputStream(filePath);
	// FileOutputStream 를 사용하여 파일을 생성 시 이미 해당 이름의 파일이 존재하면
	// 기존 파일을 덮어씌운다
	
	// 파일이 존재하는지 확인 후 없다면 파일 생성
	if(filePath.exists()) { 
		// 만약 같은 이름으로 파일이 존재한다면
		System.out.println("이미 존재하는 파일입니다.");
	}else {
		// 같은 이름으로 파일이 존재하지 않는다면
		FileOutputStream fos = new FileOutputStream(filePath);
		String msg;
		System.out.print("내용을 입력하세요 >>> ");
		msg = sc.nextLine();
		fos.write(msg.getBytes());
		System.out.println("저장 되었습니다.");
	}
}
}

FileOutputStream 의 경우 기존에 파일이 존재하는데 새로 생성하려고할 때 기존 파일을 파기해버린 후 새로 생성한다

그래서 파일을 생성할땐 해당 이름의 파일 또는 디렉토리가 이미 존재하는지 여부를 확인 후 진행해야 한다

 

 

 

 

 

FileInputStream

 

package file;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class Ex06 {
public static void main(String[] args) throws Exception {
	String path = "E:\\\\0.핀테크\\test\\test.txt";
	FileOutputStream fos = new FileOutputStream(path, true);
	// path 뒤에 true 값은 파일이 존재하면 기존 내용을 유지하면서 내용을 추가하겠다는 뜻
	// 만약 해당 파일이 없으면 파일을 새로 생성하는 것은 동일하다
	
	// true 가 들어갔으므로 기존에 test.txt 파일이 존재한다면
	// 해당 파일의 내용 뒤에 a 라는 내용을 추가하여 저장한다
	fos.write('a');
	
	fos.close(); // 열려있는 stream 을 닫아 메모리를 효율적으로 관리한다
	
	fos = new FileOutputStream(path, true);
	fos.write('c');
	fos.close();
	
	
	FileInputStream fis = new FileInputStream(path);
	int re = fis.read();
	System.out.println((char)re); // 문자를 숫자형식으로 가져와서 a 의 int 값인 97 출력되기 때문에 char 형으로 변경
	while(true) {
		re = fis.read();
		if(re<0) {
			System.out.println();
			System.out.println("내용이 없습니다 : " + re);
			break;
		}
		System.out.print((char)re);
	}
	fis.close();
}
}

파일의 내용을 읽어오는 방법

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

보조 스트림 ( BufferedOutputStream )

 

package file;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

public class Ex07 {
public static void main(String[] args) throws Exception {
	String path = "E:\\\\0.핀테크\\test\\test.txt";
	FileOutputStream fos = new FileOutputStream(path);
	
	// 보조 스트림
	// 파일을 매번 접근하지 않고 한번에 파일 작업을 모아서 한번 접근하여 모두 처리하게끔 해줌
	BufferedOutputStream bos = new BufferedOutputStream(fos);
	
	for( char ch='0' ; ch<='9' ; ch++ ) {
		Thread.sleep(1000);
		
		// fos.write(ch);
		// 파일에 1초마다 1, 2, 3, 4, 5, 6, 7, 8, 9 내용이 순차적으로 저장됨
		// 문자 하나를 입력할때마다 파일에 한번씩 접근함 -> 처리 속도가 느리다
		
		bos.write(ch); // 반복문을 돌면서 저장된 123456789 데이터를 보조 스트림에 모아놓은 상태
	}
	bos.flush(); // 보조스트림에 저장된 내용을 파일로 보내주는 flush() 메소드
	bos.write("안녕하세요".getBytes());
	bos.flush();
	
	bos.close(); // 메모리를 효율적으로 사용하기 위해 스트림을 종료
	fos.close(); // 메모리를 효율적으로 사용하기 위해 스트림을 종료
}
}

보조 스트림 ( BufferedOutputStream ) 을 사용하는 이유

- 문자를 입력받을 때 한꺼번에 처리하기 위해

 

 

 

 

 

보조 스트림 ( DataInputStream )

DataInputStream 을 사용하는 이유는 보조스트림 중 하나인 BufferedOutputStream 이나 FileOutputStream 의 경우 값을 입력할 때 byte 자료형이나 int 자료형밖에 사용할 수 없지만 DataInputStream 은 문자열이나 double 자료형 등을 형변환 하지 않고 입력할 수 있다.

 

package file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class Ex08 {
public static void main(String[] args) throws Exception {
	String path = "E:\\\\0.핀테크\\test\\test.txt";
	FileOutputStream fos = new FileOutputStream(path);
	BufferedOutputStream bos = new BufferedOutputStream(fos);
	DataOutputStream dos = new DataOutputStream(bos);
	
	// writeUTF - 문자열 한글 입력 가능
	dos.writeUTF("안녕하세요");
	dos.writeInt(123456);
	dos.writeDouble(0.12345);
	dos.close(); bos.close(); fos.close();
	
	FileInputStream fis = new FileInputStream(path);
	BufferedInputStream bis = new BufferedInputStream(fis);
	DataInputStream dis = new DataInputStream(bis);
	
	// 파일에 저장된 순서대로 값을 읽어와야 한다
	String msg = dis.readUTF();
	int num = dis.readInt();
	double dou = dis.readDouble();
	System.out.println(msg); // 안녕하세요
	System.out.println(num); // 123456
	System.out.println(dou); // 0.12345
	
}
}

보조 스트림 ( DataInputStream ) 을 사용하는 이유

728x90

 

 

 

 

 

롬복 적용 방법

 

JavaC

 

projectlombok.org

상단 탭에서 Download 를 눌러 lombok 을 다운로드 받아서 사용한다.

 

다운로드 받은 lombok.jar 파일을 잘라내서

 

이클립스가 존재하는 파일 경로에 붙여넣기 이후 이클립스를 닫는다

 

eclipse.ini 파일을 메모장으로 열어준 뒤

 

아래 두 줄 추가 후 저장후 종료 후 이클립스 실행

 

install - javac 클릭

 

해당 내용 프로젝트 안에 module-info.java 파일에 내용 추가

 

module-info.java 안에 내용 추가한 모습

 

롬복을 사용할 패키지에서 우클릭 - Properties 클릭

 

Java Build Path - Libraries - Modulepath 클릭 후 우측에 add External JARs... 박스 클릭

 

설치한 lombok.jar 선택 후 열기

 

정상적으로 올라갔으면 Apply and Close 선택 후 이클립스 재부팅

 

롬복을 설치하면 어노테이션 형태로 getter / setter 와 필드 값을 모두 포함한 생성자 선언, 기본 생성자 선언 등을 어노테이션으로 간단하게 선언할 수 있다.

@getter - getter 메소드 생성

@setter - setter 메소드 생성

@Data - getter / setter, toString(), equalsAndHashCode() 를 모두 생성

@NoArgsConstructor - 기본 생성자 생성

@AllArgsConstructor - 필드 값을 모두 포함한 생성자를 생성

 

어노테이션 선언 이후 정상적으로 생성자나 getter / setter 가 생성되는지 확인해야 한다.

 

 

추가적인 롬복의 어노테이션 종류는 " 롬복 어노테이션 종류 " 를 검색하여 찾아서 사용하면 된다.

728x90

 

 

 

 

 

회원 관리 프로젝트

현재 사용하는 DB 가 없으므로 DAO 를 생성하여 ArrayList 객체를 생성하여 DataBase 를 구현

회원관리 기능은 구현 완료, 로그인 기능은 미구현

 

DAO - 데이터베이스에서 가져온 데이터를 객체로 변환하여 비즈니스 로직에서 사용할 수 있도록 함

DTO - Service와 DB를 연결하는 역할

 

package collection.main;

import java.util.Scanner;

import collection.service.MemberService;
import collection.service.MemberServiceImpl;

public class MainClass {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int num;
		MemberService ms = new MemberServiceImpl();
		while(true) {
			System.out.println("1. 회원관리");
			System.out.println("2. 로그인기능");
			System.out.print(">>> : ");
			num = sc.nextInt();
			switch(num) {
			case 1 : 
				ms.display();
				break;
			case 2 : 
				// 미구현
				break;
			}
		}
	}
}

MainClass 클래스

 

package collection.service;

public interface MemberService {
	// 중간자 역할
	public void register();
	public void memberViews();
	public void display();
	public void search();
}

MemberService 인터페이스 ( 구현해야 하는 메소드를 정의 )

 

package collection.dto;

public class MemberDTO {
	private String name, addr;
	
	// getter/setter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddr() {
		return addr;
	}
	public void setAddr(String addr) {
		this.addr = addr;
	}
}

MemberDTO 클래스 ( 데이터베이스에서 가져온 데이터를 객체로 변환하여 비즈니스 로직에서 사용할 수 있도록 함 )

 

package collection.dao;

import java.util.ArrayList;

import collection.dto.MemberDTO;

public class MemberDAO {
	// DAO = Data Access Object
	// DAO 는 특정 저장소에 연결하는 역할을 함
	
	// 현재 DB 가 존재하지 않기 때문에 데이터를 유지하기 위해
	// static 으로 생성
	public static ArrayList<MemberDTO> arr;
	
	// arr 초기화 - 	다음과 같이 static 으로 초기화 하는 이유는 초기화 하면서 코드를
	//				추가할 수 있기 때문
	static {
		arr = new ArrayList<>();
	}
	
	// 데이터를 ArrayList 에 저장하는 역할
	public void register(MemberDTO dto) {
		System.out.println("dao register 연동");
		// System.out.println( dto.getName() );
		// System.out.println( dto.getAddr() );
		arr.add(dto);
	}
	
	// 데이터를 반환하는 역할
	public ArrayList<MemberDTO> getData() {
		return arr;
	}
	
	public MemberDTO search(String name) {
		for(MemberDTO a : arr) {
			if(a.getName().equals(name)) {
				return a;
			}
		}
		return null;
	}
	
	public MemberDAO() {
		
	}	
}

MemberDAO 클래스 ( Service와 DB를 연결하는 역할 )

 

package collection.service;

import java.util.ArrayList;
import java.util.Scanner;

import collection.dao.MemberDAO;
import collection.dto.MemberDTO;

public class MemberServiceImpl implements MemberService {
	// MemberService 를 상속 받아서 실제 기능을 구현
	MemberDAO dao;
	public MemberServiceImpl() {
		dao = new MemberDAO();
	}

	@Override
	public void register() {
		System.out.println("회원 가입 기능입니다!!!!");
		String name, addr;
		MemberDTO dto = new MemberDTO();
		Scanner sc = new Scanner(System.in);
		
		System.out.print("이름 입력 : ");
		name = sc.next();
		System.out.print("주소 입력 : ");
		dto.setAddr(sc.next());
		dto.setName(name);
		dao.register(dto);
	}

	@Override
	public void memberViews() {
		System.out.println("멤버 보기 기능입니다!!!!");
		ArrayList<MemberDTO> arr = dao.getData();
		for(MemberDTO a : arr) {
			System.out.println("이름 : " + a.getName());
			System.out.println("주소 : " + a.getAddr());
			System.out.println("-----------------");
		}
	}
	
	public void display() {
		Scanner sc = new Scanner(System.in);
		int num;
		
		while(true) {
			System.out.println("1. 저장");
			System.out.println("2. 목록확인");
			System.out.println("3. 종료");
			System.out.println("4. 검색");
			System.out.print(">>> : ");
			num = sc.nextInt();
			switch(num) {
			case 1 : 
				register();
				break;
			case 2 : 
				memberViews();
				break;
			case 3 : return;
			case 4 : 
				search();
				break;
			}
		}
	}
	
	public void search() {
		Scanner sc = new Scanner(System.in);
		String name;
		System.out.print("검색할 이름 입력 : ");
		name = sc.next();
		MemberDTO m = dao.search( name );
		if( m == null ) {
			System.out.println(name + " 사용자는 존재하지 않습니다.");
		}else {
			System.out.println("사용자 이름 : " + m.getName());
			System.out.println("사용자 주소 : " + m.getAddr());
		}
	}
}

MemberServiceImpl 클래스 ( 실제 기능 구현부 )

728x90

 

 

 

 

 

컬렉션 ( collection ) 을 사용한 객체 리스트

package collection;

import java.util.ArrayList;

class DTO01{
	private String name, id;
	
	// setter/getter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
}

public class Ex01 {
	public static void main(String[] args) {
		// DTO01 자료형 타입으로 자료를 받겠다
		ArrayList<DTO01> arr = new ArrayList<>();
		DTO01 d01 = new DTO01();
		d01.setName("홍길동");
		d01.setId("aaa");
		// DTO01 자료형 타입으로 생성된 d01 변수를
		// arr 에 0 번째 인덱스로 추가
		arr.add(d01);
		DTO01 dd = arr.get(0);
		System.out.println(dd.getId()); // aaa
		System.out.println(dd.getName()); // 홍길동
		
		
		DTO01 d02 = new DTO01();
		d02.setName("김개똥");
		d02.setId("bbb");
		arr.add(d02);
		System.out.println(arr.get(1).getId()); // bbb
		System.out.println(arr.get(1).getName()); // 김개똥
		
		// for 문을 사용하여 arr 에 저장된 DTO01 자료형의 값들 모두 출력
		for (int i=0; i<arr.size(); i++) {
			DTO01 ddd = arr.get(i);
			System.out.println("id : " + ddd.getId());
			System.out.println("이름 : " + ddd.getName());
			// id : aaa
			// 이름 : 홍길동
			// id : bbb
			// 이름 : 김개똥
			
		// for each 문을 사용하여 arr 에 저장된 DTO01 자료형의 값들 모두 출력
		for(DTO01 a : arr) {
			System.out.println("id : " + a.getId());
			System.out.println("이름 : " + a.getName());
			// id : aaa
			// 이름 : 홍길동
			// id : bbb
			// 이름 : 김개똥
			}
		}
	}
}

ArrayList 자료형에 DTO 자료형을 받게끔 객체를 생성하여 DTO 자료형의 값들을 저장 후 출력

보통 위와 같은 형식은 DataBase 에서 자료를 받아서 저장하고 출력할때 사용된다

 

package collection;

import java.util.ArrayList;
import java.util.Scanner;

class Dto02{
	private String name, id;
	
	// getter/setter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
}

public class Ex02 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String id, name;
		ArrayList<Dto02> arr = new ArrayList<>();
		while(true) {
			System.out.println("1.저장");
			System.out.println("2.모든 내용 확인");
			int num = sc.nextInt();
			switch(num) {
			case 1: 
				Dto02 d = new Dto02();
				System.out.print("아이디 입력 >> ");
				id = sc.next();
				d.setId(id);
				System.out.print("이름 입력 >> ");
				d.setName(sc.next());
				arr.add(d);
				System.out.println("저장되었습니다!!!");
				break;
			case 2: 
				for(Dto02 a : arr) {
					System.out.println("아이디 : " + a.getId());
					System.out.println("이름 : " + a.getName());
				}
				break;
			}
		}
	}
}

이름과 아이디를 입력받아 Dto02 클래스에 저장하고 저장된 내용을 arr 이라는 ArrayList 타입에 저장한뒤 출력까지 가능한 프로그램

728x90

 

 

 

 

 

쓰레드 ( Thread )

쓰레드 ( Thread )

( 쓰레드를 사용한다고 해서 동시에 2 가지 이상의 프로세스를 처리할 수 있는 것은 아니다 )

( 매우 빠른 속도로 연산하기 때문에 동시에 처리되는 것으로 보이는 것이다 )

 

package thread;

class A01 extends Thread{
	// 쓰레드를 상속
	public void run() {
		for(int i=0; i<100; i++)
			System.out.println("i : " + i);
	}
}

class B01 extends Thread{
	// 쓰레드를 상속
	public void run() {
		for(int k=0; k<100; k++)
			System.out.println("k : " + k);
	}
}

public class Ex01 {
	public static void main(String[] args) {
		A01 a = new A01();
		B01 b = new B01();
		
		// 일반적인 메소드 사용 방식
		// 순차적으로 모드가 진행됨
		// a.run();
		// b.run();
		
		// 쓰레드를 사용하여 메소드사용하여
		// 쓰레드를 적용하려면 start() 메소드를 사용하여 호출
		a.start();
		b.start();
	}
}

상속받아 쓰레드를 사용하는 방법

 

package thread;

import java.util.Scanner;

class A03 extends Thread{
	public void run() {
		for( ; ; ) {
			System.out.println("문자가 날라왔습니다!!!!");
			try {
				sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

public class Ex03 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str;
		A03 a = new A03();
		// setDaemon = 현재 쓰레드를 종료시켜준다는 의미
		// 이 쓰레드의 종료 시점은 메소드가 실행된 곳이 종료되는 시점
		// 즉, main 이 종료되는 시점에 a 쓰레드도 실행이 종료된다
		a.setDaemon(true);
		// 쓰레드 실행
		a.start();
		
		while(true) {
			System.out.print("문자열 입력 : ");
			str = sc.next();
			System.out.println("입력한 값 : " + str);
			if(str.equals("end")) {
				System.out.println("종료합니다");
				break;
			}
		}
		System.out.println("main이 종료됩니다");
	}
}

입력 받음을 유지하면서 일정 문구를 출력하는 코드

.setDaemon() - 이 메소드를 사용하여 쓰레드가 실행된 곳이 종료될때 쓰레드도 같이 종료되게끔 설정한다

 

package thread;

class Test04 extends Thread{
	A04 a;
	public Test04(A04 a, int num) {
		this.a = a;
		System.out.println(num + " -> a : " + a);
	}
	public void run() {
		a.test();
	}
}

class A04{
	int sum = 1;
	public synchronized void test() {
	// synchronized 를 사용해 쓰레드가 공유하는 a 객체 자원을 동시에 사용하는
	// 경우를 방지한다, 만약 동시에 연산을 시작하려고 하면 쓰레드 연산에 순서를
	// 지정해준다
		for(int i=1; i<10; i++) {
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println(i + " : sum : " + sum);
			sum += i;
		}
	}
}

public class Ex04 {
	public static void main(String[] args) {
		// 하나의 객체를 생성
		A04 a = new A04();
		Test04 t01 = new Test04(a, 1);
		Test04 t02 = new Test04(a, 2);
		Test04 t03 = new Test04(a, 3);
		System.out.println("t01 : " + t01);
		System.out.println("t02 : " + t02);
		System.out.println("t03 : " + t03);
		
		t01.start();
		t02.start();
		t03.start();
		
		/*
		A04 a1 = a;
		a.test();
		System.out.println(a1.sum);
		a1.test();
		System.out.println(a.sum);
		*/
		
		/*
		// !!!싱글톤 패턴 사용!!!
		// 생성된 객체를 공유
		// 즉 a 와 같은 공간을 공유!!!
		A04 a1 = a;
		
		System.out.println("a : " + a); // a : thread.A04@2133c8f8
		System.out.println("a1 : " + a1); // a1 : thread.A04@2133c8f8
		
		a1.sum = 12345;
		
		System.out.println(a.sum); // 12345
		System.out.println(a1.sum); // 12345
		*/
	}
}

synchronized - 동기화

- 쓰레드가 자원을 공유해서 사용할 때 동일한 시간에 동일한 공유 자원을 사용하면 문제가 발생하는데 이때 syncronized 즉, 동기화를 사용해 쓰레드가 동시에 공유 자원을 사용하는 순간 사용 순서를 지정해줘서 문제를 해결시켜준다.

 

 

동기화 ( synchronized ) 사용과 사용하지 않는 경우의 차이점

728x90

 

 

 

 

 

람다 ( Lambda )

람다 ( Lambda )

 

package lambda;

interface Test02{
	public void test02();
}

public class Ex02 {
	public static void main(String[] args) {
		
		// 인터페이스 자체를 객체화 할 수 있다
		// 인터페이스를 객체화 할 땐 메소드를 정의해줘야 한다
		Test02 t = new Test02() {
			@Override
			public void test02() {
				System.out.println("test 실행");
			}
		};
		t.test02(); // test 실행 출력
		
		System.out.println("--- 람다 ---");
		
		// 람다식 사용
		// () 의 의미는 Test02 의 메소드임을 의미
		// -> 를 사용하여 () 메소드의 내용을 우측에 정의
		// ★ 람다식을 사용할땐 무조건 메소드가 하나만 존재해야 한다 ★
		Test02 t02 = () -> System.out.println("test실행222");
		t02.test02(); // test실행222 출력
	}
}

람다식 사용법

 

package lambda;

interface Test03{
	public void test(int num, String msg);
}

public class Ex03 {
	public static void main(String[] args) {
		Test03 t = new Test03() {
			@Override
			public void test(int num, String msg) {
				System.out.println("num : " + num);
				System.out.println("msg : " + msg);
			}
		};
		t.test(100, "안녕하세요");
		// num : 100
		// msg : 안녕하세요
		
		System.out.println("--- 람다 ---");
		
		// 람다식 사용
		// 전달 받고자 하는 매개변수의 이름을 임의로 넣으면 됨
		Test03 t02 = (n, s) -> {
			System.out.println("n : " + n);
			System.out.println("s : " + s);
		};
		t02.test(500, "연습");
		// n : 500
		// s : 연습
	}
}

매개변수가 존재하는 인터페이스를 객체화할 때 람다식 사용법

 

package lambda;

interface Test04{
	public void test();
}

class TestClass04{
	// 인터페이스 객체를 변수로 받아 사용하는 메소드를 생성
	public void TestClass(Test04 t) {
		System.out.println("기능을 실행합니다!!!!!");
		t.test();
	}
}

public class Ex04 {
	public static void main(String[] args) {
		TestClass04 t01 = new TestClass04();
		
		// 람다식을 사용하여 인터페이스 객체화
		Test04 t04 = () -> System.out.println("test 실행됩니다");
		// 매개변수로 인터페이스 객체를 필요로 하는 메소드를 실행
		t01.TestClass(t04);
		// 기능을 실행합니다!!!!!
		// test 실행됩니다
		
		
		// 객체를 외부에 생성하지 않고 한 코드 안에서만 사용한 뒤
		// 버리는 경우 람다식을 사용해 간단하게 사용할 수 있다
		t01.TestClass(() -> {System.out.println("t1111111 실행");});
		// 기능을 실행합니다!!!!!
		// t1111111 실행
		// 위 문구 2줄 출력 후 생성되었던 인터페이스 객체는
		// 다음 코드로 넘어가면서 소멸된다
	}
}

람다식 사용 예시

( 인터페이스 객체를 매개변수로 요구하는 객체에 사용하는 경우 )

728x90

 

 

 

 

 

싱글톤 ( Singleton ) 패턴

싱글톤 ( singleton ) 패턴

 

싱글톤 패턴을 사용하는 방법

- 생성자 자체를 은닉화 ( private 을 사용하여 )

- 생성자를 은닉화 시키면 객체화하지 못하기 때문에 메소드를 public static 으로 선언하여 생성자를 메소드를 통해 생성할 수 있게함

- 이때 메소드에서 객체를 담을 변수를 사용하게 되는데 이 변수도 생성자를 사용하기 전에 메소드에서 사용되어야 함으로 static 을 사용하여 미리 클래스에 선언해줘야 함

728x90

 

 

 

 

 

추상 클래스 ( Abstract )

추상 클래스 ( Abstract )

 

package abstract_;

// 추상 메소드를 가진 추상 클래스임을 선언
abstract class Test01{
	// 추상 메소드임을 선언
	public abstract void speed();
	public void myBreak() {
		System.out.println("멈춤 기능");
	}
}

class TestClass01 extends Test01{
	// 상속한 Test01 클래스에 추상 메소드가 존재하므로
	// 무조건 오버라이딩을 진행해줘야 한다 ( 하지 않으면 컴파일 오류 발생 )
	public void speed() {
		System.out.println("2025년식 최고속도 : 250km");
	}
	public void autoSysem() {
		System.out.println("자동 운전 모드");
	}
}

class TestClass02 extends Test01{
	// 상속한 Test01 클래스에 추상 메소드가 존재하므로
	// 무조건 오버라이딩을 진행해줘야 한다 ( 하지 않으면 컴파일 오류 발생 )
	public void speed() {
		System.out.println("2026년식 최고속도 : 300km");
	}
	public void autoSysem() {
		System.out.println("자동 운전 모드");
	}
}

public class Ex01 {
	public static void main(String[] args) {
		TestClass01 t = new TestClass01();
		t.speed();
		t.myBreak();
		t.autoSysem();
	}
}

※ 추상화를 사용하면 무조건 오버라이딩을 진행해야 한다 ※

추상화 클래스를 이용하는 경우 상속받았을때 무조건 오버라이딩을 상속 받는 클래스에 작성해야하기 때문에 다형성이 생긴다

 

 

 

 

 

 

 

 

 

 

인터페이스 ( interface )

인터페이스 ( interface ) - 변수에 static final 을 적지 않으면 default 로 적용된다

 

package interface_;

// 인터페이스 생성
interface A01{
	// 인터페이스의 메소드는는 {} 를 가지지 않는다
	public void test1();
}

// 인터페이스 생성
interface B01{
	// 인터페이스의 메소드는는 {} 를 가지지 않는다
	public void test1();
}

// 클래스 2개 생성
class Class01{}
class Class02{}

public class Ex01 extends Class01 implements A01, B01{
	// 인터페이스를 상속받을 경우 implements 를 사용
	// 인터페이스는 다중 상속이 가능하다!!!!
	
	@Override
	public void test1() {
		// 인터페이스에 test1() 추상 메소드가 존재한다
		// test1() 메소드를 선언하지 않으면 컴파일 오류가 발생한다
	}
}

인터페이스 코드 작성

 

인터페이스를 파일로 생성하여 상속

 

 

- 인터페이스를 사용하면 좋은 점 -

1. 메소드 이름을 단일화 할 수 있다 ( A 와 B 가 각자 개발해도 동일한 이름으로 기능을 다르게 개발 )

2. 인터페이스를 자료형으로 객체를 생성하여 내부에 담긴 인터페이스 메소드만 사용하거나 확인할 수 있다.

인터페이스 자료형으로 객체를 생성한 모습

728x90

+ Recent posts