[java] C ++과 Java에서 “일반”유형의 차이점은 무엇입니까?

Java에는 제네릭이 있으며 C ++은 templates를 사용 하여 매우 강력한 프로그래밍 모델을 제공합니다 . 그렇다면 C ++과 Java 제네릭의 차이점은 무엇입니까?



답변

그들 사이에는 큰 차이가 있습니다. C ++에서는 제네릭 형식에 대한 클래스 나 인터페이스를 지정할 필요가 없습니다. 그렇기 때문에 타이핑이 느슨해지면 진정한 일반 함수와 클래스를 만들 수 있습니다.

template <typename T> T sum(T a, T b) { return a + b; }

위의 방법은 동일한 유형의 두 객체를 추가하며 “+”연산자를 사용할 수있는 모든 유형 T에 사용할 수 있습니다.

Java에서는 전달 된 객체에서 메소드를 호출하려면 다음과 같이 유형을 지정해야합니다.

<T extends Something> T sum(T a, T b) { return a.add ( b ); }

C ++에서 일반 함수 / 클래스는 헤더에서만 정의 할 수 있습니다. 컴파일러는 서로 다른 유형 (함수 호출)에 대해 다른 함수를 생성하기 때문입니다. 따라서 컴파일 속도가 느려집니다. Java에서 컴파일에는 큰 페널티가 없지만 Java는 런타임에 일반 유형이 지워지는 “삭제”라는 기술을 사용하므로 런타임에 Java가 실제로 호출됩니다 …

Something sum(Something a, Something b) { return a.add ( b ); }

따라서 Java의 일반적인 프로그래밍은 실제로 유용하지 않으며 새로운 foreach 구문을 돕는 것은 약간의 구문 설탕 일뿐입니다.

편집 : 유용성에 대한 위의 의견은 젊은 자아에 의해 작성되었습니다. Java의 제네릭은 물론 형식 안전성을 지원합니다.


답변

Java Generics는 C ++ 템플릿 과 크게 다릅니다.

기본적으로 C ++ 템플릿에서는 기본적으로 영광스러운 전 처리기 / 매크로 세트입니다 ( 참고 : 일부 사람들은 유추를 이해할 수 없기 때문에 템플릿 처리가 매크로라고 말하지 않습니다). Java에서는 기본적으로 객체의 상용구 캐스팅을 최소화하기 위해 구문 설탕입니다. 다음은 C ++ 템플릿과 Java 제네릭에 대한 꽤 괜찮은 소개 입니다.

이 점을 자세히 설명하려면 C ++ 템플릿을 사용할 때 기본적으로 #define매크로 를 사용하는 것처럼 다른 코드 사본을 작성 합니다. 이를 통해 int배열의 크기 등을 결정하는 템플릿 정의에 매개 변수 가있는 것과 같은 작업을 수행 할 수 있습니다 .

Java는 그런 식으로 작동하지 않습니다. Java에서 모든 객체는 java.lang.Object 에서 확장됩니다. 되므로 pre-Generics는 다음과 같은 코드를 작성합니다.

public class PhoneNumbers {
  private Map phoneNumbers = new HashMap();

  public String getPhoneNumber(String name) {
    return (String)phoneNumbers.get(name);
  }

  ...
}

모든 Java 콜렉션 유형이 Object를 기본 유형으로 사용했기 때문에 무엇이든 넣을 수 있기 때문입니다. Java 5는 다음과 같은 작업을 수행 할 수 있도록 제네릭을 추가하고 추가합니다.

public class PhoneNumbers {
  private Map<String, String> phoneNumbers = new HashMap<String, String>();

  public String getPhoneNumber(String name) {
    return phoneNumbers.get(name);
  }

  ...
}

그리고 그것은 모든 Java Generics입니다 : 객체를 캐스팅하기위한 래퍼. Java Generics가 정제되지 않았기 때문입니다. 그들은 유형 삭제를 사용합니다. 이 결정은 Java Generics가 너무 늦게 나왔기 때문에 이전 버전과의 호환성을 깨뜨리고 싶지 않았습니다 (a Map<String, String>가 필요할 때마다 사용할 수 있음 Map). 유형 삭제가 사용되지 않는 .Net / C #과 비교하면 모든 종류의 차이점이 발생합니다 (예 : 기본 유형 IEnumerableIEnumerable<T> 서로 아무 관계도지지 않습니다).

Java 5+ 컴파일러로 컴파일 된 제네릭을 사용하는 클래스는 JDK 1.4에서 사용할 수 있습니다 (Java 5+가 필요한 다른 기능이나 클래스를 사용하지 않는다고 가정).

그렇기 때문에 Java Generics를 구문 설탕 이라고합니다. 합니다.

그러나 제네릭을 수행하는 방법에 대한이 결정은 많은 영향을 미치므로 (최상의) Java 제네릭 FAQ 가 사람들이 Java 제네릭에 대해 가지고있는 많은 질문에 대답하기 위해 생겨났습니다.

C ++ 템플릿에는 Java Generics에없는 많은 기능이 있습니다.

  • 기본 유형 인수 사용

    예를 들면 다음과 같습니다.

    template<class T, int i>
    class Matrix {
      int T[i][i];
      ...
    }

    Java는 제네릭 형식에서 기본 형식 인수를 사용할 수 없습니다.

  • 기본 유형 인수를 사용합니다 . Java에서 놓칠 수있는 기능 중 하나이지만 이전 버전과의 호환성 이유가 있습니다.

  • Java는 인수의 경계를 허용합니다.

예를 들면 다음과 같습니다.

public class ObservableList<T extends List> {
  ...
}

다른 인수를 가진 템플릿 호출은 실제로 다른 유형이라는 점을 강조해야합니다. 정적 멤버도 공유하지 않습니다. Java에서는 그렇지 않습니다.

제네릭과의 차이점 외에도 완전성을 위해 C ++과 Java (및 다른 것 )의 기본 비교가 있습니다. ) 있습니다.

또한 Thinking in Java를 제안 할 수도 있습니다 . C ++ 프로그래머로서 객체와 같은 많은 개념은 이미 제 2의 특성이지만 미묘한 차이점이 있으므로 부품을 훑어 보더라도 소개 텍스트를 갖는 것이 좋습니다.

Java를 배울 때 배우게 될 많은 것들이 모든 라이브러리 (JDK에 포함 된 표준 라이브러리)와 스프링과 같이 일반적으로 사용되는 것을 포함하는 비표준 라이브러리입니다. Java 구문은 C ++ 구문보다 더 장황하며 많은 C ++ 기능 (예 : 연산자 오버로드, 다중 상속, 소멸자 메커니즘 등)을 갖지 않지만 C ++의 하위 집합으로 만들어지는 것은 아닙니다.


답변

C ++에는 템플릿이 있습니다. Java에는 제네릭이 있는데 C ++ 템플릿과 비슷하지만 매우 다릅니다.

템플릿은 이름에서 알 수 있듯이 템플릿 매개 변수를 입력하여 형식이 안전한 코드를 생성하는 데 사용할 수있는 (기다리는 중 …) 템플릿을 컴파일러에 제공하여 작동합니다.

제네릭은 내가 이해하는 것처럼 다른 방법으로 작동합니다. 유형 매개 변수는 컴파일러에서 사용하여 코드를 사용하여 코드가 안전한지 확인하지만 결과 코드는 전혀 유형없이 생성됩니다.

C ++ 템플릿은 정말 좋은 매크로 시스템으로, Java 제네릭은 자동으로 타입 캐스트를 생성하는 도구로 생각하십시오 .

 


답변

C ++ 템플릿의 또 다른 기능으로는 Java 제네릭에는없는 특수화 기능이 있습니다. 이를 통해 특정 유형에 대해 다른 구현을 가질 수 있습니다. 예를 들어 int에 대해 고도로 최적화 된 버전을 유지하면서도 나머지 유형에 대한 일반 버전을 유지할 수 있습니다. 또는 포인터 및 비 포인터 유형에 대해 다른 버전을 가질 수 있습니다. 포인터를 넘길 때 역 참조 된 객체를 조작하려는 경우에 유용합니다.


답변

필립와 들러 (Philip Wadler)의 Maurice Naftalin의 Java Generics and Collections 에이 주제에 대한 훌륭한 설명이 있습니다. 나는이 책을 강력히 추천한다. 인용 :

Java의 제네릭은 C ++의 템플릿과 유사합니다. … 구문은 의도적으로 유사하며 시맨틱은 의도적으로 다릅니다. … 의미 적으로 Java 제네릭은 삭제에 의해 정의되며 C ++ 템플릿은 확장에 의해 정의됩니다.

여기 에서 전체 설명을 읽으 십시오 .

대체 텍스트
(출처 : oreilly.com )


답변

기본적으로 AFAIK, C ++ 템플릿은 각 유형에 대한 코드 사본을 생성하는 반면 Java 제네릭은 정확히 동일한 코드를 사용합니다.

예, 당신은 말할 수있는 C ++ 템플릿이 자바 일반에 해당한다는 개념 (더 제대로 자바 제네릭 개념 ++ C에 해당합니다 말을하는 것입니다하지만)

C ++의 템플릿 메커니즘에 익숙하다면 제네릭은 비슷하지만 유사성은 피상적이라고 생각할 수 있습니다. 제네릭은 각 전문 분야마다 새로운 클래스를 생성하지 않으며 “템플릿 메타 프로그래밍”을 허용하지도 않습니다.

보낸 사람 : Java Generics


답변

Java (및 C #) 제네릭은 간단한 런타임 형식 대체 메커니즘 인 것 같습니다.

C ++ 템플릿은 필요에 맞게 언어를 수정할 수있는 컴파일 타임 구문입니다. 그것들은 실제로 컴파일러가 컴파일하는 동안 실행하는 순전히 기능적인 언어입니다.