자바 스터디

[자바의 정석] CH 9(Math ~ Objects)

changha. 2023. 6. 29. 13:50

Math 클래스

- 기본적인 수학계산에 쓰이는 메서드로 이루어짐

- 생성자의 접근제어자가 private

- 메서드는 모두 static

- E(자연로그), PI(원율) 2개의 상수를 정의함 

소수점 n번째 자리에서 반올림한 값을 얻기 위해서는 round()를 사용해야 한다.

이 메서드는 항상 소수점 첫째자리에서 반올림을 해서 정수값을 결과로 돌려준다.

 

public void main(String args[]){
	double val = 90.7552;
    System.out.println("round(" + val + ")=" +round(val)); //반올림  
    
    val *= 100;
    System.out.println("round(" + val + ")=" +round(val)); //반올림 
    System.out.println("round(" + val + ")/100.0=" + round(val)/100.0); // 반올림
    
}

//실행 결과
// round(90.7552)=91
// round(9075.52)=9076
// round(9075.52)/100.0=90.76

· Math.abs = 절댓값 

· Math.ceil = 올림

· Math.floor = 버림

· Math.max = 두 값 중 최댓값 

· Math.min = 두 값 중 최솟값

· Math.random = 랜덤 

· Math.rint = 짝수 반올림(1.5, 2.5, 3.5 등 가운데는 짝수를 반환)

    - 계속해서 round쓰면 소수점 첫째 자리가 0.5이상일 때 오차가 커질 수 있으니  

· Math.round = 반올림 

 

예외 발생 

정수형간 연산에서 발생할 수 있는 오버플로우를 감지하기 위한 -Exact 메서드 

-> 오버플로우 발생 시, 예외(ArithmeticException)을 발생시킴 

int addExact(int x, int y) // x + y
int subtractExact(int x, int y) // x - y
int multiplyExact(int x, int y) // x * y
...

 

 

래퍼(wrapper) 클래스

8개의 기본형을 객체로 다뤄야할 때 사용하는 클래스

Integer와 Character만 제외하고 앞글자만 대문자로 바꾸면 래퍼 클래스가 된다.

 

여담으로 자바가 기본형이 객체가 아니기 때문에 100% 객체지향은 아니다!

 

그럼 왜 기본형을 사용할까?

바로 성능 때문이다.

참조 변수를 읽고 주소로 가야하는 객체 특성에 반해 기본형은 바로 읽을 수 있다.

 

public static void main(String[] args){

	Integer i = new Integer(100);
    Integer i2 = new Integer(100);
    
    System.out.println("i==i2 ? " + (i==i2)); // false
    System.out.println("i.equals(i2) ? " + i.equals(i2)); // true 
    System.out.println("i.compareTo(i2)=" + i.compareTo(i2)); // 0
    
}

compareTo 

같으면 0, 오른쪽이 작으면 양수, 크면 음수 

 

Number클래스

모든 숫자 래퍼 클래스의 조상

public abstract class Number implements java.io.Serializable {
	public abstract it intValue();
    public abstract long longValue();
    public abstract float floatValue();
    ...
    
}

래퍼 객체를 기본형으로 바꾸는 메서드를 가지고 있다.(new Integer(100) -> 100으로 바꾸려면 intValue()를 사용하면 됨)

 

문자열을 숫자로 바꾸는 방법

int i = new Integer("100").intValue();
int i2 = Integer.parseInt("100"); // 주로 이 방법을 많이 사용.
Integer i3 = Integer.valueOf("100");
// 문자열 -> 기본형
Byte b = Byte.parseByte("100");
int i = Integer.parseInt("100");
float f = Float.parseInt("3.14");

// 문자열 -> 래퍼 클래스 
Byte b = Byte.valueOf("100");
Integer i = Integer.valueOf("100");
Float f = Float.valueOf("3.14");

JDK1.5 부터 오토박싱이 도입되어 반환값이 기본형, 래퍼 클래스 차이가 없어졌다.

그래서 그냥 구분없이 valueOf()를 쓰는 것도 괜찮다.

 

n진법의 문자열을 숫자로 변환하는 방법

int i4 = Integer.parseInt("100", 2); // 100(2) -> 4
int i5 = Integer.parseInt("100", 8); // 100(8) -> 64
int i6 = Integer.parseInt("100", 16); // 100(16) -> 256
int i7 = Integer.parseInt("FF", 16); // FF(16) -> 255
int i8 = Integer.parseInt("FF"); // error, NumberFormatException발생

 

오토박싱 & 언박싱 (autoboxing & unboxing)

오토박싱 : 기본형 -> 래퍼 객체 

언박싱 : 래퍼 객체 -> 기본형 

자바 컴파일에 의해 자동으로 처리 됨 

 

 

int i = 5;
Integer iObj = new Integer(7);
int sum = i + iObj; // error, 기본형과 참조형 간의 덧셈 불가(JDK1.5 이전)

// 현재 컴파일 후
int sum = i + iObj.intValue(); // 컴파일 시, 기본형으로 변환시킴

예제

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10); // 오토박싱. 10 -> new Integer(10);

int value = list.get(0); // 언박싱. new Integer(10) -> 10

ArrayLIst에 숫자를 저장하거나 꺼낼 때, 기본형 값을 래퍼클래스의 객체로 변환하지 않아도 되어 편리하다.

 

int i = 10;

부담갖지 말고 내부적으로 오토박싱,언박싱을 해줘서 기본형과 참조형간의 형변환이 가능해졌다

정도만 알고있으면 된다. 

 

 

java.util.Objects 클래스 

- Object클래스의 보조 클래스로 Math클래스처럼 모든 메서드가 'static', 객체의 비교나 널 체크(null check)에 유용하다.

 

Object 클래스와 이름이 비슷해서 헷갈리므로 정리하고 가자!

 

Object

: Java의 모든 클래스의 기본 클래스를 뜻함 

 

Objects

: Java7에서 추가된 유틸리티 클래스. null-safe한 메서드들을 제공하여, 객체 비교, null 처리에 편리하게 사용가능 함 

 

 

다양한 메서드 소개 

 

static boolean isNull(Object obj)
static boolean nonNull(Object obj)

isNull()은 null이면 true

nonNull()은 isNull과 정반대 

 

static <T> T requireNonNull(T obj)
static <T> T requireNonNull(T obj, String message)
static <T> T requireNonNull(T obj, Supplier<String> messageSupplier)

requireNonNull()은 해당 객체가 널이 아니어야 하는 경우에 사용 

 

void setName(String name) {
	if (name == null)
    {
    	throw new NullPointerException("name must not be null");
    }
    this.name = name;
}

->

void setName(String name) {
	this.name = Objects.requireNonNull(name, "name must not be null.");
}

 

static int compare(Object a, Object b, Comparator c)

// Comparator 예시
Comparator c = String.CASE_INSENSITIVE_ORDER; // 대소문자 구분안하는 비교
...
System.out.println("compare(\"ab\", \"AB\") = "+compare("ab", "AB", c));

// 대소문자 구분하지 않고 비교하여, 결과가 0, 즉 두 문자열이 같다는 결과가 나온다.

두 비교대상이 같으면 0, 왼쪽이 크면 양수, 작으면 음수를 반환한다.


static boolean equals(Object a, Object b)
static boolean deepEquals(Object a, Object b)

Object클래스에 정의된 equals()가 왜 Objects클래스에도 있는지 궁금할 텐데, 이 메서드의 장점은

null 검사를 하지 않아도 된다.

if (a !=null && a.equals(b){
	// a가 null인지 반드시 확인 
}

->

if(Objects.equals(a, b)) {
	// 매개변수의 값이 null인지 확인할 필요가 없음 
}
// 다차원 배열일 때 비교

String[][] str2D = new String[][]{{{"aaa", "bbb"}, {"AAA", "BBB"}}};
String[][] str2D2 = new String[][]{{{"aaa", "bbb"}, {"AAA", "BBB"}}};

System.out.println(Objects.equals(str2D, str2D2)); // false
System.out.println(Objects.deepEqauls(str2D, str2D2)); //true

deepEqauls()를 이용하여 다차원 배열의 비교도 가능


static String toString(Object o)
static String toString(Object o, String nullDefault)

내부적으로 null 검사를 하는 것 빼고는 특별한 것이 없다.

두번 째 메서드는 o가 null일 때, 대신 사용할 값을 지정할 수 있어서 유용하다.

 

static int hashCode(Object o)
static int hash(Object... values)

마지막으로 hashCode

: 객체를 식별하는 하나의 고유 정수값

hasCode()는 객체의 메모리 번지를 이용해서 hashcode를 만들어 리턴하기 때문에 객체 마다 고유의 다른 값을 가져야 함 

 

보통은 hashCode()를 오버라이딩하지만, 매개변수의 타입이 가변인자(매개변수의 개수가 변할 수 있음)인 두 번째 메서드를 사용하면 편리하다. 

'자바 스터디' 카테고리의 다른 글

[자바의 정석] CH 12 (Generics, Enum, Annotation)  (0) 2023.07.20
[자바의 정석] ch11.9 ~ ch.11.11  (0) 2023.07.12
[자바의 정석] CH8  (0) 2023.06.24
[자바의 정석] CH7  (0) 2023.06.15
[자바의 정석] CH-6  (0) 2023.05.04