java generics tutorial with examples
Java Generics는 데이터 유형에 관계없이 코드를 작성할 수있는 기능 세트입니다. 이 기사에서는 예제와 함께 Java Generics에 대해 자세히 설명합니다.
Generics는 Java의 중요한 기능 중 하나이며 Java 5부터 도입되었습니다.
정의에 따라 Generics는 프로그래머가 Generic 유형 및 함수를 사용하여 유형 안전성을 보장 할 수있는 Java 언어 기능 세트입니다.
학습 내용 :
제네릭은 Java에서 어떻게 작동합니까?
이전에 C ++로 작업 한 적이 있다면 Java Generics는 C ++의 템플릿과 동일합니다. Java Generics를 사용하면 기본 데이터 유형의 값을 갖는 클래스 / 메서드 정의에 매개 변수를 포함 할 수 있습니다.
예를 들어, 다음과 같이 Generic 클래스 'Array'를 가질 수 있습니다.
클래스 어레이 {….}
매개 변수화 된 유형은 어디에 있습니까?
다음으로 다음과 같이이 클래스에 대한 개체를 만들 수 있습니다.
Array int_array = new Array () Array char_array = new Array ();
따라서 Generic 매개 변수화 된 클래스가 주어지면 매개 변수로 데이터 유형이 다른 동일한 클래스의 객체를 만들 수 있습니다. 이것이 Java Generics 사용의 주요 본질입니다.
마찬가지로 배열을 정렬하기 위해 매개 변수화 된 유형을 사용하여 제네릭 메소드를 작성한 다음이 메소드를 모든 기본 유형으로 인스턴스화 할 수 있습니다.
Java Generics는 대부분 Java의 컬렉션 프레임 워크와 함께 사용됩니다. LinkedList, List, Map, HashMap 등과 같은 다른 컬렉션은 구현을 위해 Generics를 사용합니다. 제네릭은 유형 검사가 컴파일 타임에 수행되므로 유형 안전성을 제공하여 코드를보다 안정적으로 만듭니다.
이제 Generic 클래스와 메서드 및 기타 관련 주제에 대해 자세히 살펴 보겠습니다.
일반 클래스
Generic 클래스는 클래스 이름 뒤에 꺾쇠 괄호로 묶인 유형이 오는 것을 제외하고 일반 클래스와 동일합니다.
Generic 클래스의 일반적인 정의는 다음과 같습니다.
class class_name
{
클래스 변수;
… ..
클래스 메서드;
}
클래스가 정의되면 다음과 같이 원하는 데이터 유형의 개체를 만들 수 있습니다.
class_name obj = new class_name ();
예를 들어, Integer 객체의 경우 선언은 다음과 같습니다.
Xbox One 용 가상 현실 헤드셋
class_name obj = new class_name;
마찬가지로 문자열 데이터 유형의 경우 객체는 다음과 같습니다.
class_name str_Obj = new class_name;
Generic 클래스의 구현 예가 아래에 나와 있습니다.
class MyGenericClass { T obj; void add(T obj) { this.obj=obj; } T get() { return obj; } } class Main { public static void main(String args[]) { MyGenericClass m_int=new MyGenericClass(); m_int.add(2); MyGenericClassmstr=new MyGenericClass(); mstr.add('SoftwaretestingHelp'); System.out.println('Member of MyGenericClass:' + m_int.get()); System.out.println('Member of MyGenericClass:' + mstr.get()); } }
산출:
위 프로그램에서 MyGenericClass 클래스는 일반 클래스입니다. 두 가지 방법 즉, 추가 및 가져 오기가 있습니다. add 메소드는 일반 객체를 초기화하고 get 메소드는 객체를 반환합니다.
main 함수에서 Integer와 String 유형의 두 객체를 각각 선언합니다. add 메서드를 사용하여 이러한 개체를 각각의 초기 값으로 초기화 한 다음 get 메서드를 사용하여 이러한 개체의 내용을 출력합니다.
위의 Generic 클래스 예제에는 하나의 유형 매개 변수가 있습니다. 그러나 실제로 클래스는 둘 이상의 유형 매개 변수도 가질 수 있습니다. 이 경우 유형 매개 변수는 쉼표로 구분됩니다.
다음 예제는이를 보여줍니다.
classTest_Generics { T1 obj1; // An object of type T1 T2 obj2; // An object of type T2 // constructor to initialise T1 & T2 objects Test_Generics(T1 obj1, T2 obj2) { this.obj1 = obj1; this.obj2 = obj2; } public void print() { System.out.println('T1 Object:' + obj1); System.out.println('T2 Object:' + obj2); } } class Main { public static void main (String[] args) { Test_Genericsobj = newTest_Generics('Java Generics', 1); obj.print(); } }
산출:
이 프로그램에는 T1과 T2의 두 가지 유형 매개 변수가 있습니다. 멤버 객체를 초기화하고 내용을 인쇄하는 기능이 있습니다. 메인 함수에서 우리는 String과 Integer라는 두 가지 유형으로 객체를 선언합니다. 프로그램의 출력은 생성 된 개체의 내용을 보여줍니다.
클래스와 마찬가지로 Generic 인터페이스도 가질 수 있습니다. 인터페이스에 대한 모든 내용은 별도의 주제에서 배웁니다.
자바 일반 메소드
Generic 클래스와 인터페이스를 가질 수있는 것처럼 전체 클래스가 Generic이 될 필요가없는 경우 Generic 메서드도 사용할 수 있습니다.
다음 프로그램은 Generic 메소드“printGenericArray”의 구현을 보여줍니다. 주 함수의 메서드 호출에 유의하십시오. 여기에서는 Generic 메서드를 두 번 호출합니다. 처음에는 유형을 사용한 다음 유형을 사용합니다.
public class Main{ public static void printGenericArray(T[] items) { for ( T item : items){ System.out.print(item + ' '); } System.out.println(); } public static void main( String args[] ) { Integer[] int_Array = { 1, 3, 5, 7, 9, 11 }; Character[] char_Array = { 'J', 'A', 'V', 'A', 'T','U','T','O','R','I','A', 'L','S' }; System.out.println( 'Integer Array contents:' ); printGenericArray(int_Array ); System.out.println( 'Character Array contents:' ); printGenericArray(char_Array ); } }
산출:
경계 유형 매개 변수
Generics의 데이터 유형을 제한하려는 경우 경계 유형 매개 변수가 그림에 나타납니다. 예를 들어, 특정 제네릭 클래스 나 메서드 또는 숫자 데이터 유형에 대해서만 작동하는 인터페이스를 원할 경우 'extends'키워드를 사용하여 지정할 수 있습니다.
이것은 아래와 같습니다.
List myList = new ArrayList(); List list1 = new ArrayList();
위의 두 선언은 Long 및 Integer가 Number의 하위 클래스이므로 컴파일러에서 허용됩니다.
그러나 다음 선언은 문제가 될 것입니다.
List list = new ArrayList();
문자열이 숫자가 아니기 때문에 컴파일 타임 오류가 발생합니다. 위의 예에서‘?’기호는 와일드 카드라고하며 다음에 설명하겠습니다.
따라서 일반적으로 제한된 유형 매개 변수는 제네릭 코드에서 사용할 데이터 유형을 제한하려는 경우 주로 사용됩니다.
Java Generics 와일드 카드
Java에서 와일드 카드는 알 수없는 유형을 참조하는 데 사용되는 물음표‘?’로 표시됩니다. 와일드 카드는 대부분 제네릭과 함께 매개 변수 유형으로 사용됩니다.
일반 와일드 카드를 사용할 때는 객체가 다른 모든 클래스의 수퍼 클래스이지만 객체 컬렉션 ( 예를 들어, List)는 다른 모든 컬렉션의 수퍼 클래스가 아닙니다.
매개 변수 유형으로 사용되는 것 외에도 와일드 카드를 필드, 지역 변수 등으로 사용할 수 있습니다. 그러나 제네릭 메서드를 호출하거나 제네릭 클래스의 인스턴스를 생성하는 경우 와일드 카드를 수퍼 유형으로 사용하거나 유형 인수로 사용할 수 없습니다.
아래와 같이 매개 변수화 된 와일드 카드 유형의 예가 많이 있으며 (여기서는 하나 이상의 유형 인수가 와일드 카드 임) 다른 위치에서 사용되는 와일드 카드는 다르게 해석됩니다.
- 수집 <: 컬렉션은 사용 된 형식 인수에 관계없이 모든 컬렉션 인터페이스 인스턴스화를 나타냅니다.
- 명부 extends Number< : 목록은 요소 유형이 숫자가되는 모든 목록 유형을 나타냅니다.
- 비교기 : Stringsupertypes 인 유형 인수에 대한 모든 비교기 인터페이스 인스턴스화.
매개 변수가있는 와일드 카드 유형은 유효한 유형을 인식하기 위해 적용되는 규칙입니다. 구체적인 데이터 유형이 아닙니다. 일반 와일드 카드는 제한되거나 제한되지 않을 수 있습니다.
# 1) 무제한 와일드 카드
Unbounded Wildcards에서는 유형 변수에 대한 제한이 없으며 다음과 같이 표시됩니다.
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) 바인딩 된 와일드 카드
이미 제한된 유형에 대해 논의했습니다. 이들은 키워드 extends 또는 super를 사용하여 유형 매개 변수를 인스턴스화하는 데 사용되는 데이터 유형에 제한을 둡니다. 이러한 와일드 카드는 상한 와일드 카드와 하한 와일드 카드로 더 나눌 수 있습니다.
- 상한 와일드 카드
일반 표현식이 주어진 유형의 모든 서브 클래스에 유효하도록하려면 extends 키워드를 사용하여 Upper Bounded Wildcard를 지정합니다.
예를 들어, List, List 등을 지원하는 일반 메서드가 필요하다고 가정하면 다음과 같이 Upper Bounded Wildcard를 지정할 수 있습니다. 명부 . Number는 수퍼 클래스이므로이 일반 메서드는 모든 하위 클래스에서 작동합니다.
다음 프로그램이이를 보여줍니다.
importjava.util.*; public class Main { private static Number summation (List numbers){ double sum = 0.0; for (Number n : numbers) sum += n.doubleValue(); return sum; } public static void main(String[] args) { //Number subtype : Integer Listint_list = Arrays.asList(1,3,5,7,9); System.out.println('Sum of the elements in int_list:' + summation(int_list)); //Number subtype : Double List doubles_list = Arrays.asList(1.0,1.5,2.0,2.5,3.0,3.5); System.out.println('Sum of the elements in doubles_list:' + summation(doubles_list)); } }
산출:
여기서 우리는 함수“summation”의 유형 인수에 상한 와일드 카드 인 List를 제공했습니다. 주 함수에서 우리는 두 개의 목록, 즉 Integer 유형의 int_list와 Double 유형의 doubles_list를 정의합니다. Integer와 Double은 Number의 하위 클래스이므로 함수 합계는이 두 목록에서 완벽하게 작동합니다.
- 하한 와일드 카드
일반 표현식이 특정 유형의 모든 수퍼 클래스를 허용하도록하려면 유형 인수에 대해 하한 와일드 카드를 지정할 수 있습니다.
이에 대한 구현 예는 다음과 같습니다.
importjava.util.*; class Main { public static void main(String[] args) { //Integer List ListInt_list= Arrays.asList(1,3,5,7); System.out.print('Integer List:'); printforLowerBoundedWildcards(Int_list); //Number list ListNumber_list= Arrays.asList(2,4,6,8); System.out.print('Number List:'); printforLowerBoundedWildcards(Number_list); } public static void printforLowerBoundedWildcards(List list) { System.out.println(list); } }
산출:
이 프로그램에서 지정된 하한 와일드 카드는 '목록'입니다. 그런 다음 주 함수에는 유형 목록과 목록이 있습니다. Lower Bounded Wildcard를 사용했듯이 Number 클래스는 Integer의 수퍼 클래스가 유효한 형식 인수입니다.
Java Generics의 장점
# 1) 유형 안전성
제네릭은 유형 안전성을 보장합니다. 이는 유형 검사가 런타임이 아닌 컴파일 시간에 수행됨을 의미합니다. 따라서 올바른 유형이 사용되므로 런타임 중에 'ClassCastException'이 발생할 가능성이 없습니다.
importjava.util.*; class Main { public static void main(String[] args) { List mylist = new ArrayList(); mylist.add(10); mylist.add('10'); System.out.println(mylist); List list = new ArrayList(); list.add(10); list.add('10');// compile-time error System.out.println(list); } }
위 프로그램에는 제네릭이없는 목록과 제네릭이있는 목록이 있습니다. 비 일반 목록에는 유형 안전성이 없습니다. 정수, 문자열 등을 요소로 추가 할 수 있으며 허용됩니다.
일반 목록에서 일반 표현식에 지정된 한 가지 유형의 요소 만 추가 할 수 있습니다. 다른 유형의 요소를 추가하려고하면 컴파일시 오류가 발생합니다.
위의 프로그램에서 컴파일 타임 오류는 다음 줄에 표시됩니다.
list.add('10');
# 2) 코드 재사용 성
Generics를 사용하면 각 데이터 유형에 대해 별도의 코드를 작성할 필요가 없습니다. 단일 클래스 또는 메서드 등을 작성하고 모든 데이터 유형에 사용할 수 있습니다.
# 3) Typecasting 필요 없음
Generics를 사용할 때 컴파일러는 사용 된 유형에 대해 알고 있으므로 유형 변환이 필요하지 않습니다.
아래 코드를 고려하십시오.
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
일반 목록이 언제 사용되는지 알 수 있듯이 위의 mystr에서 수행되는 방식과 같이 목록 요소를 적절한 유형으로 형변환해야합니다.
이제 일반 목록을 사용하여 동일한 코드를 다시 작성하겠습니다.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
여기에서는 목록 선언에 대한 일반 표현식으로 문자열 유형을 지정했습니다. 따라서이 목록의 개별 요소를 검색하기 위해 유형 변환이 필요하지 않습니다.
# 4) 일반 알고리즘 구현
Generics를 사용하여 코딩 할 때 훨씬 더 많은 Generic 알고리즘을 구현할 수 있습니다.
안드로이드를위한 최고의 무료 음악 다운로더 앱은 무엇입니까
# 5) 컴파일 시간 검사
이미 언급했듯이 Java 프로그램에서 Generics를 사용할 때 컴파일러는 컴파일 시간에 유형을 확인하여 런타임에 프로그램의 비정상 종료를 방지합니다.
자주 묻는 질문
Q # 1) Java에서 Generics를 사용하는 이유는 무엇입니까?
대답: 제네릭은 유형 독립성을 보장합니다. 즉, 클래스 / 인터페이스 / 메서드 등을 정의하는 동안 유형 매개 변수를 제공 할 수 있으므로 실제 인스턴스화 중에 실제 유형을 지정할 수 있습니다. 이런 식으로 코드 재사용 성을 제공합니다.
Q # 2) Java에서 Generics가 중요합니까?
대답: 예. 사실 Generics는 타입 안전성, 즉 컴파일 타임 타입 검사를 보장하기위한 Java의 가장 중요한 기능입니다.
Q # 3) Java는 언제 Generics를 추가 했습니까?
대답: 제네릭은 Java에서 컴파일 타임 유형 안전성을 보장하기 위해 2004 년 J2SE 5.0과 함께 Java에 추가되었습니다.
Q # 4) 일반 유형이란 무엇입니까?
대답: Generic 유형은 유형 매개 변수와 함께 제공되는 Generic 클래스, 인터페이스 또는 메소드입니다. 이를 통해 유형 안전성 및 코드 재사용이 가능합니다.
Q # 5) Java에서 Array와 Generics를 사용할 수 있습니까?
대답: 아니요. Java는 일반 배열을 허용하지 않습니다.
결론
이것으로 최신 Java 버전에서 가장 중요한 기능 중 하나로 간주되는 Java 제네릭에 대한 자습서를 마칩니다. Java 프로그램에서 Generics를 사용하면 유형 안전성과 코드 재사용이 보장됩니다. 또한 프로그램이 런타임에 중단되지 않도록 컴파일 타임 검사를 보장합니다.
Java 제네릭은이 시리즈의 다른 자습서에서 자세히 설명 할 Java 컬렉션 인터페이스와 함께 주로 유용합니다.
행복한 독서 !!