views:

507

answers:

5

I have code I'm working on to instantiate a CRC algorithm dependent on a polynomial passed in, and a string s that contains "crc8" or "crc16" or "crc32".

The classes CRC8, CRC16, and CRC32 all extend a class CRC and implement an interface HashAlgorithm. Each of them has a constructor CRCx(int polynomial).

My problem is, I get this error on all 3 of the getConstructor() lines:

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

Can anyone help explain why and help me fix this?

 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  A: 

Try declaring the crc variable like this:

Constructor<? extends CRC> crc = null;
Adam Paynter
+4  A: 

Thanks to the wonders of generics, Constructor<HashFactory.CRC16> is not type compatible with Constructor<HashFactory.CRC>. You need to pick something more general for your variable, like this:

Constructor<? extends CRC> crc = null;
skaffman
A: 

You can do it if you use .Net Framework 4.0 compilers that support (co/contra)variance.

This is a Java question, not .Net
Jason S
+5  A: 

Try

    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);
    }

Or

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));
    }
}

"Factory" pattern:

    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);
    }

It can be done several other ways (e.g HashMap of algorithms to duplicatable classes of CRCs, etc.)

kd304
heh. My comments are "duh! can't believe i forgot that" and "wow", respectively.
Jason S
@Jason S: Yeah. Are you learning Java now? You seem to have a ton of rep from Java - or it is only from the ton of questions?
kd304
I would say 75% questions, 25% answers... I've been learning Java off and on for the past year or so. I'm an electrical engineer, not a software engineer, with data processing/software tasks sporadically, so I get into these bursts of needing to use Java and learn something quickly, then time in-between to forget half of what I've learned... :/
Jason S
I suspected that. Yet another good example to **Rep** is not about how good you are in the subject. Still it makes this impression for everyone I guess. Btw, are you waiting for more answer?
kd304
+1  A: 

Others have offered solutions to your problem, but my advice is to not use Java reflection where you don't need to. A solution that uses reflection is typically more slower, the code is more complex, and there typically are more "dynamic typing" failure cases to consider.

In your particular example, the "object factory" pattern is a better solution than using reflection to invoke constructors.

Stephen C