简体   繁体   English

如何调用正确返回泛型类型的方法(Java)?

[英]How to call a method returning generic type correctly (Java)?

I have a generic method which has generic type to return.我有一个泛型方法,它具有要返回的泛型类型。 I would like to call it properly in order to return compilation error in case the returning type, I use it for, does not comply the boundaries this way avoiding run-time errors (vs compilation) and use all the power of Java generic types.我想正确调用它以返回编译错误,以防我使用它的返回类型不符合边界,从而避免运行时错误(与编译)并使用 Java 泛型类型的所有功能。

public <T extends IDeserializable> T restoreObject(byte[] objectArray) {

    T object = T.getDeserialized(objectArray);
    
    return object;
}

However, calling it this way然而,这样称呼它

File ret = restoreObject(new byte[] {1,2,3});

would not produce compilation error and therefore the error will be generated at runtime only.不会产生编译错误,因此只会在运行时产生错误。 The File type does not implement IDeserializable, however java does not generate compilation error. File 类型没有实现 IDeserializable,但是 java 不会产生编译错误。

public interface IDeserializable {
        public static <T> T getDeserialized(byte[] data) {
            return null;
        }
}

There are several problems here:这里有几个问题:

  • Calling static methods on type parameters does not work the way you may think it does ( here is a question about that).对类型参数调用静态方法并不像您认为的那样工作( 是一个关于的问题)。
  • In any case, getDeserialized is an instance method, not a static method, so you can't do T.getDeserialized(objectArray) .无论如何, getDeserialized是一个实例方法,而不是静态方法,所以你不能做T.getDeserialized(objectArray)
  • The compiler cannot infer T just like that.编译器不能像那样推断T @luk2302 has corrected me - T will be inferred as the type of whatever you're assigning the result to. @luk2302 纠正了我 - T将被推断为您将结果分配给的任何类型。

You need to give restoreObject an argument of type T so that the compiler can infer T and so that you can call the getDeserialized method:您需要为restoreObject一个类型为T的参数,以便编译器可以推断出T并且您可以调用getDeserialized方法:

public <T extends IDeserializable> T restoreObject(byte[] objectArray, T t) {
    return t.getDeserialized(objectArray);
}

However, I suspect you meant getDeserialized to be a static method.但是,我怀疑您的意思是getDeserialized是一个静态方法。 Unfortunately, you cannot do that, because static methods don't get overriden.不幸的是,您不能这样做,因为静态方法不会被覆盖。 You can, however, make restoreObject take a Function parameter:但是,您可以使restoreObject带一个Function参数:

public <T extends IDeserializable> T restoreObject(byte[] objectArray, Function<byte[], T> deserialize) {
    return deserialize.apply(objectArray);
}

Then you can use a lambda or method reference for the deserialize argument.然后,您可以对deserialize参数使用 lambda 或方法引用。


You can also use Serializable , but @daniu has pointed out that Serializable will be removed some time in the future and is not a good idea.您也可以使用Serializable ,但@daniu 指出Serializable将在未来一段时间内被删除,这不是一个好主意。 There are tons of libraries out there already so you don't have to handle the serialization/deserialization yourself.已经有大量的库,因此您不必自己处理序列化/反序列化。 Here are some alternatives for serialization in Java. 以下是 Java 中序列化的一些替代方案。 Java also has its own XML API if you don't want to use outside libraries.如果您不想使用外部库,Java 也有自己的 XML API。

This gets obvious really fast, if you could imagine a theoretical type Weirdo that could do:如果你能想象一个理论类型的Weirdo可以做到:

 class Weird extends File implements IDeserializable

And then:进而:

static <T> T getDeserialized(byte[] data) {
        return new Weirdo();
}

Or even simpler (since the cast to a type parameter can't be enforced):或者更简单(因为不能强制转换为类型参数):

 static <T> T getDeserialized(byte[] data) {
      return (T) "";
 }

You can see that the problem is in your getDeserialized to begin with and callers have to trust you.您可以看到问题出在您的getDeserialized开始时,调用者必须信任您。 But if you think why static methods exist in interfaces (their main purpose is to return an instance of the interface), then you are abusing these methods.但是,如果您认为接口中存在静态方法的原因(它们的主要目的是返回接口的实例),那么您就是在滥用这些方法。 What is the point in making it static if no one can override it?如果没有人可以覆盖它,那么将其static有什么意义? You might want to rethink what you are trying to do.您可能想要重新考虑您正在尝试做什么。

But anyway, if you replace that with a class - you will get a compile time error (I will let you figure out why, though):但无论如何,如果你用一个class替换它 - 你得到一个编译时错误(不过我会让你弄清楚原因):

public static class IDeserializable {

    static <T> T getDeserialized(byte[] data) {
        return ...;
    }
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM