본문 바로가기
JAVA/이재환의 자바 프로그래밍 입문

[Java] Ch.17 자바의 기본 클래스

by ♡˖GYURI˖♡ 2023. 10. 23.

java.lang 클래스

  • 우리가 많이 사용하는 기본 클래스를 포함하는 패키지
  • 이 패키지에 속한 클래스들은 임포트하지 않아도 자동으로 임포트됨

▼대표적인 실행 예외

클래스 설명
Object 최상위 클래스로 기본적인 메서드 제공
String, StringBuffer, StringBuilder 문자열을 처리하는 메서드 제공
Number, Integer, Long, Float, Double 기본형 데이터 객체화
System 시스템 정보나 입출력을 처리하는 메서드 제공
Math 각종 수학 함수 제공
Thread 스레드를 처리하는 메서드 제공
Class 실행 중에 클래스 정보 제공

 

이 패키지에 속한 모든 클래스들은 JDK가 설치된 폴더의 하위 폴더인 lib 폴더 내 src.zip 내 java.lang 패키지에서 확인할 수 있음

 

 

Object 클래스

  • 모든 자바 클래스의 최상위 클래스
  • 모든 자바 클래스는 Object 클래스로부터 상속을 받음
  • 클래스를 만들 때 Object 클래스를 상속받는 코드를 작성한 적이 없는데? → 자동으로 extends Object가 사용됨

 

public class Ex01_Object
{
    String name;
    String getName()
    {
    	return name;
    }
}

public class Ex01_Object extends Object
{
    String name;
    String getName()
    {
    	return name;
    }
}

이 두 코드는 의미가 같음

 

자바에서 제공하는 기본 클래스들도 당연히 Object 클래스를 상속받아 만들어짐

 

이처럼 모든 클래스가 Object 클래스를 상속받았으므로 Object 클래스의 메서드를 사용할 수 있고, 재정의할 수 있고, Object형으로 형변환할 수도 있음

 

 

▼Object 클래스의 주요 메서드

메서드 설명
public String toString() 객체의 문자 정보 반환
public boolean equals(Object obj) 두 객체가 동일한지 여부 반환
public int hashcode() 객체의 해시 코드 반환
protected Object clone() 객체의 사본 생성

Object 클래스의 메서드 중에는 재정의할 수 있는 메서드도 있고, 그렇지 않은 메서드도 있음

자주 재정의하여 사용하는 메서드 두 개 : toString() 메서드, equals() 메서드

 

 

toString() 메서드

Object 클래스에 정의되어 있는 toString() 메서드의 원형

public String toString() {
	return getClass.getName() + "@" + Integer.toHexString(hashCode());
}

생성된 객체의 클래스명과 해시 코드를 보여줌

 

이 메서드는 원형 그대로 사용하는 것은 의미가 없고, 보통은 객체 정보를 String으로 바꿔서 사용할 때 많이 사용됨

우리가 자주 사용하는 String 클래스에는 이미 오버라이딩하여 재정의를 해놓고 있음

String 클래스는 클래스명과 해시 코드를 보여주는 대신 안에 들어 있는 문자열의 내용을 반환해줌

 

public class Ex02_toString1
{
    public static void main(String[] args)
    {
        String name = "홍길동";
        System.out.println(name);
        System.out.println(name.toString());
    }
}

 

class Book3
{
    String author;
}

public class Ex03_toString2
{
    public static void main(String[] args)
    {
        Book3 myBook = new Book3();
        myBook.author = "홍길동";
        System.out.println(myBook.author);
        System.out.println(myBook);	// (1)
    }
}

(1)

  • System.out.println() 메서드는 객체 자체가 매개변수로 주어졌기 때문에 객체 안의 toString() 메서드를 찾음
  • 재정의된 메서드가 아니고 상속받은 그대로의 원형이 있기 때문에 클래스명과 해시 코드가 출력 됨
  • Book3 : 클래스명
  • 2d363fb3 : 해시 코드

 

class Book4
{
    String author;
    // 메서드 오버라이딩
    public String toString()
    {
        return author;
    }
}

public class Ex04_toString3
{
    public static void main(String[] args)
    {
        Book4 myBook = new Book4();
        myBook.author = "홍길동";
        System.out.println(myBook.author);
        System.out.println(myBook);
    }
}

 

 

equals() 메서드

Object 클래스에 정의되어 있는 equals() 메서드의 원형

public boolean equals(Object obj) {
	return (this == obj);
}

 

자신과 매개변수로 들어온 객체의 주솟값 자체를 비교하여 같은지 아닌지 반환함

참조하고 있는 변수의 id(주솟값)끼리 비교 됨

 

이 메서드도 원형 그대로 사용하는 것은 의미가 없고, 보통은 오버라이딩으로 재정의하여 객체 안 변수의 값끼리 비교하는 데 많이 사용됨

 

class Book5
{
    String author;
}

public class Ex05_equals1
{
    public static void main(String[] args)
    {
        Book5 myBook1 = new Book5();
        myBook1.author = "홍길동";

        Book5 myBook2 = new Book5();
        myBook2.author = "홍길동";
        
        if ( myBook1.equals(myBook2))
            System.out.println("두 객체의 참조 id는 같습니다.");
        else
            System.out.println("두 객체의 참조 id는 다릅니다.");
    }
}

 

class Book6
{
    String author;
    public boolean equals(Object obj)
    {
        if(this.author.equals(((Book6)obj).author) )
            return true;
        else
            return false;
    }
}

public class Ex06_equals2
{
    public static void main(String[] args)
    {
        Book6 myBook1 = new Book6();
        myBook1.author = "홍길동";

        Book6 myBook2 = new Book6();
        myBook2.author = "홍길동";
        
        if ( myBook1.equals(myBook2))
            System.out.println("두 객체의 author 변수의 값은 같습니다.");
        else
            System.out.println("두 객체의 author 변수의 값은 다릅니다.");
    }
}

 

 

래퍼 클래스

자바는 기본 데이터형(정수형, 문자형, 논리형)에 대응하는 클래스를 마련해놓았음

이 클래스들을 래퍼 클래스(wrapper class)라고 함

 

래퍼 클래스란 기본 자료형에 대해서 객체로서 인식되도록 '포장'을 했다는 뜻

이 때 단순히 객체화만 한 것이 아니고 다양한 메서드도 추가하였음

 

▼기본형과 래퍼 클래스

기본 자료형 래퍼 클래스
boolean Boolean
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double

 

기본 자료형 대신 래퍼 클래스를 사용하는 이유

  • 클래스가 제공하는 편리한 메서드 사용 (값 변환, 형 변환, 진법 변환)
  • 클래스가 제공하는 상수 사용 (MIN_VALUE, MAX_VALUE)
  • 메서드 매개변수의 형이 Object여서 기본 자료형을 사용 못하고 클래스 형태인 래퍼로 넘겨야 할 때 사용 (컬렉션 프레임워크)

 

Number 클래스

java.lang.Number 클래스는 모든 수치형 래퍼 클래스가 상속하는 추상 클래스

Number 클래스를 상속한 래퍼 클래스는 모두 다음의 추상 메서드가 다 구현되어 있음

  • byteValue()
  • shortValue()
  • intValue()
  • longValue()
  • floatValue()
  • doubleValue()

 

수치형 래퍼 클래스인 Byte, Short, Integer, Long, Float, Double에서 이 메서드들을 사용하면 다른 형으로 변환한 값을 얻을 수 있음

즉, 래퍼 객체에 저장된 값을 원하는 기본 자료형 값으로 변환할 수 있음

 

public class Ex07_Number
{
    public static void main(String[] args)
    {
        //Integer num1 = new Integer(20); -> 자바 4까지 문법
        Integer num1 = Integer.valueOf(20);	// 자바 5부터 문법
        System.out.println(num1.intValue());
        System.out.println(num1.doubleValue());

        Double num2 = Double.valueOf(3.14);
        System.out.println(num2.intValue());
        System.out.println(num2.doubleValue());
    }
}

 

 

문자열 변환

수치형의 래퍼 클래스인 Byte, Short, Integer, Long, Float, Doubl에는 각각 문자열을 수치형으로 변환하는 메서드가 있음

 

▼문자열을 수치형으로 변환하는 메서드

클래스 메서드 기능
Byte parseByte() 문자열을 byte형으로 변환
Short parseShort() 문자열을 short형으로 변환
Integer parseInt() 문자열을 int형으로 변환
Long parseLong() 문자열을 long형으로 변환
Float parseFloat()  문자열을 float형으로 변환
Double parseDouble() 문자열을 double형으로 변환

 

public class Ex08_parseXXX
{
    public static void main(String[] args)
    {
        String str = "100";
        int a = Integer.parseInt(str);
        double b = Double.parseDouble("3.14");
        
        System.out.println(a + " : " + b);
    }
}

 

(클래스명.메서드명을 사용하고 있기 때문에 parseInt는 스태틱 메서드임)

 

 

오브젝트의 비교

래퍼 클래스의 오브젝트끼리 비교하려면 == 대신 equals() 메서드를 사용해야 함

모든 래퍼 클래스의 equals() 메서드는 객체 안의 기본형 데이터를 비교하는 것으로 메서드의 기능이 재정의되어 있음

Integer a = new Integer(10);
Integer b = new Integer(20);
boolean c = a.equals(b);

오브젝트들의 형과 값이 동일하다면 true 반환

 

 

다양한 static 메서드들

public class Ex09_UtilMethod
{
    public static void main(String[] args)
    {
    	// 메서드 오버로딩 (같은 메서드명인데 매개변수가 다름)
        Integer n1 = Integer.valueOf(5);
        Integer n2 = Integer.valueOf("1024");
        
        System.out.println("큰 수: " + Integer.max(n1, n2));
        System.out.println("작은 수: " + Integer.min(n1, n2));
        System.out.println("합: " + Integer.sum(n1, n2));
        System.out.println();
        
        System.out.println("12의 2진 표현: 0B" + Integer.toBinaryString(12));
        System.out.println("12의 8진 표현: 0" + Integer.toOctalString(12));
        System.out.println("12의 16진 표현: 0x" + Integer.toHexString(12));
    }
}

 

 

박싱과 언박싱

래퍼 객체들은 담고 있는 값을 수정하지 못함

기본 자료형의 값을 포장해서 만든 것이기 때문에 원재료를 바꿀 수 없는 것

따라서 값의 수정이 필요하면 다음 예제의 문장들과 같이 새로운 래퍼 객체를 생성해야 함

 

public class Ex10_BoxingUnboxing
{
    public static void main(String[] args)
    {
        // 박싱
        Integer iObj = Integer.valueOf(10);
        Double dObj = Double.valueOf(3.14);
        
        // 메소드 호출을 통한 언박싱
        int num1 = iObj.intValue();
        double num2 = dObj.doubleValue();

        System.out.println(num1 + " : " + iObj);
        System.out.println(num2 + " : " + dObj);
        System.out.println();
       
        // 래퍼 인스턴스 값의 증가 방법
        iObj = Integer.valueOf(iObj.intValue() + 10);
        dObj = Double.valueOf(dObj.doubleValue() + 1.2);
        
        System.out.println(iObj);
        System.out.println(dObj);
    }
}

래퍼 클래스의 값을 증가시키려면 언박싱으로 값을 구해오고 더한 다음 다시 박싱으로 객체를 만들어서 대입해야 함

 

 

오토 박싱과 오토 언박싱

public class Ex11_AutoBoxingUnboxing1
{
    public static void main(String[] args)
    {
        // 오토 박싱
        Integer iObj = 10;
        Double dObj = 3.14;
        
        // 오토 언박싱
        int num1 = iObj;
        double num2 = dObj;
        
        System.out.println(num1 + " : " + iObj);
        System.out.println(num2 + " : " + dObj);
    }
}

 

public class Ex12_AutoBoxingUnboxing2
{
    public static void main(String[] args)
    {
        Integer num = 10;
        
        num++;        // Integer.valueOf(num.intValue() + 1);
                      // <-- 오토 박싱과 오토 언박싱 동시에 진행.
        System.out.println(num);
        
        num += 3;     // Integer.valueOf(num.intValue() + 3);
        System.out.println(num);
        
        int r = num + 5;            // 오토 언박싱 진행
        Integer rObj = num - 5;     // 오토 언박싱 진행 + 오토 박싱 진행

        System.out.println(r);
        System.out.println(rObj);    
    }
}

 

 

Math 클래스

Math 클래스에 정의된 메서드는 모두 static으로 선언되어 있음

즉, Math는 기능 제공이 목적일 뿐, 인스턴스 생성을 목적으로 정의된 클래스는 아님

 

public class Ex13_MathUse
{
    public static void main(String[] args)
    {
        System.out.println("4의 제곱근: " + Math.sqrt(4));
        System.out.println("log2(8): " + baseLog(8, 2));
        System.out.println("2의 3승: "+ Math.pow(2, 3));
        System.out.println();
        
        System.out.println("원주율: " + Math.PI);
        System.out.println("파이에 대한 Degree: " + Math.toDegrees(Math.PI));
        System.out.println("2 파이에 대한 Degree: " + Math.toDegrees(2.0 * Math.PI));
        System.out.println();

        double radian45 = Math.toRadians(45);    // 라디안으로의 변환!
        
        System.out.println("싸인 45: " + Math.sin(radian45));
        System.out.println("코싸인 45: " + Math.cos(radian45));
        System.out.println("탄젠트 45: " + Math.tan(radian45));
    }
    
    public static double baseLog(double x, double base)
    {
        return Math.log(x) / Math.log(base);
    }
}

 

 

Random 클래스

임의의 랜덤 값을 만들어낼 때 사용하는 클래스

Random rand = new Random();

 

다양한 메서드가 제공되는데, 보통의 경우 nextInt(int bound) 메서드 이용

public boolean nextBoolean()	// boolean형의 난수 반환
public int nextInt()		// int형 난수 반환
public long nextLong()		// long형 난수 반환
public int nextInt(int bound)	// 0 이상 bound 미만 범위의 int형 난수 반환
public float nextFloat()	// 0.0 이상 1.0 미만의 float형 난수 반환
public double nextDouble()	// 0.0 이상 1.0 미만의 double형 난수 반환

 

발표 등에서 준비한 자료와 같은 값을 얻기 위해서 생성자에 시드값을 지정해줄 수도 있음

이 경우 랜덤값이 매번 같은 순서로 나오게 됨

 

import java.util.Random;

public class Ex14_RandomUse
{
    public static void main(String[] args)
    {
        // 매번 다른 수가 나옴
        Random rand1 = new Random();
        
        for(int i = 0; i < 10; i++)
            System.out.print(rand1.nextInt(10) + " ");
        System.out.println();

        // 매번 같은 순으로 값이 나옴
        Random rand2 = new Random(12);
        
        for(int i = 0; i < 10; i++)
            System.out.print(rand2.nextInt(10) + " ");
        System.out.println();
    }
}

 

 

Arrays 클래스

객체 저장 배열의 비교

배열의 비교는 두 배열에 저장된 데이터 수, 순서, 내용 모두가 같을 때 true 반환

내용이 같은 것을 체크하려면 배열에 저장되는 객체는 Object 클래스로부터 상속받은 equals() 메서드가 오버라이딩으로 재정의되어 있으면 됨

 

import java.util.Arrays;

class INum1 {
    private int num;
    
    public INum1(int num) {
        this.num = num;
    }
}

public class Ex15_ArrayObjEquals1
{
    public static void main(String[] args)
    {
        INum1[] arr1 = new INum1[2];
        INum1[] arr2 = new INum1[2];
        
        arr1[0] = new INum1(1);
        arr2[0] = new INum1(1);

        arr1[1] = new INum1(2);
        arr2[1] = new INum1(2);

        System.out.println(Arrays.equals(arr1, arr2));
    }
}

 

import java.util.Arrays;

class INum2 {
    private int num;
    
    public INum2(int num) {
        this.num = num;
    }
    
    @Override
    public boolean equals(Object obj) {
        if(this.num == ((INum2)obj).num)
            return true;
        else
            return false;
    }
}

public class Ex16_ArrayObjEquals2
{
    public static void main(String[] args)
    {
        INum2[] arr1 = new INum2[2];
        INum2[] arr2 = new INum2[2];
        
        arr1[0] = new INum2(1);
        arr2[0] = new INum2(1);

        arr1[1] = new INum2(2);
        arr2[1] = new INum2(2);

        System.out.println(Arrays.equals(arr1, arr2));
    }
}

 

 

객체 저장 배열의 정렬

객체가 저장된 배열의 정렬은 저장된 데이터 크기를 비교할 때, 어떤 기준으로 크기를 비교할지 프로그래머가 정해야 함

기준을 정했으면 Comparable 인터페이스를 구현해주면 됨

 

import java.util.Arrays;

// Comparable 인터페이스
class Person implements Comparable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }    

    public int compareTo(Object o) {
        Person p = (Person)o;

// 	이름 비교
//      int nNum = this.name.compareTo(p.name);
//      return nNum;

//	나이 비교
        if(this.age > p.age)
            return 1;
        else if(this.age < p.age)
            return -1;
        else
            return 0;
    }
    
    public String toString() {
        return name + ": " + age;
    }
}

public class Ex17_ArrayObjSort
{
    public static void main(String[] args)
    {
        Person[] arr = new Person[3];

        arr[0] = new Person("홍길동", 29);
        arr[1] = new Person("전우치", 15);
        arr[2] = new Person("손오공", 37);

        Arrays.sort(arr);

        for(Person p : arr) 
            System.out.println(p);
    }
}