Java: Как получить тип класса дженериков во время выполнения? [Дубликат]

Обычно ошибка, возникающая при сбое в работе базы данных базы данных, поэтому не забудьте подключить вашу базу данных или включить файл базы данных.

include_once(db_connetc.php');

ИЛИ

// Create a connection
$connection = mysql_connect("localhost", "root", "") or die(mysql_error());

//Select database
mysql_select_db("db_name", $connection) or die(mysql_error());

$employee_query = "SELECT * FROM employee WHERE `id` ='".$_POST['id']."';

$employee_data = mysql_query($employee_query);

if (mysql_num_rows($employee_data) > 0) {

    while ($row = mysql_fetch_array($employee_data)){
        echo $row['emp_name'];
    } // end of while loop
} // end of if
  • Лучшей практикой является запуск запроса в sqlyog, а затем его копирование в код страницы.
  • Всегда сохраняйте свой запрос в переменной и затем повторяйте эту переменную. Затем перейдите к mysql_query($query_variable);.
385
задан ROMANIA_engineer 26 December 2015 в 17:56
поделиться

21 ответ

public abstract class AbstractDao<T> <br>
{

    private final Class<T> persistentClass;


    public AbstractDao()
    {
        this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
}
6
ответ дан anacron 28 August 2018 в 12:43
поделиться

Вы не можете. Если вы добавите переменную-член типа T в класс (вам даже не нужно ее инициализировать), вы можете использовать ее для восстановления типа.

3
ответ дан andrewmu 28 August 2018 в 12:43
поделиться

Использовать Guava.

import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;

public class GenericClass<T> {
  private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) { };
  private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>

  public Type getType() {
    return type;
  }

  public static void main(String[] args) {
    GenericClass<String> example = new GenericClass<String>() { };
    System.out.println(example.getType()); // => class java.lang.String
  }
}

В то время как я вернулся, я разместил здесь несколько полнофункциональных примеров, включая абстрактные классы и подклассы здесь .

Примечание: для этого необходимо создать экземпляр подкласса в GenericClass, чтобы он мог привязать параметр типа правильно. В противном случае он просто вернет тип как T.

43
ответ дан Cody A. Ray 28 August 2018 в 12:43
поделиться

Я думаю, что есть еще одно элегантное решение.

Что вы хотите сделать (безопасно) «передать» тип типичного параметра типа от класса concerete до суперкласса.

Если вы позволяете себе думать о типе класса как «метаданных» в классе, это предполагает метод Java для кодирования метаданных во время выполнения: аннотации.

Сначала определите пользовательскую аннотацию вдоль этих строк :

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityAnnotation {
    Class entityClass();
}

Затем вы можете добавить аннотацию к вашему подклассу.

@EntityAnnotation(entityClass =  PassedGenericType.class)
public class Subclass<PassedGenericType> {...}

Затем вы можете использовать этот код, чтобы получить тип класса в базовом классе:

import org.springframework.core.annotation.AnnotationUtils;
.
.
.

private Class getGenericParameterType() {
    final Class aClass = this.getClass();
    EntityAnnotation ne = 
         AnnotationUtils.findAnnotation(aClass, EntityAnnotation.class);

    return ne.entityClass();
}

Некоторые ограничения этого подхода:

  1. Вы указываете общий тип (PassedGenericType) в двух местах, а не один, не являющийся сухим.
  2. Это возможно только в том случае, если вы можете изменить конкретные подклассы.
6
ответ дан DaBlick 28 August 2018 в 12:43
поделиться

Я не думаю, что вы можете, Java использует стирание стилей при компиляции, чтобы ваш код был совместим с приложениями и библиотеками, которые были созданы с предварительными генериками.

Из Oracle Docs:

Тип Erasure

На язык Java были введены обобщения для обеспечения более жестких проверок типа во время компиляции и поддержки общего программирования. Для реализации обобщений компилятор Java применяет стирание типа к:

Замените все параметры типа в родовых типах своими границами или объектом, если параметры типа неограничены. Таким образом, полученный байт-код содержит только обычные классы, интерфейсы и методы. При необходимости вставьте тип приведения, чтобы сохранить безопасность типа. Создание мостовых методов для сохранения полиморфизма в расширенных общих типах. Стирание стилей гарантирует, что для параметризованных типов не создаются новые классы; следовательно, дженерики не накладывают на себя лишний промежуток времени.

http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

12
ответ дан Dimitar 28 August 2018 в 12:43
поделиться

Я видел что-то вроде этого

private Class<T> persistentClass;

public Constructor() {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
 }

в hibernate GenericDataAccessObjects Example

206
ответ дан FrVaBe 28 August 2018 в 12:43
поделиться

Чтобы выполнить некоторые из ответов здесь, мне пришлось получить ParametrizedType MyGenericClass, независимо от того, насколько высока иерархия, с помощью рекурсии:

private Class<T> getGenericTypeClass() {
        return (Class<T>) (getParametrizedType(getClass())).getActualTypeArguments()[0];
}

private static ParameterizedType getParametrizedType(Class clazz){
    if(clazz.getSuperclass().equals(MyGenericClass.class)){ // check that we are at the top of the hierarchy
        return (ParameterizedType) clazz.getGenericSuperclass();
    } else {
        return getParametrizedType(clazz.getSuperclass());
    }
}
1
ответ дан galex 28 August 2018 в 12:43
поделиться

Как уже упоминалось, это возможно только при отражении в определенных обстоятельствах.

Если вам действительно нужен тип, это обычный (безопасный тип) шаблон обходного пути:

public class GenericClass<T> {

     private final Class<T> type;

     public GenericClass(Class<T> type) {
          this.type = type;
     }

     public Class<T> getMyType() {
         return this.type;
     }
}
252
ответ дан Henning 28 August 2018 в 12:43
поделиться

Вот мой трюк:

public class Main {

    public static void main(String[] args) throws Exception {

        System.out.println(Main.<String> getClazz());

    }

    static <T> Class getClazz(T... param) {

        return param.getClass().getComponentType();
    }

}
1
ответ дан HRgiger 28 August 2018 в 12:43
поделиться

Генерирует Java в основном время компиляции, это означает, что информация о типе теряется во время выполнения.

class GenericCls<T>
{
    T t;
}

будет скомпилирована для чего-то вроде

class GenericCls
{
   Object o;
}

. Чтобы получить тип информации во время выполнения вы должны добавить его как аргумент ctor.

class GenericCls<T>
{
     private Class<T> type;
     public GenericCls(Class<T> cls)
     {
        type= cls;
     }
     Class<T> getType(){return type;}
}

Пример:

GenericCls<?> instance = new GenericCls<String>(String.class);
assert instance.getType() == String.class;
31
ответ дан josefx 28 August 2018 в 12:43
поделиться

Конечно, вы можете.

Java не использует информацию во время выполнения, для соображений обратной совместимости. Но информация фактически присутствует как метаданные и может быть доступна через отражение (но она еще не используется для проверки типов).

Из официального API:

http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29

Однако для вашего сценария я бы не использовал рефлексию. Я лично больше склонен использовать это для кода рамки. В вашем случае я бы просто добавил этот тип в качестве параметра конструктора.

37
ответ дан jpaugh 28 August 2018 в 12:43
поделиться

Вот мое решение

public class GenericClass<T>
{
    private Class<T> realType;

    public GenericClass() {
        findTypeArguments(getClass());
    }

    private void findTypeArguments(Type t) {
        if (t instanceof ParameterizedType) {
            Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments();
            realType = (Class<T>) typeArgs[0];
        } else {
            Class c = (Class) t;
            findTypeArguments(c.getGenericSuperclass());
        }
    }

    public Type getMyType()
    {
        // How do I return the type of T? (your question)
        return realType;
    }
}

Независимо от того, сколько уровней ваша иерархия классов, это решение все еще работает, например:

public class FirstLevelChild<T> extends GenericClass<T> {

}

public class SecondLevelChild extends FirstLevelChild<String> {

}

В этом случае, getMyType () = java.lang.String

1
ответ дан Lin Yu Cheng 28 August 2018 в 12:43
поделиться

Во время выполнения дженерики не являются reified . Это означает, что информация отсутствует во время выполнения.

Добавление дженериков в Java при сохранении обратной совместимости было де-силовым (вы можете ознакомиться с оригинальной статьей: Создание будущего безопасный для прошлого: добавление универсальности к языку программирования Java ).

Существует богатая литература по этому вопросу, а некоторые люди недовольны текущим состоянием , некоторые говорят, что на самом деле это приманка , и в этом нет никакой реальной необходимости. Вы можете прочитать обе ссылки, я нашел их довольно интересными.

81
ответ дан malat 28 August 2018 в 12:43
поделиться

Я нашел это простым понятным и легко объяснимым решением

public class GenericClass<T> {

    private Class classForT(T...t) {
        return t.getClass().getComponentType();
    }

    public static void main(String[] args) {
        GenericClass<String> g = new GenericClass<String>();

        System.out.println(g.classForT());
        System.out.println(String.class);
    }
}
-4
ответ дан Mark Karchner 28 August 2018 в 12:43
поделиться

Это мое решение:

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class GenericClass<T extends String> {

  public static void main(String[] args) {
     for (TypeVariable typeParam : GenericClass.class.getTypeParameters()) {
      System.out.println(typeParam.getName());
      for (Type bound : typeParam.getBounds()) {
         System.out.println(bound);
      }
    }
  }
}
7
ответ дан Matthias M 28 August 2018 в 12:43
поделиться

Я использовал следующий подход:

public class A<T> {

    protected Class<T> clazz;

    public A() {
        this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Class<T> getClazz() {
        return clazz;
    }
}

public class B extends A<C> {
   /* ... */
    public void anything() {
       // here I may use getClazz();
    }
}
17
ответ дан Moesio 28 August 2018 в 12:43
поделиться

Техника, описанная в этой статье Яна Робертсона , работает для меня.

Короче, быстрый и грязный пример:

 public abstract class AbstractDAO<T extends EntityInterface, U extends QueryCriteria, V>
 {
    /**
     * Method returns class implementing EntityInterface which was used in class
     * extending AbstractDAO
     *
     * @return Class<T extends EntityInterface>
     */
    public Class<T> returnedClass()
    {
        return (Class<T>) getTypeArguments(AbstractDAO.class, getClass()).get(0);
    }

    /**
     * Get the underlying class for a type, or null if the type is a variable
     * type.
     *
     * @param type the type
     * @return the underlying class
     */
    public static Class<?> getClass(Type type)
    {
        if (type instanceof Class) {
            return (Class) type;
        } else if (type instanceof ParameterizedType) {
            return getClass(((ParameterizedType) type).getRawType());
        } else if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType) type).getGenericComponentType();
            Class<?> componentClass = getClass(componentType);
            if (componentClass != null) {
                return Array.newInstance(componentClass, 0).getClass();
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * Get the actual type arguments a child class has used to extend a generic
     * base class.
     *
     * @param baseClass the base class
     * @param childClass the child class
     * @return a list of the raw classes for the actual type arguments.
     */
    public static <T> List<Class<?>> getTypeArguments(
            Class<T> baseClass, Class<? extends T> childClass)
    {
        Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
        Type type = childClass;
        // start walking up the inheritance hierarchy until we hit baseClass
        while (!getClass(type).equals(baseClass)) {
            if (type instanceof Class) {
                // there is no useful information for us in raw types, so just keep going.
                type = ((Class) type).getGenericSuperclass();
            } else {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Class<?> rawType = (Class) parameterizedType.getRawType();

                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
                for (int i = 0; i < actualTypeArguments.length; i++) {
                    resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
                }

                if (!rawType.equals(baseClass)) {
                    type = rawType.getGenericSuperclass();
                }
            }
        }

        // finally, for each actual type argument provided to baseClass, determine (if possible)
        // the raw class for that type argument.
        Type[] actualTypeArguments;
        if (type instanceof Class) {
            actualTypeArguments = ((Class) type).getTypeParameters();
        } else {
            actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        }
        List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
        // resolve types by chasing down type variables.
        for (Type baseType : actualTypeArguments) {
            while (resolvedTypes.containsKey(baseType)) {
                baseType = resolvedTypes.get(baseType);
            }
            typeArgumentsAsClasses.add(getClass(baseType));
        }
        return typeArgumentsAsClasses;
    }
  }
14
ответ дан Ondrej Bozek 28 August 2018 в 12:43
поделиться

На всякий случай, если вы используете хранилище переменной с использованием универсального типа, вы можете легко решить эту проблему, добавив метод getClassType следующим образом:

public class Constant<T> {
  private T value;

  @SuppressWarnings("unchecked")
  public Class<T> getClassType () {
    return ((Class<T>) value.getClass());
  }
}

Я использую предоставленный объект класса позже, чтобы проверить, экземпляр данного класса, следующим образом:

Constant<?> constant = ...;
if (constant.getClassType().equals(Integer.class)) {
    Constant<Integer> integerConstant = (Constant<Integer>)constant;
    Integer value = integerConstant.getValue();
    // ...
}
2
ответ дан Pablo Trinidad 28 August 2018 в 12:43
поделиться
2
ответ дан perror 28 August 2018 в 12:43
поделиться

Вот один из способов, который я должен был использовать один или два раза:

public abstract class GenericClass<T>{
    public abstract Class<T> getMyType();
}

Наряду с

public class SpecificClass extends GenericClass<String>{

    @Override
    public Class<String> getMyType(){
        return String.class;
    }
}
1
ответ дан PJWeisberg 28 August 2018 в 12:43
поделиться
5
ответ дан Yaroslav Kovbas 28 August 2018 в 12:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: