显式类型转换示例在java中 [英] explicit type casting example in java

查看:132
本文介绍了显式类型转换示例在java中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 http://www.javabeginner.com/learn-java/上看到这个例子java-object-typecasting 和在其中谈到显式类型转换的部分有一个例子困惑我。

I have come across this example on http://www.javabeginner.com/learn-java/java-object-typecasting and in the part where it talks about explicit type casting there is one example which confuses me.

示例:

class Vehicle {

    String name;
    Vehicle() {
        name = "Vehicle";
    }
}

class HeavyVehicle extends Vehicle {

    HeavyVehicle() {
        name = "HeavyVehicle";
    }
}

class Truck extends HeavyVehicle {

    Truck() {
        name = "Truck";
    }
}

class LightVehicle extends Vehicle {

    LightVehicle() {
        name = "LightVehicle";
    }
}

public class InstanceOfExample {

    static boolean result;
    static HeavyVehicle hV = new HeavyVehicle();
    static Truck T = new Truck();
    static HeavyVehicle hv2 = null;
    public static void main(String[] args) {
        result = hV instanceof HeavyVehicle;
        System.out.print("hV is an HeavyVehicle: " + result + "\n");
        result = T instanceof HeavyVehicle;
        System.out.print("T is an HeavyVehicle: " + result + "\n");
        result = hV instanceof Truck;
        System.out.print("hV is a Truck: " + result + "\n");
        result = hv2 instanceof HeavyVehicle;
        System.out.print("hv2 is an HeavyVehicle: " + result + "\n");
        hV = T; //Sucessful Cast form child to parent
        T = (Truck) hV; //Sucessful Explicit Cast form parent to child
    }
}

最后一行,其中T被分配参考hV和类型转换为(卡车),为什么它在评论中说,这是一个成功的显式转换从父母到孩子?根据我的理解,转换(隐式或显式)只会改变对象的声明类型,而不是实际的类型(除非你实际分配一个新的类实例给该对象的字段引用,否则它不应该改变。如果hv已经分配了一个HeavyVehicle类的实例,它是Truck类的一个超类,那么该字段如何被转换成一个更具体的从HeavyVehicle类继承的Truck类的子类?

In the last line where T is assigned the reference hV and typecast as (Truck), why does it say in the comment that this is a Successful Explicit Cast from parent to child? As I understand casting (implicit or explicit) will only change the declared type of object, not the actual type (which shouldn't ever change, unless you actually assign a new class instance to that object's field reference). If hv was already assigned an instance of a HeavyVehicle class which is a super class of the Truck class, how can then this field be type cast into a more specific subclass called Truck which extends from the HeavyVehicle class?

我的理解方式是,转换的目的是限制对某个对象(类实例)的某些方法的访问。因此,你不能将一个对象作为一个更具体的类,它拥有更多的方法,然后该对象的实际分配的类。这意味着对象只能被转换为超类或与实际实例化的类相同的类。这是正确的,还是我错了?我仍然在学习,所以我不知道这是否正确的方式看待事情。

The way I understand it is that casting serves the purpose of limiting access to certain methods of an object (class instance). Therefore you can't cast an object as a more specific class which has more methods then the object's actual assigned class. That means that the object can only be cast as a superclass or the same class as the class from which it was actually instantiated. Is this correct or am I wrong here? I am still learning so I am not sure if this is the correct way of looking at things.

我也明白,这应该是一个例子下降,但我不知道如果实际类型没有类的方法,这个对象被压缩的实际工作原理。显式转换是否会改变对象的实际类型(而不只是声明的类型),以便这个对象不再是HeavyVehicle类的实例,但现在成为Truck类的实例?

I also understand that this should be an example of downcasting, but I am not sure how this actually works if the actual type doesn't have the methods of the class to which this object is being downcasted. Does explicit casting somehow change the actual type of object (not just the declared type), so that this object is no longer an instance of HeavyVehicle class but now becomes an instance of Truck class?

推荐答案

参考vs对象与类型

Reference vs Object vs Types

对我来说,一个对象和它的引用之间的差异,或者换句话说一个对象和它的类型之间的差异。

The key, for me, is understanding the difference between an object and its references, or put in other words the difference between an object and its types.

当我们用Java创建一个对象时,我们声明它的真实性质,它永远不会改变。但是Java中的任何给定对象可能有多种类型。这些类型中的一些显然是由于类层次结构给出的,其他类型不是那么明显(即泛型,数组)。

When we create an object in Java, we declare its true nature, which will never change. But any given object in Java is likely to have multiple types. Some of these types are obviously given thanks to the class hierarchy, others are not so obvious (i.e. generics, arrays).

特别是对于引用类型,类层次子类型规则。例如在你的例子中,所有卡车都是重型车辆,所有重型车辆都是车辆。因此,这种层级关系表明一辆卡车有多种兼容类型。

Specifically for reference types, the class hierarchy dictates the subtyping rules. For instance in your example all trucks are heavy vehicles, and all heavy vehicles are vehicles. Therefore, this hierarchy of is-a relationships dictates that a truck has multiple compatible types.

当我们创建一辆卡车时,我们定义一个参考 。此引用必须具有这些兼容类型之一。

When we create a Truck, we define a "reference" to get access to it. This reference must have one of those compatible types.

Truck t = new Truck(); //or
HeavyVehicle hv = new Truck(); //or
Vehicle h = new Truck() //or
Object o = new Truck();

所以这里的关键点是实现对对象的引用不是对象本身。正在创建的对象的本质永远不会改变。但是我们可以使用不同种类的兼容引用来访问对象。这是多态的特征之一。相同的对象可以通过不同兼容类型的引用来访问。

So the key point here is the realization that the reference to the object is not the object itself. The nature of the object being created is never going to change. But we can use different kinds of compatible references to gain access to the object. This is one of the features of polymorphism here. The same object may be accessed through references of different "compatible" types.

当我们进行任何类型的投放时,我们只是假定不同类型的引用之间的兼容性的性质。

When we do any kind of casting, we are simply assuming the nature of this compatibility between different types of references.

向上转换或扩大参考转换

现在,参考类型为Truck,我们很容易得出结论,车类型,因为所有卡车都是车辆。因此,我们可以上传引用,而不使用显式转换。

Now, having a reference of type Truck, we can easily conclude that is always compatible with a reference of type Vehicle, because all Trucks are Vehicles. Therefore, we could upcast the reference, without using an explicit cast.

Truck t = new Truck();
Vehicle v = t;

它也被称为扩大参考转换,基本上是因为当您在类型层次结构中上升时,类型会更多一般。

It is also called a widening reference conversion, basically because as you go up in the type hierarchy, the type gets more general.

如果你愿意的话,你可以在这里使用一个显式的转换,但是没有必要。我们可以看到 t v 引用的对象是相同的。

You could use an explicit cast here if you wanted, but it would be unnecessary. We can see that the object being referenced by t and v is the same. It is, and will always be a Truck.

下转或缩小参考转换

现在,有一个类型Vechicle的引用,我们不能安全地得出结论,它实际上参考一辆卡车。毕竟它还可以引用一些其他形式的车辆。例如

Now, having a reference of type Vechicle we cannot "safely" conclude that it actually references a Truck. After all it may also reference some other form of Vehicle. For instance

Vehicle v = new Sedan(); //a light vehicle

如果您发现 v 引用你的代码中的某处,而不知道它引用的具体对象,你不能安全论证是指向卡车还是轿车或任何其他类型的车辆。

If you find the v reference somewhere in your code without knowing to what specific object it is referencing, you cannot "safely" argument whether it points to a Truck or to a Sedan or any other kind of vehicle.

编译器知道,它不能给出任何保证被引用对象的真实性质。但是程序员通过阅读代码,可以确定他/他在做什么。与上面的情况一样,您可以清楚地看到 Vehicle v 正在引用Sedan。

The compiler knows well that it cannot give any guarantees about the true nature of the object being referenced. But the programmer, by reading the code, may be sure of what s/he is doing. Like in the case above, you can clearly see that Vehicle v is referencing a Sedan.

我们可以做一个downcast。我们这样称呼它,因为我们是在类型层次结构。我们也将此称为缩小参考文献转换。我们可以说

In those cases, we can do a downcast. We call it that way because we are going down the type hierarchy. We also call this a narrowing reference conversion. We could say

Sedan s = (Sedan) v;

这总是需要显式转换,因为编译器不能确定这是安全的,这就是为什么像询问程序员,你确定你在做什么吗?如果你骗了编译器,你会在运行时得到一个 ClassCastException

This always requires an explicit cast, because the compiler cannot be sure this is safe and that's why this is like asking the programmer, "are you sure of what you are doing?". If you lie to the compiler you will get a ClassCastException at run time, when this code is executed.

其他种类的子类型规则

Java中还有其他的子类型规则。例如,还有一个称为数字促销的概念,它自动强制表达式中的数字。如

There are other rules of subtyping in Java. For instance, there is also a concept called numeric promotion that automatically coerce numbers in expressions. Like in

double d = 5 + 6.0;

在这种情况下,由两个不同类型,整数和双精度组成的表达式,将整数在计算表达式之前需要一个双精度值,从而产生一个双精度值。

In this case an expression composed of two different types, integer and double, upcasts/coerces the integer to a double before evaluating the expression, resulting in a double value.

您还可以执行原始向上转换和向下转换。如

You may also do primitive upcasting and downcasting. As in

int a = 10;
double b = a; //upcasting
int c = (int) b; //downcasting

在这些情况下,当信息丢失时需要显式转换。

In these cases, an explicit cast is required when information can be lost.

一些子类型规则可能不那么明显,就像数组的情况一样。例如,所有引用数组都是Object []的子类型,但是原始数组不是。

Some subtyping rules may not be so evident, like in the cases of arrays. For instance, all reference arrays are subtypes of Object[], but primitive arrays are not.

在泛型的情况下,特别是使用通配符延伸,事情变得更加复杂。类似

And in the case of generics, particularly with the use of wildcards like super and extends, things get even more complicated. Like in

List<Integer> a = new ArrayList<>();
List<? extends Number> b = a;

List<Object> c = new ArrayList<>(); 
List<? super Number> d = c;

其中b的类型是a类型的子类型。并且d的类型是c类型的子类型。

Where the type of b is a subtype of the type of a. And the type of d is a subtype of the type of c.

并且装箱和拆箱也受到一些铸造规则的约束(这也是某种形式的强制在我看来)。

And also boxing and unboxing are subject to some casting rules (yet again this is also some form of coercion in my opinion).

这篇关于显式类型转换示例在java中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆