Java 정리 - 9 (Object와 오버라이딩, java.lang 패키지/오토박싱, 스트링버퍼, 스트링 클래스의 문제점, Math, java.util 패키지, 컬렉션 프레임워크, Generic)

Minseol·2022년 8월 5일
0

Java 공부

목록 보기
10/12

Object와 오버라이딩

  • Object클래스는 모든 클래스의 최상위 클래스
  • 아무것도 상속받지 않으면 자동으로 Object를 상속
  • Object가 가지고 있는 메소드는 모든 클래스에서 다 사용할 수 있다는 것을 의미

가장 많이 쓰는 메소드 세 개 (반드시 Overriding 해야 함)
equals - 객체가 가진 값을 비교할 때 사용
toString - 객체가 가진 값을 문자열로 반환
hashCode - 객체의 해시코드 값 반환

java.lang 패키지/오토박싱

자바는 기본적으로 다양한 패키지를 지원, 그중에서 가장 중요한 패키지

  • java.lang패키지의 클래스는 import를 하지 않고도 사용할 수 있다.
  • java.lang패키지에는 기본형타입을 객체로 변환시킬때 사용하는 Wrapper클래스가 있다.
    (Boolean, Byte, Short, Integer, Long, Float, Double 클래스)
  • 모든 클래스의 최상위 클래스인 Object도 java.lang패키지
  • 문자열과 관련된 String, StringBuffer, StringBuilder도 모두 java.lang패키지
  • 화면에 값을 출력할때 사용했던 System클래스도 java.lang패키지
  • 수학과 관련된 Math클래스도 java.lang패키지
  • Thread와 관련된 중요 클래스들이 java.lang패키지
  • 이외에도 다양한 클래스와 인터페이스가 java.lang패키지에 속해 있다.
    public class WrapperExam {
        public static void main(String[] args) {
            int i = 5; 
            Integer i2 = new Integer(5);
            Integer i3 = 5;     //오토박싱
            int i4 = i2.intValue();
            int i5 = i2;       //오토언박싱
        }
    }

오토박싱(Auto Boxing)

기본 타입 데이터를 객체 타입의 데이터로 자동 형변환 시켜주는 기능
Integer i3 = 5; 숫자 5는 원래 기본형이지만 자동으로 Integer형태로 변환된다.

오토 언박싱(Auto unboxing)

오토박싱과 반대로 객체 타입의 데이터를 기본형 타입 데이터로 자동 형변환
int i5 = i2; Integer객체타입의 값을 기본형 int로 자동으로 변환되어 값을 할당한다.

  • 오토박싱(Auto Boxing), 오토 언박싱(Auto unboxing) 은 JAVA 5부터 지원한다. 이때 내부적으로 Wrapper클래스들이 사용된다.
public class WrapperExam {
    public static void main(String[] args) {
        int i = 5; 
        Integer i2 = new Integer(5);
        Integer i3 = 5;                      //오토박싱
        int i4 = i2;                         //오토언박싱
        long i2_long = i2.longValue();
        long i4_long = i4.longValue();       // 오류 발생!
    }
}

스트링버퍼

아무 값도 가지고 있지 않은 StringBuffer객체를 생성


    StringBuffer sb = new StringBuffer();
    // 해당 스트링 버퍼에 "hello", 공백, "world"를 차례대로 추가

    sb.append("hello");
    sb.append(" ");
    sb.append("world");
    // StringBuffer에 추가된 값을 toString()메소드를 이용하여 반환

    String str = sb.toString();
  • 출력결과 : hello world
    StringBuffer가 가지고 있는 메소드들은 대부분 자기 자신, this를 반환
    StringBuffer sb2 = new StringBuffer();
    StringBuffer sb3 = sb2.append("hello");
    if(sb2 == sb3){
        System.out.println("sb2 == sb3");
    }
  • 자기 자신의 메소드를 호출하여 자기 자신의 값을 바꿔나가는 것을 메소드체이닝 이라고 한다.
  • StringBuffer클래스는 메소드 체인 방식으로 사용할 수 있도록 만들어져 있다.
        String str2 = new StringBuffer().append("hello").append(" ").append("world").toString();
        System.out.println(str2);
  • 앞에서 5줄로 작성했던 코드를 위와 같이 한 줄로 수정할 수 있다.
  • StringBuffer는 append메소드 외에도 길이를 구하거나, 자르거나 등의 다양한 메소드들을 가지고 있다.

스트링 클래스의 문제점

String클래스는 문자열을 다룰 때 사용하는 클래스

String클래스는 불변클래스이다.

        String str1 = "hello world";
        String str2 = str1.substring(5);
        System.out.println(str1);
        System.out.println(str2);
  • 실행결과
    hello world
     world

  • substring메소드는 5번째 부터 문자열을 잘라서 새로운 문자열을 반환하는 메소드

  • 기존의 str1은 전혀 변화 없다.

String클래스를 사용할 때 가장 문제가 발생하는 경우는 다음과 같은 코드를 사용할 때이다.

    String str3 = str1 + str2;
    System.out.println(str3);
  • 실행결과
    hello world world

문자열과 문자열을 더하게 되면 내부적으로는 다음과 같은 코드가 실행

    String str4 = new StringBuffer().append(str1).append(str2).toString();
    System.out.println(str4);

문자열을 반복문 안에서 더하는 것은 성능상 문제가 생길 수 있으니 반드시 피하도록 하자. 객체가 여러번 생성되기 때문이다.
-> 처음부터 StringBuffer를 사용하자.

Class 클래스

자바의 모든 클래스와 인터페이스는 컴파일 후 class 파일이 생성됨

Class 클래스는 컴파일 된 class 파일을 로드하여 객체를 동적 로드하고, 정보를 가져오는 메서드가 제공됨

Class.forName("클래스 이름") 메서드로 클래스를 동적으로 로드 함

동적 로딩

컴파일 시에 데이터 타입이 binding 되는 것이 아닌, 실행(runtime) 중에 데이터 타입을 binding 하는 방법

프로그래밍 시에는 문자열 변수로 처리했다가 런타임시에 원하는 클래스를 로딩하여 binding 할 수 있다는 장점

컴파일 시에 타입이 정해지지 않으므로 동적 로딩시 오류가 발생하면 프로그램의 심각한 장애가 발생가능

클래스 정보 알아보기

reflection 프로그래밍 : Class 클래스를 사용하여 클래스의 정보(생성자, 변수, 메서드)등을 알 수 있고 인스턴스를 생성하고,
메서드를 호출하는 방식의 프로그래밍

로컬 메모리에 객체 없는 경우, 원격 프로그래밍, 객체의 타입을 알 수 없는 경우에 사용

java.lang.reflect 패키지에 있는 클래스를 활용하여 프로그래밍

일반적으로 자료형을 알고 있는 경우엔 사용하지 않음

Math

Math클래스는 이름 그대로 수학계산을 위한 클래스

코싸인, 싸인, 탄젠트, 절대값, 랜덤값을 구할 수 있는 클래스

  • Math클래스는 생성자가 private으로 되어 있기 때문에 new 연산자를 이용하여 객체를 생성할 수 없다.
  • 객체를 생성할 수는 없지만 모든 메소드와 속성이 static으로 정의되어 있기 때문에 객체를 생성하지 않고도 사용할 수 있다.
    public class MathExam {
        public static void main(String[] args) {
            int value1 = Math.max(5, 20);
            int value2 = Math.min(5, -5);
            int value3 = Math.abs(-10);
            double value4 = Math.random();
            double value5 = Math.sqrt(25);  
        }
    }

java.util 패키지

java.util패키지는 유용한 클래스들을 많이 가지고 있는 패키지

  • 날짜와 관련된 클래스인 Date, Calendar클래스
  • 자료구조와 관련된 컬렉션 프레임워크와 관련된 인터페이스와 클래스
  • deprecated란 더이상 지원하지 않으니 사용하지 않는 것이 좋다란 의미다.
  • Date클래스는 지역화를 지원하지 않는다. 지역화란 국가별로 현재 날짜와 시간은 다를 수 있는데, 그 부분을 지원하지 못한다.
  • 이런 문제를 해결하기 위하여 나온 클래스가 Calendar클래스. Calendar클래스는 자바 1.1에 등장하였다.
  • 지역화와 관련된 클래스들은 Locale로 시작되는 이름을 가진 클래스들이다. 역시 1.1 이후에 등장한다.
  • List, Set, Collection, Map은 자료구조 즉 컬렉션 프레임워크와 관련된 인터페이스

객체 배열을 구현한 클래스 ArrayList

java.util 패키지에서 제공되는 ArrayList

기존의 배열 선언과 사용 방식은 배열의 길이를 정하고 요소의 개수가 배열의 길이보다 커지면 배열을 재할당하고 복사해야 했음

배열의 요소를 추가하거나 삭제하면 다른 요소들의 이동에 대한 구현을 해야 함

ArrayList는 객체 배열을 좀 더 효율적으로 관리하기 위해 자바에서 제공해 주는 클래스

이미 많은 메서드들이 최적의 알고리즘으로 구현되어 있어 각 메서드의 사용 방법만 익히면 유용하게 사용할 수 있음

ArrayList의 주요 메서드

import java.util.ArrayList;
import ch21.Book;

public class ArrayListTest {

	public static void main(String[] args) {

		ArrayList<Book> library = new ArrayList<Book>();
		
		library.add(new Book("태백산맥1", "조정래"));
		library.add(new Book("태백산맥2", "조정래"));
		library.add(new Book("태백산맥3", "조정래"));
		library.add(new Book("태백산맥4", "조정래"));
		library.add(new Book("태백산맥5", "조정래"));
		
		for(int i =0; i<library.size(); i++) {
			library.get(i).showBookInfo();
		}
	}
}

컬렉션 프레임워크

java.util패키지에는 자료를 다룰 수 있는 자료구조 클래스가 다수 존재한다. 자료구조 클래스들을 컬렉션 프레임워크라고 한다.

  • 자료구조란 자료를 저장할 수 있는 구조
  • 책을 보관하기 위해서 책장을 이용하는 것처럼 다양한 자료들을 다양한 방식으로 관리하기 위한 방법이 필요한데, 이러한 방법을 제공하는 것을 자료구조, 컬렉션 프레임워크이다.

컬렉션 프레임워크에서 가장 기본이 되는 interface는 Collection인터페이스

  • Collection인터페이스는 여기에 자료가 있다라는 것을 표현.
  • 중복도 허용하고, 자료가 저장된 순서도 기억하지 못하는 것이 Collection인터페이스.
  • Collection이 가지고 있는 대표적인 메소드는 add(), size(), iterator() 메소드
  • Collection은 저장된 순서를 기억하지 못하기 때문에 "첫번째 자료를 달라, 두번째 자료를 달라"와 같은 기능을 가질 수 없다. * * Collection은 저장된 자료를 하나씩 하나씩 꺼낼 수 있는 Iterator라는 인터페이스를 반환한다.
  • Iterator는 꺼낼것이 있는지 없는지 살펴보는 hasNext()메소드와 하나씩 자료를 꺼낼때 사용하는 next()메소드를 가지고 있다.

Set자료구조는 중복을 허용하지 않는 자료구조를 표현하는 인터페이스

  • Collection인터페이스를 상속받는다.
  • Set인터페이스는 같은 자료가 있으면 false, 없으면 true를 반환하는 add메소드를 가지고 있다.

List자료구조는 중복은 허용하면서 순서를 기억하는 자료구조를 표현.

  • Set인터페이스와 마찬가지로 Collection인터페이스를 상속받고 있다.
  • List는 순서를 기억하고 있기 때문에 0번째 1번째 n번째의 자료를 꺼낼 수 있는 get(int)메소드를 가지고 있다.

Map자료구조는 Key와 Value를 가지는 자료구조이다.

  • 저장할 때 put()메소드를 이용하여 key와 value를 함께 저장한다.
  • 원하는 값을 꺼낼때는 key를 매개변수로 받아들이는 get()메소드를 이용하여 값을 꺼낸다.
  • Map에 저장되어 있는 모든 Key들은 중복된 값을 가지면 안된다.
  • Key의 이런 특징 때문에 Map은 자신이 가지고 있는 모든 Key들에 대한 정보를 읽어들일 수 있는 Set을 반환하는 keySet()메소드를 가지고 있다.

Generic

Box 클래스

    public class Box {
        private Object obj;
        public void setObj(Object obj){
        this.obj = obj;
        }

        public Object getObj(){
        return obj;
        }
    }

BoxExam 클래스

    public class BoxExam {
        public static void main(String[] args) {
            Box box = new Box();
            box.setObj(new Object());
            Object obj = box.getObj();

            box.setObj("hello");
            String str = (String)box.getObj();
            System.out.println(str);

            box.setObj(1);
            int value = (int)box.getObj();
            System.out.println(value);
        }
    }
  • Box는 매개변수로 Object를 하나 받아들이고, Object를 반환한다.
  • Object를 받아들일 수 있다는 것은 Object의 후손이라면 무엇이든 받아들일 수 있다는 것이다.

Java5에는 Generic이라는 문법이 사용됨으로써 인스턴스를 만들때 사용하는 타입을 지정하는 문법이 추가

Generic을 이용하여 Box 클래스 수정

    public class Box<E> {
        private E obj;
        public void setObj(E obj){
            this.obj = obj;
        }

        public E getObj(){
            return obj;
        }
    }
  • 클래스 이름 뒤에 < E >가 제네릭을 적용한 것이다. Box는 가상의 클래스 E를 사용한다는 의미.
  • Object를 받아들이고, 리턴하던 부분이 E로 변경. E는 실제로 존재하는 클래스는 아니다.

Generic을 이용하여 수정한 Box를 이용하는 BoxExam클래스

    public class BoxExam {
        public static void main(String[] args) {
            Box<Object> box = new Box<>();
            box.setObj(new Object());
            Object obj = box.getObj();

            Box<String> box2 = new Box<>();
            box2.setObj("hello");
            String str = box2.getObj();
            System.out.println(str);

            Box<Integer> box3 = new Box<>();
            box3.setObj(1);
            int value = (int)box3.getObj();
            System.out.println(value);
        }
    }
  • 참조타입에 < Object > , < String >, < Integer >가 있는 것을 볼 수 있다.
  • 첫번째는 Object를 사용하는 Box를 인스턴스로 만들겠다는 의미
  • 두번째는 String을 사용하는 Box인스턴스를 만들겠다는 의미
  • 세번째는 Integer를 사용하는 Box인스턴스를 만든다는 의미

Generic을 사용함으로써 선언할때는 가상의 타입으로 선언하고, 사용시에는 구체적인 타입을 설정함으로써 다양한 타입의 클래스를 이용하는 클래스를 만들 수 있다. Generic을 사용하는 대표적인 클래스는 컬렉션 프레임워크와 관련된 클래스이다.

<T extends 클래스> 사용하기

상위 클래스의 필요성

T 자료형의 범위를 제한할 수 있음

상위 클래스에서 선언하거나 정의하는 메서드를 활용할 수 있음

상속을 받지 않는 경우 T는 Object로 변환되어 Object 클래스가 기본으로 제공하는 메서드만 사용가능

T extends 를 사용한 프로그래밍

GenericPrinter에 material 변수의 자료형을 상속받아 구현

T에 무작위 클래스가 들어갈 수 없게 Material 클래스를 상속받은 클래스로 한정

public class GenericPrinter<T extends Material> {
	private T material;
	
	public void setMaterial(T material) {
		this.material = material;
	}
	
	public T getMaterial() {
		return material;
	}
	
	public String toString(){
		return material.toString();
	}
	
	public void printing() {
		material.doPrinting();
	}
}
public class Powder extends Material{
		
	public void doPrinting() {
		System.out.println("Powder 재료로 출력합니다");
	}
	
	public String toString() {
		return "재료는 Powder 입니다";
	}
}

제네릭 메서드 활용하기

제네릭 메서드란?

  • 자료형 매개변수를 메서드의 매개변수나 반환 값으로 가지는 메서드는 자료형 매개 변수가 하나 이상인 경우도 있음
  • 제네릭 클래스가 아니어도 내부에 제네릭 메서드는 구현하여 사용할 수 있음
  • public <자료형 매개 변수> 반환형 메서드 이름(자료형 매개변수.....) { }
public class Point<T, V> {
	
	T x;
	V y;
	
	Point(T x, V y){
		this.x = x;
		this.y = y;
	}
	
	public  T getX() {
			return x;
	}

	public V getY() {
		return y;
    }
}
public class GenericMethod {

	public static <T, V> double makeRectangle(Point<T, V> p1, Point<T, V> p2) {
		double left = ((Number)p1.getX()).doubleValue();
		double right =((Number)p2.getX()).doubleValue();
		double top = ((Number)p1.getY()).doubleValue();
		double bottom = ((Number)p2.getY()).doubleValue();
		
		double width = right - left;
		double height = bottom - top;
		
		return width * height;
	}
	
	public static void main(String[] args) {
		
		Point<Integer, Double> p1 = new Point<Integer, Double>(0, 0.0);
		Point<Integer, Double> p2 = new Point<>(10, 10.0);
		
		double rect = GenericMethod.<Integer, Double>makeRectangle(p1, p2);
		System.out.println("두 점으로 만들어진 사각형의 넓이는 " + rect + "입니다.");
	}
}
profile
귀여운 설이에양

0개의 댓글