Java和哈希代码中的通用类型

时间:2015-12-27 22:04:25

标签: java generics hashcode

虽然我知道这不是创建哈希码的最有效方法,但我正在努力通过将数据转换为整数来创建哈希码,这将是它们的哈希码。我接近这个只有32位或更少的数据类型(因此只是字节,整数,字符,短和浮点)。在创建程序的过程中,我遇到了一个必须与泛型有关的问题。我有一个类只接受我在上面讨论过的数据类型,在if中使用java中的instanceof关键字:

public class HashCode<T>
{
    public static void main(String[]args)
    {
        codeAsInt(2);
        codeAsInt('C');
        codeAsInt("name");
    }
    public int codeAsInt(T value)
    {
        if(value instanceof Integer || value instanceof Character || value instanceof Short || value instanceof Float || value instanceof Byte)
        {
        int hashcode = (int)value;
        return hashcode;
        }

        else
        {
            //you cannot use this method return -1
            return -1;
        }

    }

这样做会导致错误,因为我无法将任何这些类型的“值”转换为T.无论如何,我可以将不同的数据类型传递给使用泛型的方法吗?我知道我可以使用方法重载来解决这个问题(创建接受不同数据类型的不同方法)但是从我学到的方法重载方法与使用不同方法的方法一起使用,对于我的方法它做同样的事情(将数据转换为int) )。我也知道我可以创建一个单独的类来执行此操作,但我认为这对于这么简单的任务来说效率很低。

编译时错误:

error: incompatible types: int cannot be converted to T
        codeAsInt(2);
                  ^
  where T is a type-variable:
  T extends Object declared in class HashCodes
 error: incompatible types: char cannot be converted to T
        codeAsInt('C');
                  ^
  where T is a type-variable:
   T extends Object declared in class HashCodes
 error: incompatible types: String cannot be converted to T
        codeAsInt("name");
                  ^
  where T is a type-variable:
  T extends Object declared in class HashCodes
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
3 errors

Tool completed with exit code 1

任何帮助都会受到赞赏,以及任何比我正在使用的方法更好的方法。

3 个答案:

答案 0 :(得分:1)

错误消息

我猜错误来自于从静态上下文调用泛型非静态方法。要使代码编译,但不能直接工作;),您应该将main方法中的调用更改为:

new HashCode<Integer>().codeAsInt(2);
new HashCode<Character>().codeAsInt('C');
new HashCode<String>().codeAsInt("name");

因此,在您的情况下,需要在创建对象时实例化类并指定T的类型。看来你想让编译器通过参数推断出类型。 Here Oracle提供了有关java的类型推理机制的提示,您可以按如下方式使用您的类。

HashCode<Integer> i = new HashCode<>().codeAsInt(2);
HashCode<Character> c = new HashCode<>().codeAsInt('C');
HashCode<String> s = new HashCode<>().codeAsInt("name");

i.codeAsInt(2);
c.codeAsInt('C');
s.codeAsInt("name");

因此,您可以省略实例化的类型信息,但不能声明声明。我不是100%确定是否可以使用java 1.8的类型推断以更清晰的方式编写它。

可能的解决方案

从java 1.7及更早版本开始,可以使用java的类型文字来实现类似的功能。但是,您必须始终将该文字明确地传递给该方法。你的全班并没有明确要求是通用的,如果你想在每个单独的方法调用上选择类型,那么只需要一个通用的方法就足够了。

public class SomeClass {
    public static <T> int codeAsInt(Class<T> type, T value) {
        // here you can use the type object
        if(type.isInstance(value)) {
        // ...
    }
    public static void main(String... args) {
        codeAsInt(Integer.class, 2);
        codeAsInt(Character.class, 'C');
        codeAsInt(String.class, "name");
    }
}

Class类型在运行时为您提供了类型T的对象,因为在编译之后它通常不再可用。使用type对象,您可以在运行时转换为T。有一些cast方法,需要Object并返回T。此外,如果对象的类型为T,则可以使用isInstance方法进行检查。但是,选择所描述的方法会使类型检查过时,因为如果您不小心将某些内容传递给非T类型的方法,编译器会通知您。

我仍然不确定你到底在寻找什么,但我希望这会有所帮助。如果您只想动态地将任何类型的对象强制转换为T,只需直接使用类型文字转换方法。

盲目写作,不对拼写错误或编译错误提供保证;)

答案 1 :(得分:-2)

我认为你在谈论serialization

答案 2 :(得分:-2)

这是一个使用反射的类,你必须处理抛出的异常并管理它们:

public class Test {

public static void main(String[] args) { // Manage command line argument

    try
    {
        System.out.println(getHashCode("java.lang.String", "10")); // For simplicity    
    }
    catch(Exception e)
    {
        System.err.println("There's a problem with this test ! Here is the details :\n"+e.getMessage());
    }
}

public static int getHashCode(String className, String value) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{

    Class<?> clazz = Class.forName(className);
    Constructor<?> c = clazz.getConstructor(String.class);
    Object o = c.newInstance(value);
    return o.hashCode();
}

}