gpt4 book ai didi

java - 泛型和 ReadObject

转载 作者:行者123 更新时间:2023-12-02 00:39:24 26 4
gpt4 key购买 nike

我有一个使用泛型和对象序列化的简单服务器。 (T是输入格式,U是输出格式)。仅处理输入的简化版本如下所示:

public class Server <T, U> implements Runnable {

@override
public void run () {

try (ObjectInputStream inReader = new ObjectInputStream (this.connection.getInputStream ())) {
T lastObj;
while (true) {
lastObj = (T) inReader.readObject ();
System.out.println (lastObj.getClass ().getName ());
if (null != lastObj) {
this.acceptMessage (lastObj);
}
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger (this.getClass ().getName ()).log (Level.SEVERE, ex.getMessage (), ex);
}
}
}

如果我用

启动服务器
Server <Integer, String> thisServer = new Server ();

那么我希望它只接受整数对象并返回字符串作为输出。

但是,我使用了一个简单的客户端,它从 System.in 读取数据来测试字符串并将其发送到服务器。令我惊讶的是,服务器接受了输入。只是为了确保它确实接受一个不是 T 类型的对象,我添加了一行来回显最后一个对象是什么类。

System.out.println (lastObj.getClass ().getName ());

这实际上输出了 Java.lang.String。

这完全出乎我的意料。我认为泛型应该允许您传递类本身中未指定的类型的对象,而不必强制转换对象? T 的转换似乎也没有效果。

这意味着理论上我可以通过向服务器(或其消费者)提供不期望类型的 Java 对象来攻击服务器(或其消费者)。虽然这不必非常强大(因为它是一个学术项目而不是生产软件),但我认为知道您使用 readObject 获得的对象不是您想要的对象,以便您可以处理它很重要。

我尝试添加以下内容,但它只是被标记为编译时错误。

if (lastObj instanceof T) {
}

我该如何正确处理这个问题?

最佳答案

正如其他人指出的,此问题与 type erasure 有关。在运行时,T删除至其上限,Object .

当您转换到 T 时,这被称为未检查强制转换,因为它在运行时不存在。相反,编译器已在 T 实例的位置插入了其他转换。被分配回像 Integer 这样的具体化类型。当run使用意外的类型,如 String ,JVM 无法区分,并且不会很快失败。如果有一种方法T getLastObject ,该方法的调用者可能会失败:

Server<Integer, String> thisServer = ...;
thisServer.run(); // consumes a String, but doesn't fail
Integer i = thisServer.getLastObject(); // ClassCastException thrown here

解决方法是提供 Server Class<T> object 表示要消费的对象类型并使用 cast 方法:

public class Server <T, U> implements Runnable {

private final Class<T> readObjectType;

public Server(final Class<T> readObjectType) {
this.readObjectType = readObjectType;
}

@Override
public void run () {

try (ObjectInputStream inReader = new ObjectInputStream (this.connection.getInputStream ())) {
T lastObj;
while (true) {
lastObj = readObjectType.cast(inReader.readObject());
System.out.println (lastObj.getClass ().getName ());
if (null != lastObj) {
this.acceptMessage (lastObj);
}
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger (this.getClass ().getName ()).log (Level.SEVERE, ex.getMessage (), ex);
}
}
}

readObjectType.cast(inReader.readObject())现在,当读取了错误类型的对象时,将会快速失败。

关于java - 泛型和 ReadObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18304003/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com