在 Java 中转换的成本是多少?避免它是个好主意吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26335959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:44:24  来源:igfitidea点击:

What is the cost of casting in Java? Is it a good idea to avoid it?

javacasting

提问by Hyman

I know there are two types of casting that are implicitand explicitcastings. I read different questions on the StackOverflow such as this, thisand thisbut I am still wondering what is the cost of casting in Java and is it a good idea to avoid it? What is the best practice for it?

我知道有两种类型的转换,即隐式转换显式转换。我在 StackOverflow 上阅读了不同的问题,例如thisthisthis但我仍然想知道在 Java 中转换的成本是多少,避免它是一个好主意吗?它的最佳做法是什么?

There are 2 types of casting:

有两种类型的铸造:

String s = "Cast";
Object o = s; // implicit casting

Object o = someObject;
String s = (String) o; // explicit casting

In this second case, there is overhead in runtime, because the two type must be checked and in case that casting is not feasible, the JVM must throw a ClassCastException.

在第二种情况下,运行时存在开销,因为必须检查这两种类型,并且在强制转换不可行的情况下,JVM 必须抛出一个ClassCastException.

Someone said it is better to profile the application to make sure casting is useful or not.

有人说最好对应用程序进行概要分析以确保转换是否有用。

回答by Holger

Type casts are usually an indicator that you should think about an alternative solution for your problem. After all, everything which can be checked at compile time will help the programmer.

类型转换通常是您应该考虑问题的替代解决方案的指标。毕竟,在编译时可以检查的所有内容都会对程序员有所帮助。

However, sometimes type casts are unavoidable and in Generic code they happen often without the programmer ever noticing. Therefore, significant effort was made to make type cast quite fast.

然而,有时类型转换是不可避免的,并且在通用代码中它们经常发生而程序员从未注意到。因此,我们付出了巨大的努力来使类型转换非常快。

In the past, a runtime type cast included the possibility that the super type hierarchy has to be traversed to find a match. Today, a type cast is nothing more than a number comparison plus a simple pointer comparison, if not optimized away when the analyzer could prove that the cast will always succeed.

过去,运行时类型转换包括必须遍历超类型层次结构才能找到匹配项的可能性。今天,类型转换只不过是一个数字比较加上一个简单的指针比较,如果分析器可以证明转换总是成功的时候不优化掉。

In order to make type casting fast, every class knows its depth in the class hierarchy and has a table containing all super types. To test a class, its depth is compared and if the depth is lower, it can't be a compatible class and the type cast fails. Otherwise, the table's entry at the position equal to the depth of the check class must match exactly, so that's all to test.

为了快速进行类型转换,每个类都知道它在类层次结构中的深度,并有一个包含所有超类型的表。为了测试一个类,它的深度被比较,如果深度较低,它不能是一个兼容的类并且类型转换失败。否则,表在等于检查类深度的位置的条目必须完全匹配,所以这就是要测试的。

For example:

例如:

Object o=new JButton();
Container c=(Container)o;

Class Containerhas a depth of 3 and a the following table of superclasses:

Container具有 3 的深度和下表的超类:

Object
Component
Container

Class JButtonhas a depth of 5 and a the following table of superclasses:

JButton的深度为 5,超类如下表:

Object
Component
Container
JComponent
JButton

Now the type cast checks:

现在类型转换检查:

  • JButtonhas a depth of 5 which is ≥ 3, the depth of Container, so the test might succeed
  • The third entry in the tables is checked and is an exact match:

    Object          Object
    Component       Component
    Container   <=> Container
    JComponent
    JButton
    
  • JButton深度为 5,即≥ 3的深度Container,因此测试可能会成功
  • 检查表中的第三个条目并且是完全匹配的:

    Object          Object
    Component       Component
    Container   <=> Container
    JComponent
    JButton
    

So the hierarchy is not traversed anymore and the type cast operation is rather cheap.

因此不再遍历层次结构,并且类型转换操作相当便宜。

回答by assylias

In this second case, there is overhead in runtime, because the two type must be checked and in case that casting is not feasible, JVM must throw a ClassCastException.

在第二种情况下,运行时存在开销,因为必须检查这两种类型,并且在强制转换不可行的情况下,JVM 必须抛出 ClassCastException。

Not necessarily, it is very likely that for a simple case like this the JIT will be able to figure out that the cast will always work and will optimise the check away. Running a microbenchmarkconfirms the assumption:

不一定,对于像这样的简单情况,JIT 很可能能够确定演员表始终有效,并将优化检查。运行微基准测试证实了以下假设:

Benchmark                  Mode  Samples  Score   Error  Units
c.a.p.SO26335959.cast      avgt        5  3.177 ± 0.060  ns/op
c.a.p.SO26335959.noCast    avgt        5  3.174 ± 0.108  ns/op

In more complicated situations, branch prediction will work in your favour too.

在更复杂的情况下,分支预测也会对您有利。

Bottom line, as usual: measure, don't guess!

底线,像往常一样:衡量,不要猜测!

回答by phil_20686

Unless you are writing a performance critical loop for a server, then you should not be thinking about what is faster. Think instead of what makes clean, maintainable code. And casting is almost always in tension with those goals, and can usually be eliminated by better code structure.

除非您正在为服务器编写性能关键循环,否则您不应该考虑什么更快。想想是什么让代码干净、可维护。并且强制转换几乎总是与这些目标紧张,通常可以通过更好的代码结构来消除。

To answer your questions. Up casting usually costs virtually nothing, (when you change the reference type to a parent class of the object). Knowledge of the reference type is enough to decide if uptyping is valid, it just gets the class loader to look up the inheritance map. It is also a check that can be done at compile time. (Unless the reference type was already down cast).

回答你的问题。向上转换通常几乎没有成本(当您将引用类型更改为对象的父类时)。引用类型的知识足以决定 uptyping 是否有效,它只是让类加载器查找继承映射。它也是一个可以在编译时完成的检查。(除非引用类型已经向下转换)。

Down casting is slower, as the JVM must take the reference, look up the actual object class, which may have many types (implement many interfaces), and for each such interface it then checks to see if you are casting to a valid type by (more or less) uptyping on each of the (possibly many) reference types. Since down casting makes reference to the actual object, it can only be checked at run time.

向下转换较慢,因为 JVM 必须获取引用,查找实际的对象类,它可能有许多类型(实现许多接口),然后对于每个这样的接口,它会检查您是否正在转换为有效类型(或多或少)对每个(可能很多)引用类型进行更新。由于向下转换引用了实际对象,因此只能在运行时进行检查。

Down casting is not usually a performance issue anyway, (and is probably JVM dependent), but I believe that it might be possible to make it so via a pathological choice of inheritance structure. Especially in languages that allow multiple inheritance.

无论如何,向下转换通常不是性能问题(并且可能依赖于 JVM),但我相信有可能通过病态的继承结构选择来实现它。特别是在允许多重继承的语言中。

You might find this linkinteresting

您可能会发现此链接很有趣

回答by ponomandr

Generated byte code contains instruction checkcast. So yes, casting costs something. Though it's not expensive and most likely it will be optimized by JIT in runtime.

生成的字节码包含指令checkcast。所以是的,铸造成本。虽然它并不昂贵,而且很可能会在运行时通过 JIT 进行优化。

回答by Peer Overbeck

Avoid cast if possible. Casted stuff is harder to maintain and therefore has higher cost - if you need to check an object, use 'instanceof'(for example:

如果可能,避免强制转换。铸造的东西更难维护,因此成本更高 - 如果您需要检查对象,请使用“instanceof”(例如:

if (o instanceof String) {
   // do something
}

the JVM uses this to check, whether your object is a String and will return true because you set o = s).

JVM 使用它来检查您的对象是否是一个字符串,并且将返回 true,因为您设置了 o = s)。

If you change superclass of a class later on in your code, casts may no longer work and you need to rework your code, while behind instanceof you can simply change the class it should be checked for.

如果稍后在代码中更改类的超类,则强制转换可能不再起作用,您需要重新编写代码,而在 instanceof 后面,您可以简单地更改应该检查的类。

//please correct me if I am wrong on anything.

//如果我有任何错误,请纠正我。

About the cost of casting time-wise: As I mentioned before, it will cost a lot of time if you change your code, or change superclasses, later. Runtime-wise, as casting is done because there is no type-safety, it takes less runtime for a check then it costs for an exception due to an unpermitted cast attempt.

关于时间转换的成本:正如我之前提到的,如果您稍后更改代码或更改超类,将花费大量时间。在运行时方面,由于没有类型安全性,因此进行了强制转换,因此检查所需的运行时间少于由于未经许可的强制转换尝试而导致的异常成本。