模板的类型(如果模板是返回值)(Java)

发布于 2024-08-11 03:31:59 字数 539 浏览 6 评论 0原文

我想知道如果返回设置为模板,模板变量的数据类型是什么。我在某处的代码中看到了这一点,但我不知道它将从会话中检索到的值转换到哪里。

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

外部的代码是:

MyClassType type = request.getFromSessionMap("abc");

该行在转换为我的对象时遇到 ClassCastException。但是当我添加到 watch session.getAttribute("abc") 时,它显示类型是 MyClassType。任何帮助将不胜感激。

显然,使用模板的特殊代码使 getFromSessionMap 返回变量类型,因此不需要强制转换。这适用于所有情况,但突然在代码的一部分失败了。

I was wondering what is the data type of the template variable if the return is set to a template. I have seen this in a code somewhere but I do not know where does it cast the value retrieved from the session.

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

The code for this outside is:

MyClassType type = request.getFromSessionMap("abc");

The line encounters ClassCastException when casting to my object. But when I add to watch session.getAttribute("abc"), it shows that the type is MyClassType. Any help would be appreciated.

Apparently this special code for using template makes the return of getFromSessionMap a variable type and hence no need for a cast. This works on all cases but suddenly it failed in one part of the code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦言归人 2024-08-18 03:31:59

显然这个特殊的代码用于使用
模板返回
getFromSessionMap 变量类型和
因此不需要演员表。

从根本上讲,在获取 session.getAttribute(sessionKey) 的结果和分配给 MyClassType 之间必须进行类型转换。 Java 语言(和 JVM)不允许将某些不是 MyClassType 实例(或其子类型)的对象分配给 MyClassType变量。

无论您如何编写代码,都必须进行类型转换。由于该属性(显然)不是 MyClassType (或子类型),因此您将收到 ClassCastException

所以真正的问题是为什么你没有收到编译错误?答案是@SuppressWarnings("unchecked")!如果删除该警告,您将收到此行的“不安全类型转换”错误消息:

return (T) session.getAttribute(sessionKey);

事实上,Java 无法对泛型类型执行(真实)类型转换。这就是警告/错误消息要指出的内容。事实上,一旦代码被编译,这段代码的

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

含义实际上与此没有什么不同:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

从技术上讲,这称为“类型擦除”。

那么类型检查/类型转换实际发生在哪里?答案就在这一行:

MyClassType type = request.getFromSessionMap("abc");

即使您没有在这里编写类型转换,Java 编译器生成的代码也会在将值分配给 type 之前进行类型转换。必须如此。因为据它所知,它分配的实例可以是任何对象类型。

其他发帖者建议向 getFromSessionMap 添加一个 Class 参数。就其本身而言,这绝对没有任何作用。如果您还将方法的主体替换为:,

return clazz.cast(session.getAttribute(sessionKey));

您将导致该方法实际上执行真正的类型检查。但这只会导致 ClassCastException 在不同的地方抛出。并且赋值语句仍然会进行隐藏类型转换!!

Apparently this special code for using
template makes the return of
getFromSessionMap a variable type and
hence no need for a cast.

Fundamentally, there has to be a typecast somewhere between getting the result of session.getAttribute(sessionKey) and the assignment to MyClassType. The Java language (and the JVM) will not allow some object that is not a MyClassType instance (or a subtype thereof) to be assigned to a MyClassType variable.

No matter how you write the code, a typecast has to occur. And since the attribute (apparently) is not a MyClassType (or subtype), you are getting a ClassCastException.

So the real question is why aren't you getting a compilation error? And the answer is the @SuppressWarnings("unchecked")! If you removed that warning, you would get an "unsafe type conversion" error message for this line:

return (T) session.getAttribute(sessionKey);

In truth, Java cannot do a (real) type cast to a generic type. And that is what the warning / error message is there to point out. In fact, once the code has been compiled, this code

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

is actually no different in meaning from this:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

Technically speaking this is called "type erasure".

So where is the type checking / typecast actually occurring? The answer is in this line:

MyClassType type = request.getFromSessionMap("abc");

Even though you haven't written a typecast here, the code generated by the Java compiler does a typecast before assigning the value to type. It has to. Because as far as it knows, the instance it is assigning could be any object type.

Other posters have suggested adding a Class argument to getFromSessionMap. By itself this does absolutely nothing. If you also replace the body of the method with:

return clazz.cast(session.getAttribute(sessionKey));

you will cause the method to actually do a real type check. But this only cause ClassCastException to be thrown at a different place. And the assignment statement will still do a hidden type cast!!

笨死的猪 2024-08-18 03:31:59

在问题的示例中,返回类型为 T。擦除的类型将是 Object,隐式地为 T extends Object。实际的转换是在调用方法的字节码中执行的(您可以使用 javap -c 来查看)。

一般来说,您应该使会话中“顶级”对象的数量尽可能小。这样做的好处之一是不再需要像这样的黑客方法。

In the question's example, the return type is T. The erased type will be Object as, implicitly, T extends Object. The actual cast is performed in the bytecode of the calling method (you can use javap -c to see that).

Generally, you should keep the number of "top-level" objects in sessions as small as possible. One of the benefits of doing that, is there is no longer a need for hacky methods like these.

深海不蓝 2024-08-18 03:31:59

任何帮助将不胜感激,因为我的代码遇到了 ClassCastException。

如果您收到 ClassCastException,这意味着您正在尝试将某些内容转换为它不是的内容,如以下代码所示:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

ClassCastException 应该具有启发性详细消息,例如“java.lang.String 无法转换为 java.util.Date”。

Any help would be appreciated because my code encounters ClassCastException.

If you're getting a ClassCastException, that means you're trying to cast something into something it isn't, like in the following code:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

The ClassCastException should have an enlightening detail message, like "java.lang.String cannot be cast to java.util.Date".

缘字诀 2024-08-18 03:31:59

您可以在方法主体中使用类型转换('(T)session.getAttribute(sessionKey)')。

这意味着您明确地对编译器说“我绝对确定返回的对象是 IS-A T,如果不是,则准备好处理错误”。

在这里,您对属性类型的假设不正确,并且出现错误。因此,一切都是正确的,运行时已经为您提供了真正的属性对象类型,而不是 IS-A MyClassType。

You use type cast within the method body ('(T)session.getAttribute(sessionKey)').

That means that you explicitly say to compiler 'I'm absolutely sure that returned object IS-A T and ready to handle error if it is not'.

Here your assumption about attribute type was incorrect and you got an error. So, everything is correct and runtime already provides you with the real attribute object type that is not IS-A MyClassType.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文