English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java 기본 가이드

Java 流程控制

Java 数组

Java 面向对象(I)

Java 面向对象(II)

Java 面向对象(III)

Java 예외 처리

Java 列表(List)

Java Queue(队列)

Java Map集合

Java Set集合

Java 输入输出(I/O)

Java Reader/Writer

Java 其他主题

Java 제너릭

在本教程中,我们将通过示例了解Java泛型,如何创建泛型类和方法及其优势。

在Java中,제너릭有助于创建可与不同类型的对象(数据)一起使用的类,接口和方法。因此,允许我们重用我们的代码。

意:제너릭泛型不适用于基本类型(int,float,char等)。

如何使用Java泛型

要了解在Java中如何使用제너릭,我们可以使用ArrayListJava集合框架的类。

ArrayList类是泛型类的一个示例。我们可以使用ArrayList来存储任何类型的数据。例如

import java.util.ArrayList;
class Main {
   public static void main(String[] args) {
      //创建一个数组列表来存储Integer 数据
      ArrayList<Integer> list1 = new ArrayList<>();
      list1.add(4);
      list1.add(5);
      System.out.println("ArrayList of Integer: ") + list1);
      //创建数组列表来存储String 数据
      ArrayList<String> list2 = new ArrayList<>();
      list2.add("Four");
      list2.add("Five");
      System.out.println("ArrayList of String: ") + list2);
      //Double 데이터를 저장하기 위한 배열 목록을 생성했습니다.
      ArrayList<Double> list3 = new ArrayList<>();
      list3.add(4.5);
      list3.add(6.5);
      System.out.println("ArrayList of Double: ", + list3);
   }
}

출력 결과

ArrayList of Integer: [4, 5]
ArrayList of String: [Four, Five]
ArrayList of Double: [4.5, 6.5]

위 예제에서 Integer, String, Double 타입의 요소를 저장하기 위해 같은 ArrayList 클래스를 사용했습니다. 왜냐하면Java 제너릭, 이는 가능합니다.

이 줄을 주목하세요,

ArrayList<Integer> list1 = new ArrayList<>();

귀여운 괄호 <>에서 Integer를 사용했습니다. 괄호 <>는 제너릭에서타입 파라미터.

파라미터 type는 제너릭 클래스나 메서드가 적용할 수 있는 객체(데이터)의 타입을 지정합니다.

제너릭 클래스 생성

Java에서 제너릭의 작동 방식을 알았으므로, 자신의 제너릭 클래스를 어떻게 생성할지 보겠습니다.

예제: 제너릭 클래스 생성

class Main {
  public static void main(String[] args) {
    //정수 데이터로 제너릭 클래스를 초기화했습니다.
    GenericsClass<Integer> intObj = new GenericsClass<>(5);
    System.out.println("제너릭 클래스는 다음과 같이 반환합니다:", + intObj.getData());
    //문자 데이터로 제너릭 클래스를 초기화했습니다.
    GenericsClass<String> stringObj = new GenericsClass<>("Java Programming");
    System.out.println("제너릭 클래스는 다음과 같이 반환합니다:", + stringObj.getData());
  }
}
class GenericsClass<T> {
  //T 타입 변수
  private T data;
  public GenericsClass(T data) {
    this.data = data;
  }
  //T 타입 변수를 반환하는 메서드
  public T getData() {
    return this.data;
  }
}

출력 결과

제너릭 클래스는 다음과 같이 반환합니다: 5
제너릭 클래스는 다음과 같이 반환합니다: Java Programing

위 예제에서 GenericsClass라는 제너릭 클래스를 생성했습니다. 이 클래스는 어떤 타입의 데이터를 처리할 수 있습니다.

class GenericsClass<T> {...}

이곳에서 T는타입 파라미터Main 클래스 내부에서 intObj와 stringObj라는 GenericsClass 객체를 생성했습니다.

  • intObj을 생성할 때, 타입 매개변수 T는 Integer으로 대체됩니다. 이는 intObj이 GenericsClass를 통해 정수 데이터를 처리한다는 의미입니다.

  • stringObj을 생성할 때, 타입 매개변수 T는 String으로 대체됩니다. 이는 stringObj이 GenericsClass를 통해 문자 데이터를 처리한다는 의미입니다.

전용 메서드 생성

전용 클래스와 유사하게, Java에서 전용 메서드를 생성할 수도 있습니다.

예제: 전용 메서드 생성

class Main {
  public static void main(String[] args) {
    //Integer 데이터로 클래스를 초기화합니다
    DemoClass demo = new DemoClass();
    demo.<String>genericMethod("Java Programming");
  }
}
class DemoClass {
  //전용 메서드
  public <T> void genericsMethod(T data) {
    System.out.println("이는 전용 메서드입니다.");
    System.out.println("전달된 메서드 데이터는 " + data);
  }
}

출력 결과

이는 전용 메서드입니다.
메서드에 전달된 데이터는: Java Programming

위 예제에서는 DemoClass 내부에 정의된 전용 메서드 genericsMethod를 생성했습니다.

public <T> void genericMethod(T data) {...}

이곳에서는 타입 매개변수 <T>를 수정자(public)와 반환 타입(void) 사이에 삽입합니다.

실제 타입 <String>을 메서드 이름 앞의 괄호에 두어 전용 메서드를 호출할 수 있습니다.

demo.<String>genericMethod("Java Programming");

주의대부분의 경우, 전용 매개변수를 생략할 수 있습니다. 이는 컴파일러가 메서드에 전달된 값으로 타입 매개변수를 일치시킬 수 있기 때문입니다. 예를 들어,

demo.genericsMethod("Java Programming");

제한된 타입

보통,type 매개변수모든 데이터 타입을 받을 수 있습니다(원시 타입 제외). 하지만 특정 타입(예를 들어 숫자 타입의 데이터를 받는 것)에 대해 전용 타입을 사용하고 싶다면 제한된 타입을 사용할 수 있습니다.

extends 키워드를 사용합니다. 예를 들어,

<T extends A>

이는 T가 A의 서브 타입의 데이터만 받을 수 있음을 의미합니다.

예제: 제한된 타입

class GenericsClass<T extends Number> {
  public void display() {}}
    System.out.println("This is a bounded type generics class.");
  }
}
class Main {
  public static void main(String[] args) {
    //GenericsClass 객체 생성
    GenericsClass<String> obj = new GenericsClass<>();
  }
}

위의 예제에서는 GenericsClass를 생성했다.제한된 타입의 제너릭 클래스. 여기서는 표현식에 주의해야 한다.

<T extends Number>

이는 T가 Number의 서브 타입 데이터 타입( Integer, Double 등)만 사용할 수 있다는 의미다.

그러나, 우리는 String으로 제너릭 클래스의 객체를 생성했기 때문에, 프로그램을 실행할 때 다음과 같은 오류를 받게 된다.

GenericsClass<String> obj = new GenericsClass<>();
                                                 ^
    reason: inference variable T has incompatible bounds
      equality constraints: String
      lower bounds: Number
  where T is a type-변수:
    T extends Number declared in class GenericsClass

Java 제너릭의 장점

1. 코드 재사용성

제너릭다른 타입 데이터에 적용할 수 있는 코드를 작성할 수 있게 한다. 예를 들어,

public <T> void genericsMethod(T data) {...}

여기서는 제너릭 메서드를 생성했다. 이 메서드는 정수 데이터, 문자열 데이터 등에 대해 작업할 수 있다.

2. 컴파일 시 타입 검사

제너릭type 매개변수제너릭 코드에서 사용하는 데이터 타입에 대한 정보를 제공한다.

따라서, 컴파일 시에 오류를 인식할 수 있어, 실행 시 오류보다 더 쉽게 수정할 수 있다. 예를 들어,

//제너릭을 사용하지 않음
NormalClass list = new NormalClass();
//NormalClass의 메서드 호출
list.display("String");

위의 코드에서는 일반 클래스가 있다. 이 클래스의 display() 메서드를 호출하기 위해 문자열 데이터를 전달하여 호출한다.

여기서 컴파일러는 매개변수에 전달된 값이 올바른지 모른다. 그러나, 제너릭 클래스를 사용할 때 어떻게 될지 보자.

//제너릭 사용
GenericsClass<Integer> list = new GenericsClass<>();
//GenericsClass의 메서드 호출
list2.display("String");
위의 코드에서는 제너릭 클래스가 있습니다. 여기서 타입 파라미터는 이 클래스가 Integer 데이터를 처리하고 있다는 것을 의미합니다.
따라서 문자 데이터가 매개변수로 전달될 때, 컴파일러는 오류를 생성합니다.

3.제너릭과 컬렉션을 함께 사용

콜렉션 프레임워크는 Java의 제너릭 개념을 사용합니다. 예를 들어,

// String 타입 ArrayList 생성
ArrayList<String> list1 = new ArrayList<>();
// Integer 타입 ArrayList 생성
ArrayList<Integer> list2 = new ArrayList<>();

위의 예제에서는 다른 타입의 데이터를 처리하는 데 같은 ArrayList 클래스를 사용했습니다.

ArrayList과 비슷하게, 다른 컬렉션(LinkedList, Queue, Maps 등)도 Java의 제너릭입니다.