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

时间:2014-01-26 22:34:27

标签: java

我试图理解我在一篇研究论文中读到的内容,该文章建议您可以通过使用RTTI工具来提高Java中共享对象的性能。主要思想是你有一个带有两个空子类的类来指示主类中隐式“位”的状态。我正在看的参考文献在这里:第3部分:性能中的http://cs.brown.edu/~mph/HellerHLMSS05/2005-OPODIS-Lazy.pdf

我试图用我正在处理的数据结构复制这种技术。基本上我有:

class Node {
...
}

class ValidNode extends Node {}
class DeletedNode extends Node {}

然后我用:

创建一个对象
Node item = new ValidNode();

我想以某种方式将ValidNode的实例强制转换为DeletedNode的实例。我尝试了以下内容:

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

Node dnode = (DeletedNode)node;

但是,两者都以ClassCastException终止。我必须假设我试图做的是一种有效的技术,因为作者(他将这种技术集成到Java1.6库中)清楚地知道他在做什么。但是,我似乎没有足够的Java专家来弄清楚我在这里缺少的东西。

我打算使用

的内容
if ( node instanceof DeletedNode ) { // do stuff here

提前谢谢大家。

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

看起来以下情况可能有效:

class Node {
    ...
}

class ValidNode extends Node {}

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

我会试一试。

2 个答案:

答案 0 :(得分:1)

事实是,所有Java在编译时都知道您已将item声明为Node。但是,在运行时,JVM知道对象的实际类。从那时起,从Java的角度来看,强制转换仅在继承链上是合法的。如果你没有给予足够的重视,那么即使是那个也可能会失败(例如,构建为Node的对象不能被转换为DeletedNode)。由于您继承的Node类型是兄弟类,因此继承链中的强制转换将失败并抛出众所周知的ClassCastException。

答案 1 :(得分:1)

粗略阅读您引用的A Lazy Concurrent List-Based Set Algorithm实际上指的是High Performance Dynamic Lock-Free Hash Tables and List-Based Sets中的算法说明。

值得注意的是,第一篇论文指出:

  

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

标题为AtomicMarkableReference documentation,我们看到此类存储了引用和关联的框boolean

第二篇参考文献显示了在原子比较和交换操作中使用Node的标称子类型的算法。值得注意的是,没有任何演员正在进行,只是一些实例交换。

我可以说使用AtomicReference可能比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

正如评论中所指出的那样,没有办法从一个子类转换到另一个子类,你不能说&#34; Apple&#34;是香蕉&#34;香蕉&#34;即使两者都是&#34; Fruit&#34;的类型。但是,您可以随身携带实例并交换原子引用。