在Java中投射对象
我对于在Java中投入对象意味着什么感到困惑。
假设你有…
Superclass variable = new Subclass object(); (Superclass variable).method();
这里发生了什么? variablestypes是否改变,或者variables内的对象是否改变? 非常困惑。
看看这个例子:
public class A { //statements } public class B extends A { public void foo() { } } A a=new B(); //To execute **foo()** method. ((B)a).foo();
假设你有一个超类Fruit和子类Banana ,你有一个方法addBananaToBasket()
该方法不会接受葡萄 ,所以你要确保你正在篮子里加香蕉。
所以:
Fruit myFruit = new Banana();
((Banana)myFruit).addBananaToBasket();
⇐这就是所谓的铸造
你所指的例子在java中被称为Upcasting。
它创build一个具有指向它的超类variables的子类对象。
variables不会改变,它仍然是超类的variables,但是它指向了子类的对象。
例如让我们说你有两个类机器和相机; 相机是机器的一个子类
class Machine{ public void start(){ System.out.println("Machine Started"); } } class Camera extends Machine{ public void start(){ System.out.println("Camera Started"); } public void snap(){ System.out.println("Photo taken"); } } Machine machine1 = new Camera(); machine1.start();
如果你执行上面的语句,它将创build一个Camera类的实例,引用Machine类指向它。所以,现在输出将是“ Camera Started ”。该variables仍然是Machine类的引用。 如果你尝试machine1.snap();
代码将不会编译
这里的外卖是所有相机是机器,因为相机是机器的一个子类,但所有的机器不是相机。 所以你可以创build一个子类的对象,并将其指向一个超类的引用,但是你不能要求超级类引用来完成子类对象的所有function(在我们的例子中是machine1.snap()
不会编译)。 超类引用只能访问超类已知的函数(在我们的例子中为machine1.start()
)。 你不能要求一个机器参考来捕捉。 🙂
Superclass variable = new subclass object();
这只是创build一个types的子类的对象,但分配给types的超类。 所有子类的数据都被创build等,但variables不能访问子类的数据/函数。 换句话说,你不能调用任何方法或访问特定于子类的数据,你只能访问超类的东西。
但是,您可以将Superclassvariable强制转换为子类并使用其方法/数据。
有时你会喜欢收到一个父引用的参数,并且你可能想要做一些特定的孩子。
abstract class Animal{ public abstract void move(); } class Shark extends Animal{ public void move(){ swim(); } public void swim(){} public void bite(){} } class Dog extends Animal{ public void move(){ run(); } public void run(){} public void bark(){} } ... void somethingSpecific(Animal animal){ // Here you don't know and may don't care which animal enters animal.move(); // You can call parent methods but you can't call bark or bite. if(animal instanceof Shark){ Shark shark = (Shark)animal; shark.bite(); // Now you can call bite! } //doSomethingSharky(animal); // You cannot call this method. } ...
在上面的方法中,你可以通过鲨鱼或狗,但如果你有这样的东西:
void doSomethingSharky(Shark shark){ //Here you cannot receive an Animal reference }
该方法只能通过传递鲨鱼引用来调用所以如果你有一个动物(它是深鲨鱼),你可以这样称呼它:
Animal animal... doSomethingSharky((Shark) animal)
底线,你可以使用父亲引用,通常当你不关心父母的实现,并使用强制使用儿童作为一个特定的对象,它将是完全相同的对象,但你的参考知道它,如果你不投它,你的引用将指向同一个对象,但不能确定它是什么样的动物,因此只会允许你调用已知的方法。
比方说你有A类作为超类和B类B类
public class A { public void printFromA(){ System.out.println("Inside A"); } } public class B extends A { public void printFromB(){ System.out.println("Inside B"); } } public class MainClass { public static void main(String []args){ A a = new B(); a.printFromA(); //this can be called without typecasting ((B)a).printFromB(); //the method printFromB needs to be typecast } }
在这个例子中,你的超类variables告诉子类对象实现超类的方法。 这是java对象types转换的情况。 在这里,method()函数原本是超类的方法,但超类variables不能访问超类中不存在的子类对象的其他方法。
例如,你有Animal超类和Cat子类。你的子类有speak(); 方法。
class Animal{ public void walk(){ } } class Cat extends Animal{ @Override public void walk(){ } public void speak(){ } public void main(String args[]){ Animal a=new Cat(); //a.speak(); Compile Error // If you use speak method for "a" reference variable you should downcast. Like this: ((Cat)a).speak(); } }
在某些情况下,我们不能保证我们的集合中存在的元素或对象的types,或明智的,在检索强制时,我们应该进行types转换,否则我们会得到编译时错误。
数组总是types安全的,我们可以为数组中存在的元素的types提供保证。 为了实现types安全,我们必须使用types转换。
铸造是必要的,以告诉你正在调用一个孩子,而不是父母的方法。 所以它永远向下。 但是,如果该方法已经在父类中定义并在子类中重写,则不会进行任何转换。 这里是一个例子:
class Parent{ void method(){ System.out.print("this is the parent"); } } class Child extends Parent{ @override void method(){ System.out.print("this is the child"); } } ... Parent o = new Child(); o.method(); ((Child)o).method();
这两个方法调用将打印:“这是孩子”。