본문 바로가기

issue & tip

래퍼클래스와 제네릭

반응형

래퍼클래스

자바에서는 참조형 값만 받는다고 정의되어 있으면 기본 자료형을 이용할 수 없는 경우도 있다.

이때 기본자료형을 클래스로 변환해야 한다.

자바에선 이런한 경우를 대응하고자 래퍼클래스라는 기본 자료형을 나타내는 클래스가 각각 준비되어있다.


byte - Byte

short - Short

int - Integer

long - Long

float - Float

double - Double

char - Character

boolean  - Boolean


기본 자료형과 래퍼 클래스의 변환은 자동으로 이루어진다.

단, 래퍼 클래스의 초기값은 null이 된다.

그래서 값을 설정하지 않으면 0이 아니라 null이 되므로 그때 자동으로 변환되면 예외가 발생한다.


상수

한번 대입한 값을 나중에 변경하고 싶지 않을 때 final 제한자를 붙여 다시 대입을 금지하는 방법

대시 대입할 수 없는 데이터를 상수



비교연산


주로 기본 자료형 비교에 사용

참조형일  경우 비교 연산자로 비교하면 인스턴스 값을 비교하지 않고 데이터의 참조 주소를 비교해 의도대로 값을 비교할 수 없다.

참조형의 값을 비교할 때는 equals 메서드나 compareTo 메서드를 사용


String(문자열) 비교

문자열의 경우 ""로 에워싼 같은 문자열 끼리 == 연산자로 비교하면 결과는 true

문자열을 내부에서 관리해 이미 정의된 문자열이 있을 때 그 문자열의 주소를 지정하도록 제어한다.


하지만 String의 생성자를 통해 만들어진 문자열은 내부에서 관리하는 문자열과 별도로 새로 인스턴스를 생성한다.

결과적으로 참조 주소도 달라진다.


자료형비교(instanceof 연산자)

자바에서 대상 데이터가 지정한 자료형의 인스턴스인지 확인하는 instanceof 연산자를 제공


조건

지정한 클래스

지정한 클래스를 상속한 클래스

지정한 인터페이스를 구현한 클래스


결과 true로 반환



제네릭

클래스 내부에서 사용할 자료형을 정의해 타입 세이프(타입 안정성)을 구현하는 기능이다.

제네릭은 List, Map, Set 등 컬렉션과 깊은 관련이 있다.


제네릭은 자바5부터 도입


제네릭 전

List list = new ArrayList();


list.add(13);


int num = (Integer)list.get(0);


제네릭 후

List<Integer> list = new ArrayList();


list.add(13);


int num = list.get(0);


<자료형>을 기술하여 ArrayList는 지정한 자료형만 삽입할 수 있는 리스트가 된다.

지정하는 자료형은 int, double등의 기본 자료형이 아닌 래퍼클래스 즉, 참조형이다.


제니릭을 도입전후의 기술 방식을 비교하면 도입 전에는 값을 추출할때 타입 캐스팅(type casting 형변환)을 했다.

형변환이란 앞에(자료형)을 지정해 형을 변환하는 기능.

add 메서드로 지정한 값은 모두 Object형이 되기때문에 저장할 때와 같은 형이 되게 추출하려면 자료형을 변환해야 한다.


형변환은 다른 형의 값을 자신이 지정한 형으로 추출해주는 편리한 기능이지만, 리스트에서 값을 추출 할때는 주의해야한다.

값을 저장할때 형을 지정하지 않는다.

즉, 어떤 형이라도 저장할 수 있다는 뜻이다.


List integerList = new ArrayList();

integerList.add(13);


integerList.add("사과");


int num = (Integer)integerList.get(0);


int frutis = (Integer)integerList.get(1); //형변환 오류


컴파일시 감지되지 않고 실행시 감지된다.

잠재적인 결함을 포함한 된다.


이러한 형변환 오류 문제 때문에 제네릭과 같은 형을 지정하는 기능이 필요해졌다.

제네릭에서는 저장할 값의 형이 미리 정해지므로 다른 값을 저장하면 컴파일시 오류가 발생한다.


타입 세이프

제네릭으로 형을 지정하면 컬렉션에 다른 형값이 저장되는 것을 컴파일시 발견할 수 있다.

형을 지정해 형변환 문제를 방지할 수 있는 상태를 타입 세이프라고 한다.


제네릭은 컬렉션 클래스만을 위한 기능이 아니다.

직접 만든 클래스에서도 사용할 수 있다.

public class GenericsSample<E> {

private E object;


public E getObject() {

return this.object;

}


public void setObject(E object) {

this.object = object;

}

}


클래스 정의에 < ~ > 형식으로 E라는 알파벳이 명시되고, 똑같이 메서드와 필드의 형에도 E라는 알파벳이 쓰여 있다.

E 부분은 나중에 이용자 쪽에서 결정할 수 있는 자유로운 형을 나타낸다.


public class Main {

public static void main(String[] args) {

GenericsSample<String> generic = new GenericsSample<String>();


generic.setObject("안녕");


System.out.println(generic.getObject());

}

}



클래스의 인스턴스를 생성할때 <String>으로 선언한다.


public class GenericsSample<String> {

private String object;


public String getObject() {

return this.object;

}


public void setObject(String object) {

this.object = object;

}

}


E였던 형이 String으로 치환됐다.


제네릭을 클래스 정의에 사용함으로써 클래스 정의 안에서 이용하는 형을 인스턴스를 생성할때 지정할 수 있게 된다.

이때 E를 형식 매개변수 type parameter라고 한다.

관례적으로 형식 매개 변수의 이름은 E로 한다.



람다식

자바 8에서 새로 추가된 람다식


람다식 기본 구문

(자료형 인수, ...) -> {...임의의 처리 ...}


public class LambdaSample {

public static void main(String[] args) {

// 처리를 람다식으로 구현한다.

InterfaceSample lambda = (String name) -> {

System.out.println(name + "입니다.") ;

};


//구현한 처리를 사용한다.

lambda.sampleMethod("람다");

}

}


람다식으로 InterfaceSample이라는 인터페이스의 추상 메서드를 구현했다.


public interface InterfaceSample {

abstract void sampleMethod(String name);

}


결과

람다입니다.


일반적으로 인터페이스를 구현하려면 클래스를 만들고, 메서드를 정의하고 인스턴스로 만드는 과정이 필요하다.

람다식을 도입하면 이런 복잡한 과정을 간결하게 기술할 수 있다.


익명클래스

자바 7 이전에도 람다식 처럼 구현할 수 있었다.

익명 클래스라는 구현방법을 사용했다.


익명클래스는 프로그램의 문 중간에 클래스를 선언할 수 있는 방법이다.

이 방법은 GUI(버튼이나 입력부품을 가진 그래픽 인터페이스) 소프트웨어를 작성할 때 사용했다.


public class AnonymousSample {

public static void main(String[] args) {

InterfaceSample anonymous = new InterfaceSample() {

public void sampelMethod(String name) {

System.out.println(name + "입니다");

}

};


anonymous.sampleMethod("람다");

}

}


코드양은 람다식으로 구현한 코드보다 익명 클래스쪽이 많다.


이렇게 람다식에서는 코드양을 줄이고, 프로그램을 읽기 쉽게 하는 장점이 있다.


람다식 사용

람다식 몇가지 패턴


람다식 기본



public class LambdaSample1 {

public static void main(String[] args) {

InterfaceSample1 lambda = (String name) -> {

 return name + "입니다.";

};


System.out.println(lambda.sampleMethod("람다"));

}

}


public interface InterfaceSample1 {

abstract String sampleMethod(String name);

}


생략기법: 형추론에 의한 생략

형 추론 (type interface)이라는 기능으로 람다식의 인수 부분에 지정한 형 지정을 생략


InterfaceSample lambda = (name) -> {

return name + "입니다";

};


형 추론이란 프로그래머가 형을 지정하지 않고 컴파일러가 인수의 형을 추정하는 기능이다.

이 프로그램에서는 인터페이스를 구현하고 있고 대상 인터페이스에는 String 형 인수를 가진 메서드가 하나 있다.

이를 바탕으로 컴파일러는 인수의 형을 String으로 추정한다.


생략기법: 인수가 하나인 경우의 생략


InterfaceSample lambda = name -> {

return name + "입니다";

};


생략기법: return 문만 있는 경우의 생략


InterfaceSample lambda = name -> name + "입니다";


출처-실무에서 바로 통하는 자바

반응형

'issue & tip' 카테고리의 다른 글

응집도  (0) 2018.05.09
파일 입출력  (0) 2018.04.25
부동소수점  (0) 2018.04.24
스레드  (0) 2018.04.24
문자열과 날짜  (0) 2018.04.24