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,b在c有F的情况下拥有动态E级.我会欣赏任何见解或更正.
静态类型和动态类型之间的区别
粗略地说,静态类型语言是那些在编译时已知类型的语言.动态类型语言是在运行时检查类型的语言.还有第三个类别这里,类型化的语言,如规定或组装.但我们不是在谈论它们.Java和
科特林是JVM的静态类型语言的示例.groovy是一个动态类型.在这里,阅读本文关于编程语言中的类型.
因此,在谈论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中你也有原语,它们是类型,但不是类.但是,它们可以自动包装到相应的类中.有些语言,比如ruby,将所有东西视为一个对象,因此具有类类型(没有基元).但是不要过多关注这些概念,并记住它们可以互换使用.
正如我目前所理解的那样,静态类型总是由类型注释给出
动态类我不太了解,但我最好的猜测是它始终基于
new类型
嗯,是的,我理解你的意思.只需用"运行时类型"替换"编译时类型"和"动态类"之类的"静态类型",就可以100%正确.
回顾一下:编译时类型是编译器已知的类型,它限制了您可以在源代码中调用的方法集.运行时类型可能不同,但它始终应该是编译时类型的子类型.您可以从运行时类型执行强制转换和访问方法,但可能不安全.类型擦除从字节码中擦除泛型类型,但编译器足够智能以插入安全转换和类型检查.
| 归档时间: |
|
| 查看次数: |
841 次 |
| 最近记录: |