[java] 20. java.lang패키지(1)


java.lang 패키지



이번 장에서는 자바프로그래밍에 가장 기본이 되는 클래스들을 포함하고 있는

java.lang 패키지에 대해 배워보겠습니다.

자세히 다루기보다는 약간의 설명과 예제만 간단하게 포스팅하겠습니다!



Object 클래스



Object 클래스는 모든 클래스의 최고 부모이기 때문에 Object클래스의 멤버들은 모든 클래스에서 바로 사용 가능합니다.

Object 클래스는 멤버변수는 없고 오직 11개의 메서드만 가지고 있습니다.


image



다음은 equals 메서드에 대한 예제입니다.


image



equals()는 두 참조변수가 같은 객체를 참조하고 있는지 비교하는 메서드인데요~

equals 메서드로 참조 값이 아닌 같은 값을 같는지 비교하고 싶으면 오버라이딩 해주면 됩니다.


image



String 클래스도 위의 예제와 같이 오버라이딩 되어있기 때문에,

두 String 인스턴스에 equals 메서드를 사용하면 문자열 값을 비교하도록 되어있습니다.

다음은 hashCode() 메서드에 대한 예제입니다.

이 메서드는 해싱 기법에 사용되는 해시함수를 구현한 것이고.

보통 서로 다른 객체라면 모두 다른 해시코드 값을 가지고 있습니다.


image



다음은 toString 메서드에 대한 예제입니다.

이 메서드는 인스턴스에 대한 정보를 문자열로 제공할 목적으로 정의한 것입니다.

특별히 오버라이딩 하지 않으면 클래스이름@해시코드를 출력합니다.


image



깊은 복사와 얕은 복사



깊은 복사와 얕은 복사에 대해 알아보기 전에 Object 클래스의 clone 메서드 부터 알아보겠습니다.

clone 메서드는 자신을 복제하여 새로운 인스턴스를 생성하는 일을 합니다.

clone()을 사용하려면, 먼저 복제할 클래스가 Cloneable 인터페이스를 구현해야하고,

clone()을 오버라이딩하면서 접근 제어자를 protected에서 public으로 변경해야합니다.

그래야만 상속관계가 없는 다른 클래스에서 clone()을 호출할 수 있습니다.

clone 메서드에 대한 예제입니다.


image



JDK1.5부터 공변 반환타입이라는 것이 추가되었는데, 이 기능은 오버라이딩할 때

부모 메서드의 반환타입을 자식 클래스의 타입으로 변경을 허용하는 것입니다.

따라서 위의 예제는 다음과 같이 변경 가능합니다.


image



clone을 이용해서 배열을 복사하는 것도 가능한데요~

배열도 객체이기 때문에 Object 클래스를 상속받으며,

동시에 Cloneable 인터페이스와 Serializable 인터페이스가 구현되어 있습니다.

clone()을 배열에서는 public으로 오버라이딩하였기 때문에 다음 예제처럼 직접호출이 가능합니다.


image



이제 깊은 복사와 얕은 복사에 대해 얘기해보겠습니다.

clone()은 단순히 객체에 저장된 값을 그대로 복제할 뿐, 객체가 참조하고 있는 객체까지 복제하지 않습니다.

기본형 배열인 경우에는 아무런 문제가 없지만, 객체배열을 clone()으로 복제하는 경우에는

원본과 복제본이 같은 객체를 공유하므로 완전한 복제라고 보기 어렵습니다.

이러한 복사를 얕은 복사라고 합니다. 얕은 복사에서는 원본을 변경하면 복사본도 영향을 받습니다.

반면에, 원본이 참조하고 있는 객체까지 복제하는 것을 깊은 복사라고 하며,

깊은 복사에서는 원본과 복사본이 서로 다른 객체를 참조하기 때문에 원본의 변경이 복사본에 영향을 미치지 않습니다.

다음은 깊은복사와 얕은복사에 대한 예제입니다.


image


image



getClass



getClasss() 메서드는 자신이 속한 클래스의 Class 객체를 반환하는 메서드입니다.

Class 객체는 이름이 Class인 클래스의 객체입니다.

Class 객체는 클래스의 모든 정보를 담고 있으며, 클래스 당 1개만 존재합니다.

클래스 객체는 클래스 파일이 클래스 로더에 의해서 메모리에 올라갈 때,

자동으로 생성되며, 클래스 파일을 읽어서 사용하기 편한 형태로 저장해 놓았다고 생각하시면 됩니다.

클래스의 정보가 필요할 때, 먼저 Class 객체에 대한 참조를 얻어 와야 하는데,

해당 Class 객체에 대한 참조를 얻는 방법은 여러 가지 있습니다.


Class cObj=new Card().getClass(); //생성된 객체로 부터 얻는 방법

Class cObj=Card.class; //클래스 리터럴로 부터 얻는 방법

Class cObj=Class.forName("Card"); //클래스 이름으로 부터 얻는 방법



forName()은 특정 클래스 파일, 예를 들어 데이터베이스 드라이버를 메모리에 올릴 때 주로 사용합니다.

다음은 클래스 객체에 대한 예제입니다.


image



String 클래스



기존의 다른 언어에서는 문자열을 char형의 배열로 다루었으나 자바에서는 문자열을 위한 클래스를 제공합니다.

그것이 바로 String 클래스인데, String 클래스는 문자열을 저장하고 이를 다루는데 필요한 메서드를 제공합니다.

한 번 생성된 String 인스턴스가 갖고 있는 문자열은 읽어 올 수만 있고,

변경할 수는 없습니다.

예를 들어 아래의 코드와 같이 ‘+’ 연산자를 이용해서 문자열을 결합하는 경우 인스턴스 내의 문자열이 바뀌는 것이 아니라

새로운 문자열(“ab”)이 담긴 String 인스턴스가 생성되는 것입니다.


String a="a";

String b="b";

String a= a+b; //기존의 a와 다른새로운 인스턴스가 생성됨



이처럼 덧셈연산자 +를 사용해서 문자열을 결합하는 것은 매 연산 시 마다 새로운 문자열을 가진

String 인스턴스가 생성되어 메모리 공간을 차지하게 되므로 가능한 한 결합횟수를 줄이는 것이 좋습니다.

문자열을 만들 때는 두 가지 방법, 문자열, 문자열 리터럴을 지정하는 방법과

String 클래스의 생성자를 사용해서 만드는 방법이 있습니다.


String str1="abc"; //문자열 리터럴 "abc"의 주소가 str1에 저장됨

String str2="abc"; //문자열 리터럴 "abc"의 주소가 str2에 저장됨

String str3=new String("abc"); //새로운 String인스턴스를 생성

String str4=new String("abc"); //새로운 String인스턴스를 생성



String 클래스의 생성자를 이용한 경우에는 new 연산자에 의해서 메모리할당이 이루어지기 때문에

항상 새로운 String 인스턴스가 생성됩니다.

그러나 문자열 리터럴은 이미 존재하는 것을 재사용하는 것입니다.

다음은 방금 말한 문자열을 만드는 것과 관련된 예제입니다.


image



자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장됩니다.

이 때 같은 내용의 문자열 리터럴은 한번만 저장됩니다.

문자열 리터럴도 String 인스턴스이고, 한번 생성하면 내용을 변경할 수 없으니 하나의 인스턴스를 공유하면 되기 때문입니다.

자바에서는 길이가 0인 빈 문자열도 생성이 가능합니다.


String s=""; //빈 문자열로 초기화

char c=' '; //공백으로 초기화

char c=''; //컴파일 에러 char는 반드시 하나의 문자를 지정해야함



일반적으로 변수를 선언할 때, 각 타입의 기본값으로 초기화 하지만 String은 참조형 타입의 기본값인 null보다는 빈 문자열로.

char형은 기본값인 ‘\u0000’ 대신 공백으로 초기화 하는 것이 보통입니다.



String 클래스의 생성자와 메서드



아래의 표는 String 클래스 내에 정의된 생성자와 메서드의 목록입니다.


image




image



image



image



image



image



join()과 StringJoiner



join()은 여러 문자열 사이에 구분자를 넣어서 결합합니다.

구분자로 문자열을 자르는 split()과 반대의 작업을 한다고 생각하시면 됩니다.


String animals="dog,cat,bear";

String[] arr=animals.split(","); //문자열을 ','를 구분자로 나눠서 배열에 저장

String str=String.join("-",arr); //배열을 문자열 '-'로 구분해서 결합

System.out.println(str); //dog-cat-bear



java.util.StringJoiner 클래스를 사용해서 문자열을 결합할 수도 있는데,

사용하는 방법은 간단합니다.


StringJoiner sj=new StringJoiner(",","[","]");

String[] strArr={"aaa","bbb","ccc"};

for(String s : strArr)
	sj.add(s.toUpperCase());
	
System.out.println(sj.toString()); //[AAA,BBB,CCC]




image



String.format()



format()은 형식화된 문자열을 만들어내는 간단한 방법입니다.

printf()하고 사용법이 완전히 똑같습니다.


String str=String.format("%d 더하기 %d는 %d입니다.",3,5,3+5);

System.out.println(str); //3 더하기 5는 8입니다.



String을 기본형 값으로 반환



기본형과 문자열 간의 변환방법은 다음과 같습니다.


image



만약 문자열 “A”를 문자 ‘A’로 변환하려면 char ch=”A”.charAt(0);과 같이 하면됩니다.




image