1.1 Object 클래스
Object 클래스는 모든 클래스의 최고 조상이기 때문에 Object 클래스의 멤버들은 모든 클래스에서 바로 사용이 가능
Object 클래스의 메서드
- protected Object clone() : 객체 자신의 복사본을 반환
- public boolean equals(Object obj) : 객체 자신과 객체 obj가 같은 객체인지 알려준다 (같으면 true / value아니고 주소값이 같아야함)
- public Class getClass() : 객체 자신의 클래스 정보를 담고 있는 Class 인스턴스를 반환한다.
- public int hashCode() : 객체 자신의 해시코드를 반환한다
- public String toString() : 객체 자신의 정보를 문자열로 반환
- public void notify(): 객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨운다
- public void notifyAll() : 객체 자신을 사용하려고 기다리는 모든 쓰레드를 꺠운다
- public void wait() / public void wait(long timeout) / public void wait(long timeout, int nanos) : 다른 쓰레드가 notify()나 notifyAll()을 호출할 때까지 현재 쓰레드를 무한히 또는 지정된 시간 (timeout, nanos)동안 기다리게 한다. (timeout은 천 분의 1초, nanos는 10^9분의 1초)
equals()
equals() 메서드가 주소값이 아니라 value값을 비교하게 만들려면 오버라이딩 해서 작성할 수 있다. ex) String 의 equals()는 value 비교
hashCode()
hashCode()는 해시함수를 구현한 것. 같은 객체라면 hashCode메서드를 호출했을 때의 결과값인 해시코드도 같아야 하기 때문에 적절한 오버라이딩이 필요. (특히 HashMap, HashSet 같은 클래스에 저장할 객체라면 필수) ex) String 클래스는 문자열의 내용이 같으면 동일한 해시코드를 반환하도록 hashCode메서드가 오버라이딩되어 있음
toString()
인스턴스에 대한 정보를 문자열로 제공. Object클래스에 정의된 toString 은 아래와 같다.
public String toString(){
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
String의 toString과 java.util의 Date 클래스의 toString 등은 오버라이딩 되어 있다. 이 때 조상에 정의된 메서드가 public이기 때문에 오버라이딩된 메서드 역시도 public 이어야 한다. (자손에서는 그 범위가 같거나 넓어야 하기 때문)
clone()
복제하여 새로운 인스턴스를 생성하는 일. 단순히 인스턴스 변수의 값만 복사하기 때문에 배열 처럼 참조타입의 인스턴스 변수가 있는 클래스는 완전한 인스턴스 복제가 이루어지지 않는다.(배열은 주소값만을 복제해오는 것이기 때문에 복제된 인스턴스의 작업이 원래의 인스턴스에도 영향을 미친다) 이 경우 오버라이딩해서 새로운 배열을 생성하고 배열의 내용을 복사해오도록 구성한다.
class Point implements Clonable {
...
public Object clone() {
Object obj = null;
try{
obj = super.clone(); // clone()은 예외처리 필수
} catch (CloneNotSupportedException e) {}
} return obj;
}
Clonable 인터페이스를 구현해야 하고, 접근 제어자는 public으로(상속 관계가 없는 다른 클래스에서 clone()을 호출할 수 있도록), try-catch 내에서 호출해줘야 한다.
*공변 반환타입 : 조상의 타입이 아닌 실제로 반환되는 자손 객체의 타입으로 반환할 수 있다. 따라서 번거로운 형변환이 줄어든다는 장점이 있다.
Point copy = (Point)original.clone();
->
Point copy = original.clone(); 가능
용이하게 사용하기 위해서 배열, Vector, ArrayList, LinkedList, HashSet, TreeSet, HashMap, TreeMap, Calendar, Date와 같은 클래스들은 알아서 값만 복사되도록 되어 있다. (복사된 인스턴스를 수정해도 원본 인스턴스에 영향이 없다)
얕은 복사와 깊은 복사
얕은 복사 : 원본을 변경하면 복사본도 영향을 받는다
깊은 복사 : 원본이 참조하고 있는 객체까지 복제하는 것. 원본의 변경이 복사본에 영향을 미치지 않는다.
getClass()
인스턴스의 Class객체를 반환하는 메서드. Class 객체는 클래스의 모든 정보를 담고 있으며 클래스 당 1개만 존재한다. 그리고 클래스 파일이 클래스 로더에 의해서 메모리에 올라갈 때 자동으로 생성된다. 먼저 기존에 생성된 클래스 객체가 메모리에 존재하는지 확인하고, 있으면 객체의 참조를 반환하고 없으면 클래스 패스에 지정된 경로를 따라서 클래스 파일을 읽는다.
1.2 String 클래스
특징 :
- 변경 불가능한(immutable) 클래스 - 예) 덧셈연산자를 이용해서 문자열을 결합하면 인스턴스 내의 문자열이 바뀌는 것이 아니라 새로운 문자열을 가진 String 인스턴스가 생성되는 것 (메모리 공간 차지) 따라서 문자열간의 결합이나 추출 등 문자열을 다루는 작업이 많이 필요한 경우 StringBuffer 클래스를 사용하는 것이 좋음.
- 문자열의 비교 - 문자열 리터럴을 지정 vs String 클래스의 생성자를 사용. 문자열 리터럴은 재사용되기 때문에 새로운 인스턴스가 아니다.
- 문자열 리터럴 - 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장된다. 이 때 같은 내용의 문자열 리터럴은 한번만 저장된다. 문자열 리터럴도 String 인스턴스이고 한 번 생성하면 내용을 변경할 수 없으니 하나의 인스턴스를 공유하면 되기 때문. 리터럴들은 JVM 내에 있는 상수 저장소에 저장된다.
- 빈 문자열 - 길이가 0인 배열. 'String s = "";' 과 같은 문장 (but 'char c = '';'는 불가)
* 참고: C 언어에서는 문자열의 끝에 널 문자가 항상 붙지만, 자바에서는 널 문자를 사용하지 않고 대신 문자열의 길이정보를 따로 저장한다.
String클래스의 생성자와 메서드
메서드 | 설명 |
String (char[] value) | 주어진 문자열을 갖는 String 인스턴스 생성 |
String(StringBuffer buf) | StringBuffer 인스턴스가 갖고 있는 문자열과 같은 내용의 String 인스턴스를 생성 |
char charAt(int index) | 지정된 위치(index)에 있는 문자를 알려준다(index는 0부터 시작) |
int compareTo(String str) | 문자열과 사전순서로 비교한다. 같으면 0을, 사전순으로 이전이면 음수를, 이후면 양수를 반환 |
String concat(String str) | 문자열(str)을 뒤에 덧붙인다 |
boolean contains(CharSequence s) | s 가 포함되었는지 검사한다 |
boolean endsWith(String suffix) | suffix로 끝나는지 검사 |
boolean equals(Object object) | obj와 문자열을 비교한다. 문자열이 다르면 false 반환 |
boolean equalsIgnoreCase(String str) | 문자열과 String 인스턴스의 문자열을 대소문자 구분없이 비교 |
int indexOf (int ch) | ch가 문자열에 존재하는지 확인하여 위치를 알려줌. 못 찾으면 -1 |
int indexOf (int ch, int pos) | ch가 문자열에 존재하는지 지정된 위치 pos 부터 확인하여 위치를 알려줌. 못 찾으면 -1 |
int indexOf(String str) | 주어진 문자열이 존재하는지 확인하여 그 위치를 알려줌. 못 찾으면 -1 |
String intern() | 문자열을 상수풀에 등록. |
join()과 StringJoiner
join()은 여러 문자열 사이에 구분자를 넣어서 결합. split()과 반대 작업. StirngJoiner("문자열 간에 들어갈 문자", "문자열 시작에 들어갈 문자", "문자열 끝에 들어갈 문자")로도 문자열 간의 결합 가능
기본형과 문자열 간의 변환 방법
기본형 -> 문자열 | 문자열 -> 기본형 |
String.valueOf(boolean b) String.valueOf(char c) String.valueOf(int i) String.valueOf(long l) String.valueOf(float f) String.valueOf(double d) |
Boolean.parseBoolean(String s) Byte.parseByte(String s) Short.parseShort(String s) Integer.parseInt(String s) Long.parseLong(String s) Float.parseFloat(String s) Double.parseDouble(String s) |
Boolean과 Byte처럼 기본형 타입의 이름의 첫 글자가 대문자인 것은 래퍼 클래스. 기본형 값을 감싸고 있는 클래스라는 뜻.
1.3 StringBuffer 클래스와 StringBuilder 클래스
StringBuffer클래스는 내부적으로 문자열 편집을 위한 버퍼를 가지고 있으며 StringBuffer인스턴스를 생성할 때 그 크기를 지정할 수 있다. 이 때 편집할 문자열의 길이를 고려하여 충분한 길이의 버퍼를 잡아주는 것이 좋다.
StringBuffer 생성할 때 버퍼의 크기를 지정하지 않으면 버퍼의 크기는 16이 되며, 지정한 문자열이 있다면 그것보다 15이 더 크게 버퍼를 생성하게 된다. 버퍼의 크기가 작업하려는 문자열의 길이보다 작을 때는 내부적으로 버퍼의 크기를 증가시키는 작업이 수행된다.
StringBuffer는 문자열의 끝에 문자열을 추가할 수 있고(append), append는 반환타입이 StringBuffer이다.
String 클래스는 equals() 메서드를 오버라이딩 하여 값이 같은지 확인하는 용도로 사용할 수 있지만 StringBuffer는 오버라이딩 하지 않아서 등가비교연산자(==)로 비교한 것과 같은 결과를 얻는다.
StringBuilder란?
StringBuffer는 멀티쓰레드에 안전하도록 동기화되어 있다. 동기화는 StringBuffer의 성능을 떨어뜨린다. 멀티쓰레드로 작성된 프로그램이 아닌 경우, StringBuffer의 동기화는 불필요하게 성능만 떨어뜨리게 된다. 그래서 StringBuffer에서 쓰레드의 동기화만 뺀 StringBuilder가 새로 추가되었다. 소스코드에서 StringBuffer 대신 StringBuilder를 사용하도록 바꾸기만 하면 된다. (StringBuffer의 성능도 충분히 좋기 때문에 성능 향상이 반드시 필요한 경우가 아니라면 그대로 사용해도 된다)
1.4 Math 클래스
Math 클래스의 생성자는 접근 제어자가 private으로 다른 클래스에서 Math 인스턴스를 생성할 수 없도록 되어있다. Math클래스의 메서드는 모두 static이고 PI(3.141592..)와 E(2.71828182...)의 2개의 상수만 정의해 두었다.
round() 소수점 첫째 자리에서 반올림. 반환값은 int
rint() 소수점 첫째 자리에서 반올림. 반환값은 double. 두 정수의 정 가운데에 있는 값은 가장 가까운 짝수 정수를 반환. -1.5 -> -2
예외를 발생시키는 메서드
메서드 이름에 'Exact'가 포함된 메서드들이 JDK1.8부터 추가되었다. 이들은 정수형 간의 연산에서 발생할 수 있는 오버플로우를 감지하기 위한 것이다. 이 메서드들은 오버플로우가 발생하면 예외(ArithmeticException)를 발생시킨다. 예를 들면 비트전환연산자 '~'를 적용한 경우에 사용할 수 있다. a의 부호를 바꾸는 것은 '~a+1'로 사용할 수 있는데, ~a의 결과가 int의 최대값이면 여기에 1을 더하니까 오버플로우가 발생할 수 있다. 이 때 예외처리를 통해서 a의 값을 long으로 바꿔주면 연산이 가능하다.
삼각함수와 지수, 로그
sqrt() : 제곱근 계산
pow() : n제곱 계산
StrictMath 클래스
Math클래스는 최대한의 성능을 위해서 JVM이 설치되어있는 OS의 메서드를 호출해서 사용한다. 즉 OS에 의존적인 계산을 하고 잇는 것이다. 예를 들어 부동소수점 계산의 경우, 반올림의 처리방법 설정이 OS마다 다를 수 있기 때문에 자바로 작성된 프로그램임에도 불구하고 컴퓨터마다 결과가 다를 수 있다. 이러한 차이를 없애기 위해 성능은 다소 포기하더라도 어떤 OS에서 실행되어도 항상 같은 결과를 얻도록 Math 클래스를 새로 작성한 것이 StrictMath 클래스이다.
1.5 래퍼(wrapper) 클래스
자바는 8개의 기본형을 객체로 다루지 않는다. (그래서 완전한 객체지향언어가 아니다) 대신 보다 높은 성능을 얻을 수 있다. 기본형 변수도 어쩔 수 없이 객체로 생성을 해줘야 하는 경우(예를 들면 매개변수로 객체를 요구할 때, 기본형 값이 아닌 객체로 저장해야할 때, 객체간의 비교가 필요할 때)에는 기본형 값들을 객체로 변환해서 작업을 수행해야 한다. 이 때 사용하는 것이 래퍼 클래스이다.
기본형 | 래퍼클래스 |
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
래퍼클래스에는 모두 equals()가 오버라이딩 되어 있어서 주소값이 아닌 객체가 가지고 있는 값을 비교한다. 오토박싱이 된다고 해도 Integer객체에 비교연산자를 사용할 수 없다. 대신 compareTo()를 제공한다.
toString()도 오버라이딩 되어 있어서 객체가 가지고 있는 값을 문자열로 변환하여 반환한다. 이외에도 래퍼 클래스들은 MAX_VALUE, MIN_VALUE, SIZE, BYTES, TYPE 등의 static 상수를 공통적으로 가지고 있다.
Number 클래스
이 클래스는 추상클래스로 내부적으로 숫자를 멤버변수로 갖는 래퍼 클래스들의 조상이다. Byte, Short, Integer, Long, Float, Double, BigInteger, BigDecimal이 Number을 상속받았다.
오토박싱 & 언박싱
전에는 기본형과 참조형 간의 연산이 불가능했기 때문에 래퍼 클래스로 기본형을 객체로 만들어서 연산해야 했다. 그러나 이제는 컴파일러가 자동으로 변환하는 코드를 넣어주기 때문에 기본형과 참조형 간의 덧셈이 가능하다.
컴파일 전의 코드 | 컴파일 후의 코드 |
int i = 5; Integer iObj = new Integer(7); int sum = i + iObj; |
int i = 5; Integer iObj = new Integer(7); int sum = i + iObj.intValue(); |
이 외에도 내부적으로 객체 배열을 가지고 있는 Vector이나 ArrayList 클래스에 기본형 값을 저장해야 할 때나 형변환이 필요할 때도 컴파일러가 자동적으로 코드를 추가해준다. 기본형 값을 래퍼 클래스의 객체로 자동 변환해주는 것을 오토박싱 이라 하고 반대로 변환하는 것을 언박싱이라고 한다.
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10); // 오토박싱. 10 -> new Integer(10)
int value = list.get(0); //언박싱. new Integer(10) -> 10
2. 유용한 클래스
2.1 java.util.Objects 클래스
Object클래스의 보조 클래스로 Math클래스처럼 모든 메서드가 'static'이다.
- isNull() : true 면 널
- nonNull() : true면 널 아님
- requireNonNull() : 해당 객체가 널이 아니어야 하는 경우에 사용. 만약 객체가 널이면 NullPointerException을 발생시킴.
- compare() : Object 클래스에는 대소 비교를 위한 메서드가 없어서 Objects에는 가 추가되었다. 두 비교 대상이 같으면 0, 크면 양수, 작으면 음수를 반환.
- equals() : null인지 확인하지 않고도 매개변수가 동일한지 확인 가능
2.2 java.util.Random 클래스
Math.random() 과 동일하게 사용 가능(Math.random() 내부에서도 java.util.Random 클래스의 인스턴스를 생성해서 사용하는 것)
2.3 정규식 - java.util.regex 패키지
정규식 : 텍스트 데이터 중에서 원하는 조건(패턴)과 일치하는 문자열을 찾아내기 위해 사용하는 것으로 미리 정의된 기호와 문자를 이용해서 작성한 문자열을 말한다.
Pattern은 정규식을 정의하는데 사용되고 Matcher는 정규식(패턴)을 데이터와 비교하는 역할을 한다. 정규식을 정의하고 데이터를 비교하는 과정을 단계별로 설명하면 다음과 같다.
1. 정규식을 매개변수로 Pattern 클래스의 static 메서드인 Pattern compile(String regex)을 호출하여 Pattern인스턴스를 얻는다.
2. 정규식으로 비교할 대상을 매개변수로 Pattern클래스의 Matcher matcher(CharSequence input)를 호출해서 Matcher 인스턴스를 얻는다
3. Matcher 인스턴스에 boolean matches()를 호출해서 정규식에 부합하는지 확인한다.
2.4 java.util.Scanner 클래스
다양한 입력소스로부터 데이터를 읽어올 수 있다. 정규식 표현을 이용한 라인단위의 검색을 지원하며 구분자(delimiter)에도 정규식 표현을 사용할 수 있어서 복잡한 형태의 구분자도 처리가 가능하다. nextLine() 대신 nextInt(), nextLong()과 같은 메서드를 사용할 수 있어서 입력받은 문자를 다시 변환해주는 수고를 덜어 준다.
2.5 java.util.StringTokenizer 클래스
긴 문자열을 지정된 구분자를 기준으로 토큰이라는 여러 개의 문자열로 잘라내는 데 사용된다. String의 split이나 Scanner의 useDelimiter를 사용할 수도 있지만 이 두 가지 방식은 정규식 표현을 사용해야 하므로 익숙하지 않은 경우는 StringTokenizer를 사용할 수 있다. 구분자가 두 문자 이상이라면 Scanner나 split 메서드를 사용해야 한다.
2.6 java.math.BigInteger 클래스
정수형으로 표현할 수 있는 값의 한계가 있다. long으로 표현해도 10진수로 19자리 정도이다. 더 큰 값을 계산하기 위해 사용하는 것이 BigInteger이다. 내부적으로 int 배열을 사용해서 값을 다룬다. 따라서 long에 비해 훨씬 큰값을 다룰 수 있지만 대신 성능이 떨어진다. BigInteger은 부호를 따로 저장하고 배열에는 값 자체만 저장한다. 그래서 signum(부호) 값이 -1, 즉 음수인 경우 2의 보수법에 맞게 mag의 값을 변환해서 처리한다. 부호만 다른 두 값의 mag는 같고, signum은 다른 2의 보수의 형태로 표현한다.
짝수인지 확인할 때 정수를 2로 나머지 연산한 결과가 0인지 확인하면 꽤 복잡해진다. 대신 짝수는 가장 오른쪽 비트가 0일 것이므로, testBit(0)으로 마지막 비트를 확인하는 것이 더 효율적이다. 이처럼 가능하면 산술연산 대신 비트연산으로 처리하도록 노력해야 한다.
2.7 java.math.BigDecimal 클래스
double 타입으로 표현할 수 있는 값은 상당히 범위가 넓지만, 정밀도가 최대 13자리 밖에 되지 않고 실수형의 특성상 오차를 피할 수 없다. BigDecimal은 실수형과 달리 정수를 이용해서 실수를 표현한다. 앞에서 배운 것과 같이 실수의 오차는 10진 실수를 2진 실수로 정확히 변환할 수 없는 경우가 있기 때문에 발생하는 것으로 오차가 없는 2진 정수로 변환하여 다루는 것이다.
'TIL > Java | Spring Boot' 카테고리의 다른 글
[Java] 스터디 6주차_Generics, enums, annotation (1) | 2022.05.29 |
---|---|
[Java] 스터디 5주차_컬렉션 프레임웍 (0) | 2022.05.22 |
[Java] 스터디 3주차_예외 처리 (exception handling) (0) | 2022.05.06 |
[Java] 스터디 2주차_객체지향프로그래밍2 (2) - 추상클래스, 인터페이스, 내부 클래스 (0) | 2022.05.01 |
[Java] 스터디 2주차_객체지향프로그래밍2 (1) - 상속, 오버라이딩, 제어자, 다형성 (0) | 2022.05.01 |
댓글