Java 和哈希码中的通用类型

Generic Types in Java and Hash Codes

虽然我知道这不是创建哈希码的最有效方法,但我正在努力通过将数据转换为整数来制作哈希码,这将是它们的哈希码。我正在处理只有 32 位或更少的数据类型(因此只有字节、整数、字符、短整型和浮点型)。在创建程序时,我 运行 遇到了一个必须由泛型引起的问题。我有一个 class,它只接受我上面讨论的数据类型,方法是在 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;
        }

    }

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

编译时出错:

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

任何帮助以及任何比我正在使用的方法更好的方法都将不胜感激。

我想你说的是 serialization

错误信息

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

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

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

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 的类型文字来实现类似的功能。但是随后您必须始终将该文字显式传递给该方法。您的整个 class 没有明确要求是通用的,如果您想 select 在每个单独的方法调用上使用类型,那么将单个方法设为通用就足够了。

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

如果对象的类型为 T,则 Class type gives you an object for the type T at runtime, because that isn't usually available anymore after compilation. With the type object you can do casting to T at runtime. There is some cast method, which takes an Object and returns a T. Furthermore you can check with the isInstance 方法。然而,选择所描述的方法会使类型检查过时,因为如果您不小心将某些内容传递给非 T.

类型的方法,编译器会通知您

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

盲写,不保证拼写错误或编译错误;)

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

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

}