220612_인터넷 강의_Object 클래스 외

창고·2022년 10월 20일
0

티스토리에 저장했던 글을 옮겼습니다.
https://mrcocoball.tistory.com/84

1. Object 클래스의 개념

(1) java.lang 패키지 개념

  • 프로그래밍 시 import 하지 않아도 자동으로 import됨
  • 많이 사용 하는 기본 클래스들이 속한 패키지 (String, Integer, System...)

(2) Object 클래스 개념

  • java.lang.Object 클래스로 모든 클래스의 최상위 클래스
  • 모든 클래스는 Object에서 상속받고 그렇기 때문에 Object 클래스의 일부 메소드는 재정의해서 사용이 가능
    (자동으로 컴파일러가 extends Object를 추가)

2. toString() 메소드

  • 객체의 정보를 String으로 바꾸어서 사용할 떄 사용
  • String, Integer 클래스는 이미 재정의 되어 있음
  • 예제
class Book {
	
	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);
		
		String str = new String("test");		
		System.out.println(str); // str.toString() 이 오버라이딩이 되어 있음

	}

}

  • book 객체를 String화 하기 위해 toString을 재정의
	@Override
	public String toString() {
		return title + "," + author;
	}

3. equals() 메소드와 hashCode() 메소드

(1) equals() 메소드

  • 두 인스턴스의 주소, 번지 값을 비교하여 true/false 리턴
  • equals() 메소드를 재정의하여 두 인스턴스가 논리적으로 동일한지를 확인할 수 있음
    (예시 : 두 객체가 물리적 위치가 다르더라도 논리적으로는 동일한 객체라면 두 객체는 동일하다고 판별해야 함. 학번, 사번, 아이디가 같다던지 등...)

(2) hashCode() 메소드

  • 인스턴스의 저장 주소를 리턴
  • 힙 메모리에 인스턴스가 저장되는 방식이 hash(정보를 저장, 검색하는 자료 구조) 방식
  • 자료의 특정 값(키 값)에 대한 저장 위치를 반환해주는 해시 함수 사용
index = hash(key)
// index = 저장 위치
// hash = 해시 함수
// key = 객체 정보
  • hashCode() 메소드를 재정의하여 두 객체가 동일한 hashCode 값이 반환되도록 정의

(3) equals() - hashCode() 메소드

  • 두 객체가 논리적으로 동일한 객체인지 판별 (equals()) 하여, 동일한 객체일 경우 동일한 hashCode값을 반환하도록 진행 (hashCode())
  • equals()와 hashCode() 재정의 진행
public class Student implements Cloneable {
	
	private int studentNum;
	private String studentName;
	
	public Student(int studentNum, String studentName) {
		this.studentNum = studentNum;
		this.studentName = studentName;
	}
	
	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	
	public String toString() {
		return studentNum + "," + studentName;
	}

	@Override
	public int hashCode() {
		return studentNum;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Student) { // 다운캐스팅 전 instanceof 로 형 확인
			Student std = (Student) obj; // 다운 캐스팅
			if (this.studentNum == std.studentNum) { // 학번이 같은지
				return true;
			}
		}
		return false;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
}
  • 테스트
public class EqualTest {

	public static void main(String[] args) throws CloneNotSupportedException {
		
		Student std1 = new Student(100, "리코");
		Student std2 = new Student(100, "리코");
		Student std3 = std1; // 주소가 같음
		
		System.out.println("std1 == std2 : " + (std1 == std2));
		System.out.println("std1 == std3 : " + (std1 == std3)); // true 반환	
		
		System.out.println(std1.hashCode()); // hashCode() 재정의를 통해 조작 가능
		System.out.println(std2.hashCode()); // hashCode() 재정의를 통해 조작 가능
		
		System.out.println(System.identityHashCode(std1)); // 실제 물리적 위치
		System.out.println(System.identityHashCode(std2)); // 실제 물리적 위치
		
		System.out.println("std1 == std2 : " + (std1.equals(std2))); // 재정의를 통해 논리적 구조가 같을 경우 같다고 조작 가능
	
		std1.setStudentName("마리");
		Student copyStudent = (Student)std1.clone();
		System.out.println(copyStudent);

	}

}
  • equals() 메소드를 재정의하지 않고 그대로 사용했다면 std1 == std2 false 출력
  • 실제 물리적 위치 : System.identityHashCode()

4. clone() 메소드

  • 객체의 원본을 복제하는데에 사용하는 메소드
  • clone()은 생성자 (초기화하여 초기값을 지정하여 객체를 생성) 와 달리 객체를 그대로 복제
  • 생성 과정의 복잡한 과정을 반복하지 않고 복제 가능
  • 객체의 정보가 동일한 또 다른 인스턴스가 생성되는 것으로 OOP의 정보 은닉, 객체 보호의 관점에서 위배될 수 있음
  • 해당 클래스의 clone() 메소드의 사용을 허용한다는 의미로 Cloneable 인터페이스를 구현한다고 명시
@Override
protected Object clone() throws CloneNotSupportedException {
	// TODO Auto-generated method stub
    return super.clone();

5. StringBuilder, StringBuffer 클래스

(1) String 클래스의 특성

  • String 선언 방식에 따라 차이가 있음

    • String str1 = new String("abc"); = 힙 메모리에 인스턴스로 생성되는 경우
    • String str2 = "abc"; = 상수 풀(constrant pool) 에 있는 주소를 참조하는 경우
  • 힙 메모리는 생성 시마다 다른 주소 값을 가지지만 상수 풀의 문자열은 모두 같은 주소 값을 가짐

String str1 = new String("abc");
String str2 = new String("abc");

str1 == str2; // false (다른 주소를 가지므로 다른 객체로 판별)

String str3 = "abc";
String str4 = "abc"; 

str3 == str4; // true (두 변수 모두 "abc" 를 참조하고 있으므로)
  • String은 한번 생성되면 불변(immutable) 하기에 String을 연결하면 기존 String에 연결되는 것이 아닌, 새로운 문자열이 생성 > 메모리를 계속 잡아먹게 됨
public class StringTest {

	public static void main(String[] args) {

		String java = new String("java");
		String android = new String("android");
		
		System.out.println(System.identityHashCode(java));
		java = java.concat(android); // 연결을 하더라도
		System.out.println(java);
		System.out.println(System.identityHashCode(java)); // 기존 java에 연결된 것이 아니라 아예 새로 생성되어 해시값이 다름

	}

}

(2) StringBuilder, StringBuffer 클래스

  • 문자열을 여러번 연결하거나 변경 시 사용
  • StringBuilder 변수 = new StringBuilder(String 타입 인스턴스);
  • append로 연결
public class StringBuilderTest {

	public static void main(String[] args) {
		
		String java = new String("java");
		String android = new String("android");
		
		System.out.println(System.identityHashCode(java));
		StringBuilder buffer = new StringBuilder(java);
		buffer.append(android);
		System.out.println(System.identityHashCode(java));
		
		String test = buffer.toString(); // string 인자로 사용하기 위해서는 toString() 필요
		System.out.println(test);

	}

}

  • StringBuilder와 StringBuffer의 차이
    • StringBuffer는 멀티 쓰레드 프로그래밍에서 동기화 보장하므로 멀티 쓰레드,
    • StringBuilder는 단일 쓰레드에서 사용 추천
  • toString() 메소드로 String 변환 필요

6. Class 클래스

(1) Class 클래스와 동적 로딩

  • Java의 모든 클래스, 인터페이스는 컴파일 후 class 파일 생성
  • Class 클래스 : 컴파일 된 class 파일을 로드하여 객체를 동적 로드하여 정보를 가져오는 메소드 제공
  • Class.forName("클래스명") 메소드로 클래스를 동적 로드 **
Class c = Class.forName("java.lang.String"); << 클래스명은 클래스의 전체 주소를 적을 것
  • 클래스 이름으로 직접 Class 클래스 가져오기
Class c = 클래스명.Class

Class c = String.Class
  • 생성된 인스턴스에서 Class 클래스 가져오기
String s = new String();
Class c = s.getClass(); // Object 메소드 
  • 동적 로딩
    • 컴파일 시가 아니라 실행 도중에 데이터 타입을 binding 하는 방법
    • 프로그래밍 시에는 문자열 변수로 처리 했다가 실행 도중에 원하는 클래스를 로딩할 수 있음.
    • 다만 컴파일 시 타입이 정해지지 않아 동적 로딩 시 오류 발생하게 되면 (오탈자 등) 프로그램에 심각한 장애가 발생
  • newInstance() 메소드 : new 키워드를 사용하지 않고 클래스 정보를 활용하여 인스턴스 생성
public class StringTest {

	public static void main(String[] args) throws ClassNotFoundException {
		
		Class c = Class.forName("java.lang.String"); // String 클래스 동적 로드
		
		Constructor[] cons = c.getConstructors(); // Constructor 배열 리스트 생성, String 클래스의 Constructor
		for(Constructor co : cons) {
			System.out.println(co);
		}
		
		Method[] m = c.getMethods(); // Method 배열 리스트 생성, String 클래스의 Method
		for (Method mth : m) {
			System.out.println(mth);
		}

	}

}

(2) 클래스 정보 알아보기

  • reflection 프로그래밍 : Class 클래스를 사용, 클래스의 정보 (생성자, 변수, 메소드 )등을 알 수 있으며 인스턴스를 생성, 메소드를 호출
  • 로컬 메모리에 객체가 없거나 원격 프로그래밍, 객체의 타입을 알 수 없을 때 사용
  • java.lang.reflect 패키지에 있는 클래스를 활용
  • 일반적으로 자료형을 알고 있는 경우에는 사용하지 않음
public class Person {
	
	private String name;
	private int age;
	
	public Person() {}
	
	public Person(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String toString() {
		return name;
	}

}
public class ClassTest {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, 
	IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		
		Class c1 = Class.forName("ch04_Class.Person"); // Person 클래스 동적 로딩
		
		Person person = (Person) c1.newInstance(); // 다운 캐스팅한 후 newInstance() 로 객체 생성
		
		person.setName("리코");
		System.out.println(person);
		
		Class c2 = person.getClass(); // 이미 인스턴스가 있어야 함
		Person p = (Person) c2.newInstance();
		System.out.println(p);
		
		Class[] parameterTypes = {String.class};
		Constructor cons = c2.getConstructor(parameterTypes);
		
		Object[] initargs = {"마리"};
		Person mariPerson = (Person)cons.newInstance(initargs);
		System.out.println(mariPerson);
		
		// 위의 코드와 동일한 기능
		Person mariPerson2 = new Person("마리");

	}

}
profile
공부했던 내용들을 모아둔 창고입니다.

0개의 댓글