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

给定以下类层次结构,以下语句的动态和静态类型是什么?

类层次结构:

class Alpha {} class Beta extends Alpha {} class Gamma extends Alpha {} class Epsilon extends Alpha{} class Fruit extends Gamma{} class Golf extends Beta {} class Orange extends Fruit{} 

对于以下每个语句,静态类型? 动态类型?:

 Fruit f = new Fruit(); Alpha a = f; Beta b = f; a = b; Gamma g = f; 

我的回答/问题
我知道Fruit f = new Fruit()将是静态和动态类型的Fruit。
Alpha a = f; 在编译时将是Alpha类型(静态)并在运行时键入Fruit(动态)。
Gamma g = f; 在编译时将是Gamma类型(静态)并在运行时键入Fruit(动态)。
但是我不知道另外两个答案。 Beta b = f是一个实例,其中同一个超类的两个子类彼此分配,所以我不确定它在编译时是类型Beta还是类型Alpha(静态)。 并且a = b是声明后的赋值,所以我不确定答案是什么。 有人请帮帮我谢谢!

我正在匆匆打字,所以请原谅任何错别字(我稍后会在有机会时解决这些问题)。

我知道Fruit f = new Fruit()将是静态和动态类型的Fruit。

我认为您将static and dynamic类型与编译时和运行时类型混淆了一下(或者在将类型A的对象的地址分配给类型B的指针时,如在C ++中为父类, A.)

除了reflection技巧,Java中没有动态类型。 在编译时,所有内容都是静态输入的。 运行时对象的类型与编译到的对象类型相同。

发生的事情是,您将对象引用(a,b,c,f)与在堆中实例化的实际对象(使用new创建的任何对象)混淆。

在Java中, f是对象引用,而不是对象本身。 而且, f的引用类型是Fruit and sub-classes of it 。 您分配给它的对象( new Fruit() )恰好是Fruit类型。

现在您的示例代码中的所有其他引用,a是reference to A and sub-classes of it的类型reference to A and sub-classes of it ; b是reference to B and sub-classes of it类型reference to B and sub-classes of it ; 等等

请记住这一点,因为它非常重要。

Alpha a = f; 在编译时将是Alpha类型(静态)并在运行时键入Fruit(动态)。

a是’对类型A和子类的引用’的类型。 f的类型是’类型Fruit和子类的引用’。

对象f指向的是’Fruit’类型。 当你说’a = f’时,你没有将’f’分配给’a’。 你说’现在将引用f当前引用的东西’。

那么在那个任务之后,什么是引用? 对象引用f在赋值时指向的类型为Fruit的对象。

记住,a,b,g,f,它们不是对象。 它们是使用new运算符以某种方式创建的对象的引用或句柄。

诸如a,b或f之类的引用变量与使用new创建的对象不同。 但事实恰恰相反,前者可以指向后者。

在运行时使用new创建的对象的类型与在编译时确定的对象的类型相同。

伽玛g = f; 在编译时将是Gamma类型(静态)并在运行时键入Fruit(动态)。

与上面相同。 变量greference to type Gamma and sub-classes的类型reference to type Gamma and sub-classes的对象引用。 在这个赋值中, g被指向f指向的同一个对象。 那个对象的类型是什么? 在编译时给出的相同:果实。

但是我不知道另外两个答案。 Beta b = f是一个实例,其中同一个超类的两个子类彼此分配,所以我不确定它在编译时是类型Beta还是类型Alpha(静态)。

b是reference to type Beta and sub-classes of it类型reference to type Beta and sub-classes of it 。 在赋值b = f之后它指向的对象是Fruit类型,它在编译时具有的类型。

  1. 在编译时确定对象a,b,g和f的类型。 它们是静态类型的,不会在运行时更改。

  2. 使用new创建的对象的类型也在编译时确定。 它们也是静态类型的,不会在运行时更改。

  3. 对象,stuff对象引用a,b,g和f指向运行时 ,这取决于编译器是否发现语句有效。 赋值可以更改,但这与对象引用或对象本身是静态还是动态类型无关。

如果要查看动态和静态类型之间的明确区别,请考虑以下事项:

 // Java, statically typed. int x = 3; x = 5; // good x = "hi"; // compiler error ## Ruby, dynamically typed x = 3 # ok x = 5 # ok x = "hi" # still ok 

然后是强类型和弱/鸭类型语言之间的区别(两者都可以动态输入。)有很多关于这个主题的文献。

希望能帮助到你。

以下语句的动态和静态类型

嗯,一个语句没有类型,至少在Java语言规范中没有这样的概念。 规范确实定义了两种不同的类型: 声明的变量类型 ,字段或参数,以及对象的运行时类

如名称所示, 声明的变量,字段或参数类型是您在声明中提到的类型。 例如,声明Foo bar; 声明一个名为Foo的变量的变量。

对象的运行时类由用于构造它的类实例或数组创建表达式确定,并且在该对象的整个生命周期内保持不变。

所以代码:

 Integer i = 1; Number n = i; Object o = n; 

声明分别为IntegerNumberObject类型的3个变量,所有这些变量都引用具有运行时类Integer的单个对象。

f的具体运行时类型是Fruit(正如您在问题中正确指出的那样)。

所以Beta b = f; 初始化一个变量,其声明的编译时类型为Beta,其运行时类型为Fruit。 这不会编译,因为f的编译时类型是Fruit,而Fruit不是Beta的子类,所以f不能分配给Beta类型的变量。

a = b;b ,其运行时类型为Fruit(见上文)被赋值给变量a ,声明为Alpha a 。 所以编译时的类型是Alpha,它的运行时类型是Fruit。

首先澄清“参考变量”类型:

 Object obj; 

指向任何东西,参考变量obj将没有类型。 现在

 Object obj = new String(); System.out.println(obj.getClass());//prints class java.lang.String 

obj指向String,引用变量obj指向String类型。

关键是Java是一种静态类型语言,所有引用类型变量都有一个在编译时分配的类型。 引用变量obj可以指向其他对象,只要它是Object的子类即可。 在这种情况下几乎任何事情 考虑

 Object obj = new String(); System.out.println(obj.getClass());//prints class java.lang.String Number num = new Byte((byte)9); obj = num; System.out.println(obj.getClass());//prints class java.lang.Byte 

在运行时,与编译时相同,引用变量obj具有类型Byte。

对我来说,对象的静态/动态类型与inheritance有关。 更具体地说,是压倒一切的机制。 也称为动态多态和后期绑定。

考虑覆盖Object类中的equals():

 public class Types { @Override public boolean equals(Object obj){ System.out.println("in class Types equals()"); return false;//Shut-up compiler! } public static void main(String[] args){ Object typ = new Types(); typ.equals("Hi");//can do this as String is a subclass of Object } } 

现在我们知道引用变量typ的类型是Types。

 Object typ = new Types(); 

到那个时刻

 typ.equals("Hi"); 

这就是我认为编译器的想法。

如果等于()是

1.NOT静态和最终,它是。

2.从基类引用(更多关于这一点)。

然后编译器推迟调用JVM的方法。 调用的确切方法取决于调用该方法的变量的动态类型 (更快)。 在我们的例子中,参考变量是典型的。 这称为动态方法调用。

现在引用一个基类:从上面的代码

 Object typ = new Types(); typ.equals("Hi"); 

类型Object可以被视为typ的基本类型,也称为引用变量的静态类型 ,equals()从基类型引用,在本例中为Object。

如果我们有

 Types typ = new Types(); 

没有基类型的引用,因此没有动态方法调用。

现在到参考变量的动态类型

 Object typ = new Types(); typ.equals("Hi"); 

类型动态类型是类型,根据动态方法调用,类类型中的equals()将在运行时调用。

还可以说我们有另一个扩展Types,TypesSubClass的类。 而TypesSubClass也有一个重写的equals()。 然后

 Object typ = new TypesSubClass(); typ.equals("Hi"); 

是否会在运行时调用Typ TypeSubClass和TypesSubClass的equals()的动态类型

说实话,我个人不知道为什么我们需要所有这些并且已经发布了一个有关此问题的问题。 查

在像Java这样的静态类型语言中动态方法解析背后的原因是什么

你应该看一下这篇文章: http : //www.sitepoint.com/typing-versus-dynamic-typing/

静态类型是指语言不需要初始化变量。

例如。

 /* C code */ static int num, sum; // explicit declaration num = 5; // now use the variables sum = 10; sum = sum + num; 

动态类型是指语言需要初始化变量。

例如。

 /* Python code */ num = 10 // directly using the variable