no image
[JAVA] API Document
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 자바 표준 모듈에서 제공하는 라이브러리는 방대하기 때문에 쉽게 찾아서 사용할 수 있도록 도와주는 API(Application Programming Interface) 문서가 있다. 라이브러리가 클래스와 인터페이스의 집합이라면, API 도큐먼트는 이를 사용하기 위한 방법을 기술 한 것이다. API 도큐먼트는 자바 표준 모듈에 있는 패키지 중 public과 prtected로 접근 제한된 클래스와 메소드만 소개한다. 자바 표준 모듈에 있는 패키지 중에서 default와 private로 접근 제한된 클래스와 메소드는 접근 제한자에 대해 잘 알고 있다면 우리는 접근할 수 없다는 것을 알 수 있..
2023.07.27
no image
[Java] 백준 15단계 - 1735번 문제 (분수 합)
문제설명 소스코드 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int arr[] = new int[4]; for(int i = 0; i < 4; ++i) arr[i] = in.nextInt(); int a = (arr[0] * arr[3]) + (arr[1]* arr[2]); int b = arr[1] * arr[3]; int minDivisor = gcd(a, b); System.out.println(a / minDivisor + " " + b / minDivisor); } public static int gcd(int a, i..
2023.07.26
no image
[Java] 백준 15단계 - 13241번 문제 (최소공배수)
문제설명 소스코드 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); long a = in.nextLong(); long b = in.nextLong(); System.out.println(a * b / gcd(a, b)); } public static long gcd(Long a, Long b) { if(b == 0) return a; else return gcd(b, a % b); } } 설명 최소공배수와 최대공약수와의 관계는 아래와 같다. 두 자연수의 곱 = 최대공약수 × 최소공배수 최소공배수 = 두 자연수의 곱 / 최대공약수 유클..
2023.07.26
no image
[JAVA] 사용자 정의 예외
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 사용자 정의 예외 사용자 정의 예외란 예를 들어 은행의 뱅킹 프로그램에서 잔고보다 더 많은 출금 요청이 들어온 경우에는 잔고 부족 예외를 발생 시킬 필요가 있다. 하지만 잔고 부족 예외는 자바의 표준 라이브러리에는 존재하지 않기 때문에 직접 예외 클래스를 정의해서 사용해야 한다. 이렇게 사용자가 직접 예외 클래스를 정의하는 것을 사용자 정의 예외 클래스라고 한다. 사용자 정의 예외는 일반 예외와 실행 예외로 선언할 수 있다. 일반 예외 : 컴파일러가 체크, Exception의 자식 클래스로 선언 실행 예외 : 컴파일러가 체크하지 않음, RunTimeException의 자식 클래스로 선..
2023.07.26
no image
[Java] 백준 15단계 - 1934번 문제 (최소공배수)
문제설명 소스코드 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int T = in.nextInt(); for(int i = 0; i < T; i++) { int a = in.nextInt(); int b = in.nextInt(); System.out.println(a * b / gcd(a, b)); } } public static int gcd(int a, int b) { if(b == 0) return a; else return gcd(b, a % b); } } 설명 최소공배수와 최대공약수와의 관계는 아래와 같다. 두 자연수의..
2023.07.25
no image
[JAVA] 리소스(resource) 자동 닫기
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 리소스란 데이터를 제공하는 객체(DB 등)를 뜻한다. 리소스를 사용하기 위해선 열어야 하고, 사용이 끝나면 반드시 닫아야 한다. 리소스를 사용하고 닫지 않으면 불안정한 상태로 남게 된다. try-catch-finally문 리소스를 자동으로 닫는 기본적인 방법은 try-catch-finally문에서 finally 부분에 리소스를 닫는 코드를 넣어주면 된다. finally는 예외가 발생하든 안 하든, 메소드가 return문을 만나도 무조건 실행되기 때문이다. FileInputStream fis = null; try { fis = new FileInputStream("file.tsxt");..
2023.07.25
no image
[Java] Getter와 Setter 메소드
일반적으로 객체 지향 프로그래밍에서는 객체의 필드를 객체 외부에서 직접적으로 접근하는 것을 막는다. 왜냐하면 예를 들어 속력은 음수가 될 수 없는데, 외부에서 속력을 저장하는 변수에 음수를 저장하면 문제가 생긴다. 이를 무결성이 깨졌다고 한다. 이러한 문제점을 해결하기 위해 객체 지향 프로그래밍에서는 메소드를 통해서 필드를 변경하는 방법을 선호한다. 필드는 외부에서 접근할 수 없게 하고(private 접근 제한자 사용), 메소드는 접근할 수 없는 필드에 접근할 수 있도록 한다. 이러한 메소드를 Setter라고 한다. 외부 객체에서 데이터를 읽을 때도 메소드를 사용하는 것이 좋다. 왜냐하면 필드값을 직접 사용하면 부적절한 경우도 있기 때문이다. 이런 경우에는 메소드로 필드값을 가공한 후 외부로 전달하면 된..
2023.07.24
no image
[C++] 백준 14단계 - 11478번 문제 (서로 다른 부분 문자열의 개수)
문제설명 소스코드 #include #include #include using namespace std; int main() { string input; int count = 0; cin >> input; for (int i = 0; i < input.length(); ++i) { vector vec; for (int j = 0; j < input.length() - i; ++j) { string strTmp = input.substr(j, i + 1); //문자열 잘라내기 vec.push_back(strTmp); //벡터에 원소 추가 } sort(vec.begin(), vec.end()); //벡터 정렬 vec.erase(unique(vec.begin(), vec.end()), vec.end()); //..
2023.07.24

이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 


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

라이브러리가 클래스와 인터페이스의 집합이라면, API 도큐먼트는 이를 사용하기 위한 방법을 기술 한 것이다.

API 도큐먼트는 자바 표준 모듈에 있는 패키지 중 public과 prtected로 접근 제한된 클래스와 메소드만 소개한다.
자바 표준 모듈에 있는 패키지 중에서 default와 private로 접근 제한된 클래스와 메소드는 접근 제한자에 대해 잘 알고 있다면 우리는 접근할 수 없다는 것을 알 수 있을 것이다.
따라서 API 문서는 public과 protected 접근 제한을 갖는 것들만 소개한다.

링크 : https://docs.oracle.com/en/java/javase/

 

Java Platform, Standard Edition Documentation - Releases

Java Platform, Standard Edition documentation, current and previous releases

docs.oracle.com

 

위 사이트에 들어가면 아래와 같은 화면이 나온다.

 

원하는 JDK 버전에 들어가면

 

이런 화면이 나오는데 왼쪽 API Documentation을 클릭하면

여기서 자바 표준 모듈에서 제공하는 라이브러리를 볼 수 있다.

문제설명

 

 

소스코드

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int arr[] = new int[4];
		for(int i = 0; i < 4; ++i) arr[i] = in.nextInt();
		int a = (arr[0] * arr[3]) + (arr[1]* arr[2]);
		int b = arr[1] * arr[3];
		int minDivisor = gcd(a, b);
		System.out.println(a / minDivisor + " " + b / minDivisor);
	}
	public static int gcd(int a, int b)
	{
	    if(b == 0) return a;
	    else return gcd(b, a % b);
	}
}

 

설명

  • 입력받은 정수를 arr[0], ar[1], arr[2], ar[3]라고 하면
    a = (arr[0] * arr[3]) + (arr[1]* arr[2])
    b = arr[1] * arr[3];
  • a와 b의 최대공약수를 유클리드 호제법으로 구한다.
  • a와 b를 최대공약수로 나눈 값을 출력한다.

문제설명

 

소스코드

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		long a = in.nextLong();
		long b = in.nextLong();
		System.out.println(a * b / gcd(a, b));
	}
	public static long gcd(Long a, Long b)
	{
	    if(b == 0) return a;
	    else return gcd(b, a % b);
	}
}

 

설명

  • 최소공배수와 최대공약수와의 관계는 아래와 같다.
    두 자연수의 곱 = 최대공약수 × 최소공배수
    최소공배수 = 두 자연수의 곱 / 최대공약수
  • 유클리드 호제법으로 최대공약수를 구한다(재귀 이용)
유클리드 호제법
위 알고리즘은 유클리드 호제법을 이용한 것이다.
두 정수를 직사각형의 두 변의 길이라고 생각하면 두 정수의 최대공약수를 구하는 문제는
직사각형을 정사각형으로 완전히 채우고 이렇게 만들 수 있는 정사각형의 가장 긴 변의 길이를 구하면 된다.

1.짧은 변의 길이를 한 번으로 하는 정사각형으로 채운다.
2.남은 직사각형에 대해 같은 작업을 반복
3.정사각형만으로 구성되었을 때의 변의길이가 최대공약수

 

이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 


사용자 정의 예외

사용자 정의 예외란 예를 들어 은행의 뱅킹 프로그램에서 잔고보다 더 많은 출금 요청이 들어온 경우에는 잔고 부족 예외를 발생 시킬 필요가 있다.

하지만 잔고 부족 예외는 자바의 표준 라이브러리에는 존재하지 않기 때문에 직접 예외 클래스를 정의해서 사용해야 한다.

이렇게 사용자가 직접 예외 클래스를 정의하는 것을 사용자 정의 예외 클래스라고 한다.

 

사용자 정의 예외는 일반 예외와 실행 예외로 선언할 수 있다.

  • 일반 예외 : 컴파일러가 체크, Exception의 자식 클래스로 선언
  • 실행 예외 : 컴파일러가 체크하지 않음, RunTimeException의 자식 클래스로 선언
public class XXXException extends [Exception | RunTimeException] { //일반 예외를 상속할지, 실행 예외를 상속할지 선택
	public XXXException() { //기본 생성자
	}

	public XXXException(String message) { //예외 메시지를 입력받는 생성자
		super(message);
	}
}

예외 메시지는 부모 생성자 매개값으로 넘겨주는데, 그 이유는 예외 객체의 공통 메소드인 getMessage()의 리턴 값으로 사용하기 위해서이다.

 


 

예외 발생 시키기

  • 자바에서 제공하는 표준 예외뿐만 아니라 사용자 정의 예외를 직접 코드에서 발생시키려면 throw 키워드와 함께 예외 객체를 제공하면 된다.
  • 예외의 원인에 해당하는 메시지를 제공하고 싶다면 생성자 매개값으로 전달하면 된다.
throws(예외 떠넘기기) 키워드와 thorw(예외 발생시키기) 키워드는 다른 것이니 혼동하지 말자.
  • throw된 예외는 직접 try-catch 문으로 예외를 처리할 수도 있지만, 대부분은 메소드를 호출한 곳에서 예외를 처리하도록 throws 키워드로 예외를 떠넘긴다.

 

아래의 코드는 계좌의 잔고보다 많은 금액을 출금하려고 하면 사용자 정의 예외를 발생시켜서 출금을 하지 못하게하는 예제 코드이다.

 

InsufficientException.java(사용자 정의 예외 클래스)

public class InsufficientException extends Exception {
	public InsufficientException() {
	}

	public InsufficientException(String message) {
		super(message);
	}
}

 

Account.java

public class Account {
	private long balance;
	
	public Account() { }

	public long getBalance() { //금액 확인
		return balance;
	}
	public void deposit(int money) { //입금
		balance += money;
	}
	public void withdraw(int money) throws InsufficientException { //출금, 사용자 정의 예외 클래스로 떠넘기기
		if(balance < money) {
			throw new InsufficientException("잔고 부족: "+(money-balance)+" 모자람"); //사용자 정의 예외 발생
		}
		balance -= money;
	}
}

 

Main.java

public class Main {
	public static void main(String[] args) {
		Account account = new Account();
		//예금하기
		account.deposit(10000); //만 원 입금
		System.out.println("예금액: " + account.getBalance());

		//출금하기
		try {
			account.withdraw(30000); //3만 원 출금
		} catch(InsufficientException e) { //사용자 정의 예외가 발생한다면
			String message = e.getMessage();
			System.out.println(message);
		}
	}
}
/*
예금액: 10000
잔고 부족: 20000 모자람
*/

문제설명

 

소스코드

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int T = in.nextInt();
		for(int i = 0; i < T; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			System.out.println(a * b / gcd(a, b));
		}
	}
	public static int gcd(int a, int b)
	{
	    if(b == 0) return a;
	    else return gcd(b, a % b);
	}
}

 

설명

  • 최소공배수와 최대공약수와의 관계는 아래와 같다.
    두 자연수의 곱 = 최대공약수 × 최소공배수
    최소공배수 = 두 자연수의 곱 / 최대공약수
  • 유클리드 호제법으로 최대공약수를 구한다(재귀 이용)
유클리드 호제법
위 알고리즘은 유클리드 호제법을 이용한 것이다.
두 정수를 직사각형의 두 변의 길이라고 생각하면 두 정수의 최대공약수를 구하는 문제는
직사각형을 정사각형으로 완전히 채우고 이렇게 만들 수 있는 정사각형의 가장 긴 변의 길이를 구하면 된다.

1.짧은 변의 길이를 한 번으로 하는 정사각형으로 채운다.
2.남은 직사각형에 대해 같은 작업을 반복
3.정사각형만으로 구성되었을 때의 변의길이가 최대공약수

이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다. 


  • 리소스란 데이터를 제공하는 객체(DB 등)를 뜻한다.
  • 리소스를 사용하기 위해선 열어야 하고, 사용이 끝나면 반드시 닫아야 한다.
  • 리소스를 사용하고 닫지 않으면 불안정한 상태로 남게 된다.

 

try-catch-finally문

리소스를 자동으로 닫는 기본적인 방법은 try-catch-finally문에서 finally 부분에 리소스를 닫는 코드를 넣어주면 된다.

finally는 예외가 발생하든 안 하든, 메소드가 return문을 만나도 무조건 실행되기 때문이다.

FileInputStream fis = null;
    try {
        fis = new FileInputStream("file.tsxt");
    } catch(IOException e) {
        //예외 처리 코드 작성
    }finally {
        fis.close(); //리소스 닫기
    }

 


 

try-with-resources문

try-catch-finally문과 다르게 finally문을 작성하지 않아도 된다.

이 또한 예외 발생 여부와 상관없이 리소스를 자동으로 닫아준다.

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

 

하지만 try-with-resources문을 사용하려면 리소스는 java.lang.AutoCloseable 인터페이스를 구현하고 해당 인터페이스의 close() 메소드를 오버라이딩(재정의) 해야 한다.

java.lang.AutoCloseable 인터페이스는 자바가 기본적으로 제공한다.
따라서 우리는 구현 객체만 만들면 된다.

MyResource.java

public class MyResource implements AutoCloseable{
	//...
	@Override
	public void close() throws Exception {
		//리소스를 닫는 코드 작성
	}

}

 

Main.java

public class Main {
	public static void main(String[] args) {
		try {
			MyResource fis1 = new MyResource("file1.txt");
			MyResource fis2 = new MyResource("file2.txt");
		}catch(IOException e) {
			//예외 처리 코드 작성
		}
        //finally문을 작성하지 않아도 자동으로 리소스가 닫힌다.
	}
}
Java 9 버전 이후부터는  외부 리소스 변수를 사용할 수 있다.
public class Main {
	public static void main(String[] args) {
		MyResource fis1 = new MyResource("file1.txt");
		MyResource fis2 = new MyResource("file2.txt");
		try (fis1; fis2){
			
		}catch(IOException e) {
			//예외 처리 코드 작성
		}
	}
}​

 

아래의 예제는 try-with-resources문을 이용하여 제대로 리소스를 닫을 수 있는지를 확인하는 예제이다.

결과를 확인하면 제대로 예외가 발생해도 close() 메소드가 자동으로 호출되어 리소스를 자동으로 닫을 수 있다는 것을 확인할 수 있다.

 

MyResource.java

public class MyResource implements AutoCloseable {
	private String name;
	
	public MyResource(String name) {
		this.name = name;
		System.out.println("[MyResource(" + name + ") 열기]");
	}
	
	public String read1() {
		System.out.println("[MyResource(" + name + ") 읽기]");
		return "100";
	}
	
	public String read2() {
		System.out.println("[MyResource(" + name + ") 읽기]");
		return "abc";
	}
	
	@Override
	public void close() throws Exception {
		System.out.println("[MyResource(" + name + ") 닫기]");
	}
}

 

Main.java

public class Main {
	public static void main(String[] args) {
		try (MyResource res = new MyResource("A")) {
			String data = res.read1();
			int value = Integer.parseInt(data);
		} catch(Exception e) {
			System.out.println("예외 처리: " + e.getMessage());
		}
		System.out.println();
        
		///////////////////////////////////////////////////
        
		try (MyResource res = new MyResource("A")) {
			String data = res.read2();
			//NumberFormatException 발생
			int value = Integer.parseInt(data);
		} catch(Exception e) {
			System.out.println("예외 처리: " + e.getMessage());
		}
		System.out.println();
        
		///////////////////////////////////////////////////
        
		try (
			MyResource res1 = new MyResource("A"); 
			MyResource res2 = new MyResource("B")
		) {
			String data1 = res1.read1();
			String data2 = res2.read1();
		} catch(Exception e) {
			System.out.println("예외 처리: " + e.getMessage());
		}
		System.out.println();
        
		///////////////////////////////////////////////////
        
		MyResource res1 = new MyResource("A"); 
		MyResource res2 = new MyResource("B");
		try (res1; res2) {
			String data1 = res1.read1();
			String data2 = res2.read1();
		} catch(Exception e) {
			System.out.println("예외 처리: " + e.getMessage());
		}
	}
}
/*
[MyResource(A) 열기]
[MyResource(A) 읽기]
[MyResource(A) 닫기]

[MyResource(A) 열기]
[MyResource(A) 읽기]
[MyResource(A) 닫기]
예외 처리: For input string: "abc"

[MyResource(A) 열기]
[MyResource(B) 열기]
[MyResource(A) 읽기]
[MyResource(B) 읽기]
[MyResource(B) 닫기]
[MyResource(A) 닫기]

[MyResource(A) 열기]
[MyResource(B) 열기]
[MyResource(A) 읽기]
[MyResource(B) 읽기]
[MyResource(B) 닫기]
[MyResource(A) 닫기]
*/

일반적으로 객체 지향 프로그래밍에서는 객체의 필드를 객체 외부에서 직접적으로 접근하는 것을 막는다.

왜냐하면 예를 들어 속력은 음수가 될 수 없는데, 외부에서 속력을 저장하는 변수에 음수를 저장하면 문제가 생긴다.

이를 무결성이 깨졌다고 한다.

 

이러한 문제점을 해결하기 위해 객체 지향 프로그래밍에서는 메소드를 통해서 필드를 변경하는 방법을 선호한다.

필드는 외부에서 접근할 수 없게 하고(private 접근 제한자 사용), 메소드는 접근할 수 없는 필드에 접근할 수 있도록 한다.

이러한 메소드를 Setter라고 한다.

 

외부 객체에서 데이터를 읽을 때도 메소드를 사용하는 것이 좋다.

왜냐하면 필드값을 직접 사용하면 부적절한 경우도 있기 때문이다. 이런 경우에는 메소드로 필드값을 가공한 후 외부로 전달하면 된다.

이러한 메소드를 Getter라고 한다.

 

Car.java

public class Car {
	private int speed; //외부에서 접근할 수 없도록 접근 제한
	
	public int getSpeed() { //Getter
		return speed;
	}
	public void setSpeed(int speed) { //Setter
		if(speed < 0) { 
			this.speed = 0;
			return;
		} else {
			this.speed = speed;
		}
	}
}

 

Test.java

public class Test {
	public static void main(String[] args) {	
		Car myCar = new Car();
		
		myCar.setSpeed(-50); //잘못 된 속도로 변경
		
		System.out.println("현재 속도 : " + myCar.getSpeed());
		
		myCar.setSpeed(60); //올바른 속도로 변경
		
		System.out.println("현재 속도 : " + myCar.getSpeed());
	}
}
/*
현재 속도 : 0
현재 속도 : 60
*/

문제설명

 

소스코드

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    string input;
    int count = 0;
    cin >> input;
    for (int i = 0; i < input.length(); ++i)
    {
        vector<string> vec;
        for (int j = 0; j < input.length() - i; ++j)
        {
            string strTmp = input.substr(j, i + 1); //문자열 잘라내기
            vec.push_back(strTmp); //벡터에 원소 추가
        }
        sort(vec.begin(), vec.end()); //벡터 정렬
        vec.erase(unique(vec.begin(), vec.end()), vec.end()); //중복 항목 제거
        count += vec.size(); //벡터의 원소 개수를 더함
    }
    cout << count;
}

 

설명

문자열 ababc가 주어졌을 때, 벡터인 vec에 들어가는 원소는 아래와 같다.

i j 원소
0 0 a
1 b
2 a - erase에 의해 제거
3 b - erase에 의해 제거
4 c
1 0 ab
1 ba
2 ab - erase에 의해 제거
3 bc
2 0 aba
1 bab
2 abc
3 0 abab
1 babc
4 0 ababc