2009-11-04 9 views
2

있음. NET, 나는 이런 식으로 할 수있다 :Generics 및 "where"절

public static T[] CreateAndFillArray<T>(int size) where T : new() 
{ 
    T[] array = new T[size]; 
    for (int i = size - 1; i >= 0; i--) 
     array[i] = new T(); 
    return array; 
} 

우리는 "where T : new()"절을 지정해야한다.

Java로 만드는 방법은 무엇입니까?

+0

* T : new() *는 무엇을합니까? – OscarRyz

+4

@Oscar Reyes :'T : new()'는'T'가 public 매개 변수없는 생성자를 가져야 함을 의미합니다. 참조 : http://msdn.microsoft.com/en-us/library/d5x73970.aspx –

답변

3

Java에서 일반 배열을 인스턴스화 할 수 없습니다. (예 : new T [size]가 작동하지 않음) 런타임시 제네릭 유형이 손실 ("삭제")되어 복구 할 수 없기 때문입니다.

예를 들어 새로운 ArrayList <T>()과 같이 사용할 수없는 이유가 있습니까?

+0

물론 ArrayList를 사용할 수 있습니다. 내가 자바에서 그렇게 할 수 있는지 알고 싶었다;) –

+1

@mykhaylo : 응? 'ArrayList' *는 Java의 일부입니다.그리고'ArrayList'를 매개 변수로 받아들이도록 함수를 변경하지 않는다면'ArrayList'는 모든 문제를 해결하지 못할 것입니다. 'new T [size]'를 할 수없는 것처럼'T'가 런타임에 실제로 지워지기 때문에'new ArrayList ()'도 할 수 없습니다. –

+0

@ 대니얼 - ** 할 수 있습니다 ** 새로운 ArrayList ()'; 매개 변수로 Class 을 전달하지 않고 새로운 T 인스턴스로 채울 수 없습니다. – ChssPly76

11

매개 변수로 T를 전달하지 않으면 Java에서 일반 "T"유형의 배열을 만들 수 없습니다.

public static <T> T[] createAndFillArray(Class<T> cls, int size) { 
    T[] result = (T[]) Array.newInstance(cls, size); 
    for (int i=0; i<size; i++) { 
    result[i] = cls.newInstance(); 
    } 
    return result; 
} 
+2

수정하십시오. C#과 달리 Java는 제네릭을 구체화하지 않았습니다. 그래서'T'의 실제 타입은 새로운 객체를 만드는 데 사용할 수 없습니다. –

+2

CLR은 실제로'new T()'(그리고'typeof (T)'와'T를 정말로 알아야하는 다른 유사한 것들 ')과 비슷한 트릭을 수행한다는 점이 흥미 롭습니다. 후드 아래의 유형 핸들에 대한 메서드 매개 변수입니다. 유일한 차이점은 C#이나 IL 수준에서는 볼 수 없다는 것입니다. 런타임의 구현 세부 사항입니다. –

3

Java에는 동일한 구조가 없습니다. 생성자를 포함하는 클래스에는 컴파일 타임 안전성이 없습니다.

런타임에는이 작업을 수행 할 수 있지만 null이 아닌 T 또는 클래스를 매개 변수로 전달해야합니다. 사용 된 실제 유형 매개 변수는 런타임에 보존되지 않습니다.

public static <T> T[] createAndFillArray(T sampleObject, int size) throws Exception { 
     Class<T> klass = sampleObject.getClass(); 
     T[] arr = (T[]) Array.newInstance(klass, size); 
     for (int i = 0; i < size; i++) { 
      arr[i] = klass.newInstance(); 
     } 
     return arr; 
} 

위의 코드는 작동하지만 인수 생성자가 public이 아닌 경우 예외가 발생합니다. 당신은 컴파일러가 그것을 강제하도록 할 수 없습니다.

편집 : ChssPly76이 문제에 봉착 했으므로 위의 코드를 수정하여 실제 개체 샘플을 전달하는 예제를 제공하고이를 수행하는 방법을 보여줍니다. 이러한 경우 일반적으로 sampleObject가 배열로 끝나지 않으므로 클래스를 전달하게됩니다.

0

Java는 구조 유형 검사를 지원하지 않으므로 Java에서는이 작업을 수행 할 수 없습니다.

스칼라는 그렇지만 적절한 인터페이스를 구현하는 것보다 훨씬 느립니다 (함수 호출을하기 위해 내부적으로 리플렉션을 사용하기 때문에). Scala는 객체 생성자의 형식에 제약 조건을 설정할 수 없습니다. JVM은 형식 지우기를 사용하므로 일반 코드는 실제로 작동중인 유형을 알지 못하므로 어쨌든 해당 유형의 새 객체를 생성 할 수 없습니다.

import java.lang.reflect.Array; 

public class Main 
{ 
    public static void main(String[] args) 
    { 
     final String[] array; 

     array = createAndFillArray(String.class, 10, new StringCreator()); 

     for(final String s : array) 
     { 
      System.out.println(s); 
     } 
    } 

    public static <T> T[] createAndFillArray(final Class<T> clazz, 
              final int  size, 
              final Creator<T> creator) 
    { 
     T[] result = (T[]) Array.newInstance(clazz, size); 

     for (int i=0; i<size; i++) 
     { 
      result[i] = creator.newInstance(); 
     } 

     return result; 
    } 
} 

interface Creator<T> 
{ 
    T newInstance(); 
} 

class StringCreator 
    implements Creator<String> 
{ 
    public String newInstance() 
    { 
     // not the best example since String is immutable but you get the idea 
     // you could even have newInstance take an int which is the index of the 
     // item being created if that could be useful (which it might). 
     return ("hello"); 
    } 
} 

이 실제로 당신이 대신하려는 경우 생성자를 제어 할 수 있기 때문에 당신이 설명하는 C#을 방법보다 더 유연 :

1

당신은 다른 답변에서 확인 컴파일 시간의 부족을 해결하기 위해이 아이디어를 사용할 수 있습니다 단순히 인수가없는 것을 호출하는 것보다.