简体   繁体   English

用于投射的Java规则

[英]Java rules for casting

When can a certain object be cast into another object? 何时可以将某个对象转换为另一个对象? Does the casted object have to be a subtype of the other object? 铸造对象是否必须是另一个对象的子类型? I'm trying to figure out the rules... 我正试图找出规则......

Edit : I realized that I didn't explain my issue at all: basically I am casting an object to an interface type. 编辑 :我意识到我根本没有解释我的问题:基本上我正在将一个对象转换为接口类型。 However, at run-time, I get a java.lang.ClassCastException . 但是,在运行时,我得到一个java.lang.ClassCastException What needs to happen with my object so that I can cast it to this interface? 我的对象需要发生什么才能将其转换为此接口? Does it have to implement it? 是否必须实施它?

Thanks 谢谢

In Java there are two types of reference variable casting: 在Java中,有两种类型的引用变量:

  • Downcasting : If you have a reference variable that refers to a subtype object, you can assign it to a reference variable of the subtype. 向下转换 :如果您有一个引用子类型对象的引用变量,则可以将其指定给子类型的引用变量。 You must make an explicit cast to do this, and the result is that you can access the subtype's members with this new reference variable. 您必须进行显式转换才能执行此操作,结果是您可以使用此新引用变量访问子类型的成员。

  • Upcasting : You can assign a reference variable to a supertype reference variable explicitly or implicitly. 上传 :您可以显式或隐式地将引用变量分配给超类型引用变量。 This is an inherently safe operation because the assignment restricts the access capabilities of the new variable. 这是一种固有的安全操作,因为赋值限制了新变量的访问能力。

Yes , you need to implement the interface directly or indirectly to enable assigning your class object reference to the interface type. 是的 ,您需要直接或间接地实现接口,以便将类对象引用分配给接口类型。

Suppose we want to cast d object to A, 假设我们想将d对象转换为A,

A a = (C)d; A =(C)d;

So internally 3 rules have been checked by Compiler and JVM. 因此编译器和JVM已经检查了内部3个规则。 The compiler is checking first 2 rules at Compile time and JVM will check last one rule at Runtime. 编译器在编译时检查前2个规则,JVM将在运行时检查最后一个规则。

Rule 1 (Compile time checking): 规则1(编译时间检查):

Type of 'd' and C must have some relation (child to parent or parent to child or same time).If there is no relationship then we will get a compile error(inconvertible types). 'd'和C的类型必须有一些关系(子到父或子到子或同一时间)。如果没有关系,那么我们将得到编译错误(不可转换的类型)。

Rule 2 (Compile time checking): 规则2(编译时间检查):

'C' must be either same type or derived type(subclass) of 'A' otherwise we will get a compile error(incompatible types). 'C'必须是'A'的相同类型或派生类型(子类),否则我们将得到编译错误(不兼容的类型)。

Rule 3 (Runtime Exception): 规则3(运行时异常):

Runtime object type of 'd' must be same or derived a type of 'C' otherwise we will get a runtime exception (ClassCastException Exception). 运行时对象类型'd'必须相同或派生类型为'C'否则我们将获得运行时异常(ClassCastException异常)。

Find following examples to get more idea, 找到以下示例以获得更多想法,

String s = new String("hello"); StringBuffer sb = (StringBuffer)s;  // Compile error : Invertible types because there is no relationship between.

Object o = new String("hello"); StringBuffer sb = (String)o;       // Compile error : Incompatible types because String is not child class of StringBuffer.

Object o = new String("hello"); StringBuffer sb = (StringBuffer)o; // Runtime Exception : ClassCastException because 'o' is string type and trying to cast into StingBuffer and there is no relationship between String and StringBuffer.

This will work: 这将有效:

class Foo implements Runnable {
    public void run() {}
}

Foo foo = new Foo();
System.out.println((Runnable) foo);

But this will not: 但这不会:

class Bar {
    public void run() {}
}

Bar bar = new Bar();
System.out.println((Runnable) bar);

Because although Bar has a run() method that could implement Runnable.run() , Bar is not declared to implement Runnable so it cannot be cast to Runnable . 因为虽然Bar有一个可以实现Runnable.run()run()方法, 但是没有声明Bar实现Runnable所以它不能被强制转换为Runnable

Java requires that you declare implemented interfaces by name . Java要求您按名称声明实现的接口。 It does not have duck typing , unlike some other languages such as Python and Go 与其他语言(如PythonGo)不同,它没有鸭子类型

There's an intuitive way of thinking about this - you're not changing an object with a cast, you're only doing something that would already be permitted if the type was known - inotherwords, you can only cast to a type that your object already is. 有一个直观的思考方式 - 你不是用一个演员来改变一个对象,你只是做了一个已经被允许的东西,如果知道了这个类型 - 换句话说,你只能转换为你的对象的类型是。 So just look "up" the object chain to see what kinds apply to your object. 因此,只需查看对象链“向上”以查看适用于您的对象的类型。

So you can cast to an interface only if it's defined somewhere higher up in the chain (eg if your classes parent implements it, etc. etc). 因此, 只有在链接中更高的位置定义接口时才可以转换为接口(例如,如果您的类实现它,等等)。 It has to be explicit - from your question it sounds like you may be thinking that if you implement method "void foo()" then you should be able to cast to an interface that defines the method "void foo()" - this is sometimes described as "duck typing" (if it quacks like a duck, it's a duck) but is not how java works. 它必须是显式的 - 从你的问题来看,你可能会想到如果你实现方法“void foo()”那么你应该能够转换为定义方法“void foo()”的接口 - 这是有时被描述为“鸭子打字” (如果它像鸭子一样嘎嘎叫,它是一只鸭子)但不是java的工作方式。

You can cast if the runtime type of an object is a subtype of what you're trying to cast it into. 如果对象的运行时类型是您尝试将其强制转换为的子类型,则可以进行强制转换。

EDIT: 编辑:

Yes, the object that you're trying to cast will need to implement the interface in order for you to cast it successfully. 是的,您尝试投射的对象需要实现该界面才能成功投射它。

If: 如果:

interface MyInterface{}

class MyClass implements MyInterface{}

Then 然后

MyClass m = new MyClass();
MyInterface i = (MyInterface)m;

is possible. 是可能的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM