[英]Cast an Object into a class
我正在尝试将Object转换为类实例。 当然,classes实例的Object应该继承所有方法。
所以这是示例代码(2)中的问题,因为我无法确切解释我的意思:
Class Fish {}
Class Dog {}
class Instances() {
private Fish fish = new Fish();
private Dog dog = new Dog();
public Object getInstance(String className) {
if( className.equals("fish") )
return fish;
else
return dog;
}
}
class test() {
Instances in = new Instances();
public static void main(String[] args) {
// 1: works (transmits all the methods of fish)
Fish fish = (Fish)in.getInstance("fish");
// 2: doesn't work (fishObj only has access to the methods of an object and can't access the methods of Fish!)
Object fishObj = null;
fishObj = (Fish)in.getInstance("fish");
}
}
先感谢您!
当您将对象引用分配给变量时,对引用变量所做的任何进一步操作都将限于为其类型定义的操作。
因此,您可以将Fish
分配给Object
变量。 但是,只要使用Object
变量,就只能使用Object
中定义的方法,例如toString()
, hashCode()
等。
但是您在注释中指出要在两个类中运行类似的方法。 我假设这意味着您的Dog
和Fish
类具有名称,参数和返回类型相似的方法,例如getLegCount()
,对于Dog
,该方法将返回4
;对于Fish
,将返回0
。
当出现这种情况时,您要么必须将这两种类型都声明为另一个具有必需方法的类的子类:
public abstract class Animal {
public abstract int getLegCount();
}
class Fish extends Animal {
@Override
public int getLegCount() {
return 0;
}
}
然后, getInstance()
的返回类型应该是Animal
,而不是Object
。 然后将结果放入Animal
变量中,然后可以使用getLegCount()
方法。
另一种选择是将所需的通用方法定义为接口。 它的工作方式相同,如果预期的Animal
类型中没有实现细节,而仅方法定义, Animal
可取:
public interface Animal {
int getLegCount();
}
class Fish implements Animal {
@Override
public int getLegCount() {
return 0;
}
}
再次,您将从getInstance
的返回类型声明为Animal
而将变量声明为Animal
而不是Object
。
Java编译器会阻止你使用任何方法fishObj
比其他Object
,因为你宣布你的变量fishObj
为类型的Object
。 编译器无法预测在运行时该变量实际上将引用哪种类型的对象,因此它由声明决定。
当然,您和我都可以发现,在调用该方法时, fishObj
将保留对Fish
的引用,但是通常不总是能够找出这种情况,并且Java编译器不会尝试。
你的演员什么也没做。 它通知编译器该表达式的值实际上是Fish
,但是随后将该值分配给Object
类型的变量,就编译器如何查看该变量而言,没有任何改变。 (您的#getInstance
的唯一可能影响是,如果#getInstance
实际上返回的内容不是Fish
, ClassCastException
在运行时会收到ClassCastException
。)
您可以使用Java的反射类获取无法通过变量的声明类型访问的对象的方法。 例如:
fishObj.getClass().getMethod("swim").invoke(fishObj);
让我们看一下您的一些代码:
Object fishObj = null;
fishObj = (Fish)in.getInstance("fish");
那么,为什么可以将Fish类的Object分配给数据类型为Object的变量呢? 在Java中,每个类都派生自Object类,因此Object是每个类的超类。 我们可以将子类的对象分配给超类的变量。 这就是您在这里所做的。
fishObj = (Fish)in.getInstance("fish");
您将Fish类的Object分配给变量fishObj。 这是可能的,因为Fish扩展了Object(即使您没有明确指出它)。 因此,我们可以说fishObj具有静态类型Object(在这种情况下为通用数据类型),以及动态类型Fish(分配给变量的Object)。
静态类型定义可访问的方法,而动态类型定义方法的行为方式。
这是什么意思 ? 让我们看一下Object类的Oracle文档 。 我们可以看到它具有多种方法,例如hashCode()或equals()。 如果静态类型为Object,则可以调用所有这些方法,因为每个子类都需要具有这些方法。 因此,无论发生什么情况,通话都不会失败。
假设您的Fish类具有方法swim()并再次查看一些代码。
Object fishObj = new Fish();
那么什么是静态类型,什么是动态类型? 对象将是静态类型,再次获取动态类型。 现在我们不愿进行以下呼叫。
fishObj.swim(); //won't work
为什么会这样 ? 静态类型的类Object没有一个称为swim()的方法。 因此,我们不能肯定地说我们可以分配给变量fishObj的每个对象肯定都实现了mehtod swim()。
总结一下,我们可以说,由于您的静态类型是Object,因此Fish类的特定方法对您隐藏了,以确保对分配给Variable fishObj的Object的调用始终有效。
Object fishObj = null; fishObj = (Fish)in.getInstance("fish");
该对象被强制转换为具有(Fish)的Fish,但由于您的引用是一个Object引用,因此它又被扩展回Object,因此,这是您看到的唯一方法。
((Fish)fishObj ).printFish();
首先,您的实例在= new Instances();中。 应该是静态的,因为您正在静态变量中使用它
您已将Fish对象关联到基本的Java对象
这被称为运行时多态或动态方法调度,是一个在运行时而不是编译时解决对覆盖方法的调用的过程。 更多
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.