노트코드
노트코드
노트코드

블로그 메뉴

  • 홈
  • 이력서
  • 이전 블로그
  • 글쓰기
  • 관리자페이지
  • 분류 전체보기 (57)
    • 코틀린 (2)
      • 실무 프로젝트로 배우는 Kotlin & Sprin.. (2)
    • JAVA (1)
      • 디자인패턴 (1)
      • 객체지향 5대원칙 (0)
    • SPRING (32)
      • JPA (11)
      • 스프링시큐리티 (1)
      • 스프링 (8)
      • QueryDsl (1)
      • 스프링배치 (11)
    • AZURE (0)
    • ETC (10)
      • MAVEN (0)
      • GIT (0)
      • ReMind (3)
      • Exception (1)
      • CS (6)
    • 책 (8)
      • 이것이 자바다 (8)

최근 글

최근 댓글

태그

  • 스프링
  • JPA
전체 방문자
오늘
어제
hELLO · Designed By 정상우.
노트코드

노트코드

책/이것이 자바다

[11장]기본 API클래스

2022. 2. 14. 10:07

11.2 java.lang과 java.util패키지

11.2.1 java.lang 패키지

java.lang 패키지는 자바 프로그램의 기본적인 클래스를 담고 있는 패키지이다.

클래스 용도
Object 자바 클래스의 최상위 클래스로 사용
System -표준 입력 장치로부터 데이터를 입력받을 때 사용
-표준 출력 장치로 출력하기 위해 사용
-자바 가상 기계를 종료시킬 때 사용
-쓰레기 수집기를 실행 요청할 때 사용
Class -클래스를 메모리로 로딩할 때 사용
String -문자열을 저장하고 여러 가지 정보를 얻을 때 사용
StringBuffer, StringBuilder -문자열을 저장하고, 내부 문자열을 조작할 때 사용
Math -수학 함수를 이용할 때 사용
Wrapper (Byte,Short,Character,Integer,Float, Double, Boolean, Long) -기본 타입의 데이터를 갖는 객체를 만들 때 사용
-문자열을 기본 타입으로 변활할 때 사용
-입력값 검사에 사용

 

11.2.2 java.util 패키지

자바 프로그램 개발에 조미료 같은 역할을 하는 클래스를 담고 있다.

 

클래스 용도
Arrays -배열을 조작할 때 사용
Calendar -운영체제의 날짜와 시간을 얻을 때 사용
Date -날짜와 시간 정보를 저장하는 클래스
Objects -객체 비교, 널 여부 등을 조사할 때 사용
StringTokenizer -특정 문자로 구분된 문자열을 뽑아낼 때 사용
Random -난수를 얻을 때 사용

11.3 Object 클래스

클래스를 선언할 때 extends 키워드로 다른 클래스를 상속하지 않으면 암시적으로 java.lang.Object 클래스를 상속하게 된다.
자바의 모든 클래스는 Object 클래스의 자식이거나 자손 클래스이다

11.3.1 객체 비교(equals())

public boolean equals(Object obj){...}

equals() 메소드의 매개 타입은 Object인데, 이것은 모든 객체가 매개값으로 대입될 수 있음을 말한다.
Object가 최상위 타입이므로 모든 객체는 Object 타입으로 자동 타입 변환될 수 있기 때문이다.

Object 클래스의 equals() 메소드는 비교 연산자인 ==과 동일한 결과를 리턴한다.
두 객체가 동일한 객체라면 true를 리턴하고 그렇지 않다면 false를 리턴한다.
*int와 boolean과 같은 primitive type에 대해서는 값을 비교, reference type에 대해서는 메모리의 같은 주소값을 가지고 있는지에 대한 비교

Object obj1 = new Object();
Object obj2 = new Object();

boolean result = obj1.equals(obj2); //false
boolean result = (obj1 == obj2)//false
// 결과가 동일하다
  • equals() 메소드는 두 객체를 비교해서 논리적으로 동등하면 Ture, 그렇지 않다면 false를 리턴한다.
  • 논리적으로 동등하다는 것은 같은 객체이건, 다른 객체이건 상관없이 객체가 저장하고 있는 데이터가 동일함을 뜻함
    String 객체의 equals() 메소드는 String 객체의 번지를 비교하지 않고 문자열이 동일한지 비교한다. (Sting클래스가 Object의 equals()를 재정의했기 때문)
  • Member 객체는 다르지만 id필드값이 같으면 논리적으로 동등한 객체로 취급하고 싶을 경우 Object의 equals()메소드를 재정의해서 id필드값이 같음을 비교한다.
📢 equals() 메소드를 재정의 할 때에는 매개값이 기준 객체와 동일한 타입의 객체인지 먼저 확인해야한다. 동일하지 않다면 false를 리턴해야 한다.
public class Member {
    public String id;

    public Member(String id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Member){
            Member member = (Member) obj;
            if(id.equals(member.id)){
                return true;
            }
        }
        return false;
    }
}
public class MemberExample {
    public static void main(String[] args) {
        Member obj1 = new Member("blue");
        Member obj2 = new Member("blue");
        Member obj3 = new Member("red");

        if(obj1.equals(obj2)){
            System.out.println("obj1과 obj2는 동등합니다"); //o
        }else{
            System.out.println("obj1과 obj2는 다릅니다.");
        }

        if(obj1.equals(obj3)){
            System.out.println("obj1과 obj3는 동등합니다");
        }else{
            System.out.println("obj1과 obj3는 다릅니다."); //o
        }
    }
}

11.3.2 객체 해시코드

  • 객체 해시코드란 객체를 식별할 하나의 정수값을 말한다.
  • Object의 hashCode()메소드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체마다 다른 값을 가지고 있다.
  • 논리적 동등 비교 시 hashCode()를 오버라이딩 할 필요성이 있다.

HashCode()를 실행해서 리턴된 해시코드 값이 같은지를 본다. 해시코드 값이 다르면 다른 객체로 판단하고, 해시코드 값이 같으면 equals() 메소드로 다시 비교한다.

그렇기 때문에 hashCode()메소드가 true가 나와도 equals()의 리턴값이 다르면 다른 객체가 된다.

  • hashCode 클래스 설명 보여주기

  • 예제
      package chap11;
    
      import java.util.HashMap;
    
      public class KeyExample {
          public static void main(String[] args) {
              HashMap<Key, String> hashMap = new HashMap<>();
                      Key key = new Key(1);
              hashMap.put(new Key(1), "홍길동");
                      //주소값이 100
    
              String result = hashMap.get(new Key(1));
                      //주소값은 200
              System.out.println("result = " + result);
    
          }
      }
    
      //결과 null
      package chap11;
    
      public class KeyAddHashCode {
          public int number;
    
          public KeyAddHashCode(int number) {
              this.number = number;
          }
    
          @Override
          public boolean equals(Object obj) {
              if(obj instanceof KeyAddHashCode){
                  KeyAddHashCode compareKey = (KeyAddHashCode) obj;
                  if(this.number == compareKey.number){
                      return true;
                  }
              }
              return false;
          }
    
          @Override
          public int hashCode() {
              return number;
          }
      }
      package chap11;
    
      import java.util.HashMap;
    
      public class KeyHashCodeExample {
          public static void main(String[] args) {
              HashMap<KeyAddHashCode, String> hashMap = new HashMap<>();
    
              hashMap.put(new KeyAddHashCode(1), "홍길동");
                      //1
              String result = hashMap.get(new KeyAddHashCode(1));
                      //1
              System.out.println("result = " + result);
    
          }
      }
      //결과 홍길동
  • package chap11; public class Key { public int number; public Key(int number) { this.number = number; } @Override public boolean equals(Object obj) { if(obj instanceof Key){ Key compareKey = (Key) obj; if(this.number == compareKey.number){ return true; } } return false; } }

keyExample 문제

  • 입력매개변수의 hashcode값과 출력매개변수의 hashcode값이 다르다.
  • 다른 hashcode값으로 조회하려하니 못찾게 되고 null값이 반환

keyAddHashcodeExample

  • 입력매개변수의 hashcode값이 number로 고정되어있다.
  • 같은 hashcode값으로 조회하니 결과값이 찾아진다.

11.3.3 객체 문자 정보(toString())

Obejct 클래스의 toString() 메소드는 객체의 문자 정보를 리턴한다. 객체의 문자 정보란 객체를 문자열로 표현한 값을 말한다.

기본적으로 Object 클래스의 toString() 메소드는 "클래스명 @16진수해시코드"로 구성된 문자 정보를 리턴한다.(개발자에게 쓸모없는 정보)

package main.java.chap11.tostring;

public class SmartPhone {
    private String company;
    private String os;

    public SmartPhone(String company, String os) {
        this.company = company;
        this.os = os;
    }

    @Override
    public String toString() {
        return company + "," + os;
    }
}
package main.java.chap11.tostring;

public class SmartPhoneExample {

    public static void main(String[] args) {
        SmartPhone smartPhone = new SmartPhone("samsung", "안드로이드");

        System.out.println("smartPhone = " + smartPhone);
    }
}

11.3.4 객체 복제 (clone())

객체 복제는 원복 객체의 필드값과 동일한 값을 가지는 새로운 객체를 생성하는 것을 말한다.
객체를 복제하는 이유는 원복 객체를 안전하게 보호하기 위해서이다.

  • 신뢰하지 않는 영역으로 원복 객체를 넘겨 작업할 경우 원본 객체의 데이터가 훼손될 수 있기 때문에
    복제된 객체를 만들어 신뢰하지 않는 영역으로 넘기는 것이 좋다.
  • 복제된 객체의 데이터가 훼손되더라도 원복 객체는 아무런 영향을 받지 않기 때문에 안전하게 데이터를 보호 할 수 있다.
  • 객체를 복제하는 방법에는 얕은 복제와 깊은 복제가 있다.

얕은 복제

얕은 복제는 단순히 필드 값을 복사해서 객체를 복제하는 것을 말한다.

필드값만 복제하기 때문에 필드가 기본 타입일 경우 값 복사가 일어나고, 필드가 참조 타입일 경우에는 객체의 번지가 복사된다.

때문에 원복객체에서 참조 객체를 변경하면 원복 객체도 변경된 객체를 가지게 된다. 이것이 얕은 복제의 단점이다.

Object의 Clone()메소드는 자신과 동일한 필드값을 가진 얕은 복제된 객체를 리턴한다.
이 메소드로 객체를 복제하려면 원복 객체는 반드시 java.lang.Cloneable인터페이스를 구현하고 있어야 한다.
메소드 선언이 없음에도 불구하고 Cloneable 인터페이스를 명시적으로 구현하는 이유는 클래스 설계자가 복제를 허용한다는 의도적인 표시를 하기 위해서다.

Cloneable 인터페이스를 구현하지 않으면 clone() 메소드를 호출할 때 CloneNotSupportedException 예외가 발생하여 복제가 실패한다.
clone()은 CloneNotSupportedException 예외 처리가 필요한 메소드이기 때문에 try-catch구문이 필요하다.

package main.java.chap11.clone;

public class Member implements Cloneable{
    private String id;
    private String name;
    private String password;
    private int age;
    private boolean adult;

    public Member(String id, String name, String password, int age, boolean adult) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.age = age;
        this.adult = adult;
    }

    public Member getMember(){
        Member cloned = null;
        try{
            cloned = (Member) clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return cloned;
    }
}
package main.java.chap11.clone;

import java.util.Arrays;

public class MemberCloneExample {
    public static void main(String[] args) {
        Member original = new Member("blue", "홍길동", "12345", 25, true, new int[]{1,2});

        Member cloned = original.getMember();
        cloned.password = "55555";
        cloned.score[1] = 10;

        System.out.println("origin.password = " + original.password);
        System.out.println("cloned.password = " + cloned.password);

        System.out.println("original.score = " + original.score.toString());
        System.out.println("original.score = " + original.score[1]);
        System.out.println("cloned.score = " + cloned.score.toString());
        System.out.println("cloned.score = " + cloned.score[1]);
    }
}
origin.password = 12345
cloned.password = 55555
original.score = [I@33c7353a
original.score = 10
cloned.score = [I@33c7353a
cloned.score = 10

깊은 복제

얕은 복제의 반대 개념은 깊은 복제이다. 깊은 복제란 참조하고 있는 객체도 복제하는 것을 말한다.

깊은 복제를 하려면 Object의 Clone()메서드를 재정의해서 참조 객체를 복제하느 코드를 직접 작성해야한다.

package main.java.chap11.deepClone;

public class Car {
    public String model;

    public Car(String model) {
        this.model = model;
    }
}
package main.java.chap11.deepClone;

import java.util.Arrays;

public class Member implements Cloneable{
    private String name;
    private int age;
    public int[] score;
    public Car car;

    public Member(String name, int age, int[] score, Car car) {
        this.name = name;
        this.age = age;
        this.score = score;
        this.car = car;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Member cloned = (Member)super.clone();
        cloned.score = Arrays.copyOf(this.score, this.score.length);

        cloned.car = new Car(this.car.model);
        return cloned;

    }

    public Member getMember(){
        Member cloned = null;
        try{
            cloned = (Member) clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return cloned;
    }
}
package main.java.chap11.deepClone;

public class MemberCloneExample {
    public static void main(String[] args) {
        Member original = new Member("홍길동",25,new int[]{90,90}, new Car("소나타"));

        Member cloned = original.getMember();
        cloned.score[0] = 100;
        cloned.car.model = "그랜져";

        System.out.println("original.score[0] = " + original.score[0]);//90
        System.out.println("original.car.model = " + original.car.model);
        System.out.println("cloned.score[0] = " + cloned.score[0]); //100
        System.out.println("cloned.car.model = " + cloned.car.model);

    }
}

11.3.5 객체 소멸자(finalize())

참조하지 않는 배열이나 객체는 쓰레기 수집기(Garbage Collector)가 힙 영역에서 자동적으로 소멸 시킨다.
쓰레기 수집기는 객체를 소멸하기 직전에 마지막으로 객체의 소멸자(finalize())를 실행 시킨다.

만약 객체가 소멸되기 전에 마지막으로 사용했던 자원을 닫고 싶거나, 중요한 데이터를 저장하고 싶다면 Object의 finalize()를 재정의 할 수 있다.

@Override
protedcted void finalize() throws Throwable{
    System.out.println(no + "번 객체의 finalize()가 실행됨")
}
public class FinalizeExample{
    public static void main(){
        //
        System.gc()//메서드로 실행
    }
}

11.4 Objects클래스

Object와 유사한 이름을 가진 java.util.Objects 클래스는 객체 비교 해시코드 생성, null여부, 객체 문자열 리턴 등의 연산을 수행하는
Object의 유틸클래스이다.

11.4.1 객체 비교(compare(T a, T b , Comparatorc))

Object.compare(T a, T b , Comparatorc) 메소드는 두 객체를 비교자로 비교해서 int 값을 리턴한다.

java.util.Comparator는 제네릭 인터페이스 타입으로 두객체를 비교하는 compare(T a , T b) 메소드가 정의되어 있다.

compare메소드의 리턴 타입은 int인데 a가 b보다 작으면 음수,같으면 0 크면 양수를 리턴하도록 구현 클래스를 만들어야 한다.

public interface Comparator<T>{
    int compare(T a, T b);
}
package main.java.chap11.compare;

public class Student {
    public int sno;
        public int age;

    public Student(int sno) {
        this.sno = sno;
    }
}
package main.java.chap11.compare;

import java.util.Comparator;

public class StudentComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
//        if(o1.sno < o2.sno) return -1;
//        else if(o1.sno == o2.sno) return 0;
//        else return 1;

        return Integer.compare(o1.sno, o2.sno);
    }
}
package main.java.chap11.compare;

import java.util.Comparator;
import java.util.Objects;

public class CompareExample {
    public static void main(String[] args) {
        Student student1 = new Student(1);
        Student student2 = new Student(2);
        Student student3 = new Student(3);

        int result = Objects.compare(student1, student2, new StudentComparator());
        System.out.println("result = " + result);

        int compare = Objects.compare(student1, student2, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Integer.compare(o1.sno, o2.sno);
            }
        });

        System.out.println("compare anomyousClass result =" + compare);
    }
}

11.4.2 동등 비교(equals()와 deepEquals())

Objects.equals(Object a, Object b)두 객체의 동등성을 비교하는데 특이한 점은 a와 b가 모두 null일 경우 true를 리턴한다는 점이다.

a b Objects.equals(a,b)
not null not null a.equals(b)의 리턴값
null not null false
not null null false
null null true

 

Objects.deepEquals(Object a, Object b)역시 두 객체의 동등을 비교하는데, a와 b가 서로 다른 배열일 경우, 항목 값이 모두 같으면 true를 리턴한다.

a b Objects.equals(a,b)
not null(not array) not null(not array) a.equals(b)의 리턴값
not null(array) not null(array) Arrays.deepEquals(a,b)의 리턴값
not null null false
null not null false
null null true

 

11.4.3 해시코드 생성(hash(), hashCode())

Object.hash()메소드는 매개값으로 주어진 값들을 이용해서 해시코드를 생성하는 역할을 한다.

주어진 매개값들로 배열을 생성하고 Arrays.hashCode(Objec[])를 호출해서 해시코드를 얻고 이 값을 리턴한다.

이 메소드는 클래스가 hashCode()를 재 정의 할 때 리턴값을 생성하기 위해 사용하면 좋다.

클래스가 여러 필드를 가지고 있을 때 이 필드들로부터 해시코드를 생성하게 되면 동일한 필드값을 가지는 객체는 동일한 해시코드를 가질 수 있다.

@Override
public int hashCode(){
    return Objects.hash(field1, field2, field3)
}

Objects.hashCode(Object o )는 매개값으로 주어진 객체의 해시코드를 리턴하기 때문에 o.hashCode()의 리턴값과 동일하다.
차이점은 매개값이 null이면 0을 리턴한다.

11.4.4 널 여부 조사(isNull(), nonNull(), requireNonNull())

Objects.isNull(Object obj)는 매개값이 null일 경우 true를 반환한다.
반대로 nonNull(Object obj)는 매개값이 not null일 경우 true를 리턴한다

package main.java.chap11.objetshashcode;

import main.java.chap11.compare.Student;

import java.util.Objects;

public class HashCodeExample {
    public static void main(String[] args) {
        HashcodeStudent s1 = new HashcodeStudent(1, "홍길동");
        HashcodeStudent s2 = new HashcodeStudent(1, "홍길동");
                HashcodeStudent s3 = new HashcodeStudent(1, "홍");
        System.out.println(Objects.hashCode(s1)); //같음
        System.out.println(Objects.hashCode(s2));//같음
                System.out.println(Objects.hashCode(s3));//다름

    }

    static class HashcodeStudent{
        int sno;
        String name;

        public HashcodeStudent(int sno, String name) {
            this.sno = sno;
            this.name = name;
        }

        @Override
        public int hashCode() {
            return Objects.hash(sno, name);
        }
    }
}

requireNonNull()은 다음 세가지로 오버로딩 되어있다.

  • requireNonNull(T obj) : not null → obj
    null → NullpointException
  • requireNonNull(T obj, String message) : not null → obj
    null → NullpointException(message)
  • requireNonNull(T obj, Supplier msgSupplier) : not null → obj
    null → NullpointException(msgSupplier.get())
String name= Objects.requireNonNull(str2, () -> "이름이 없다니까요");

11.4.5 객체 문자 정보(toString())

Objects.toString()은 객체의 문자 정보를 리턴하는데, 다음 두 가지로 오버로딩 되어있다.

  • toString(Object o) : not null → o.toString();
    null → "null"
  • toString(Object o, String nullDefault) : not null → o.toString();
    null → nullDefault

11.5 System클래스

자바 프로그램은 운영체제상 바로 실행되는 것이 아니라 JVM 위에서 실행된다.

따라서 운영체제의 모든 기능을 자바 코드로 직접 접근하기란 어렵다.
하지만 java.lang 패키지에 속하는 System 클래스를 이용하면 운영체제의 일부 기능을 이용할 수 있다.

11.5.1 프로그램 종료(exit())

경우에 따라서는 강제적으로 JVM을 종료시킬 때도 있다

정상적으로 종료할때는 0을 넘겨주고, 비정상 종료일 경우 0 이외의 다른값을 준다.

System.exit(0)

System.exit()가 실행되면 보안 관리자의 checkExit() 메소드가 자동 호출 되는데, 이 메소드에서 종료 상택값을 조사해서 특정 값이 입력되지 않으면

SecurityException을 발생시켜 System.exit()를 호출한 곳에서 예외 처리를 할 수 있도록 해준다. checkExit()가 정상적으로 실행되면 JVM은 종료된다

System.setSecurityManager(new SecurityManager(){
    @Override
    public void checkExit(int status){
        if(status != 5){
            throw new SecurityException()
        }
    }
}

11.5.2 쓰레기 수집기 실행(gc())

  • Heap영역에서 떠도는 아무도 참조하지않는 객체를 삭제한다 .
  • 쓰레기 수집기는 개발자가 직접 코드로 실행 시킬 수 없고, JVM에게 가능한 빨리 실행해 달라고 요청할 수 는 있다.

11.5.3 현재 시각 읽기(currentTimeMillis(), nanoTime())

System 클래스의 currentTimeMillis()메소드와 nanoTime()메소드는 컴퓨터의 시계로부터 현재 시간을 읽어서 밀리세컨드 단위와 나노세컨드 단위의 Lon값을 리턴함

Long time = System.currentTimeMillis();
Long time = System.nanoTime();

11.5.4 시스템 프로퍼티 읽기

JVM이 시작할 때 자동 설정되는 시스템의 속성값을 말한다.

ex) os.name, java.version, java.home, fileseparator, user.name, user.home, user.dir

String value = System.getProperty(String key);

Properties props = System.getProperties();

set keys= props.keySet();
for(Object object  keys){
    String key = (String)object;
    String value = System.getProperty(key);
}

11.5.5 환경 변수 읽기(getenv())

String value = System.getenv(String name);
System.getenv("JAVA_HOME")

'책 > 이것이 자바다' 카테고리의 다른 글

[11장] 기본API클래스(3)  (0) 2022.02.14
[11장] 기본API클래스(2)  (0) 2022.02.14
[10장]예외처리  (0) 2022.02.14
[9장]중첩 클래스와 중첩 인터페이스  (0) 2022.02.14
[8장]인터페이스  (0) 2022.02.14
    '책/이것이 자바다' 카테고리의 다른 글
    • [11장] 기본API클래스(3)
    • [11장] 기본API클래스(2)
    • [10장]예외처리
    • [9장]중첩 클래스와 중첩 인터페이스
    노트코드
    노트코드
    노션 블로그에서 티스토리로 이전공사중

    티스토리툴바