자바에는 다양한 유용한 클래스들이 포함되어 있어 개발자들이 흔히 필요한 기능을 쉽게 사용할 수 있게 합니다. 여기서는 몇 가지 대표적인 유용한 클래스를 소개하겠습니다.
– Object 클래스
– java.lang 패키지
- 프로그래밍시 import 하지 않아도 자동으로 import 됨
- import.java.lang*;
- 많이 사용하는 기본 클래스들이 속한 패키지
- String, Integer, System …
- java.lang.Object 클래스
– 모든 클래스는 Object 클래스를 상속 받는다
- 모든 클래스의 최상위 클래스
- 모든 클래스는 Object 에서 상속받고, Object 클래스의 메서드 중 일부는 재정의해서 사용할 수 있음
- 컴파일러가 extends Object를 추가함
class Student => class Student extends Object
– toString() 메서드
- 객체의 정보를 String 으로 바꾸어서 사용할 때 쓰임
- String 이나 Integer 클래스는 이미 재정의 되어 있음
- toString() 메서드 재정의 예
class Book extends Object { private String title; private String author; public Book(String title, String author) { this.title = title; this.author = author; } @Override public String toString() { return title + "," + author; } } public class BookTest { public static void main(String[] args) { Book book = new Book("태백산맥", "조정래"); System.out.println(book.toString()); String str = new String("test"); System.out.println(str); Integer integer = new Integer(100); System.out.println(integer); } }
– equals() 메서드
- 두 인스턴스의 주소 값을 비교하여 true / false 를 반환
- 재정의 하여 두 인스턴스가 논리적으로 동일함의 여부를 구현함
- 인스턴스가 다르더라도 논리적으로 동일한 경우 true를 반환하도록 재정의 할 수 있음
(같은 학번, 같은 사번, 같은 아이디의 회원 … )
public class Student extends Object { private int studentId; private String studentName; public Student(int studentId, String studentName){ this.studentId = studentId; this.studentName = studentName; } @Override public boolean equals(Object obj) { if(obj instanceof Student){ Student std = (Student) obj; if (this.studentId == std.studentId){ return true; } else return false; } return false; } } public class EqualTest { public static void main(String[] args) { Student Lee = new Student(100, "Lee"); Student Lee2 = Lee; Student Shun = new Student(100,"Lee"); System.out.println(Lee.equals(Lee2)); System.out.println(Lee == Lee2); System.out.println(Lee.equals(Shun)); System.out.println("======================"); String str1 = new String("test"); String str2 = new String("test"); System.out.println(str1.equals(str2)); System.out.println(str1 == str2); } }
– hashCode() 메서드
- hashCode() 는 인스턴스의 저장 주소를 반환함
- 힙 메모리에 인스턴스가 저장되는 방식이 hash
- hash : 정보를 저장, 검색하는 자료구조
- 자료의 특정 값(키 값)에 대한 저장 위치를 반환해주는 해시 함수를 사용
- 두 인스턴스가 같다는 것은?
두 인스턴스에 대한 equals() 의 반환 값이 true
동일한 hashCode() 값을 반환 - 논리적으로 동일함을 위해 equals() 메서드를 재정의 하였다면 hashCode() 메서드도 재정의 하여 동일한 hashCode 값이 반환 되도록 한다
public class Student extends Object { private int studentId; private String studentName; public Student(int studentId, String studentName){ this.studentId = studentId; this.studentName = studentName; } @Override public boolean equals(Object obj) { if(obj instanceof Student){ Student std = (Student) obj; if (this.studentId == std.studentId){ return true; } else return false; } return false; } @Override public int hashCode() { return studentId; } } public class EqualTest { public static void main(String[] args) { Student Lee = new Student(100, "Lee"); Student Lee2 = Lee; Student Shun = new Student(100,"Lee"); System.out.println(Lee.hashCode()); System.out.println(Shun.hashCode()); System.out.println(System.identityHashCode(Lee)); System.out.println(System.identityHashCode(Shun)); System.out.println("======================"); System.out.println(Lee.equals(Lee2)); System.out.println(Lee == Lee2); System.out.println(Lee.equals(Shun)); System.out.println("======================"); String str1 = new String("test"); String str2 = new String("test"); System.out.println(str1.equals(str2)); System.out.println(str1 == str2); System.out.println(str1.hashCode()); System.out.println(str2.hashCode()); System.out.println(System.identityHashCode(str1)); System.out.println(System.identityHashCode(str2)); } }
– clone() 메서드
- 객체의 원본을 복제하는데 사용하는 메서드
- 생성과정의 복잡한 과정을 반복하지 않고 복제 할 수 있음
- clone() 메서드를 사용하면 객체의 정보(멤버 변수 값등..)가 동일한 또 다른 인스턴스가 생성되는 것이므로, 객체 지향 프로그램에서의 정보 은닉, 객체 보호의 관점에서 위배될 수 있음
- 해당 클래스의 clone() 메서드의 사용을 허용한다는 의미로 cloneable 인터페이스를 명시해 줌
public class Student implements Cloneable { private int studentId; private String studentName; public Student(int studentId, String studentName){ this.studentId = studentId; this.studentName = studentName; } @Override public boolean equals(Object obj) { if(obj instanceof Student){ Student std = (Student) obj; if (this.studentId == std.studentId){ return true; } else return false; } return false; } @Override public int hashCode() { return studentId; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return studentName; } } public class EqualTest { public static void main(String[] args) throws CloneNotSupportedException { Student Lee = new Student(100, "Lee"); Student Lee2 = Lee; Student Shun = new Student(100,"Lee"); System.out.println(Lee.hashCode()); System.out.println(Shun.hashCode()); System.out.println(System.identityHashCode(Lee)); System.out.println(System.identityHashCode(Shun)); System.out.println("======================"); System.out.println(Lee.equals(Lee2)); System.out.println(Lee == Lee2); System.out.println(Lee.equals(Shun)); System.out.println("======================"); String str1 = new String("test"); String str2 = new String("test"); System.out.println(str1.equals(str2)); System.out.println(str1 == str2); System.out.println(str1.hashCode()); System.out.println(str2.hashCode()); System.out.println(System.identityHashCode(str1)); System.out.println(System.identityHashCode(str2)); System.out.println("======================"); Student Lees = (Student)Lee.clone(); System.out.println(Lees.toString());
– String 클래스
- String 선언하기
- 힙 메모리에 인스턴스로 생성되는 경우와 상수 풀(constant pool)에 있는 주소를 참조하는 두 가지 방법
- 힙 메모리에 생성될때마다 다른 주소 값을 가지지만, 상수 풀의 문자열은 모두 같은 주소 값을 가짐
- 한번 생성된 String은 불변(immutable)
- String을 연결하면 기존의 String에 연결되는 것이 아닌 새로운 문자열이 생성됨 (메모리 낭비가 발생할 수도)
public class StringTest { public static void main(String[] args) { String str1 = new String("abc"); String str2 = new String("abc"); System.out.println(str1 == str2); //인스턴스로 따로 생성됨 String str3 = "abc"; String str4 = "abc"; System.out.println(str3 == str4); //상수 풀에서 가져다 씀 } }
– StringBuilder, StringBuffer 활용하기
- 내부적으로 가변적인 char[]를 멤버 변수로 가짐
- 문자열을 여러번 연결하거나 변경할 때 사용하면 유용함
- 새로운 인스턴스를 생성하지 않고 char[] 를 변경함
- StringBuffer는 멀티 쓰레드 프로그래밍에서 동기화(synchronization)을 보장
- 단일 쓰레드 프로그램에서는 StringBuilder 사용을 권장
- toString() 메서드로 string반환
public class StringBuilderTest { public static void main(String[] args) { String java = new String("java"); String android = new String("android"); StringBuilder buffer = new StringBuilder(java); System.out.println(System.identityHashCode(buffer)); buffer.append(android); System.out.println(buffer); System.out.println(System.identityHashCode(buffer)); java = buffer.toString(); } }
– text block사용하기(java 13에서 프리뷰로 추가되고 15에서 정식 발표됨)
- 문자열을 “”” “”” 사이에 이어서 만들 수 있음
- html, json 문자열을 만드는데 유용하게 사용할 수 있음
public class StringTextBlock { public static void main(String[] args) { String strBlock = """ This is text block test."""; System.out.println(strBlock); System.out.println(getBlockOfHtml()); } public static String getBlockOfHtml() { return """ <html> <body> <span>example text</span> </body> </html>"""; } }
– Class 클래스
- 자바의 모든 클래스와 인터페이스는 컴파일 후 class 파일이 생성됨
- Class 클래스는 컴파일 된 class 파일을 로드하여 객체를 동적 로드하고, 정보를 가져오는 메서드가 제공됨
- Class.forName(“클래스 이름”) 메서드로 클래스를 동적으로 로드 함
– 동적로딩
- 컴파일 시에 데이터 타입이 binding 되는 것이 아닌, 실행(runtime) 중에 데이터 타입을 binding 하는 방법
- 프로그래밍 시에는 문자열 변수로 처리했다가 런타임시에 원하는 클래스를 로딩하여 binding 할 수 있다는 장점
- 컴파일 시에 타입이 정해지지 않으므로 동적 로딩시 오류가 발생하면 프로그램의 심각한 장애가 발생가능
– 클래스 정보 알아보기
- reflection 프로그래밍 : Class 클래스를 사용하여 클래스의 정보(생성자, 변수, 메서드)등을 알수 있고 인스턴스를 생성하고, 메서드를 호출하는 방식의 프로그래밍
- 로컬 메모리에 객체 없는 경우, 원격 프로그래밍, 객체의 타입을 알 수 없는 경우에 사용
- java.lang.reflect 패키지에 있는 클래스를 활용하여 프로그래밍
- 일반적으로 자료형을 알고 있는 경우엔 사용하지 않음