logo

Java의 제네릭

제네릭 수단 매개변수화된 유형 . 아이디어는 유형(정수, 문자열 등 및 사용자 정의 유형)이 메소드, 클래스 및 인터페이스에 대한 매개변수가 되도록 허용하는 것입니다. Generics를 사용하면 다양한 데이터 유형으로 작동하는 클래스를 생성할 수 있습니다. 매개변수화된 형식에서 작동하는 클래스, 인터페이스 또는 메서드와 같은 엔터티는 일반 엔터티입니다.

왜 제네릭인가?

그만큼 물체 다른 모든 클래스의 슈퍼클래스이며 객체 참조는 모든 객체를 참조할 수 있습니다. 이러한 기능에는 유형 안전성이 부족합니다. 제네릭은 이러한 유형의 안전 기능을 추가합니다. 나중에 예제에서 이러한 유형의 안전 기능에 대해 논의하겠습니다.



Java의 제네릭은 C++의 템플릿과 유사합니다. 예를 들어 HashSet, ArrayList, HashMap 등과 같은 클래스는 제네릭을 매우 잘 사용합니다. 제네릭 형식에 대한 두 가지 접근 방식에는 몇 가지 근본적인 차이점이 있습니다.

Java 제네릭의 유형

일반 방법: 일반 Java 메소드는 매개변수를 사용하고 작업을 수행한 후 일부 값을 반환합니다. 이는 일반 함수와 똑같습니다. 그러나 일반 메소드에는 실제 유형에 의해 인용되는 유형 매개변수가 있습니다. 이를 통해 일반적인 방법을 보다 일반적인 방식으로 사용할 수 있습니다. 컴파일러는 긴 개별 유형 캐스팅을 수행할 필요가 없기 때문에 프로그래머가 쉽게 코딩할 수 있도록 안전한 유형을 관리합니다.

일반 클래스: 제네릭 클래스는 제네릭이 아닌 클래스와 똑같이 구현됩니다. 유일한 차이점은 유형 매개변수 섹션이 포함되어 있다는 것입니다. 쉼표로 구분된 두 가지 이상의 매개변수 유형이 있을 수 있습니다. 하나 이상의 매개변수를 허용하는 클래스를 매개변수화된 클래스 또는 매개변수화된 유형이라고 합니다.



일반 클래스

C++와 마찬가지로 일반 클래스 생성 시 매개변수 유형을 지정하는 데 사용됩니다. 일반 클래스의 객체를 생성하려면 다음 구문을 사용합니다.

// To create an instance of generic class BaseType obj = new BaseType ()>

메모: Parameter 유형에서는 'int', 'char' 또는 'double'과 같은 기본 형식을 사용할 수 없습니다.

자바






// Java program to show working of user defined> // Generic classes> // We use to specify Parameter type> class> Test {> >// An object of type T is declared> >T obj;> >Test(T obj) {>this>.obj = obj; }>// constructor> >public> T getObject() {>return> this>.obj; }> }> // Driver class to test above> class> Main {> >public> static> void> main(String[] args)> >{> >// instance of Integer type> >Test iObj =>new> Test(>15>);> >System.out.println(iObj.getObject());> >// instance of String type> >Test sObj> >=>new> Test(>'GeeksForGeeks'>);> >System.out.println(sObj.getObject());> >}> }>

>

>

산출

15 GeeksForGeeks>

Generic 클래스에서 여러 Type 매개변수를 전달할 수도 있습니다.

자바

파이썬 경로 설정




// Java program to show multiple> // type parameters in Java Generics> // We use to specify Parameter type> class> Test> {> >T obj1;>// An object of type T> >U obj2;>// An object of type U> >// constructor> >Test(T obj1, U obj2)> >{> >this>.obj1 = obj1;> >this>.obj2 = obj2;> >}> >// To print objects of T and U> >public> void> print()> >{> >System.out.println(obj1);> >System.out.println(obj2);> >}> }> // Driver class to test above> class> Main> {> >public> static> void> main (String[] args)> >{> >Test obj => >new> Test(>'GfG'>,>15>);> >obj.print();> >}> }>

>

>

산출

GfG 15>

일반 기능:

또한 제네릭 메서드에 전달된 인수 유형에 따라 다양한 유형의 인수로 호출할 수 있는 제네릭 함수를 작성할 수도 있습니다. 컴파일러는 각 메서드를 처리합니다.

자바

리눅스의 grep 명령




// Java program to show working of user defined> // Generic functions> class> Test {> >// A Generic method example> >static> >void> genericDisplay(T element)> >{> >System.out.println(element.getClass().getName()> >+>' = '> + element);> >}> >// Driver method> >public> static> void> main(String[] args)> >{> >// Calling generic method with Integer argument> >genericDisplay(>11>);> >// Calling generic method with String argument> >genericDisplay(>'GeeksForGeeks'>);> >// Calling generic method with double argument> >genericDisplay(>1.0>);> >}> }>

>

>

산출

java.lang.Integer = 11 java.lang.String = GeeksForGeeks java.lang.Double = 1.0>

제네릭은 참조 유형에서만 작동합니다.

제네릭 유형의 인스턴스를 선언할 때 유형 매개변수에 전달된 유형 인수는 참조 유형이어야 합니다. 다음과 같은 기본 데이터 유형을 사용할 수 없습니다. 정수 , 숯.

Test obj = new Test(20);>

위 줄은 기본 유형을 캡슐화하기 위해 유형 래퍼를 사용하여 해결할 수 있는 컴파일 시간 오류를 발생시킵니다.

그러나 기본 유형 배열은 참조 유형이므로 유형 매개변수에 전달될 수 있습니다.

ArrayList a = new ArrayList();>

일반 유형은 유형 인수에 따라 다릅니다.

다음 Java 코드를 고려하십시오.

자바




// Java program to show working> // of user-defined Generic classes> // We use to specify Parameter type> class> Test {> >// An object of type T is declared> >T obj;> >Test(T obj) {>this>.obj = obj; }>// constructor> >public> T getObject() {>return> this>.obj; }> }> // Driver class to test above> class> Main {> >public> static> void> main(String[] args)> >{> >// instance of Integer type> >Test iObj =>new> Test(>15>);> >System.out.println(iObj.getObject());> >// instance of String type> >Test sObj> >=>new> Test(>'GeeksForGeeks'>);> >System.out.println(sObj.getObject());> >iObj = sObj;>// This results an error> >}> }>

>

>

산출:

error: incompatible types: Test cannot be converted to Test>

iObj와 sObj는 Test 유형이지만 유형 매개변수가 다르기 때문에 서로 다른 유형에 대한 참조입니다. 제네릭은 이를 통해 유형 안전성을 추가하고 오류를 방지합니다.

Java Generics의 유형 매개변수

제네릭을 철저하게 배우려면 유형 매개변수 명명 규칙이 중요합니다. 일반적인 유형 매개변수는 다음과 같습니다.

60의 10%
  • T – 유형
  • E – 요소
  • K – 열쇠
  • N – 숫자
  • V – 가치

제네릭의 장점:

Generics를 사용하는 프로그램은 제네릭이 아닌 코드에 비해 많은 이점을 제공합니다.

1. 코드 재사용: 메소드/클래스/인터페이스를 한 번만 작성하면 원하는 모든 유형에 사용할 수 있습니다.

2. 유형 안전: 제네릭은 런타임보다 컴파일 타임에 오류가 나타나도록 합니다(런타임에 코드가 실패하도록 만드는 것보다 컴파일 타임에 코드의 문제를 아는 것이 항상 더 좋습니다). 학생의 이름을 저장하는 ArrayList를 만들고 싶다고 가정하고 프로그래머가 실수로 문자열 대신 정수 개체를 추가하면 컴파일러가 이를 허용합니다. 그러나 ArrayList에서 이 데이터를 검색하면 런타임에 문제가 발생합니다.

자바




// Java program to demonstrate that NOT using> // generics can cause run time exceptions> import> java.util.*;> class> Test> {> >public> static> void> main(String[] args)> >{> >// Creatinga an ArrayList without any type specified> >ArrayList al =>new> ArrayList();> >al.add(>'Sachin'>);> >al.add(>'Rahul'>);> >al.add(>10>);>// Compiler allows this> >String s1 = (String)al.get(>0>);> >String s2 = (String)al.get(>1>);> >// Causes Runtime Exception> >String s3 = (String)al.get(>2>);> >}> }>

>

>

출력 :

Exception in thread 'main' java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at Test.main(Test.java:19)>

제네릭은 이 문제를 어떻게 해결합니까?

ArrayList를 정의할 때 이 목록이 String 개체만 사용할 수 있도록 지정할 수 있습니다.

자바




// Using Java Generics converts run time exceptions into> // compile time exception.> import> java.util.*;> class> Test> {> >public> static> void> main(String[] args)> >{> >// Creating a an ArrayList with String specified> >ArrayList al =>new> ArrayList ();> >al.add(>'Sachin'>);> >al.add(>'Rahul'>);> >// Now Compiler doesn't allow this> >al.add(>10>);> >String s1 = (String)al.get(>0>);> >String s2 = (String)al.get(>1>);> >String s3 = (String)al.get(>2>);> >}> }>

지도 자바

>

>

산출:

15: error: no suitable method found for add(int) al.add(10); ^>

3. 개별 유형 캐스팅이 필요하지 않습니다. 제네릭을 사용하지 않으면 위의 예에서 ArrayList에서 데이터를 검색할 때마다 이를 타입캐스트해야 합니다. 모든 검색 작업에서 타입 캐스팅을 수행하는 것은 큰 골칫거리입니다. 목록에 문자열 데이터만 포함되어 있다는 것을 이미 알고 있다면 매번 이를 형변환할 필요가 없습니다.

자바




// We don't need to typecast individual members of ArrayList> import> java.util.*;> class> Test {> >public> static> void> main(String[] args)> >{> >// Creating a an ArrayList with String specified> >ArrayList al =>new> ArrayList();> >al.add(>'Sachin'>);> >al.add(>'Rahul'>);> >// Typecasting is not needed> >String s1 = al.get(>0>);> >String s2 = al.get(>1>);> >}> }>

>

>

4. Generics는 코드 재사용성을 촉진합니다. Java의 제네릭을 사용하면 다양한 유형의 데이터에 대해 작동하는 코드를 작성할 수 있습니다. 예를 들어,

int, char, String 등과 같은 다양한 데이터 유형의 배열 요소를 정렬하고 싶다고 가정해 보겠습니다.

기본적으로 우리는 다양한 데이터 유형에 대해 다양한 기능이 필요합니다.

단순화를 위해 버블 정렬을 사용하겠습니다.

하지만 사용하여 제네릭, 코드 재사용성 기능을 달성할 수 있습니다.

자바




public> class> GFG {> >public> static> void> main(String[] args)> >{> >Integer[] a = {>100>,>22>,>58>,>41>,>6>,>50> };> >Character[] c = {>'v'>,>'g'>,>'a'>,>'c'>,>'x'>,>'d'>,>'t'> };> >String[] s = {>'Virat'>,>'Rohit'>,>'Abhinay'>,>'Chandu'>,>'Sam'>,>'Bharat'>,>'Kalam'> };> >System.out.print(>'Sorted Integer array : '>);> >sort_generics(a);> >System.out.print(>'Sorted Character array : '>);> >sort_generics(c);> >System.out.print(>'Sorted String array : '>);> >sort_generics(s);> > >}> >public> static> extends Comparable>void sort_generics(T[] a) { //비원시 데이터 유형을 비교하므로 //Comparable 클래스를 사용해야 합니다. //버블 정렬 논리 for (int i = 0; i 1; i++) { for (int j = 0; j 1; j++) { if (a[j].compareTo(a[j + 1])> 0) { swap(j, j + 1, a); } } } // 정렬된 요소를 인쇄합니다 for (T i : a) { System.out.print(i + ', '); } System.out.println(); } public static void swap(int i, int j, T[] a) { T t = a[i]; a[i] = a[j]; a[j] = t; } }>

>

CSS 코멘트
>

산출

Sorted Integer array : 6, 22, 41, 50, 58, 100, Sorted Character array : a, c, d, g, t, v, x, Sorted String array : Abhinay, Bharat, Chandu, Kalam, Rohit, Sam, Virat,>

여기서는 제네릭 메서드를 만들었습니다. 이와 동일한 방법을 사용하여 정수 데이터, 문자열 데이터 등에 대한 작업을 수행할 수 있습니다.

5. 일반 알고리즘 구현: 제네릭을 사용하면 다양한 유형의 객체에 대해 작동하는 알고리즘을 구현할 수 있으며 동시에 유형에도 안전합니다.