2017-12-17 6 views
1

현재 Java의 제네릭에 대해 배우고 있습니다. C++에서 상당히 차이가 있습니다. C++에서 벡터 추가를 원합니다. 이렇게 보일 것입니다. 나는 자바와 동일한 작업을 수행하려고Java에서 두 개의 제네릭 추가 (캐스트가 작동하지 않음)

#include <iostream> 
#include <vector> 
template <typename T> 
class Vect{ 
    public: 
     std::vector<T> vect; 
     Vect(std::vector<T> t){vect = t;} 
     T index(int i){return vect[i];} 
     void print(){ 
      for(int i = 0; i < vect.size(); ++i){ 
       std::cout << vect[i] << " "; 
      } 
      std::cout << std::endl; 
     } 
     void add(Vect<T> other){ 
      for(int i = 0; i < vect.size(); ++i){ 
       vect[i] = vect[i]+other.index(i); 
      } 
     } 
}; 

int main(){ 
    std::vector<int> p1; 
    p1.push_back(1); 
    p1.push_back(2); 
    p1.push_back(3); 
    p1.push_back(4); 
    Vect<int> vec1 = Vect<int>(p1);; 
    Vect<int> vec2 = Vect<int>(p1);; 
    vec1.print(); 
    vec2.print(); 
    vec1.add(vec2); 
    vec1.print(); 

    return 0; 
} 

(이 코드가 잘 기록되지 않습니다 것을 알고, 내가하고 싶은 것을 보여주기 위해 그냥 빨리 예입니다)하지만 난 방법을 얻을 수 없다 두 제네릭 T를 추가하고 첫 번째 벡터에 값 (a T)을 넣으십시오. 그래서 이중 인쇄 않습니다

public class Vect0<T extends Number> { 

    //Attributs 
    private T[] _vec; 

    //Constructeur 
    public Vect0(T[] vec){ 
     System.out.println("Construction du _vec !"); 
     _vec = vec; 
    } 
    //Getter 
    public int get_length() { 
     return _vec.length; 
    } 
    //Methodes 
    public void print(){ 
     System.out.print("["); 
     for (int i = 0; i < _vec.length; ++i){ 
      if (i != _vec.length-1) { 
       System.out.print(_vec[i] + ", "); 
      } 
      else { 
       System.out.print(_vec[i]); 
      } 
     } 
     System.out.println("]"); 
    } 
    public T index(int i) { 
     return _vec[i]; 
    } 
    public void sum(Vect0<T> other) { 
     if (other.get_length() == this.get_length()) { 
      for(int i = 0; i < this.get_length(); ++i) { 
       Double res = (this.index(i).doubleValue() + other.index(i).doubleValue()); 
       System.out.print(res); 
       T t = (T) res; 
       _vec[i] = t; 
      } 
     } 
    } 
} 

을,하지만 캐스팅이 작동하지 않습니다 나는 오류 얻을 : 나는이 일을하고 스레드 "주요"java.lang.ArrayStoreException에서

예외 : Main.main (Main.java:12)에서 Vect0.sum (Vect0.java:37)에서 java.lang.Double에

난 당신이 날이 알아낼 도움이 될 수 있기를 바랍니다. 대단히 감사합니다.

+0

당신이 Vect0 에 두 배를 저장하기 위해 찾고있는 타입인가? – jzarob

+0

@jzarob 아니, 이상적으로 나는 두 개의 T 1과 T t2를 더하고 t 1에 결과를 저장하려고했지만 '+'는 Number에 정의되어 있지 않으므로 작동하지 않습니다. C++과 비교하여 유형 삭제 및 Java가 제네릭을 처리하는 방식 때문이라고 생각하십니까? – Culpeo

답변

1

아래 코드를 살펴보십시오. 귀하의 문제에 대한 설명은 코멘트에 있습니다. 당신은 ArrayStoreException를 읽어 경우

public class TestGenerics { 

    public static void main(String[] args) { 
     Integer[] ints = new Integer[] { 1 }; 
     Double[] doubles = new Double[] { 1.0 }; 

     // By not telling the compiler which types you're 
     // expecting it will not be able to deduce if 
     // the usage of the generic methods are going 
     // to be ok or not, because the generics notation is 
     // erased and is not available at runtime. 
     // The only thing you will receive by doing this 
     // is a warning telling you that: 
     // "Vect0 is a raw type. 
     // References to generic type Vect0<T> should be parameterized" 
     Vect0 rawVect0 = new Vect0(ints); 
     Vect0 rawVect1 = new Vect0(doubles); 

     // This will throw java.lang.ArrayStoreException 
     // because you're trying, at runtime, to cast 
     // a Double object to Integer inside your sum method 
     // The compiler doesn't have a clue about that so it 
     // will blow at runtime when you try to use it. 
     // If you're only working with Integers, than you should not 
     // cast the result to double and should always work with intValues 
     rawVect0.sum(rawVect1); 

     // In Java, when using generics, you should be 
     // explict about your types using the diamond operator 
     Vect0<Integer> vect2 = new Vect0<>(ints); 
     Vect0<Double> vect3 = new Vect0<>(doubles); 

     // Now that you told the compiler what your types are 
     // you will receive a compile time error: 
     // "The method sum(Vect0<Integer>) in the type Vect0<Integer> 
     // is not applicable for the arguments (Vect0<Double>)" 
     vect2.sum(vect3); 
    } 
} 

이 명확하게 될 것이다 :

공용 클래스 ArrayStoreException를이 RuntimeException을 확장 에 슬로우 시도가 배열로 객체의 잘못된 유형을 저장 한 것을 나타 내기 개체. 예를 들어, 다음 코드 는 ArrayStoreException를 생성 : 일반 방법을 취급 할 때마다 사용해야하는 프로듀서가 확장 것을 생각해야하고, 소비자가 슈퍼 사용해야

Object x[] = new String[3]; 
x[0] = new Integer(0); 

- PECS합니다. 이것은 알아두면 좋은 일입니다. 이 질문에 체크 아웃 : 당신이 정말로 Number의 다른 유형을 추가 할 수 있도록하려면, 귀하의 경우에 What is PECS (Producer Extends Consumer Super)?

하나의 솔루션을, 항상 하나 개의 특정 유형 (Double)로 Vect0 객체 내부에서 작업하는 것입니다. 아래의 코드를 체크 아웃 :

public class Vect0<T extends Number> { 
    // Attributs 
    private Double[] _vec; 

    // Constructeur 
    public Vect0(T[] vec) { 
     System.out.println("Construction du _vec !"); 
     if (vec instanceof Double[]) { 
      _vec = (Double[]) Arrays.copyOf(vec, vec.length); 
     } else { 
      _vec = Arrays.stream(vec).map(Number::doubleValue).toArray(Double[]::new); 
     } 
    } 

    // Getter 
    public int get_length() { 
     return _vec.length; 
    } 

    // Methodes 
    public void print() { 
     System.out.print("["); 
     for (int i = 0; i < _vec.length; ++i) { 
      if (i != _vec.length - 1) { 
       System.out.print(_vec[i] + ", "); 
      } else { 
       System.out.print(_vec[i]); 
      } 
     } 
     System.out.println("]"); 
    } 

    public Double index(int i) { 
     return _vec[i]; 
    } 

    public void sum(Vect0<T> other) { 
     if (other.get_length() == this.get_length()) { 
      for (int i = 0; i < this.get_length(); ++i) { 
       // Now you're only working with Doubles despite of the other object's true type 
       _vec[i] = index(i) + other.index(i); 
      } 
     } 
    } 
} 

그리고 그것을 사용하기 위해

,이 같은 슈퍼 클래스 Number를 사용하여 객체를 참조해야합니다 :

Vect0<Number> vect2 = new Vect0<>(ints1); 
Vect0<Number> vect3 = new Vect0<>(doubles1); 
// now it will be able to add two different types without complaining 
vect2.sum(vect3); 

당신이 뭔가 더 정교한 원한다면, 당신은 할 수 이 질문을 확인하여 시작하십시오. How to add two java.lang.Numbers?

건배!

참고 :

+0

시간과 답변에 진심으로 감사드립니다. 그래서 T [] _vec 속성을 가질 방법이 없습니다. ? 유형 T와 상관없이, 내 배열에는 Doubles가 포함됩니까? – Culpeo

+0

그런 경우 Double []를 제외한 모든 유형의 배열 T []를 사용하여 복 수행을 시도 할 수 없습니다. 예를 들어 Double을 정수로 직접 변환 할 수있는 방법이 없기 때문입니다. 그리고 런타임에 벡터는 Integer []와 같은 특정 유형이됩니다. – wleao