API : Application Programming Interface
프로그래밍에서, 프로그램을 작성하기 위한 일련의 부 프로그램, 프로토콜 등을 정의하여 상호 작용을 하기 위한 인터페이스 사양을 말한다. API는 소프트웨어 컴포넌트(Function, Method, Operation으로 불리는 그것이다)의 기능, 입력, 출력, 그리고 이에 사용되는 자료형으로 표현된다. API 자체는 어디까지나 사양(Specification)만을 정의하기 때문에 구현(Implementation)과는 독립적이다. 잘 설계된 API는 프로그램 개발을 보다 쉽게 해준다. API는 다양한 형태로 존재하며, 유닉스의 POSIX 표준, 윈도우의 MFC나 Win32, C++의 표준 템플릿 라이브러리 (STL), Java SE API 등이 이에 해당한다.
좀 더 추가적인 설명을 원하면 위 링크를 참조.
API는 그냥 한 마디로... 개발을 쉽게 해주는 '도구'다.
import java.util.Random;
import java.util.Scanner;
public class WhatIstheAPI {
Random r = new Random();
Scanner s = new Scanner(System.in);
}
여기서
java.util.Random
java.util.Scanner
이런것들도 모두 API라 할 수 있다.
이건 어디에 있는걸까요?
우리가 프로젝트를 만들면 그동안 src에 .java 파일들만 관리했는데요... 그 위에 보면 'JRE System Library'라는 곳에 있습니다.
JRE System Library > java.base > java.util 을 가보면
Random.class와 Scanner.class가 있는 것을 볼 수 있습니다.
다시 Random.class를 열어보면
이런 것들이 확인됩니다.
여기서 Random()을 누르면 이 Random.class에서 해당 메소드가 정의된 곳으로 이동합니다.
그렇다면 우리가 자주 사용하는 Random.nextInt()를 찾아가봅니다.
/**
* Returns the next pseudorandom, uniformly distributed {@code int}
* value from this random number generator's sequence. The general
* contract of {@code nextInt} is that one {@code int} value is
* pseudorandomly generated and returned. All 2<sup>32</sup> possible
* {@code int} values are produced with (approximately) equal probability.
*
* <p>The method {@code nextInt} is implemented by class {@code Random}
* as if by:
* <pre> {@code
* public int nextInt() {
* return next(32);
* }}</pre>
*
* @return the next pseudorandom, uniformly distributed {@code int}
* value from this random number generator's sequence
*/
public int nextInt() {
return next(32);
}
/**
* Returns a pseudorandom, uniformly distributed {@code int} value
* between 0 (inclusive) and the specified value (exclusive), drawn from
* this random number generator's sequence. The general contract of
* {@code nextInt} is that one {@code int} value in the specified range
* is pseudorandomly generated and returned. All {@code bound} possible
* {@code int} values are produced with (approximately) equal
* probability. The method {@code nextInt(int bound)} is implemented by
* class {@code Random} as if by:
* <pre> {@code
* public int nextInt(int bound) {
* if (bound <= 0)
* throw new IllegalArgumentException("bound must be positive");
*
* if ((bound & -bound) == bound) // i.e., bound is a power of 2
* return (int)((bound * (long)next(31)) >> 31);
*
* int bits, val;
* do {
* bits = next(31);
* val = bits % bound;
* } while (bits - val + (bound-1) < 0);
* return val;
* }}</pre>
*
* <p>The hedge "approximately" is used in the foregoing description only
* because the next method is only approximately an unbiased source of
* independently chosen bits. If it were a perfect source of randomly
* chosen bits, then the algorithm shown would choose {@code int}
* values from the stated range with perfect uniformity.
* <p>
* The algorithm is slightly tricky. It rejects values that would result
* in an uneven distribution (due to the fact that 2^31 is not divisible
* by n). The probability of a value being rejected depends on n. The
* worst case is n=2^30+1, for which the probability of a reject is 1/2,
* and the expected number of iterations before the loop terminates is 2.
* <p>
* The algorithm treats the case where n is a power of two specially: it
* returns the correct number of high-order bits from the underlying
* pseudo-random number generator. In the absence of special treatment,
* the correct number of <i>low-order</i> bits would be returned. Linear
* congruential pseudo-random number generators such as the one
* implemented by this class are known to have short periods in the
* sequence of values of their low-order bits. Thus, this special case
* greatly increases the length of the sequence of values returned by
* successive calls to this method if n is a small power of two.
*
* @param bound the upper bound (exclusive). Must be positive.
* @return the next pseudorandom, uniformly distributed {@code int}
* value between zero (inclusive) and {@code bound} (exclusive)
* from this random number generator's sequence
* @throws IllegalArgumentException if bound is not positive
* @since 1.2
*/
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
int r = next(31);
int m = bound - 1;
if ((bound & m) == 0) // i.e., bound is a power of 2
r = (int)((bound * (long)r) >> 31);
else {
for (int u = r;
u - (r = u % bound) + m < 0;
u = next(31))
;
}
return r;
}
그러면 해당 메소드의 설명과 어떻게 구현이 되어있는지를 확인할 수 있습니다.
직접 찾아 들어가기는 너무 힘들죠. 따라서, Eclipase 하단에서는 'Javadoc'이 있는데 키보드 커서가 위치하면 간략하게 설명을 보여줍니다.
String은 기본 자료형이 아닌 API다.
아래는 JRE System Library > java.base > java.util > String.class > String > String()이다.
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String() {
this.value = "".value;
this.coder = "".coder;
}
String은 int와 같은 기본 자료형이 아니다. 워낙 많이 사용하기 때문에 기본 자료형처럼 사용할 수 있도록 편의성을 제공해주는 API다.
import java.util.Random;
import java.util.Scanner;
public class WahtIsAPI {
public static void main(String[] args) {
Random r = new Random();
Scanner s = new Scanner(System.in);
String a = "abc";
int b = 10;
// String은 많이 쓰기 때문에 기본 자료형처럼 사용할 수 있도록 편의성을 제공해주는 것 뿐이다.
// String은 사실 JRE System Library > java.base > java.util > String.class에 정의되어있다.
// /**
// * Initializes a newly created {@code String} object so that it represents
// * an empty character sequence. Note that use of this constructor is
// * unnecessary since Strings are immutable.
// */
// public String() {
// this.value = "".value;
// this.coder = "".coder;
// }
// 따라서 사실 String a = "abc";는 다음과 같다. (변수 중복으로 a1이라 함.)
String a1 = new String("abc");
int aa = r.nextInt();
}
}
따라서,
String a = "abc"; 는
String a = new String("abc"); 와 같다.
왜 자바에서 문자열 비교는 '=='가 아닌 '.equals()'를 사용할까?
우선 다음 2가지 개념을 먼저 알아두고 아래를 봅니다.
자바에서 '=='은 메모리 주소를 비교한다.
주소가 아닌 실제 들어있는 '값'을 비교할 때는 '.equals()'를 사용한다.
public class WhatIsString {
public static void main(String[] args) {
String a = "Hello";
System.out.println(a);
System.out.println(a.hashCode());
System.out.println();
// String은 매번 새로운 메모리 공간을 할당한다. (메모리 공간 재활용 X)
a = a + "1";
System.out.println(a);
System.out.println(a.hashCode());
System.out.println();
a = a + "1";
System.out.println(a);
System.out.println(a.hashCode());
System.out.println();
StringBuffer b = new StringBuffer("Hello");
System.out.println(b);
System.out.println(b.hashCode());
System.out.println();
// StringBuffer는 메모리 공간을 재활용한다.
b = b.append("1");
System.out.println(b);
System.out.println(b.hashCode());
System.out.println();
}
}
결과 :
Hello
69609650
Hello1
-2137068097
Hello11
-1824601518
Hello
292938459
Hello1
292938459
String의 특성 때문에 비교연산할 때 '=='가 아닌 .equals()를 사용하는 것이다.
이런 것들은 모두 class 파일로 이미 제공되는 것들입니다. 따라서 우리는 클래스를 생성할 때 절대로 기본 제공되는 API의 이름과 동일한 클래스는 생성해서는 안 됩니다!! (생성 자체에서 오류가 발생하지는 않습니다. 대신 실행시 String이라는 API 로 제공되는 클래스를 찾아가는게 아닌 내가 만든 String이라는 클래스를 먼저 찾게 되기 때문에 실행할 메소드가 없어 에러가 발생합니다.)
String에서 많이 사용하는 메소드
equals() : 특정 문자열의 내용물 비교
charAt() : 특정 위치의 char 찾기
trim() : 문자열 앞, 뒤의 공백 없애기
getBytes() : 문자열의 내용을 byte[]로 변환
StringBuffer/StringBuilder에서 많이 사용하는 메소드
append()
reverse()
public class WhatIsString {
public static void main(String[] args) {
StringBuffer b = new StringBuffer("Hello");
System.out.println(b);
System.out.println(b.hashCode());
System.out.println();
// StringBuffer의 활용
StringBuffer str = new StringBuffer("Hello"); // 같은 문자열이지만 변수가 다르기 때문에 메모리 주소는 달라진다. (내용을 기준으로 재활용 하는 것이 아닌 변수를 기준으로 재활용 하는 것이다.)
System.out.println(str);
System.out.println(str.hashCode());
System.out.println();
str.append(" Politech");
System.out.println(str);
System.out.println(str.hashCode());
System.out.println();
str.reverse();
System.out.println(str);
System.out.println(str.hashCode());
System.out.println();
}
}
결과 :
Hello
292938459
Hello
917142466
Hello Politech
917142466
hcetiloP olleH
917142466
날짜 관련 클래스 Date, Calendar
System.currentTimeMills() : long 타입의 1/1000 초
Date : JDK 1.0부터 지원되는 날짜 처리 클래스
Calendar : JDK 1.1부터 변경된 날짜 처리 클래스 (Gregorian Calendar)
날짜 관련해서 가장 많이 쓰이는 작업들
특정 날짜의 년, 월, 일, 요일 확인하기
특정 월의 마지막 날짜 구하기
문자열을 Date/Calendar로 변환하기
날짜들 간의 시간 차이 구하기
시간차 관련 클래스 Timer, TimerTask
시간차(interval)을 두고 어떤 작업을 하고 싶은 경우 사용. (i.e. 작업의 순서)
TimerTask를 상속해서 하고 싶은 작업 작성
Timer 객체를 이용해 Schedule 등록
Random 활용 방법
Math.random()
Random() 클래스를 활용 : java.util.Random
외부 데이터 입력 방법
Scanner() 클래스를 활용 : java.util.Scanner (JDK 1.5부터 제공)
java.io.BufferedReader : JDK 1.4까지 사용
Wrapper 클래스
JDK 1.4까지는 기본 자료형(int, double, ...) 등이 객체 자료형(Integer, Byte, Character, DOuble, Long, Boolean)과 엄밀하게 구분되었기 때문에 사용했다.)
JDK 1.5부터는 Auto Boxing/Auto Unboxing이 지원되므로 필요치 않음.
Formatter
출력하는 형태를 format이라고 하고, Formatter는 데이터의 출력 형태를 지정하는 것
문자열 포맷팅 : %S
소수 포맷팅 : %.3f
날짜 포맷팅 : %tY, %ty, %tm, %td, %tA, %ta
'개발자 > Java' 카테고리의 다른 글
Java(자바) java.lang.NullPointerException 에러 (0) | 2020.05.12 |
---|---|
Java (자바) 포맷팅 및 문자열 분리 예제 (0) | 2020.05.10 |
Java (자바) Interface (인터페이스) (0) | 2020.05.09 |
Java (자바) 이클립스 JDK 실행 버전 변경 (0) | 2020.05.08 |
Java (자바) 학생들 클래스 모으기 (서로 다른 클래스를 일반화 시키기) (0) | 2020.05.07 |