Java 动态、静态投射
Java dynamic, static casting
import javax.swing.*;
public class Toast {
static Object[] objects = { new JButton(),
new String("Example"), new Object() };
public static void main(String[] args) {
System.out.println( new Count(objects) );
for (Object o : objects)
System.out.println(o);
}
}
class Count {
int b, s, o;
public Count(Object[] objects) {
for (int i=0; i<objects.length; i++)
count(objects[i]);
}
public void count(JButton x) { b++; }
public void count(String x) { s++; }
public void count(Object x) { o++; }
public String toString() {
return b + " : " + s + " : " + o + "\n";
}
}
以上是一段代码,它以某种形式出现在我即将进行的一项考试的过去试卷中。这个问题的目的是衡量你是否完全理解多态性、动态和静态转换。 OO的基本思想。
我想发表我认为正确的内容,如果人们能够纠正我或添加要点,我们将不胜感激。
从上面的代码可以看出:
项目被向上转换为对象数组中的对象,因为 java 中的每个 class 在技术上都继承自对象 class。这就是为什么当计数为 运行 时,它会说有 3 个对象,而不是 1 个 Jbutton、1 个字符串和 1 个对象。
当增强的 for 循环是 运行 该对象类型的 toString,例如来自对象的字符串和内存地址的示例(不确定 JButton 将打印什么)。由于这是在 运行 时间完成的,因此称为动态铸造。
我看不到与上述代码相关的任何其他要点。
以下是我要带走的内容:
编译器在执行赋值时隐式向上转型。这包括在初始化期间分配给数组元素。
编译器和 JVM 在选择方法重载时不会隐式向下转换。对象数组的静态类型是Object[]
,所以count(Object)
方法总是会被调用。
JVM 在调用虚方法时隐式地"downcast"(某种意义上)。 println 循环将始终调用实际对象实例的 toString 方法,而不是始终调用 Object.toString.
在您的 Count() 方法中,将始终调用 count(object),因为所有对象都向上转换为 object。
为防止您可以调用方法实例,然后向下转换对象并调用计数
public Count(Object[] objects) {
for (int i=0; i<objects.length; i++)
{
if(objects[i] instanceof JButton)
count((JButton) objects[i]);
else if(objects[i] instanceof String)
count((String) objects[i]);
else
count(objects[i]);
}
}
静态转换和动态转换背后的思想与需要做出类型决定的时刻有关。如果它需要由编译器制作,那么它就是静态转换。如果编译器将决定推迟到运行时,那么它就是动态转换。
所以,你的第一个观察是不正确的。 upcast 不解释计数。对象不会松散它们的类型,但编译器需要执行 static cast 来决定调用哪个方法并选择 count(Object)
。 java 中没有动态调度,这意味着调用的方法总是在编译时决定的。
你的第二个观察也不正确。使用的是多态性。在 Java 中,方法总是针对实例的类型调用,而不是针对代码中的类型。此外,这里没有动态转换。编译器可以验证所有类型。只是方法调用总是 virtual
但这不是强制转换。
实际上在这个例子中,我没有看到一个动态转换的案例。编译器可以验证所有类型。您通常只会在向下转换时看到动态转换,而没有这种情况。
import javax.swing.*;
public class Toast {
static Object[] objects = { new JButton(),
new String("Example"), new Object() };
public static void main(String[] args) {
System.out.println( new Count(objects) );
for (Object o : objects)
System.out.println(o);
}
}
class Count {
int b, s, o;
public Count(Object[] objects) {
for (int i=0; i<objects.length; i++)
count(objects[i]);
}
public void count(JButton x) { b++; }
public void count(String x) { s++; }
public void count(Object x) { o++; }
public String toString() {
return b + " : " + s + " : " + o + "\n";
}
}
以上是一段代码,它以某种形式出现在我即将进行的一项考试的过去试卷中。这个问题的目的是衡量你是否完全理解多态性、动态和静态转换。 OO的基本思想。
我想发表我认为正确的内容,如果人们能够纠正我或添加要点,我们将不胜感激。
从上面的代码可以看出:
项目被向上转换为对象数组中的对象,因为 java 中的每个 class 在技术上都继承自对象 class。这就是为什么当计数为 运行 时,它会说有 3 个对象,而不是 1 个 Jbutton、1 个字符串和 1 个对象。
当增强的 for 循环是 运行 该对象类型的 toString,例如来自对象的字符串和内存地址的示例(不确定 JButton 将打印什么)。由于这是在 运行 时间完成的,因此称为动态铸造。
我看不到与上述代码相关的任何其他要点。
以下是我要带走的内容:
编译器在执行赋值时隐式向上转型。这包括在初始化期间分配给数组元素。
编译器和 JVM 在选择方法重载时不会隐式向下转换。对象数组的静态类型是
Object[]
,所以count(Object)
方法总是会被调用。JVM 在调用虚方法时隐式地"downcast"(某种意义上)。 println 循环将始终调用实际对象实例的 toString 方法,而不是始终调用 Object.toString.
在您的 Count() 方法中,将始终调用 count(object),因为所有对象都向上转换为 object。 为防止您可以调用方法实例,然后向下转换对象并调用计数
public Count(Object[] objects) {
for (int i=0; i<objects.length; i++)
{
if(objects[i] instanceof JButton)
count((JButton) objects[i]);
else if(objects[i] instanceof String)
count((String) objects[i]);
else
count(objects[i]);
}
}
静态转换和动态转换背后的思想与需要做出类型决定的时刻有关。如果它需要由编译器制作,那么它就是静态转换。如果编译器将决定推迟到运行时,那么它就是动态转换。
所以,你的第一个观察是不正确的。 upcast 不解释计数。对象不会松散它们的类型,但编译器需要执行 static cast 来决定调用哪个方法并选择 count(Object)
。 java 中没有动态调度,这意味着调用的方法总是在编译时决定的。
你的第二个观察也不正确。使用的是多态性。在 Java 中,方法总是针对实例的类型调用,而不是针对代码中的类型。此外,这里没有动态转换。编译器可以验证所有类型。只是方法调用总是 virtual
但这不是强制转换。
实际上在这个例子中,我没有看到一个动态转换的案例。编译器可以验证所有类型。您通常只会在向下转换时看到动态转换,而没有这种情况。