일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- join
- doitandroid
- 티스토리챌린지
- 코틀린
- Til
- Kotlin
- MySQL
- select
- 코테
- 오블완
- 안드로이드
- CS
- 프로그래머스
- Android
- 정보처리기사
- 기술면접
- 인프런
- 자바
- 카카오코테
- 자료구조
- groupby
- 스터디
- java
- 혼공단
- 알고리즘
- 혼공챌린지
- 안드로이드스튜디오
- 혼공파
- SQL
- 정처기
- Today
- Total
Welcome! Everything is fine.
[Java/Study] 김영한의 실전 자바 중급 1편 - 스터디 7회차 본문
인프런 강의 <김영한의 실전 자바 - 중급 1편>을 보고 정리한 내용입니다.
매주 모여 각자 정리한 내용을 기반으로 발표하고 질문 공유하는 스터디입니다.
📘String 클래스
String 클래스란?
- String 클래스 : 문자열을 편리하게 다룰 수 있는 클래스. 직접 char[]에 문자를 하나하나 넣어서 문자를 다루는 것은 불편하기 때문에 String 클래스를 제공해 더 편리하게 문자열을 사용할 수 있다.
String 클래스에서 문자열을 생성하는 방법에 1) 쌍따옴표를 사용하거나, 2) 객체를 생성하는 방법이 있다. String은 클래스, 즉 참조형이기 때문에 참조값만 들어갈 수 있다. 그러나 문자열은 매우 자주 사용되기 때문에 자바에서는 1)번 방법을 사용하더라도 2)번으로 변경해준다. 같은 이유로, 참조형이지만 편의상 + 연산을 사용할 수 있다.
String str1 = "hello";
String str1 = new String("hello");
String 클래스 구조
String 클래스의 구조는 대략 다음과 같다. char[] 혹은 byte[]에 실제 문자열 값이 보관되고, 그런 문자열을 다룰 수 있는 다양한 기능을 제공한다.
public final class String {
//문자열 보관
private final char[] value;// 자바 9 이전
private final byte[] value;// 자바 9 이후
//여러 메서드
public String concat(String str) {...}
public int length() {...}
...
}
✔️ String 클래스 주요 메서드
- length() : 문자열의 길이를 반환한다.
- charAt(int index) : 특정 인덱스의 문자를 반환한다.
- substring(int beginIndex, int endIndex) : 문자열의 부분 문자열을 반환한다.
- indexOf(String str) : 특정 문자열이 시작되는 인덱스를 반환한다.
- toLowerCase() , toUpperCase() : 문자열을 소문자 또는 대문자로 변환한다.
- trim() : 문자열 양 끝의 공백을 제거한다.
- concat(String str) : 문자열을 더한다.
동일성과 동등성
다음과 같이 str1와 str2 두 변수가 각각 new string()을 사용해 인스턴스를 생성했다고 할 때, 두 변수는 같을까?
String str1 = new String("hello");
String str2 = new String("hello");
str1과 str2는 동일성 비교(==)에는 실패하고, 동등성 비교(equals())에는 성공한다고 말할 수 있다. 동일성과 동등성이란 다음과 같이 설명할 수 있다.
- 동일성(Identity): == 연산자를 사용해서 두 객체의 참조가 동일한 객체를 가리키고 있는지 확인(물리적으로 같은지)
- 동등성(Equality): equals() 메서드를 사용하여 두 객체가 논리적으로 같은지 확인
즉, str1과 str2는 서로 다른 인스턴스이므로(다른 참조값을 가리키고 있으므로) 동일성 비교에 실패하는 것이다. 대신 둘 다 내부에 "hello"라는 값을 가지고 있어 논리적으로 같기 때문에 동등성 비교에 성공하는 것이다. 참고로 String 클래스는 내부 문자열 값을 비교하도록 equals() 메서드를 재정의해두었다. 이 부분은 지난 주에 정리를 하면서 스스로 궁금증이 생겨 포스팅한 내용이다. String 클래스의 equals() 메서드는 단순히 == 으로 비교하지 않고, 보다 복잡하게 비교한다.
그렇다면 다음과 같이 둘 다 문자열 리터럴을 사용하는 경우에는 어떨까? 이때는 == 비교와 equals() 비교 모두 true가 된다.
String str3 = "hello";
String str4 = "hello";
이렇게 문자열 리터럴을 사용할 때는 자바가 메모리 효율성과 성능 최적화를 위해 문자열 풀을 사용한다.
✔️ 문자열 풀?
- 필요한 String 인스턴스를 미리 만들어두는 곳
- 여러 곳에서 재사용함으로써 성능과 메모리 최적화
- 힙 영역을 사용
- 해시 알고리즘을 사용해 빠르게 String 인스턴스를 찾을 수 있음
str3과 str4를 비교하려고 할 때, 자바가 실행되는 시점에 다음과 같은 일이 일어난다.
1) 클래스에 문자열 리터럴이 있을 경우 문자열 풀에 String 인스턴스 생성
2) 문자열 풀에서 "hello"라는 문자를 가진 String 인스턴스 탐색 후 찾은 인스턴스의 참조 반환
3) str4 역시 같은 문자열이므로 str3과 같은 참조 사용
이 과정을 거쳐 str3과 str4는 같은 문자를 사용하기 때문에 성능을 최적화할 수 있다. 또한 같은 참조값을 가지므로 equals() 비교뿐만 아니라 == 비교도 성공한다.
하지만, 개발을 할 때 만나는 수많은 String 인스턴스가 new String()으로 만들어진 것인지, 문자열 리터럴로 만들어진 것인지 하나하나 확인하기는 어렵다. 개발자가 여러명이라면 더 그렇다.
⭐ 따라서, 문자열 비교는 항상 equals() 비교를 사용해서 동등성 비교를 해야한다!
불변 객체
String은 불변 객체이므로, 변경이 필요하면 기존 값을 변경하는 대신 새로운 결과를 만들어 반환한다.
String 클래스 주요 메서드
✔️ 문자열 정보 조회
- length() : 문자열의 길이를 반환한다.
- isEmpty() : 문자열이 비어 있는지 확인한다. (길이가 0)
- isBlank() : 문자열이 비어 있는지 확인한다. (길이가 0이거나 공백(Whitespace)만 있는 경우), 자바 11
- charAt(int index) : 지정된 인덱스에 있는 문자를 반환한다.
✔️ 문자열 비교
- equals(Object anObject) : 두 문자열이 동일한지 비교한다.
- equalsIgnoreCase(String anotherString) : 두 문자열을 대소문자 구분 없이 비교한다.
- compareTo(String anotherString) : 두 문자열을 사전 순으로 비교한다.
- compareToIgnoreCase(String str) : 두 문자열을 대소문자 구분 없이 사전적으로 비교한다.
- startsWith(String prefix) : 문자열이 특정 접두사로 시작하는지 확인한다.
- endsWith(String suffix) : 문자열이 특정 접미사로 끝나는지 확인한다.
✔️ 문자열 검색
- contains(CharSequence s) : 문자열이 특정 문자열을 포함하고 있는지 확인한다.
- indexOf(String ch) / indexOf(String ch, int fromIndex) : 문자열이 처음 등장하는 위치를 반환한다.
- lastIndexOf(String ch) : 문자열이 마지막으로 등장하는 위치를 반환한다.
✔️ 문자열 조작 및 변환
- substring(int beginIndex) / substring(int beginIndex, int endIndex) : 문자열의 부분 문자열을 반환한다.
- concat(String str) : 문자열의 끝에 다른 문자열을 붙인다.
- replace(CharSequence target, CharSequence replacement) : 특정 문자열을 새 문자열로 대체한다.
- replaceAll(String regex, String replacement) : 문자열에서 정규 표현식과 일치하는 부분을 새 문자열로 대체한다.
- replaceFirst(String regex, String replacement) : 문자열에서 정규 표현식과 일치하는 첫 번째 부분을 새 문자열로 대체한다.
- toLowerCase() / toUpperCase() : 문자열을 소문자나 대문자로 변환한다.
- trim() : 문자열 양쪽 끝의 공백을 제거한다. 단순 Whitespace 만 제거할 수 있다.
- strip() : Whitespace 와 유니코드 공백을 포함해서 제거한다.
✔️ 문자열 분할 및 조합
- split(String regex) : 문자열을 정규 표현식을 기준으로 분할한다.
- join(CharSequence delimiter, CharSequence... elements) : 주어진 구분자로 여러 문자열을 결합한다.
✔️ 기타 유틸리티
- valueOf(Object obj) : 다양한 타입을 문자열로 변환한다.
- toCharArray() : 문자열을 문자 배열로 변환한다.
- format(String format, Object... args) : 형식 문자열과 인자를 사용하여 새로운 문자열을 생성한다.
- matches(String regex) : 문자열이 주어진 정규 표현식과 일치하는지 확인한다.
StringBuilder
- StringBuilder : 자바에서 제공하는 가변 String으로, 내부에 final이 아닌 변경할 수 있는 byte[]을 가지고 있다.
불변인 String은 내부 값을 변경할 수 없기 때문에 문자를 변경하려고 할 때마다 계속 새로운 객체를 생성해야한다는 단점이 있다. 새로운 객체를 만들면 그만큼 메모리를 더 많이 사용하게 된다. 이런 문제를 해결하기 위해서 자바는 성능과 메모리 사용면에서 더 효율적인 StringBuilder를 제공한다. StringBuilder 는 보통 문자열을 변경하는 동안만 사용하다가 문자열 변경이 끝나면 안전한(불변) String으로 변환하는 것이 좋다.
String 최적화
자바 컴파일러는 다음과 같이 문자열 리터럴을 더하는 부분을 자동으로 합쳐준다.
String helloWorld = "Hello, " + "World!"; // 컴파일 전
String helloWorld = "Hello, World!"; // 컴파일 후
문자열 변수의 경우, 자바 버전에 따라 다른 방식으로 최적화를 수행한다.
String result = str1 + str2;
다음과 같이 StringBuilder를 사용할 수도 있고, 자바 9부터는 StringConcatFactory를 사용해 최적화를 한다.
String result = new StringBuilder().append(str1).append(str2).toString();
하지만 반복문에서 문자열 연산이 일어날 경우, 컴파일러는 얼마나 많은 반복이 일어날지 알 수 없다. 따라서 이런 상황에서는 직접 StringBuilder를 사용하면 된다.
✔️StringBuilder를 직접 사용하는 것이 더 좋은 경우
- 반복문에서 반복해서 문자를 연결할 때
- 조건문을 통해 동적으로 문자열을 조합할 때
- 복잡한 문자열의 특정 부분을 변경해야 할 때
- 매우 긴 대용량 문자열을 다룰 때
메서드 체이닝
- 메서드 체이닝(Method Chaining) : 여러 메서드를 하나의 연속된 줄로 호출할 수 있도록 메서드가 객체 자신을 반환하는 방식
✔️ 메서드 체이닝의 동작 원리
- 메서드는 객체 자신(this)을 반환
- 반환된 객체에서 다시 다른 메서드 호출 가능
- 결과적으로 여러 메서드 호출을 한 줄로 이어서 쓰기 가능
다음과 같은 클래스가 있다고 해보자. 여기서 add() 함수는 value에 addValue를 더한 값 자체를 반환하는 것이 아니라, 객체 자신을 반환하고 있다.
public class ValueAdder {
private int value;
public ValueAdder add(int addValue) {
value += addValue;
return this; // 객체 자신 반환
}
public int getValue() {
return value;
}
}
그리고나서 다음과 같이 메서드를 계속 연결해서 사용하는 것이 가능하다. 메서드를 호출하고 반환된 참조값을 즉시 사용해서 바로 메서드를 호출할 수 있는 것이다. 메서드 체이닝 기법은 코드를 간결하고 읽기 쉽게 만들어준다.
public static void main(String[] args) {
ValueAdder adder = new ValueAdder();
int result = adder.add(1).add(2).add(3).getValue();
System.out.println("result = " + result);
}
📘래퍼, Class 클래스
기본형의 한계
기본형은 한계가 있다.
- 객체가 아니므로 객체 프로그래밍의 장점을 살릴 수 없다.
- null 값을 가질 수 없다.
기본형인 int는 그저 데이터 조각이기 때문에 그 자체에서 다양한 기능을 사용할 수는 없다. 그래서 아래 코드와 같이 int를 클래스로 만들어 더 유용하게 사용할 수 있다. 이렇게 특정 기본형을 감싸서 만드는 클래스를 래퍼 클래스라 한다.
public class MyInteger {
private final int value;
public MyInteger(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public int compareTo(int target) { // 인스턴스에 소속된 메서드로 만듦
if (value < target) {
return -1;
} else if (value > target) {
return 1;
} else {
return 0;
}
}
@Override
public String toString() {
return String.valueOf(value);
}
}
MyInteger 클래스는 기본형 변수인 int value를 갖고, value를 편리하게 사용하기 위한 다양한 메서드를 제공한다. 이 중에서도 compareTo() 메서드는 들어오는 숫자와 자기 자신을 비교할 수 있다. 이런식으로 기본형을 클래스로 감싸면서 기본형을 객체로 다룰 수 있게 되었다.
우리가 '데이터가 없음'이라는 값을 표현하기 위해서 null 이라는 값이 필요할 때가 있다. 하지마 기본형은 항상 값이 있어야하기 때문에 보통 -1 또는 0을 사용한다. 하지만 상황에 따라 -1이 정말 -1을 뜻하는지, 데이터가 없다는걸 뜻하는지 명확하지 않다. 따라서 다음과 같이 래퍼 클래스를 통해 null 값을 표현할 수 있다.
public class MyIntegerNullMain1 {
public static void main(String[] args) {
MyInteger[] intArr = {new MyInteger(-1), new MyInteger(0), new MyInteger(1)};
System.out.println(findValue(intArr, -1)); // -1
System.out.println(findValue(intArr, 0));
System.out.println(findValue(intArr, 1));
System.out.println(findValue(intArr, 100)); // null
}
private static MyInteger findValue(MyInteger[] intArr, int target) {
for (MyInteger myInteger : intArr) {
if (myInteger.getValue() == target) {
return myInteger;
}
}
return null;
}
}
래퍼 클래스
자바는 다음과 같이 기본형에 대응하는 래퍼 클래스를 기본으로 제공한다. 래퍼 클래스는 기본형의 객체 버전이라고 할 수 있다. 래퍼 클래스는 불변이며, 객체이기 때문에 equals()로 비교해야 한다.
- byte → Byte
- short → Short
- int → Integer
- long → Long
- float → Float
- double → Double
- char → Character
- boolean → Boolean
래퍼 클래스의 사용법은 대략 다음과 같다.
public static void main(String[] args) {
Integer newInteger = new Integer(10); // 미래에 삭제 예정, 대신에 valueOf() 사용
Integer integerObj = Integer.valueOf(10); // -128 ~ 127 자주 사용하는 숫자 값 재사용, 불변
Long longObj = Long.valueOf(100);
Double doubleObj = Double.valueOf(10.5);
System.out.println("newInteger = " + newInteger);
System.out.println("integerObj = " + integerObj);
System.out.println("longObj = " + longObj);
System.out.println("doubleObj = " + doubleObj);
System.out.println("내부 값 읽기");
int intValue = integerObj.intValue();
System.out.println("intValue = " + intValue);
long longValue = longObj.longValue();
System.out.println("longValue = " + longValue);
System.out.println("비교");
System.out.println("==: " + (newInteger == integerObj));
System.out.println("equals:" + (newInteger.equals(integerObj)));
}
✔️ 박싱(Boxing)과 언박싱(Unboxing)
- 박싱(Boxing) : 기본형을 래퍼 클래스로 변경하는 것 - valueOf()
- 언박싱(Unboxing) : 래퍼 클래스에 들어있는 기본형 값을 다시 꺼내는 것 - xxxValue()
오토 박싱 / 오토 언박싱
개발자들이 박싱/언박싱을 많이 사용하다보니, 이 기능을 더 편리하게 사용할 수 있도록 자바 1.5부터 오토 박싱과 오토 언박싱을 지원한다. 말 그대로 컴파일러가 자동으로 박싱/언박싱을 해줘서 기본형과 래퍼형을 서로 편리하게 변환할 수 있다. 즉, 컴파일러가 valueOf(), xxxValue() 등의 코드를 추가해준다.
public static void main(String[] args) {
// Primitive -> Wrapper
int value = 7;
// Integer boxedValue = Integer.valueOf(value);
Integer boxedValue = value; // 오토 박싱(Auto-boxing)
// Wrapper -> Primitive
// int unboxedValue = boxedValue.intValue();
int unboxedValue = boxedValue; // 오토 언박싱(Auto-unboxing)
System.out.println("boxedValue = " + boxedValue);
System.out.println("unboxedValue = " + unboxedValue);
}
래퍼 클래스 주요 메서드와 성능
✔️ 래퍼 클래스 주요 메서드
- valueOf() : 래퍼 타입을 반환한다. 숫자, 문자열을 모두 지원한다.
- parseInt() : 문자열을 기본형으로 변환한다. 각 타입에 parseXxx() 가 존재한다.
- compareTo() : 내 값과 인수로 넘어온 값을 비교한다. 내 값이 크면 1 , 같으면 0 , 내 값이 작으면 -1 을 반환한다.
- Integer.sum() , Integer.min() , Integer.max() : static 메서드이다. 간단한 덧셈, 작은 값, 큰 값 연산을 수행한다.
✔️ 기본형 vs 래퍼형 성능 차이
⭐ 결론부터 말하자면, 기본형 연산이 래퍼 클래스보다 빠르다!
다음과 같이 기본형 long에 더할 때와 래퍼형 Long에 더할 때를 각각 나누어 테스트 하면, 기본형 연산이 더 빠르다는 것을 알 수 있다. 래퍼 클래스는 자바에서 객체 자체를 다루는데 필요한 객체 메타데이터를 포함하기 때문에 더 많은 메모리를 사용한다.
public static void main(String[] args) {
int iterations = 1_000_000_000; // 반복 횟수 설정, 10억
long startTime, endTime;
// 기본형 long 사용
long sumPrimitive = 0;
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
sumPrimitive += i;
}
endTime = System.currentTimeMillis();
System.out.println("sumPrimitive = " + sumPrimitive);
System.out.println("기본 자료형 long 실행 시간: " + (endTime - startTime) + "ms");
// 래퍼 클래스 Long 사용
Long sumWrapper = 0L;
startTime = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
sumWrapper += i; // 오토 박싱 발생
}
endTime = System.currentTimeMillis();
System.out.println("sumWrapper = " + sumWrapper);
System.out.println("래퍼 클래스 Long 실행 시간: " + (endTime - startTime) + "ms");
}
하지만 CPU 연산이 매우 많은 경우가 아닌 일반적인 경우라면 유지보수하기에 더 나은 것을 선택하는 것이 좋다. 강의에서는 유지보수와 최적화 중, 유지보수하기 좋은 코드를 먼저 고민해야 한다고 말하고 있다. 개발 이후 성능 테스트를 해보고 문제가 되는 부분을 찾아 최적화를 하는 것이 권장된다.
Class 클래스
- Class 클래스 : 클래스의 정보(메타데이터)를 다루는데 사용되는 클래스
- 타입 정보 얻기: 클래스의 이름, 슈퍼클래스, 인터페이스, 접근 제한자 등과 같은 정보 조회
- 리플렉션: 클래스에 정의된 메서드, 필드, 생성자 등 조회, 이들을 통해 객체 인스턴스를 생성하거나 메서드를 호출하는 등의 작업
- 동적 로딩과 생성: Class.forName() 메서드를 사용하여 클래스를 동적으로 로드, newInstance() 메서드를 통해 새로운 인스턴스 생성
- 애노테이션 처리: 클래스에 적용된 애노테이션(annotation) 조회 및 처리 기능 제공
public static void main(String[] args) throws Exception {
// Class 조회
Class clazz = String.class; // 1. 클래스에서 조회
// Class clazz1 = new String().getClass(); // 2.인스턴스에서 조회
// Class clazz2 = Class.forName("java.lang.String"); // 3. 문자열로 조회
// 모든 필드 출력
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("field = " + field.getType() + " " + field.getName());
}
// 모든 메서드 출력
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("method = " + method);
}
// 상위 클래스 정보 출력
System.out.println("Superclass: " + clazz.getSuperclass().getName());
// 인터페이스 정보 출력
Class[] interfaces = clazz.getInterfaces();
for (Class i : interfaces) {
System.out.println("Interface: " + i.getName());
}
}
예시에서 사용된 주요 메서드는 다음과 같다.
- getDeclaredFields() : 클래스의 모든 필드를 조회한다.
- getDeclaredMethods() : 클래스의 모든 메서드를 조회한다.
- getSuperclass() : 클래스의 부모 클래스를 조회한다.
- getInterfaces() : 클래스의 인터페이스들을 조회한다.
또한, Class 클래스에는 클래스의 모든 정보가 들어있어서 이 정보를 바탕으로 인스턴스를 생성하거나 메서드를 호출하는 등의 작업을 할 수 있다.
public static void main(String[] args) throws Exception {
Class helloClass = Hello.class;
// getDeclaredConstructor() - 생성자 선택
// newInstance() - 선택한 생성자 기반으로 인스턴스 생성
Hello hello = (Hello) helloClass.getDeclaredConstructor().newInstance();
String result = hello.hello();
System.out.println("result = " + result);
}
System 클래스
- System 클래스 : 시스템과 관련된 기본 기능들을 제공하는 유틸리티 클래스 . 표준 입/출력, 오류 스트림 관리, 시스템 속성, 환경 변수, 시간 측정, 메모리 관리와 작업을 처리한다.
public static void main(String[] args) {
// 현재 시간(밀리초)을 가져온다.
long currentTimeMillis = System.currentTimeMillis();
System.out.println("currentTimeMillis = " + currentTimeMillis);
// 현재 시간(나노초)을 가져온다.
long currentTimeNano = System.nanoTime();
System.out.println("currentTimeNano = " + currentTimeNano);
// 환경 변수를 읽는다.
System.out.println("getenv = " + System.getenv());
// 시스템 속성을 읽는다.
System.out.println("propertise = " + System.getProperties());
System.out.println("Java version: " + System.getProperty("java.version"));
// 배열을 고속으로 복사한다.
char[] originalArray = {'h', 'e', 'l', 'l', 'o'};
char[] copiedArray = new char[5];
System.arraycopy(originalArray, 0, copiedArray, 0, originalArray.length);
// 배열 출력
System.out.println("copiedArray = " + copiedArray);
System.out.println("Arrays.toString = " + Arrays.toString(copiedArray));
// 프로그램 종료 - 가급적이면 사용 권장하지 않음
System.exit(0);
System.out.println("hello"); // 위에서 프로그램 종료 -> 출력X
}
✔️ 표준 스트림
- System.in : 표준 입력 (키보드 입력)
- System.out : 표준 출력 (콘솔 출력)
- System.err : 표준 에러 출력 (에러 메시지 출력)
✔️ 시간 측정
- System.currentTimeMillis() : 현재 시간을 밀리초 단위로 반환
- System.nanoTime() : 현재 시간을 나노초 단위로 반환
✔️ 환경 변수
- System.getenv() : 운영 체제의 환경 변수를 가져옴
- 특정 환경 변수의 값을 얻으려면 키를 전달 (System.getenv("PATH"))
✔️ 시스템 속성
- System.getProperties() : 현재 JVM의 모든 시스템 속성을 반환
- System.getProperty(String key) : 특정 시스템 속성을 가져옴
- 예: os.name (운영 체제 이름), java.version (Java 버전)
✔️ 프로그램 종료
- System.exit(int status) : 프로그램을 종료하며 상태 코드를 반환.
- 0 : 정상 종료
- 0이 아님 : 비정상 종료 (에러 발생 등)
✔️ 배열 복사
- System.arraycopy : 고성능 배열 복사 메서드로, 직접 반복문을 사용하는 것보다 빠름
- 형식: System.arraycopy(src, srcPos, dest, destPos, length)
Math 클래스
- Math 클래스 : 수학 연산을 수행하기 위해 제공되는 유틸리티 클래스.
✔️ 기본 연산 메서드
- abs(x) : 절대값
- max(a, b) : 최대값
- min(a, b) : 최소값
✔️ 지수 및 로그 연산 메서드
- exp(x) : e^x 계산
- log(x) : 자연 로그
- log10(x) : 로그 10
- pow(a, b) : a의 b 제곱
✔️ 반올림 및 정밀도 메서드
- ceil(x) : 올림
- floor(x) : 내림
- rint(x) : 가장 가까운 정수로 반올림
- round(x) : 반올림
✔️ 삼각 함수 메서드
- sin(x) : 사인
- cos(x) : 코사인
- tan(x) : 탄젠트
✔️ 기타 유용한 메서드
- sqrt(x) : 제곱근
- cbrt(x) : 세제곱근
- random() : 0.0과 1.0 사이의 무작위 값 생성
Random 클래스
- Random 클래스 : 난수를 생성하기 위해 제공되는 유틸리티 클래스. Math.random()도 내부에서는 Random 클래스를 사용한다. Random 클래스로 더 다양한 랜덤값을 구할 수 있다.
public static void main(String[] args) {
Random random = new Random();
// Random random = new Random(1); // seed가 같으면 Random의 결과가 같음
int randomInt = random.nextInt();
System.out.println("randomInt: " + randomInt);
double randomDouble = random.nextDouble();// 0.0d ~ 1.0d
System.out.println("randomDouble: " + randomDouble);
boolean randomBoolean = random.nextBoolean();
System.out.println("randomBoolean: " + randomBoolean);
// 범위 조회
int randomRange1 = random.nextInt(10); // 0 ~ 9까지 출력
System.out.println("0 ~ 9: " + randomRange1);
int randomRange2 = random.nextInt(10) + 1; // 1 ~ 10까지 출력
System.out.println("1 ~ 10: " + randomRange2);
}
랜덤은 내부에서 씨드(Seed)값을 사용해서 랜덤 값을 구한다. 그런데 이 씨드 값이 같으면 항상 같은 결과가 출력된다.
- new Random() : 생성자를 비워두면 내부에서 System.nanoTime() 에 여러가지 복잡한 알고리즘을 섞어서 씨드값을 생성한다. 따라서 반복 실행해도 결과가 항상 달라진다.
'Java' 카테고리의 다른 글
[Java/Study] 김영한의 실전 자바 중급 1편 - 스터디 9회차 (0) | 2024.12.18 |
---|---|
[Java/Study] 김영한의 실전 자바 중급 1편 - 스터디 8회차 (4) | 2024.12.09 |
[Java/Study] 김영한의 실전 자바 중급 1편 - 스터디 6회차 (2) | 2024.11.20 |
[Java] 동등성과 동일성, equals() 메서드 파헤치기 (2) | 2024.11.13 |
[Java/Study] 김영한의 실전 자바 기본 - 스터디 5회차 (2) | 2024.11.07 |