Java Generics 예제 자습서 – 일반 메서드, 클래스, 인터페이스
Java Genrics는 Java 5에 도입 된 가장 중요한 기능 중 하나입니다.
Java Collections 및 버전 5 이상에서 작업 한 적이 있다면 사용해 보셨을 것입니다.
컬렉션 클래스가있는 Java의 제네릭은 매우 쉽지만 단순히 생성하는 것보다 훨씬 더 많은 기능을 제공합니다. 컬렉션 유형.
이 기사에서는 제네릭의 기능을 배우려고 노력할 것입니다. 전문 용어를 사용하면 제네릭을 이해하는 것이 때때로 혼란 스러울 수 있으므로 간단하고 이해하기 쉽게 유지하려고합니다.
Java의 Generics
Generics는 컴파일 타임 유형 검사를 제공하고 작업하는 동안 일반적이었던 ClassCastException
의 위험을 제거하기 위해 Java 5에 추가되었습니다. 컬렉션 클래스와 함께. 전체 컬렉션 프레임 워크는 형식 안전성을 위해 제네릭을 사용하도록 다시 작성되었습니다. 제네릭이 컬렉션 클래스를 안전하게 사용하는 데 어떻게 도움이되는지 살펴 보겠습니다.
위의 코드는 잘 컴파일되지만 요소 중 하나가 Integer 유형 인 반면 목록의 Object를 String으로 캐스팅하려고하기 때문에 런타임에 ClassCastException이 발생합니다. Java 5 이후에는 아래와 같은 컬렉션 클래스를 사용합니다.
목록 생성시 목록의 요소 유형이 String이되도록 지정했습니다. 따라서 목록에 다른 유형의 객체를 추가하려고하면 프로그램에서 컴파일 타임 오류가 발생합니다. 또한 for 루프에서는 목록에있는 요소의 유형 변환이 필요하지 않으므로 런타임에 ClassCastException을 제거합니다.
Java Generic Class
우리는 자체 클래스를 정의 할 수 있습니다. 제네릭 유형으로. 제네릭 유형은 유형에 대해 매개 변수화 된 클래스 또는 인터페이스입니다. 꺾쇠 괄호 (< >)를 사용하여 유형 매개 변수를 지정합니다.
이점을 이해하기 위해 다음과 같이 가정 해 보겠습니다. 다음과 같은 간단한 클래스가 있습니다.
이 클래스를 사용하는 동안 유형 캐스팅을 사용해야하며 런타임에 ClassCastException을 생성 할 수 있습니다. 이제 자바 제네릭 클래스를 사용하여 아래와 같은 클래스를 다시 작성합니다.
메인 메서드에서 GenericsType 클래스를 사용하는 것에 유의하십시오. 타입 캐스팅을 할 필요가 없으며 런타임에 ClassCastException을 제거 할 수 있습니다. 생성시 유형을 제공하지 않으면 컴파일러는 “GenericsType이 원시 유형입니다.
제네릭 유형 GenericsType에 대한 참조 < T >는 매개 변수화되어야합니다.”유형을 제공하지 않으면 유형이 Object
가되므로 두 문자열을 모두 허용합니다. 그러나 런타임 오류를 생성 할 수있는 원시 유형을 작업하는 동안 유형 캐스팅을 사용해야하므로 항상이를 피해야합니다.
또한 자바 오토 박싱을 지원한다는 점에 유의하세요.
Java Generic Interface
비교 가능한 인터페이스는 인터페이스에서 Generics의 훌륭한 예이며 다음과 같이 작성됩니다.
비슷한 방식으로 Java에서 일반 인터페이스를 만들 수 있습니다. Map 인터페이스에서와 같이 여러 유형 매개 변수가 있습니다. 매개 변수화 된 유형에도 매개 변수화 된 값을 제공 할 수 있습니다. 예를 들어 new HashMap<String, List<String>>();
는 유효합니다.
Java Generic Type
Java Generic Type Naming 규칙은 코드를 쉽게 이해하는 데 도움이되며 이름 지정 규칙을 갖는 것은 Java 프로그래밍 언어의 모범 사례 중 하나입니다. 따라서 제네릭에는 자체 명명 규칙도 있습니다. 일반적으로 유형 매개 변수 이름은 단일 대문자로 Java 변수와 쉽게 구별 할 수 있습니다. 가장 일반적으로 사용되는 유형 매개 변수 이름은 다음과 같습니다.
- E – 요소 (Java Collections Framework에서 광범위하게 사용됩니다 (예 : ArrayList, Set 등))
- K – 키 ( 지도에서 사용됨)
- N – 숫자
- T – 유형
- V – 값 (지도에서 사용됨)
- S, U, V 등 – 두 번째, 세 번째, 네 번째 유형
Java Generic Method
때로는 전체 클래스가 매개 변수화되는 것을 원하지 않습니다.이 경우 다음을 수행 할 수 있습니다. 자바 제네릭 메서드를 만듭니다. 생성자는 특별한 종류의 메소드이므로 생성자에서도 제네릭 유형을 사용할 수 있습니다.
다음은 자바 제네릭 메소드의 예를 보여주는 클래스입니다.
isEqual 메소드에 유의하세요. 메서드에서 제네릭 유형을 사용하는 구문을 보여주는 서명. 또한 Java 프로그램에서 이러한 메소드를 사용하는 방법에 주목하십시오. 이러한 메서드를 호출하는 동안 유형을 지정하거나 일반 메서드처럼 호출 할 수 있습니다. Java 컴파일러는 사용할 변수의 유형을 결정할만큼 똑똑합니다.이 기능을 유형 추론이라고합니다.
Java Generics Bounded Type Parameters
예를 들어 두 객체를 비교하는 메소드에서 매개 변수화 된 유형에서 사용할 수있는 객체 유형을 제한하고 싶다고 가정합니다. 허용 된 객체가 Comparable인지 확인하십시오. 경계 유형 매개 변수를 선언하려면 유형 매개 변수의 이름, extends 키워드, 상위 경계를 나열합니다 (아래 방법과 유사).
The 이러한 메서드의 호출은 Comparable이 아닌 클래스를 사용하려고하면 컴파일 타임 오류가 발생한다는 점을 제외하면 무제한 메서드와 유사합니다.
바운드 유형 매개 변수는 메서드와 함께 사용할 수 있습니다. 클래스 및 인터페이스.
Java Generics는 다중 경계도 지원합니다. 즉, < T는 A를 확장합니다. & B & C >. 이 경우 A는 인터페이스 또는 클래스가 될 수 있습니다. A가 클래스이면 B와 C는 인터페이스 여야합니다. 여러 경계에 둘 이상의 클래스를 가질 수 없습니다.
Java Generics and Inheritance
우리는 Java 상속을 통해 A가 B의 하위 클래스 인 경우 변수 A를 다른 변수 B에 할당 할 수 있습니다. 따라서 A의 모든 일반 유형이 B의 일반 유형에 할당 될 수 있다고 생각할 수 있지만 그렇지 않습니다. 간단한 프로그램으로 살펴 보겠습니다.
MyClass < String > 변수를 MyClass에 할당 할 수 없습니다. < Object > 변수는 관련이 없으므로 실제로 MyClass < T > parent는 Object입니다.
Java Generic Classes and Subtyping
일반 클래스 또는 인터페이스를 확장하거나 구현하여 하위 유형을 지정할 수 있습니다. 한 클래스 또는 인터페이스의 유형 매개 변수와 다른 유형 매개 변수 간의 관계는 extends 및 implements 절에 의해 결정됩니다.
유형 인수를 변경하지 않는 한 하위 유형 관계는 유지됩니다. 아래는 여러 유형 매개 변수의 예를 보여줍니다.
목록의 하위 유형 < 문자열 >는 MyList < String, Object >, MyList < String, Integer > 등.
Java Generics Wildcards
물음표 (?)는 제네릭의 와일드 카드이며 알 수없는 유형. 와일드 카드는 매개 변수, 필드 또는 지역 변수의 유형으로, 때로는 반환 유형으로 사용할 수 있습니다. 제네릭 메서드를 호출하거나 제네릭 클래스를 인스턴스화하는 동안에는 와일드 카드를 사용할 수 없습니다. 다음 섹션에서는 상한 와일드 카드, 하한 와일드 카드 및 와일드 카드 캡처에 대해 알아 봅니다.
9.1) Java Generics Upper Bounded Wildcard
Upper bounded wildcards are used to relax the 메서드의 변수 유형에 대한 제한. 목록에있는 숫자의 합계를 반환하는 메서드를 작성한다고 가정 해 보겠습니다. 따라서 구현은 다음과 같습니다.
이제 문제는 위의 구현은 List < Integer > 및 List
Double >는 관련이 없습니다. 상한 와일드 카드가 도움이되는 경우입니다. extends 키워드와 함께 제네릭 와일드 카드를 사용하고 상한 또는 하위 클래스 유형의 인수를 전달할 수있는 상한 클래스 또는 인터페이스를 사용합니다.
위 구현은 아래 프로그램과 같이 수정할 수 있습니다.
인터페이스 측면에서 코드를 작성하는 것과 비슷합니다. 위의 메서드에서는 상한 클래스 Number의 모든 메서드를 사용할 수 있습니다. 상한 목록을 사용하면 null을 제외한 어떤 객체도 목록에 추가 할 수 없습니다. sum 메소드 내의 목록에 요소를 추가하려고하면 프로그램이 컴파일되지 않습니다.
9.2) Java Generics Unbounded Wildcard
때로는 우리가 일반 메소드가 모든 유형과 함께 작동하기를 원합니다.이 경우 제한되지 않은 와일드 카드를 사용할 수 있습니다. <를 사용하는 것과 동일합니까? 개체를 확장합니다 >.
목록을 제공 할 수 있습니다. < String > 또는 List < Integer > 또는 기타 유형의 객체 목록 인수를 printData 메서드. 상한 목록과 마찬가지로 목록에 아무것도 추가 할 수 없습니다.
9.3) Java Generics Lower bounded Wildcard
메서드의 정수 목록에 정수를 추가한다고 가정하면 인수 유형을 List < Integer로 유지할 수 있습니다. >하지만 정수와 연결되지만 List < Number > 및 List < Object >도 정수를 보유 할 수 있으므로이를 위해 하한 와일드 카드를 사용할 수 있습니다. 이를 달성하기 위해 super 키워드 및 하한 클래스와 함께 제네릭 와일드 카드 (?)를 사용합니다.
하한 또는 하한의 모든 상위 유형을 인수로 전달할 수 있습니다.이 경우 Java 컴파일러는 하한을 추가 할 수 있습니다. 개체 유형을 목록에 바인딩했습니다.
Generics Wildcard를 사용한 하위 입력
Java Generics Type Erasure
Generics in Java는 컴파일시 유형 검사를 제공하기 위해 추가되었으며 런타임에는 사용되지 않으므로 Java 컴파일러는 유형 삭제 기능을 사용하여 바이트 코드에서 모든 제네릭 유형 검사 코드를 제거하고 필요한 경우 유형 캐스팅을 삽입합니다. 유형 삭제는 매개 변수화 된 유형에 대해 새 클래스가 생성되지 않도록합니다. 결과적으로 제네릭은 런타임 오버 헤드를 발생시키지 않습니다.
예를 들어 아래와 같은 제네릭 클래스가있는 경우
Java 컴파일러는 경계 유형 매개 변수 T를 첫 번째 경계 인터페이스 인 Comparable로 대체합니다. , 아래 코드와 같이 :
Generics FAQ
12.1) Java에서 Generics를 사용하는 이유는 무엇입니까?
Generics는 강력한 컴파일 타임 유형 검사를 제공하고 위험을 줄입니다. ClassCastException 및 명시 적 객체 캐스팅.
12.2) Generics에서 T는 무엇입니까?
< T 를 사용하여 일반 클래스, 인터페이스 및 메서드를 만듭니다. T는 사용할 때 실제 유형으로 대체됩니다.
12.3) Java에서 Generics는 어떻게 작동합니까?
Generic 코드는 유형 안전성을 보장합니다. 컴파일러는 런타임시 오버로드를 줄이기 위해 컴파일 타임에 모든 유형 매개 변수를 제거하기 위해 유형 삭제를 사용합니다.
Java의 제네릭 – 추가 자료
Java, Java의 제네릭에 대한 모든 것입니다. 제네릭은 정말 방대한 주제이며 효과적으로 이해하고 사용하려면 많은 시간이 필요합니다. 이 게시물은 제네릭에 대한 기본 세부 정보를 제공하고이를 사용하여 유형 안전성으로 프로그램을 확장하는 방법을 제공합니다.