2017-03-23 15 views
0

스트레스 테스트를 위해 임의의 클래스의 임의 생성기를 만들려고합니다.클래스 <?>이 리플렉션으로 다른 인스턴스에 있는지 확인합니다.

내 발전기 목표는 기본 생성자와 모든 클래스를 생성하고

내가 Number 유형의 필드를 채우기 위해 또한 싶습니다 (반사에 의해) 원시적 및 문자열 필드를 채우기 위해 (정수, 롱, 더블 ...) 그들은 프리미티브로 쉽게 변환 할 수 있기 때문입니다.

그러나 유형간에 간단한 접근법을 찾을 수 없습니다. instanceof. 문제를 일으키는 하나의 경우 여기에

는 방법

public static <V> Collection<V> createMassiveCollection(Class<V> clazz, int amount, Class<?> collectionType) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { 

     Random r = new Random(); 
     RandomGenerator rg = new RandomGenerator(); 
     @SuppressWarnings("unchecked") 
     Collection<V> collection = (Collection<V>) collectionType.newInstance(); 
     for (int i = 0; i < amount; i++) { 
      V item = clazz.newInstance(); 

      for (Field field : item.getClass().getDeclaredFields()) { 

       if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) || java.lang.reflect.Modifier.isFinal(field.getModifiers())) 
        continue; 

       field.setAccessible(true); 

       if (field.getType().equals(String.class)) 
        field.set(item, rg.nextCompliment()); 

       else if (field.getType().isPrimitive() && (field.getType() != boolean.class && field.getType() != byte.class && field.getType() != char.class)) 
        field.set(item, r.nextInt(1000000)); 

       else { 
        Constructor<?> c = null; 

        try { 
         c = field.getType().getConstructor(String.class); 
        } 
        catch (Exception e) {} 
        if (c != null && Number.class.isInstance(c.newInstance("1"))) 
         field.set(item, field.getType().getConstructor(String.class).newInstance(r.nextInt(1000000) + "")); 
       } 

      } 

      collection.add(item); 
     } 
     return collection; 
    } 

세 번째입니다 내가 좋아하는 뭔가를 싶습니다 "Type<C>Type<V>의 하위 유형 인 경우"그러나 모든 방법은 내가 개체의 유효한 인스턴스를 필요로 발견 확인하다.

ex. field.getType()이 Type의 인스턴스이므로 Number.class.isInstance(field.getType())field.getType() instanceof Number이 작동합니다.

가능한 경우 누구에게 알 수 있습니까?

내가하고 싶은 내 메소드 서명에서 (덜 중요한) 또 다른 문제는

Class<? extends Collection<V>> collectionType 

을 가지고 있지만합니다 내가

createMassiveCollection(User.class, 100000, new ArrayList<User>().getClass()); 

같은 메소드를 호출 할 때 컴파일러가 실패 할 경우! 그래서 컴파일 할 수 있도록해야합니다. 사용자가 Collection을 매개 변수로 확장하는 일부 유형을 전달한다고 믿어야합니다.

+0

새로운 ArrayList () .getClass()는 항상 * 지우기 * 유형'Class >'이므로,'Class > '안전하지 않은'캐스팅으로 확장합니다. 그리고 실제로 그렇게 할 필요는 없습니다. 왜냐하면'Class >'는 당신의 필요에 완벽하게 맞습니다 : 어쨌든 새로운 콜렉션을 생성하고 채우는 경우 그 콜렉션 유형이 ''일 경우 실제로 누가 신경을 씁니까? –

답변

1

가 확인하려면 출력 :

public static <V, C extends Collection<?>> Collection<V> createMassiveCollection(Class<V> clazz, int amount, Class<C> collectionType) 

이 일반도 C extends Collection<V>으로 정의 할 수 있지만 컴파일러 경고를 생성하고 createMassiveCollection(String.class, 10, new ArrayList<Number>().getClass())과 같은 호출을 방지하지는 않습니다.

그건 그렇고, 내 마지막 매개 변수는 ArrayList.class 것입니다.

0

Check Class#isAssignableFrom()은 하나의 클래스가 다른 클래스의 하위 유형인지 여부를 확인할 수있게합니다. 예 : 당신의 두번째 질문에 대해

if (Number.class.isAssignableFrom(field.getType()) { // ... 

당신이 2 일반적인 필요합니다

System.out.println(String.class.isAssignableFrom(Object.class)); 
System.out.println(Object.class.isAssignableFrom(String.class)); 

그것은 클래스를 사용하면 isAssignableFrom을 사용해야하는 또 다른의 서브 클래스 인 경우

false 
true 
1
  1. field.getType() return Class<?> 제네릭이없고 따라서 Type 인터페이스가없는 경우 type 속성 이름은 Java 1에서옵니다. 그것은 첫눈에 혼란 스러울지도 모르지만.Class<?>가 나타내는 클래스가 다른 나타내는 클래스의 하위 유형 인 경우

  2. 는 테스트하려면 Class<?> 당신이 classA.isAssignableFrom(classB)를 사용해야합니다. 예 : Number.class.isAssignableFrom(Integer.class)이 true를 반환합니다.

  3. 명시 적으로 안전하지 않은 캐스트없이 Class<? extends Collection<V>>의 인스턴스를 가져올 수 없기 때문에 Class<? extends Collection<V>> collectionType을 쓸 수도 있지만 무의미합니다.

    1. Attempting to write class literals of generic types, except a wildcard type, will result in compile time errors.
    2. Object.getClass() 때문에 삭제 유형을 반환합니다. 예 : new ArrayList<User>().getClass()의 반환 값 유형은 의미가 동일한 ArrayList 또는 ArrayList<?>이됩니다.

    명시 적으로 안전하지 않은 캐스트가 없으면 V이 와일드 카드 일 때만이 메서드를 호출 할 수 있습니다.