помогите с отражением + конструкторы - PullRequest
1 голос
/ 17 июля 2009

У меня есть код, над которым я работаю для создания алгоритма CRC, зависящего от переданного полинома, и строка s, которая содержит "crc8" или "crc16" или "crc32".

Классы CRC8, CRC16 и CRC32 расширяют класс CRC и реализуют интерфейс HashAlgorithm. У каждого из них есть конструктор CRCx(int polynomial).

Моя проблема в том, что я получаю эту ошибку на всех 3 строках getConstructor ():

Type mismatch: 
  cannot convert from Constructor<HashFactory.CRC16> 
  to Constructor<HashFactory.CRC>

Может кто-нибудь помочь объяснить, почему и помочь мне это исправить?

    int polynomial; // assign from somewhere
    Constructor<CRC> crc = null;
    if ("crc8".equals(s))
    {
        crc = CRC8.class.getConstructor(Integer.TYPE);
    }
    if ("crc16".equals(s))
    {
        crc = CRC16.class.getConstructor(Integer.TYPE);
    }
    if ("crc32".equals(s))
    {
        crc = CRC32.class.getConstructor(Integer.TYPE);
    }
    if (crc != null)
    {
        CRC crcInstance = crc.newInstance(polynomial);
        return (HashAlgorithm) crcInstance;
    }

Ответы [ 4 ]

5 голосов
/ 17 июля 2009

Попробуйте

    int polynomial; // assign from somewhere
    if ("crc8".equals(s)) {
            return new CRC8(polynomial);
    } else
    if ("crc16".equals(s)) {
            return new CRC16(polynomial);
    } else
    if ("crc32".equals(s)) {
            return new CRC32(polynomial);
    }

Или

package tests;
import java.lang.reflect.Constructor;
public class Construct {
    static interface CRC { }
    static class CRC8 implements CRC {
        public CRC8(int p) { }
    }
    static class CRC16 implements CRC {
        public CRC16(int p) { }
    }
    static class CRC32 implements CRC {
        public CRC32(int p) { }
    }
    public static CRC getAlg(String s, int polynomial) {
        try {
            Class<?> clazz = Class.forName("tests.Construct$" + s.toUpperCase());
            Constructor<?> c = clazz.getConstructor(Integer.TYPE);
            return CRC.class.cast(c.newInstance(polynomial));
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new AssertionError("Unknown algorithm: " +s);
    }
    public static void main(String[] args) throws Exception {
        System.out.println(getAlg("crc8", 0));
        System.out.println(getAlg("crc16", 0));
        System.out.println(getAlg("crc32", 0));
        System.out.println(getAlg("crc48", 0));
    }
}

«Фабричный» рисунок:

    public static HashAlgorithm getHashAlgorithm(String s, int polynomial) {
        if ("crc8".equals(s)) {
            return new CRC8(polynomial);
        } else
        if ("crc16".equals(s)) {
            return new CRC16(polynomial);
        } else
        if ("crc32".equals(s)) {
            return new CRC32(polynomial);
        }
        throw new AssertionError("Unknown algorithm: " +s);
    }

Это можно сделать несколькими другими способами (например, HashMap алгоритмов для дублирующихся классов CRC и т. Д.)

4 голосов
/ 17 июля 2009

Благодаря чудесам дженериков, Constructor<HashFactory.CRC16> не совместим по типу с Constructor<HashFactory.CRC>. Вам нужно выбрать что-то более общее для вашей переменной, например:

Constructor<? extends CRC> crc = null;
4 голосов
/ 17 июля 2009

Попробуйте объявить переменную crc следующим образом:

Constructor<? extends CRC> crc = null;
1 голос
/ 19 июля 2009

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

В вашем конкретном примере шаблон "фабрика объектов" является лучшим решением, чем использование отражения для вызова конструкторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...