Java:将一个子类转换为另一个子类?

Java:将一个子类转换为另一个子类?,java,Java,我试图理解我在一篇研究论文中读到的一些东西,该论文建议您可以通过使用RTTI工具来提高Java中共享对象的性能。其主要思想是,您有一个包含两个空子类的类,以指示主类中隐式“位”的状态。我正在看的参考资料在这里的论文中:第3节:性能 我正试图用我正在研究的数据结构来复制这项技术。基本上,我有: class Node { ... } class ValidNode extends Node {} class DeletedNode extends Node {} 然后,我创建一个具有以下内容的对

我试图理解我在一篇研究论文中读到的一些东西,该论文建议您可以通过使用RTTI工具来提高Java中共享对象的性能。其主要思想是,您有一个包含两个空子类的类,以指示主类中隐式“位”的状态。我正在看的参考资料在这里的论文中:第3节:性能

我正试图用我正在研究的数据结构来复制这项技术。基本上,我有:

class Node {
...
}

class ValidNode extends Node {}
class DeletedNode extends Node {}
然后,我创建一个具有以下内容的对象:

Node item = new ValidNode();
我想以某种方式将我的
ValidNode
实例强制转换为
DeletedNode
的实例。我尝试了以下方法:

Node dnode = DeletedNode.class.cast( node );

但是,两者都以ClassCastException终止。我必须假设我所尝试的是一种有效的技术,因为作者(他将此技术集成到Java1.6库中)清楚地知道自己在做什么。然而,我似乎没有足够的Java大师来找出我在这里遗漏了什么

我打算用一些类似于

if ( node instanceof DeletedNode ) { // do stuff here
提前谢谢大家

============= 编辑:

看起来以下方法可能有效:

class Node {
    ...
}

class ValidNode extends Node {}
然后,我创建(未删除)类型为
ValidNode
的节点。当我希望将一个节点标记为已删除时,我会将该节点向上转换为键入
node
。然后,我可以使用
if(!(node instanceof ValidNode))
测试节点是否已被删除


我将尝试一下。

事实是,Java在编译时只知道您已经将
声明为
节点
。然而,在运行时,JVM知道对象的实际类。从那时起,从Java的角度来看,强制转换只在继承链上合法。如果您没有给予足够的注意,即使这样也可能失败(例如,构建为节点的对象不能转换为DeletedNode)。由于继承的节点类型是同级类,沿继承链的强制转换将失败,并将抛出众所周知的ClassCastException。

粗略阅读引用的节点类型实际上指向中的算法描述

值得注意的是,第一份文件指出:

实现在下一个指针中标记位的效果比使用
AtomicMarkableReference
更有效,方法是为每个条目对象创建两个普通(空)子类,并在运行时使用RTTI确定当前实例是哪个子类,其中每个子类表示标记位的状态

转到,我们看到这个类存储了一个引用和一个相关的装箱
布尔值

第二篇参考文献展示了在原子比较和交换操作中使用
节点
的标称子类型的算法。值得注意的是,没有铸造进行,只是一些实例交换

我可以推断,使用可能比使用
AtomicMarkableReference
更快,因为在CAS操作期间要获取和设置的内容更少。使用子类实际上可能更快,但代码如下所示:

AtomicReference<? extends Node> ref = new AtomicReference<? extends Node>();
Node deletedNode = new DeletedNode();
Node validNode = new ValidNode();
...
ref.compareAndSet(validNode, deletedNode); // or some logic

AtomicReferencerti在Java中被称为“反射”。作者可能知道他在做什么,但你可能不理解他正确地做了什么。把苹果扔给香蕉是没有意义的。苹果是苹果,不能通过浇铸而变成香蕉。将一个水果转换为苹果是有意义的,并且只有当水果确实是苹果时才会起作用。在那篇文章中,我没有看到任何关于在子类之间转换的内容。记住RTTI中的I代表推断(或识别),你不需要对类型做任何事情,只需要尝试确定它是什么。我看第11页的底部,作者提到了“LockFreeRTTI”算法,它指的是拥有一个实体的两个空子类,并在运行时使用RTTI确定当前实例是什么。一个子类表示位为“开”的实例,另一个子类表示位为“关”的实例。这也意味着必须有某种方法来“翻转”该(隐含)位,因为实现的原始算法涉及设置引用位。强制转换只会更改引用。我不确定作者在那里说的是什么。不能在运行时更改对象的类。我想你误解了演员的实际工作。强制转换不会更改对象的类型,只更改引用的类型。因此,理论上,我可以创建一个带有“ValidNode”(空)子类的“节点”,为了“旋转”位,我将该ValidNode强制转换为其超类,然后我可以检查(ValidNode的节点实例)如果节点还没有被删除,你会告诉我吗?这是同一件事。你基本上是说你想沿着链条往上走,然后走另一条路。不,它不是按您所说的方式工作。要检查节点是否被删除,您可能需要在基类中添加一个方法isDeleted()或其他内容,然后在子类中重写它。您可以编写类似if(item.isDeleted())的内容,而不是奇怪的强制转换,这样更为优雅。再说一遍,我不知道你的最终目标是什么,所以…@KenP:casting不会改变对象的类型。从未。而且没有办法改变对象的类型。你所能做的就是创建另一个不同类型的对象。我的最终目标是尽可能地复制本文中描述的算法,以便将我的(新)算法与它进行比较。我已经向其中一位作者请求了他们使用的原始代码,但从未发布过,原始实体(Sun实验室)也不再存在。
AtomicReference<? extends Node> ref = new AtomicReference<? extends Node>();
Node deletedNode = new DeletedNode();
Node validNode = new ValidNode();
...
ref.compareAndSet(validNode, deletedNode); // or some logic