出自《java puzzle》
本谜题要测试你对Java的两个最经典的操作符:instanceof和转型的理解程度。下面的三个程序每一个都会做些什么呢?
public class Type1 {
public static void main(String[] args) {
String s = null;
System.out.println(s instanceof String);
}
}
public class Type2 {
public static void main(String[] args) {
System.out.println(new Type2() instanceof String);
}
}
public class Type3 {
public static void main(String args[]) {
Type3 t3 = (Type3) new Object();
}
}
第一个程序,Type1,展示了instanceof操作符应用于一个空对象引用时的行为。尽管null对于每一个引用类型来说都是其子类型,但是instanceof操作符被定义为在其左操作数为null时返回false。因此,Type1将打印false。这被证明是实践中非常有用的行为。如果instanceof告诉你一个对象引用是某个特定类型的实例,那么你就可以将其转型为该类型,并调用该类型的方法,而不用担心会抛出ClassCastExceptionNullPointerException异常。
第二个程序,Type2,展示了instanceof操作符在测试一个类的实例,以查看它是否是某个不相关的类的实例时所表现出来的行为。你可能会期望该程序打印出false。毕竟,Type2的实例不是String的实例,因此该测试应该失败,对吗?不,instanceof测试在编译时刻就失败了,我们只能得到下面这样的出错消息:
Type2.java:3: inconvertible types
found : Type2, required: java.lang.String
System.out.println(new Type2() instanceof String);
^
该程序编译失败是因为instanceof操作符有这样的要求:如果两个操作数的类型都是类,其中一个必须是另一个的子类型[JLS 15.20.2, 15.16, 5.5]。Type2和String彼此都不是对方的子类型,所以instanceof测试将导致编译期错误。这个错误有助于让你警惕instanceof测试,它们可能并没有去做你希望它们做的事情。
第三个程序,Type3,展示了当要被转型的表达式的静态类型是转型类型的超类时,转型操作符的行为。与instanceof操作相同,如果在一个转型操作中的两种类型都是类,那么其中一个必须是另一个的子类型。尽管对我们来说,这个转型很显然会失败,但是类型系统还没有强大到能够洞悉表达式new Object()的运行期类型不可能是Type3的一个子类型。因此,该程序将在运行期抛出ClassCastException异常。这有一点违背直觉:第二个程序完全具有实际意义,但是却不能编译;而这个程序没有任何实际意义,但是却可以编译。
总之,第一个程序展示了instanceof运行期行为的一个很有用的冷僻案例。第二个程序展示了其编译期行为的一个很有用的冷僻案例。第三个程序展示了转型操作符的行为的一个冷僻案例,在此案例中,编译器并不能将你从你所做荒唐的事中搭救出来,只能靠VM在运行期来帮你绷紧这根弦。
分享到:
相关推荐
标题“C# 读取文件类型,不是文件后缀”暗示我们需要关注第二种方法,即不依赖文件扩展名来确定文件类型。这种方法在某些场景下非常重要,因为文件后缀可以被随意更改,但文件的实际内容不会改变。 首先,理解文件...
同时,`System.ValueType`重写了`object`的`Equals()`方法,使得值类型在比较时基于实例的值,而不是引用地址。 C#的统一类型系统允许值类型通过装箱和拆箱与对象进行交互。装箱是将值类型转换为`System.Object`的...
引用类型在内存中存储的是对象的引用,而不是实际的数据。当变量赋值或传递给函数时,传递的是对同一块内存区域的引用,而非拷贝。这意味着改变引用类型的变量会影响所有指向该内存区域的对象。引用类型在内存管理上...
值类型变量直接存储其值,这意味着当你对一个值类型变量进行赋值操作时,实际上是复制了该变量的值。这种复制行为发生在栈上,因为值类型变量通常具有较小的内存占用。栈是一种快速但空间有限的内存区域。 - 特性:...
例如,你不能直接约束一个参数为数组中的特定元素类型,也不能约束为资源类型。此外,PHP的类型约束并不包括自定义类型(如枚举或联合类型),这些通常在其他强类型语言中是可能的。 7. 返回类型提示:除了参数类型...
它们允许你在单个列中存储一组值,而不是单一的值。Oracle提供了两种主要的集合类型:VARRAY(固定大小数组)和NESTED TABLE(可变大小表格)。VARRAY有固定的元素数量限制,而NESTED TABLE则可以动态增长。 例如,...
本文旨在帮助你全面理解指针,让你不再对其感到恐惧。 首先,我们需要理解指针的基本概念。指针是一个变量,它存储的是另一个变量的内存地址。在C语言中,每个变量都有一个内存地址,指针就是这个地址的载体。指针...
这意味着当你创建一个引用类型的实例时,它会分配在堆内存中,并且变量只包含一个指向这个堆内存地址的引用。 #### 二、引用类型赋值过程解析 当我们对引用类型的变量进行赋值操作时,实际上是将源变量所指向的...
需要注意的是,易语言中的自定义数据类型在内存中是以值传递的方式进行操作的,这意味着当你将一个自定义数据类型的变量赋值给另一个变量时,实际上是复制了整个数据结构的内容,而不是引用。这种机制在处理大量数据...
当创建一个引用类型变量时,实际上创建的是对内存中对象的引用,而不是对象本身。例如,`string str = "Hello";`声明了一个字符串变量str,它指向内存中包含"Hello"的字符串对象。 变量是存储数据的容器,它们在...
资源不是内置类型,而是特定扩展创建的。 8. **NULL**:表示变量没有值。当变量被声明但未赋值时,其默认值就是`NULL`。 判断变量类型的函数在PHP中有以下几种: 1. **gettype()**:返回变量的数据类型作为字符串...
易语言是一种国产的、以中文编程为特色的...通过理解这些概念,你可以编写出更加灵活和强大的字符串处理程序。在实践中,还可以结合其他易语言函数,如`字符串比较()`、`字符转换()`等,来实现更复杂的字符处理需求。
强类型DataSet使开发者能够直接操作具有明确数据类型的对象,而不是无类型的DataRow集合。 **强类型DataSet的优势:** 1. **类型安全**:在编译时就能检查代码中对数据的操作是否正确,避免了运行时错误。 2. **更...
例如,如果你有一个`Object`类型的变量,但你知道它应该是一个`String`,你可以先用`is`关键字来检查,然后再进行转换: ```csharp object obj = "Hello, World!"; if (obj is string str) { Console.WriteLine...
然而,不是所有`PolymorphicTest`对象都能被安全地转换为`PolymorphicChild`。只有当`PolymorphicTest`引用实际指向`PolymorphicChild`实例时,这种转化才是安全的,否则会引发`ClassCastException`。 总之,`final...
2. **编译时检查**:由于类型是在编译时确定的,开发者可以立即获取有关类型不匹配或潜在错误的反馈,而不是在程序运行时才暴露问题。这样可以减少调试时间,提高开发效率。 3. **对象实例化**:在强类型登录系统中...
在互联网世界中,MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)类型是一种...通过阅读提供的“mime类型大全.txt”文件,你可以获取更多具体的MIME类型及其用途,进一步提升你的网页制作技能。
在Oracle数据库中更改数据表字段类型虽然不是一项简单的任务,但通过合理的步骤安排和谨慎的操作,完全可以避免潜在的风险,并顺利完成变更。希望本文提供的方法能够帮助你在实际工作中解决类似问题。
在Android应用开发中,数据库是数据持久化的重要手段,而Greendao则是一个高效、轻量级的对象关系映射(ORM)框架,它允许开发者直接操作对象,而不是SQL语句。当应用程序需要进行数据库升级时,例如添加新的数据...
例如,如果你有一个NUMBER类型的字段,想将其转换为VARCHAR2类型,可以使用以下语句: ```sql SELECT CAST(column_name AS VARCHAR2(20)) FROM table_name; ``` 这里,`VARCHAR2(20)`指定了转换后的字符串长度。 2....