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

Add*_*dem 2 java static types class dynamic

我已经看到几个资源讨论静态类型和动态类型之间的区别,以及类型和类之间的区别.然而,谈论静态类型和动态类是一个不同的问题,或者我只是没有得到足够的概念来解决我已经知道的事情.

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

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();
Run Code Online (Sandbox Code Playgroud)

正如我目前所理解的那样,静态类型总是由类型注释给出,因此它a具有类型Object和其他类型C.动态类我不太了解,但我最好的猜测是它总是基于new类型.因此a,bc有F的情况下拥有动态E级.我会欣赏任何见解或更正.

mad*_*ead 6

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

粗略地说,静态类型语言是那些在编译时已知类型的语言.动态类型语言是在运行时检查类型的语言.还有第三个类别这里,类型化的语言,如.但我们不是在谈论它们.Java和是JVM的静态类型语言的示例.是一个动态类型.在这里,阅读本文关于编程语言中的类型.

因此,在谈论Java时没有"动态类型".在程序执行之前,所有类型都已知.你可能被欺骗的是多态.它只是意味着"汽车"可以是"卡车"或"小型货车",动物可以是"猫","狗",甚至是"蛇".可以有中间类型,如"哺乳动物"或"蜥蜴".但这意味着所有这些事情都有一些共同之处.即"汽车"有轮子(至少截至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); }
}
Run Code Online (Sandbox Code Playgroud)

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

final DeLoreanTimeMachine docsCar = new DeLoreanTimeMachine();
Run Code Online (Sandbox Code Playgroud)

但是,正如我们所知,DeLoreanTimeMachine它仍然是DMC12汽车,a TimeMachine,a PassengerCar,最后是a Car,因此这些表达式也是有效的:

final DMC12 dmc12 = new DeLoreanTimeMachine();
final TimeMachine timeMachine = new DeLoreanTimeMachine();
final PassengerCar passengerCar = new DeLoreanTimeMachine();
final Car car = new DeLoreanTimeMachine();
Run Code Online (Sandbox Code Playgroud)

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

可能有其他类(以及对象)实现和扩展这些接口.在不同的组合.TARDIS是一台时间机器,但不是Car.擎天柱是a Car,a Truck和a Transformer(那些类不在我们的等级中),但他不能穿越时间(可以吗?).

但是你告诉我的那个伎俩是什么?好吧,他们中的一大堆,用术语联合起来.你可以用反射做什么?

你可以知道真正的运行时类型并进行演员表演!例如

passengerCar instanceOf Car
passengerCar instanceOf TimeMachine
passengerCar instanceOf DMC12
passengerCar instanceOf DeLoreanTimeMachine
Run Code Online (Sandbox Code Playgroud)

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

((DeLoreanTimeMachine) passengerCar).travelTo("Oct. 26, 1985 1:21 A.M");
Run Code Online (Sandbox Code Playgroud)

哇!你只是撕开连续体并前往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
Run Code Online (Sandbox Code Playgroud)

在这里,我们遇到了另一个打字"维度"..请记住,Java是强烈(和静态)类型的,并且不允许您这样做(为了您自己的利益).但是在Groovy中,你将能够覆盖methodMissing并响应来自任何类的任何调用.也就是说,打字很弱.

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

类型和类之间的差异

它们几乎相同,但在Java中你也有原语,它们是类型,但不是类.但是,它们可以自动包装到相应的类中.有些语言,比如将所有东西视为一个对象,因此具有类类型(没有基元).但是不要过多关注这些概念,并记住它们可以互换使用.

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

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

嗯,是的,我理解你的意思.只需用"运行时类型"替换"编译时类型"和"动态类"之类的"静态类型",就可以100%正确.

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