Java中静态类型和动态类之间的区别

时间:2017-11-06 01:54:02

标签: java class dynamic types static

我已经看到几个资源谈论静态类型和动态类型之间的区别,以及类型和类之间的区别。然而,与静态类型和动态类进行对话要么是另一回事,要么就是根据我已经知道的事情,我没有足够的概念来解决它。

要给出具体案例,请参考代码

public interface I {}

public class C {}

public class E extends C implements I {}

public class F extends E {}

Object a = new E();

C b = new E();

C c = new F();

正如我目前所理解的那样,静态类型总是由类型注释给出,因此a具有类型Object而其他类型为C.动态类我不太了解,但我最好的猜测是它始终基于new类型。因此ab具有动态类E,而c具有F.我非常感谢任何见解或更正。

1 个答案:

答案 0 :(得分:5)

  

静态类型和动态类型之间的区别

粗略地说,静态类型的语言是那些在编译时已知类型的语言。 动态类型语言是在运行时检查类型的语言。这里有第三类,无类型语言,如。但我们并没有谈论它们。 Java和是JVM的静态类型语言的示例。 是动态类型的。在这里,阅读有关编程语言类型的this article

所以,没有"动态类型"在谈论Java时。在程序执行之前,所有类型都已知。你可能被欺骗的是polymorphism。它只是意味着" Car"可以是"卡车"或者" Minivan",动物可以是" Cat"," Dog",甚至是" Snake"。可以有中间类型,例如"哺乳动物"或者"蜥蜴"。但这意味着所有这些事情都有一些共同之处。即"汽车"有轮子(至少截至2017年底,没有太多的飞行汽车)并在道路上行驶。 "动物" ......好吧,"动物"可能是一个坏的,非常通用的例子,但它们的细胞中都含有碳。 "哺乳动物"有热血和蜥蜴" - 冷。你明白了。类型的特定越多,它指定的属性就越多。子类型可以覆盖并指定超类型的属性和方法。在层次结构的最后,有一些具体的可实例化的类,例如" DeLorean DMC-12"或者"阿比西尼亚猫"。

让我们考虑一下汽车。可能存在这样的层次结构:

public interface Car {
    String manufacturer();
}

public interface PassengerCar {
    Integer numberOfSeats();
}

public interface TimeMachine {
    void travelTo(Date destination);
}

public class DMC12 implements PassengerCar {
    @Override
    public String manufacturer() { return "DeLorean Motor Company"; }

    @Override
    public Integer numberOfSeats() { return 2; }
}

pubblic class DeLoreanTimeMachine extends DMC12 implements TimeMachine {
    private FluxCapacitor fluxCapacitor = new FluxCapacitor();

    @Override
    public void travelTo(Date destination) { fluxCapacitor.travelTo(destination); }
}

即使在课程下面也有对象。对象是类的具体实例。回到我们的例子,可能有"博士。 Emmett Brown的时间机器",DeLoreanTimeMachine的实例:

final DeLoreanTimeMachine docsCar = new DeLoreanTimeMachine();

但是,我们知道DeLoreanTimeMachine仍然是DMC12汽车,TimeMachinePassengerCar,最后是Car,所以这些表达式也是有效的:

final DMC12 dmc12 = new DeLoreanTimeMachine();
final TimeMachine timeMachine = new DeLoreanTimeMachine();
final PassengerCar passengerCar = new DeLoreanTimeMachine();
final Car car = new DeLoreanTimeMachine();

区别在于您可以通过此类引用访问的方法集。在静态类型语言中,编译已知的car类型只是Car,因此您只需car.manufacturer()即可。即使它是功能强大的磁通电容器的全功能时间机器,可以帮助您前往1985年,您不能使用(没有额外的技巧)该功能。多么浪费!同样,您只能通过passengerCar参考知道座位数,只能通过timeMachine来计算时间等等。

可能有其他类(以及对象)实现和扩展这些接口。在不同的组合。 TARDIS是时间机器,但不是CarOptimus PrimeCarTruckTransformer(这些类不在我们的等级中),但他无法穿越时间(可以吗?)。

但是你说的那个伎俩是什么?嗯,他们中的一大堆,用一个术语 联合起来。你可以用反射做什么?

你可以知道真正的运行时类型并进行演员表演! E.g。

passengerCar instanceOf Car
passengerCar instanceOf TimeMachine
passengerCar instanceOf DMC12
passengerCar instanceOf DeLoreanTimeMachine

一切都是真的!因为实际上我们示例中的passengerCar是Doc的汽车。即使编译已知的类型是PassengerCar,它也不允许您从其他类/接口调用方法,您将能够执行此操作:

((DeLoreanTimeMachine) passengerCar).travelTo("Oct. 26, 1985 1:21 A.M");

哇!你只是拆开连续体并前往1985年!快点,上车,注意Lybian恐怖分子!

但这些会因ClassCastException而失败:

((PassengerCar) tardis).numberOfSeats(); // you'd expect it to be 1 or what?
((TimeMachine) optimusPrime).travelTo("Oct. 26, 1985 1:21 A.M"); // wrong universe, pal

在这里,我们遇到了另一种打字"尺寸"。 vs 。请记住,Java是强烈(和静态)类型的,并且不允许您这样做(为了您自己的利益)。但是在Groovy中,你可以覆盖methodMissing并对任何类的任何调用做出回应。也就是说,打字很弱。

关于Java中的类型还有一件事。你应该知道type erasure。它适用于generic types,只是意味着在运行时,对象的类型可以被剥离到Object(或众所周知的上限),因此,使得变量类型无类型。但是编译器会在泛型的情况下生成一些额外的类型检查和强制转换,这样你就可以了。

  

类型和类之间的区别

它们几乎相同,但在Java中,您还有primitives,它们是类型,但不是类。但是,它们可以自动包装到相应的类中。有些语言,如将所有内容视为对象,因此具有类类型(无基元)。但是不要过多关注这些概念,并记住它们可以互换使用。

  

正如我目前所理解的那样,静态类型总是由类型注释

给出      

动态类我不太了解,但我最好的猜测是它始终基于new类型

嗯,是的,我理解你的意思。只需替换"静态类型"类似"编译时间类型"和"动态课"使用"运行时类型"并且你将100%正确。

总结一下:编译时类型是编译器已知的类型,它限制了您可以在源代码中调用的方法集。运行时类型可能不同,但它始终应该是编译时类型的子类型。您可以从运行时类型执行强制转换和访问方法,但可能不安全。类型擦除从字节码中删除泛型类型,但编译器足够智能以插入安全转换和类型检查。