- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
基于此oracle doc example我尝试创建自己的示例来测试它。当然,按照建议引用了示例工作。但是当我尝试基于 Class.cast 方法时,我遇到了问题:
我的代码是
CL3 扩展 CL2 扩展 CL1 扩展 CL0 扩展 Base。
public class CL3 extends CL2 {
int x = 3;
public int getX() { return x; }
}
public class CL2 extends CL1 {
int x = 2;
public int getX() { return x; }
}
public class CL1 extends CL0 {
int x = 1;
public int getX() { return x; }
}
public class CL0 extends Base {
int x = 0;
public int getX() { return x; }
public String getPath() {
System.out.println("before obj : " + getClass().cast(this));
System.out.println("before class : " + getClass());
System.out.println("before x : " + getClass().cast(this).x);
System.out.println("before getX() : " + getClass().cast(this).getX());
System.out.println();
return getClazzPath(getClass());
}
}
public abstract class Base {
int x = -1;
abstract int getX();
@SuppressWarnings("unchecked")
public <T extends CL0> String getClazzPath(Class<T> clazz) {
System.out.println("clazz : " + clazz);
System.out.println("cast : " + clazz.cast(this));
System.out.println("cast.x : " + clazz.cast(this).x);
System.out.println("cast.getX() : " + clazz.cast(this).getX());
System.out.println("#");
return clazz.cast(this).x + (clazz == CL0.class ? "" : "/" + getClazzPath((Class<T>) clazz.getSuperclass()));
}
}
主要功能代码为:
public static void main(String[] args) {
CL3 cl3 = new CL3();
System.out.println("cl3.getX()=" + cl3.getX());
System.out.println("((CL2)cl3).getX()=" + ((CL2) cl3).getX());
System.out.println("((CL1)cl3).getX()=" + ((CL1) cl3).getX());
System.out.println("((CL0)cl3).getX()=" + ((CL0) cl3).getX());
System.out.println("((IdentyfiedScope)cl3).getX()=" + ((Base) cl3).getX());
System.out.println();
System.out.println("cl3.x=" + cl3.x);
System.out.println("((CL2)cl3).x=" + ((CL2) cl3).x);
System.out.println("((CL1)cl3).x=" + ((CL1) cl3).x);
System.out.println("((CL0)cl3).x=" + ((CL0) cl3).x);
System.out.println("((IdentyfiedScope)cl3).x=" + ((Base) cl3).x);
System.out.println();
System.out.println(cl3.getPath());
}
输出是:
cl3.getX()=3
((CL2)cl3).getX()=3
((CL1)cl3).getX()=3
((CL0)cl3).getX()=3
((IdentyfiedScope)cl3).getX()=3
cl3.x=3
((CL2)cl3).x=2
((CL1)cl3).x=1
((CL0)cl3).x=0
((IdentyfiedScope)cl3).x=-1
before obj : test.code.hierarchy.read.CL3@70dea4e
before class : class test.code.hierarchy.read.CL3
before x : 0
before getX() : 3
clazz : class test.code.hierarchy.read.CL3
cast : test.code.hierarchy.read.CL3@70dea4e
cast.x : 0
cast.getX() : 3
#
clazz : class test.code.hierarchy.read.CL2
cast : test.code.hierarchy.read.CL3@70dea4e
cast.x : 0
cast.getX() : 3
#
clazz : class test.code.hierarchy.read.CL1
cast : test.code.hierarchy.read.CL3@70dea4e
cast.x : 0
cast.getX() : 3
#
clazz : class test.code.hierarchy.read.CL0
cast : test.code.hierarchy.read.CL3@70dea4e
cast.x : 0
cast.getX() : 3
#
0/0/0/0
问题是 - 为什么当我们使用 Class.cast(由 getPath().getClazzPath() 调用)方法时,我们得到的结果与直接访问 x 字段时由强制转换运算符产生的结果不同?正如我们看到 getClazzPath 方法 ('clazz : ') 的输出返回正确的类型 CL3 -> CL2 -> CL1 -> CL0 但 x 始终引用 0。
我发现这与 getClazzPath 方法中的 T 类型有关 - 但我不知道如何正确解释它。
是否有任何专家可以解释为什么在我的情况下强制转换运算符和 Class.cast 之间的行为不同?
最佳答案
类型转换不会改变对象的类型。它仅更改对其引用的编译时类型,并在需要时进行有效性检查。
由于强制转换不会更改对象的类型,因此它永远不会更改调用可重写方法(如 getX()
)的结果。 ,它将始终调用最具体的方法。同样,将对象附加到 String
时,强制转换没有效果,因为结果将是调用可重写方法 toString()
.
当涉及到字段或private
时方法中,引用的编译时类型可能会影响访问哪个字段或方法,但是,由于有关类型的知识仅限于泛型方法的类型参数,因此您不能期望对类型产生影响只有调用者知道。
所以当你更换时
@SuppressWarnings("unchecked")
public <T extends CL0> String getClazzPath(Class<T> clazz) {
System.out.println("clazz : " + clazz);
System.out.println("cast : " + clazz.cast(this));
System.out.println("cast.x : " + clazz.cast(this).x);
System.out.println("cast.getX() : " + clazz.cast(this).getX());
System.out.println("#");
return clazz.cast(this).x + (clazz == CL0.class ? "" : "/" + getClazzPath((Class<T>) clazz.getSuperclass()));
}
与
@SuppressWarnings("unchecked")
public <T extends CL0> String getClazzPath(Class<T> clazz) {
System.out.println("clazz : " + clazz);
System.out.println("cast : " + (T)this);
System.out.println("cast.x : " + ((T)this).x);
System.out.println("cast.getX() : " + ((T)this).getX());
System.out.println("#");
return clazz.cast(this).x + (clazz == CL0.class ? "" : "/" + getClazzPath((Class<T>) clazz.getSuperclass()));
}
结果不会改变。与普通类型转换没有区别(T)…
和clazz.cast(…)
当clazz
是 Class<T>
,两者都具有更改对 T
的引用的编译时类型的效果。 1。
但是 T
是什么? ?该方法不知道,它只知道它可以分配给 CL0
,由于声明<T extends CL0>
,因此允许访问 CL0
的成员,包括字段 CL0.x
.
您可能会认为允许访问不可重写的成员(例如 CL0
的字段)是一个语言设计错误。通过类型 T
的引用,尽管T
可以是一个子类,声明自己的同名字段。事实上,对于private
成员,编译器在通过 T
类型的引用访问它们时会生成错误,即使 private
CL0
的成员可以访问。
进一步证明普通类型转换和 Clazz.cast
之间没有区别,你可以改变
System.out.println("cl3.getX()=" + cl3.getX());
System.out.println("((CL2)cl3).getX()=" + ((CL2) cl3).getX());
System.out.println("((CL1)cl3).getX()=" + ((CL1) cl3).getX());
System.out.println("((CL0)cl3).getX()=" + ((CL0) cl3).getX());
System.out.println("((IdentyfiedScope)cl3).getX()=" + ((Base) cl3).getX());
System.out.println();
System.out.println("cl3.x=" + cl3.x);
System.out.println("((CL2)cl3).x=" + ((CL2) cl3).x);
System.out.println("((CL1)cl3).x=" + ((CL1) cl3).x);
System.out.println("((CL0)cl3).x=" + ((CL0) cl3).x);
System.out.println("((IdentyfiedScope)cl3).x=" + ((Base) cl3).x);
你的main
方法
System.out.println("cl3.getX()=" + cl3.getX());
System.out.println("((CL2)cl3).getX()=" + CL2.class.cast(cl3).getX());
System.out.println("((CL1)cl3).getX()=" + CL1.class.cast(cl3).getX());
System.out.println("((CL0)cl3).getX()=" + CL0.class.cast(cl3).getX());
System.out.println("((IdentyfiedScope)cl3).getX()=" + Base.class.cast(cl3).getX());
System.out.println();
System.out.println("cl3.x=" + cl3.x);
System.out.println("((CL2)cl3).x=" + CL2.class.cast(cl3).x);
System.out.println("((CL1)cl3).x=" + CL1.class.cast(cl3).x);
System.out.println("((CL0)cl3).x=" + CL0.class.cast(cl3).x);
System.out.println("((IdentyfiedScope)cl3).x=" + Base.class.cast(cl3).x);
结果也是一样的。这些方法之间没有区别,重要的是在一个地方,您要转换为具体类型 CL3
, CL2
, CL1
, CL0
,或Base
,另一方面,您正在转换为类型参数 T
.
1 区别在于 Class.cast
将在运行时检查有效性,与未经检查的强制转换不同,但由于它们在本例中都是有效的,因此结果不会改变,我们可以关注对成员选择的影响。
关于Java 转换之谜 - Class.cast 与强制转换运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56059363/
我只想知道它们之间的区别: .class .class{ font-size:14px; } 对比: .class > .class{ font-size:14px; } 是一样的东西吗? 最佳答案
PrimeFaces 文档的以下摘录使标题中描述的两个选择器之间似乎存在差异: .ui-widget, .ui-widget .ui-widget { font-size: 90% !imp
我正在尝试选择特定值。但我遇到了一个问题。 我有两个元素,一个有 X Y,另一个有 X Y Z。 当选择 X Y Z 时,我也收到 X Y 的值...有没有办法让它寻找 X AND Y AND Z 而
.class.class 和 .class .class 有什么区别? 最佳答案 .class .class 匹配类 .class 的任何元素,这些元素是类 .class< 的另一个元素的后代/. .
我正在研究 Classname.class 和 Classname.class.toString() 并发现了一些不寻常的东西。 .class 在同一个类上运行时似乎等同于 .class。尽管 .cl
我试图在Dart中扩展列表并在此列表中使用另一个类。 这是我的示例,其中注释出了问题: import "Radio.dart"; // extends ListBase { List ra
我有一个很大的“经理”类,我认为它做得太多了,但我不确定如何将它划分为更多逻辑单元。 一般来说类主要由以下方法组成: class FooBarManager{ GetFooEntities();
我在一个文件中定义了一个抽象父类(super class),在另一个文件中定义了一个子类。我需要父类(super class)文件和堆栈跟踪报告来找到一个包含它。 但是,当它到达“extends”行时
我在 A. Alexenderscu 的现代 C++ 设计中找到了一些模板示例 作者使用以下行的地方 template class CheckingPolicy // class SmartPt
看一下这段代码: public static class A { public void doA() { } } public static class B extends A {
我有两个具有 .body 类的 div,但是,一个位于另一个具有 .box 类的 div 中 - 如下所示: 我只想为 .box 内部的 .body 设置样式...但我在下面所
我一定是遗漏了 C++ 规范中的某些内容,因为我无法解释为什么以下代码可以成功编译: class MyClass { static void fun(); }; int main() { MyClas
我正在尝试在 python 中“模拟”命名空间。我使用内部和外部类层次结构来创建我的命名空间。例如,您希望将文件(如资源)的路径保存在一个位置。我试过这样的事情: src = #path to sou
在试验 online crystal compiler 时(这太棒了),我遇到了一个我似乎无法找到解释的错误: class Person class Current < self end
在查看我的一段代码时,我陷入了如下的一条语句。 TMyObjectClass = TMyObject 类; 我有点困惑,不知道这句话是什么意思。由于 TMyObjectClass 在该语句上方没有声明
我正在编写一个简单的应用程序,以学习一些基本的Dart编程,但无法弄清楚其结构和包含的内容-我得到了一个重复的类Point 首先,我有一个叫做MouseTrack的主类。它将初始化列表并产生循环。 #
在 org.springframework.core.SerializableTypeWrapper (版本 5.2.3),第 112 行有以下代码: if (GraalDetector.in
我希望将鼠标悬停在子导航中的列表项上,以激活页面上该类别中所有项的类(不仅仅是父元素或同级元素)。有任何想法吗?这是我的意思的一个例子: img.BLUE {border:1px solid #FF
我正在通过 ClassLoader 加载类: Class clazz = urlClassLoader.loadClass(name.substring(0, name.length() - 6).r
以下简化的类在从 get() 返回值时执行不同的操作,具体取决于该类是被赋予 double 值还是数组作为模板参数: #include "array" #include "type_traits" t
我是一名优秀的程序员,十分优秀!