将一种对象类型分配给另一种对象类型时,Java变量是如何工作的?
我真的不知道如何立即解释我的怀疑,所以我将从一个例子开始。我有以下几行:
Object myObject = null;
Integer myInteger = 10;
myObject = myInteger;
基本上,我知道我可以将一个子类对象分配给一个超类对象(在这个场景中,myInteger类型为Integer
,而myObject类型为Object
)。到目前为止还不错,但现在。。。假设我想得到myObject的类
System.out.println("myObject: " + myObject.getClass());
它打印了这个:
myObject: class java.lang.Integer
它说是类型Integer
我知道一个变量实际上在内存中存储了对实际对象的引用,因此方法getClass()
返回实际对象的类。但是
为什么我不能通过myObject访问类
Integer
的方法,因为它指向类型为Integer
的对象?我是说,为什么我不能做这样的事myObject.intValue();
如果我只能通过myObject访问
Object
的方法(即使它指向类型为Integer
的对象),Java如何知道可以通过myObject调用哪些方法?变量本身存储一种类型的类
基本上,我想知道Java在变量中存储了什么信息,它只是一个引用吗?或者它还有一个类名?如果变量已将引用分配给子类对象,它如何知道可以调用哪些方法
我希望我的疑问是清楚的,请原谅我的语法
# 1 楼答案
一般商品:
贵重物品:
奢侈品:
让我们看看你的流程步骤是怎么做的:
在线系统:
保安:
你觉得这些场景怎么样
提示:不,系统知道他们有普通货物层,不提供专门的守卫服务李>
提示:没有(仍然),因为系统知道这是一个普通商品预订李>
提示:是的。但客户仍然无法获得奢侈品服务。对吧李>
提示:不,它不能,因为它不知道客户在想什么,也不能检查物品李>
提示:是的,因为他们可以看到物理项目并确定它实际上是什么。而且,由于保险禁止在更高级别的低价值物品,警卫可以阻止这种情况李>
Java也是如此(粗略地说):
换句话说,在线系统就像编译器,物理位置就像运行时。
在Java中,在线保留的层类型称为“静态类型”,即编译时(预订时)已知的类型。放入框中的实际类型称为“运行时类”,是动态的(就像一个普通的商品层盒子可以容纳黄金,或者一个中等价值的物品,比如电视)
就像盒子一样,只有运行时知道变量的实际/运行时类:只有现场工作人员知道它是盒子里的金子。当你调用
myObject.getClass()
时,这正是你想要的:myObject
的运行时类(这是调用其构造函数或使用new
的类;或者在某些情况下,是文本类,例如int
或Integer
,但这是另一天的故事)。但即使在运行时它被称为Integer
,编译器(在线系统,记得吗?)不会让你调用Integer
上的方法,因为myObject
被声明为Object
:在线系统不会让你看到普通商品预订的视频片段,即使盒子里有钻石。你可以用类型转换强制编译器接受Integer
上的myObject
方法,如Sweeper's good answer所示,这有点像是升级到网站上的奢侈品,之后在线系统会让你获得更高级别的服务:)这种类比在某些方面可能是荒谬的,例如编译器阻止您将不兼容或更广泛的类型化值分配给变量。。。但这只是一个例子,一个有限的例子我>
# 2 楼答案
你的问题的答案基本上可以归结为两个关键点:“编译器不允许你做危险的事情”和“编译器没有你想象的那么聪明”
您知道这一点,因为您看到行
myObject = myInteger;
,所以您知道myObject
将有一个intValue()
方法当编译器看到您调用
myObject.intValue();
时,它不会像您那样返回几行来找出myObject
实际引用的内容。它只看到它的类型是Object
,并且只允许使用Object
中定义的可用内容。因为它不会回顾myObject
实际上指的是什么,就编译器而言,myObject
可以指的是Integer
,但它也可以指的是String
,因为您可以做到:String
没有intValue()
方法。“安全总比抱歉好”,编译器说,而且不允许你调用intValue
。您可以通过强制转换告诉编译器您更了解:这是由表达的类型决定的。表达式
myObject
的类型为Object
,因为变量myObject
的类型为Object
。另一方面,表达式((Integer)myObject)
是类型Integer