- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个使用泛型和对象序列化的简单服务器。 (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/
我是一名优秀的程序员,十分优秀!