为什么我要使用 java.lang.Class.cast

发布于 2024-12-12 08:59:04 字数 336 浏览 0 评论 0 原文

我最近偶然发现了一段这样的代码:

Object o = .. ;
Foo foo = Foo.class.cast(o);

我实际上甚至不知道 java.lang.Class 有一个强制转换方法,所以我查看了文档,根据我收集的信息,这只是简单地强制转换为Class 对象代表的类。所以上面的代码大致相当于

Object o = ..;
Foo foo = (Foo)o;

所以我想知道为什么我想使用强制转换方法而不是简单地“以旧方式”进行强制转换。有没有人有一个很好的例子,其中使用强制转换方法比进行简单强制转换更有好处?

I recently stumbled upon a piece of code that went like this:

Object o = .. ;
Foo foo = Foo.class.cast(o);

I was actually not even aware that java.lang.Class had a cast method, so I looked into the docs, and from what I gather this does simply do a cast to the class that the Class object represents. So the code above would be roughly equivalent to

Object o = ..;
Foo foo = (Foo)o;

So I wondered, why I would want to use the cast method instead of simply doing a cast "the old way". Has anyone a good example where the usage of the cast method is beneficial over doing the simple cast?

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

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

发布评论

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

评论(8

末が日狂欢 2024-12-19 08:59:04

我认为它并不像您所展示的那样经常使用。我见过的最常见的用途是使用泛型的人们试图做与此等效的事情:

public static <T extends Number> T castToNumber(Object o) {
    return (T)o;
}

由于类型擦除,这并没有真正做任何有用的事情。

而这有效,并且类型安全(模 ClassCastExceptions):

public static <T extends Number> T castToNumber(Object o, Class<T> clazz) {
    return clazz.cast(o);
}

编辑:来自 google guava 的几个使用示例:

I don't think it's often used exactly as you have shown. Most common use I have seen is where folks using generics are trying to do the equivalent of this:

public static <T extends Number> T castToNumber(Object o) {
    return (T)o;
}

Which doesn't really do anything useful because of type erasure.

Whereas this works, and is type safe (modulo ClassCastExceptions):

public static <T extends Number> T castToNumber(Object o, Class<T> clazz) {
    return clazz.cast(o);
}

EDIT: Couple of examples of use from google guava:

微暖i 2024-12-19 08:59:04

在 Java 中,剥猫皮的方法通常不止一种。如果您有框架代码,此类功能可能会很有用。想象一个方法,它接受一个 Class 对象实例和一个 Object 实例,并返回 Object 实例作为类:

public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o)
    {
        SomeBaseClass castObj =  whatToCastAs.cast(o);
        castObj.doSomething();
    }

通常,使用更简单的转换,除非它不够。

In Java there is often more than one way to skin a cat. Such functionality may be useful in cases where you have framework code. Imagine a method which accepts a Class object instance and an Object instance and returns the Object case as the class:

public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o)
    {
        SomeBaseClass castObj =  whatToCastAs.cast(o);
        castObj.doSomething();
    }

In general, use the simpler casting, unless it does not suffice.

注定孤独终老 2024-12-19 08:59:04

在某些情况下,您只知道在运行时将对象强制转换为的类型,此时您必须使用强制转换方法。

In some cases, you only know the type to cast an object to during runtime, and that's when you have to use the cast method.

别把无礼当个性 2024-12-19 08:59:04

完全没有理由写Foo.class.cast(o),它相当于(Foo)o

一般来说,如果X可具体化的类型,并且Class可具体化的类型。 clazz,则 clazz.cast(o)(X)o 相同。

如果所有类型都是可具体化的,则方法 Class.cast() 是多余且无用的。

不幸的是,由于当前版本的 Java 中的擦除,并非所有类型都是可具体化的。例如,类型变量是不可具体化的。

如果 T 是类型变量,则不选中强制转换 (T)o,因为在运行时,JVM 不知道 T 的确切类型, JVM 无法测试 o 是否确实是 T 类型。可能会错误地允许强制转换,这可能会在以后引发问题。

这不是什么大问题;通常,当程序员执行(T)o时,他已经推断出强制转换是安全的,并且不会在运行时引起任何问题。应用逻辑检查转换。

假设一个 Class clazz 在强制转换时可用,那么我们在运行时就知道 T 是什么;我们可以添加额外的运行时检查以确保 o 确实是 T

check clazz.isInstance(o);
(T)o;

这本质上就是 Class.cast() 的作用。

我们永远不会期望转换在任何情况下都会失败,因此在正确实现的应用程序中,检查 clazz.isInstance(o) 必须始终成功,因此 clazz.cast(o) code> 相当于 (T)o - 再次假设代码是正确的。

如果可以证明代码是正确的并且转换是安全的,出于性能原因,人们可能会更喜欢 (T)o 而不是 clazz.cast(o)。在另一个答案中提出的 MutableClassToInstanceMap 示例中,我们显然可以看到强制转换是安全的,因此简单的 (T)o 就足够了。

There is absolutely no reason to write Foo.class.cast(o), it is equivalent to (Foo)o.

In general, if X is a reifiable type, and Class<X> clazz, then clazz.cast(o) is same as (X)o.

If all types are reifiable, method Class.cast() is therefore redundant and useless.

Unfortunately, due to erasure in current version of Java, not all types are reifiable. For example, type variables are not reifiable.

If T is a type variable, cast (T)o is unchecked, because at runtime, the exact type of T is unknown to JVM, JVM cannot test if o is really type T. The cast may be allowed erroneously, which may trigger problems later.

It is not a huge problem; usually when the programmer does (T)o, he has already reasoned that the cast is safe, and won't cause any problem at runtime. The cast is checked by app logic.

Suppose a Class<T> clazz is available at the point of cast, then we do know what T is at runtime; we can add extra runtime check to make sure o is indeed a T.

check clazz.isInstance(o);
(T)o;

And this is essentially what Class.cast() does.

We would never expect the cast to fail in any case, therefore in a correctly implemented app, check clazz.isInstance(o) must always succeed anway, therefore clazz.cast(o) is equivalent to (T)o - once again, under the assumption that the code is correct.

If one can prove that the code is correct and the cast is safe, one could prefer (T)o to clazz.cast(o) for performance reason. In the example of MutableClassToInstanceMap raised in another answer, we can see obviously that the cast is safe, therefore simple (T)o would have sufficed.

§对你不离不弃 2024-12-19 08:59:04

class.cast 是为泛型类型设计的。

当你构造一个带有泛型参数T的类时,你可以传入一个
班级。然后您可以使用静态和动态进行转换
检查,(T)不会给你。它也不会产生未经检查的
警告,因为它已被检查(此时)。

class.cast is designed for generics type.

When you construct a class with generic parameter T, you can pass in a
Class. You can then do the cast with both static and dynamic
checking, which (T) does not give you. It also doesn't produce unchecked
warnings, because it is checked (at that point).

夜深人未静 2024-12-19 08:59:04

常见的示例是当您从持久层检索使用类对象和某些条件引用的实体集合时。返回的集合可能包含未经检查的对象,因此如果您只是将其强制转换为指向 G_H,则此时将抛出强制转换异常,而不是在访问值时抛出强制转换异常。

一个示例是,当您从返回未经检查的集合的 DAO 检索集合并在您的服务上对其进行迭代时,这种情况可能会导致 ClassCastException。

解决这个问题的一种方法是,当您拥有所需的类和未检查的集合时,对其进行迭代并将其投射到 DAO 中,将集合转换为检查的集合,然后返回它。

The common sample for that is when you retrieve from persistent layer a collection of entity referenced with a Class Object and some conditions. The returned collection could contain unchecked objects, so if you just cast it as pointed G_H, you will throw the Cast Exception at this point, and not when the values are accessed.

One example for this is when you retrieve a collection from a DAO that returns an unchecked collection and on your service you iterate over it, this situation can lead to a ClassCastException.

One way to solve it, as you have the wanted class and the unchecked collection is iterate over it and cast it inside the DAO transforming the collection in a checked collection and afterwards return it.

爱的那么颓废 2024-12-19 08:59:04

因为你可能有这样的东西:

Number fooMethod(Class<? extends Number> clazz) {
    return clazz.cast(var);
}

Because you might have something this:

Number fooMethod(Class<? extends Number> clazz) {
    return clazz.cast(var);
}
我只土不豪 2024-12-19 08:59:04

Java 中的“强制转换”,例如 (Number)var,其中括号内的内容是引用类型,实际上由两部分组成:

  • 编译时:强制转换表达式的结果具有以下类型您转换为运行时的类型
  • :它插入一个检查操作,这基本上是说,如果该对象不是该类的实例,则抛出一个 ClassCast Exception(如果您要转换为的对象)是一个类型变量,那么它检查的类将是类型变量的下限)

要使用语法,您需要在编写代码时了解类。假设您在编译时不知道要转换为哪个类;你只有在运行时才知道。

现在你可能会问,那么铸造的意义是什么?转换的目的不就是在编译时将表达式转换为所需的类型吗?因此,如果您在编译时不知道类型,那么在编译时就没有任何好处,对吧?确实如此,但这只是上面的第一项。您忘记了强制转换的运行时组件(上面的第二项):它根据类检查对象。

因此,运行时强制转换(即Class.cast())的目的是检查该对象是否是该类的实例,如果不是,则抛出异常。它大致相当于这个,但更短:

if (!clazz.isInstance(var))
    throw new ClassCastException();

有些人提到 Class.cast() 也有一个很好的返回类型,它基于传入的类的类型参数,但这只是一个无论如何,编译时功能都是由编译时强制转换提供的。因此,为了这个目的,使用 Class.cast() 是没有意义的。

A "cast" in Java, e.g. (Number)var, where the thing inside the parentheses is a reference type, really consists of two parts:

  • Compile time: the result of the cast expression has the type of the type you cast to
  • Run time: it inserts a check operation, which basically says, if the object is not an instance of that class, then throw a ClassCast Exception (if the thing you're casting to is a type variable, then the class it checks would be the lower bound of the type variable)

To use the syntax, you need to know the class at the time you write the code. Suppose you don't know at compile-time what class you want to cast to; you only know it at runtime.

Now you would ask, then what is the point of casting? Isn't the point of casting to turn the expression into the desired type at compile time? So if you don't know the type at compile time, then there is no benefit at compile-time, right? True, but that is just the first item above. You're forgetting the runtime component of a cast (second item above): it checks the object against the class.

Therefore, the purpose of a runtime cast (i.e. Class.cast()) is to check that the object is an instance of the class, and if not, throw an exception. It is roughly equivalent to this but shorter:

if (!clazz.isInstance(var))
    throw new ClassCastException();

Some people have mentioned that Class.cast() also has a nice return type that is based on the type parameter of the class passed in, but that is just a compile-time feature that is provided by a compile-time cast anyway. So for that purpose there is no point in using Class.cast().

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