Java中动态和静态类型赋值的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20504714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between Dynamic and Static type assignments in Java
提问by user3088470
Given the follow class hierarchy what are the dynamic and static types for the following statements?
鉴于以下类层次结构,以下语句的动态和静态类型是什么?
Class hierarchy:
类层次结构:
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{}
For each of the following statements, Static Type? Dynamic Type?:
对于以下每个语句,静态类型?动态类型?:
Fruit f = new Fruit();
Alpha a = f;
Beta b = f;
a = b;
Gamma g = f;
My answers/questions
I understand that Fruit f = new Fruit()
will be of both static and dynamic type Fruit. Alpha a = f;
Will be of type Alpha at at compile time (static) and type Fruit at runtime (dynamic).
Gamma g = f;
Will be of type Gamma at compile time (static) and type Fruit at runtime (dynamic).
However I do not know the other two answers. Beta b = f is an instance in which two subclasses of the same super class are assigned to one another so I'm not sure if it would be of type Beta or type Alpha at compile time (static). And a = b is an assignment after declaration so I'm not sure what the answer for that would be. Someone please help me out thanks!
我
知道我的答案/问题Fruit f = new Fruit()
将是静态和动态类型的水果。Alpha a = f;
在编译时为 Alpha 类型(静态),在运行时为 Fruit 类型(动态)。
Gamma g = f;
在编译时为 Gamma 类型(静态),在运行时为 Fruit 类型(动态)。
但是我不知道其他两个答案。Beta b = f 是一个实例,其中同一个超类的两个子类相互分配,所以我不确定它在编译时是 Beta 类型还是 Alpha 类型(静态)。a = b 是声明后的赋值,所以我不确定答案是什么。有人请帮帮我谢谢!
采纳答案by luis.espinal
I'm typing this in a hurry, so pls excuse any typos (I'll fix those later when I get a chance).
我打字很匆忙,所以请原谅任何错别字(我稍后有机会时会修正这些)。
I understand that Fruit f = new Fruit() will be of both static and dynamic type Fruit.
我知道 Fruit f = new Fruit() 将是静态和动态类型的 Fruit。
I think you are confusing a bit the terms static and dynamic
types with compile-time and run-time types (or as in C++ when you assign the address of a object of type A to a pointer of type B with B being the parent class of A.)
我认为您有点混淆了术语static and dynamic
类型与编译时和运行时类型(或者在 C++ 中,当您将类型 A 的对象的地址分配给类型 B 的指针,而 B 是 A 的父类时。 )
Barring reflection tricks, there is no dynamic typing in Java. Everything is statically typed at compile time. The type of an object at run-time is the same as the one it got compiled to.
除了反射技巧,Java 中没有动态类型。一切都是在编译时静态输入的。运行时对象的类型与其编译后的类型相同。
What is happening is that you are confusing object references (a, b, c, f) with actual objects instantiated in the heap (anything created with new
.)
发生的事情是您将对象引用(a、b、c、f)与在堆中实例化的实际对象(使用new
.创建的任何对象)混淆了。
In Java, f
is an object reference, not the object itself. Moreover, the reference type of f
is Fruit and sub-classes of it
. The object (new Fruit()
) that you assign to it happens to be of type Fruit
.
在Java中,f
是对象引用,而不是对象本身。此外, 的引用类型f
是Fruit and sub-classes of it
。new Fruit()
您分配给它的 object( ) 恰好是类型Fruit
。
Now all the other references in your sample code, a is of type reference to A and sub-classes of it
; b is of type reference to B and sub-classes of it
; etc, etc.
现在示例代码中的所有其他引用 a 的类型为reference to A and sub-classes of it
; b 是类型reference to B and sub-classes of it
;等等等等。
Keep this in mind because it is very important.
请记住这一点,因为它非常重要。
Alpha a = f; Will be of type Alpha at at compile time (static) and type Fruit at runtime (dynamic).
阿尔法 a = f; 在编译时为 Alpha 类型(静态),在运行时为 Fruit 类型(动态)。
a is of type 'reference to type A and sub-classes'. f is of type 'reference to type Fruit and sub-classes'.
a 是“对类型 A 和子类的引用”类型。f 属于“对水果类型和子类的引用”类型。
The object f points to is of type 'Fruit'. When you say 'a = f' you are not assigning 'f' to 'a'. You are saying 'a now will reference that thing f is currently referencing to'.
f 指向的对象是“水果”类型。当您说 'a = f' 时,您并没有将 'f' 分配给 'a'。您是在说“a 现在将引用 f 当前正在引用的事物”。
So after that assignment, what is a
referencing? The object of type Fruit
the object reference f
pointed to at the time of assignment.
那么在那个任务之后,什么是a
引用?Fruit
对象引用f
在赋值时所指向的类型的对象。
Remember, a, b, g, f, they are not objects. They are references or handles to objects created one way or another with the new
operator.
请记住,a、b、g、f,它们不是对象。它们是对使用new
运算符以一种或另一种方式创建的对象的引用或句柄。
A reference variable such as a, b or f are different beasts from the objects created with new
. But it just so happen that the former can point to the later.
诸如 a、b 或 f 之类的引用变量与使用new
. 但碰巧前者可以指向后者。
The type of the object created with new at run-time is the same as the one determined at compile time.
运行时用 new 创建的对象类型与编译时确定的对象类型相同。
Gamma g = f; Will be of type Gamma at compile time (static) and type Fruit at runtime (dynamic).
伽马 g = f; 在编译时为 Gamma 类型(静态),在运行时为 Fruit 类型(动态)。
Same as above. The variable g
is an object reference of type reference to type Gamma and sub-classes
. In this assignment, g
is made to point to the same object pointed by f
. What is the type of that object? The same given at compile time: Fruit.
和上面一样。该变量g
是一个类型为 的对象引用reference to type Gamma and sub-classes
。在此赋值中,g
指向由 指向的同一对象f
。该对象的类型是什么?编译时给出的相同:水果。
However I do not know the other two answers. Beta b = f is an instance in which two subclasses of the same super class are assigned to one another so I'm not sure if it would be of type Beta or type Alpha at compile time (static).
但是我不知道其他两个答案。Beta b = f 是一个实例,其中同一个超类的两个子类相互分配,所以我不确定它在编译时是 Beta 类型还是 Alpha 类型(静态)。
b is of type reference to type Beta and sub-classes of it
. The object it points to after the assignment b = f
is of type Fruit
, the type it had at compile time.
b 是 类型reference to type Beta and sub-classes of it
。赋值后它指向的对象b = f
是 type Fruit
,它在编译时的类型。
The type of object references a, b, g, and f is determined at compile time. They are statically typed and do not change at run-time.
The type of an object created with
new
is also determined at compile time. They are also statically typed and do not change at run-time.The objects, the stuff object references a, b, g and f point to at run-time, that is determined by whether the statements are found valid by the compiler. The assignments can change, but that has nothing do with whether the object references or the object themselves are statically or dynamically typed.
对象引用 a、b、g 和 f 的类型在编译时确定。它们是静态类型的,在运行时不会改变。
创建的对象的类型
new
也在编译时确定。它们也是静态类型的,不会在运行时更改。对象,stuff 对象引用 a、b、g 和 f在运行时指向,这取决于编译器是否发现语句有效。赋值可以改变,但这与对象引用或对象本身是静态类型还是动态类型无关。
If you want to see a clear distinction between dynamic and static typing consider the following:
如果您想清楚区分动态类型和静态类型,请考虑以下几点:
// 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
Then there is the distinction between strongly typed and weakly/duck typed languages (both of which can be dynamically typed.) There is plenty of literature on this subject out there.
然后是强类型和弱/鸭子类型语言(两者都可以动态类型)之间的区别。关于这个主题有很多文献。
Hope it helps.
希望能帮助到你。
回答by JB Nizet
The concrete, runtime type of f
is Fruit (as you correctly stated in your question).
具体的运行时类型f
是 Fruit (正如您在问题中正确说明的那样)。
So Beta b = f;
initilalizes a variable whose declared, compile-time type is Beta, and whose runtime type is Fruit. This won't compile though, because the compile-time type of f
is Fruit, and Fruit is not a subclass of Beta, so f
can't be assigned to a variable of type Beta.
因此Beta b = f;
初始化一个变量,其声明的编译时类型为 Beta,运行时类型为 Fruit。但是这不会编译,因为编译时类型f
是 Fruit,而 Fruit 不是 Beta 的子类,所以f
不能分配给 Beta 类型的变量。
In a = b;
, b
, whose runtime type is Fruit (see above) is assigned to the variable a
, declared as Alpha a
. So a
's compile-time type is Alpha and its runtime type is Fruit.
在a = b;
, 中b
,其运行时类型为 Fruit(见上文)被分配给a
声明为的变量Alpha a
。Soa
的编译时类型是 Alpha,它的运行时类型是 Fruit。
回答by Adjit
You should take a look at this article: http://www.sitepoint.com/typing-versus-dynamic-typing/
你应该看看这篇文章:http: //www.sitepoint.com/typing-versus-dynamic-typing/
Static typing is when a language does not require the variable to be initialized.
静态类型是指语言不需要初始化变量。
eg.
例如。
/* C code */
static int num, sum; // explicit declaration
num = 5; // now use the variables
sum = 10;
sum = sum + num;
Dynamic typing is when a language requires the variable to be initialized.
动态类型是指语言需要初始化变量。
eg.
例如。
/* Python code */
num = 10 // directly using the variable
回答by meriton
the dynamic and static types for the following statements
以下语句的动态和静态类型
Erm, a statement doesn't have a type, at least there is no such notion in the Java Language Specification. The spec does define two different kinds of types: the declared typeof variable, field, or parameter, and the runtime classof an object.
嗯,语句没有类型,至少Java语言规范中没有这样的概念。该规范确实定义了两种不同的类型:变量、字段或参数的声明类型,以及对象的运行时类。
As the name indicates, the declared typeof a variable, field or parameter is the type you mention in the declaration. For instance, the declaration Foo bar;
declares a variable named bar
of type Foo
.
顾名思义,变量、字段或参数的声明类型就是您在声明中提到的类型。例如,声明Foo bar;
声明了一个名为bar
type的变量Foo
。
The runtime classof an object is determined by the class instance or array creation expression used to construct it, and remains the same throughout the lifetime of that object.
对象的运行时类由用于构造它的类实例或数组创建表达式确定,并且在该对象的整个生命周期中保持不变。
So the code:
所以代码:
Integer i = 1;
Number n = i;
Object o = n;
declares 3 variables of types Integer
, Number
and Object
, respectively, all of which refer to a single object with runtime class Integer
.
分别声明了 3 个类型为Integer
、Number
和 的变量Object
,所有这些变量都引用了具有运行时类的单个对象Integer
。
回答by Clive Ferreira
First to clarify "Reference Variable" type:
首先澄清“参考变量”类型:
Object obj;
Points to nothing and the Reference Variable obj would have NO type. Now
不指向任何内容,引用变量 obj 将没有类型。现在
Object obj = new String();
System.out.println(obj.getClass());//prints class java.lang.String
obj points to a String and the Reference Variable obj has type String.
obj 指向一个字符串,引用变量 obj 的类型为字符串。
The point is Java is a statically typed language and all reference type variables have a type assigned at compile time. The reference variable obj can point to some other object as long as it is a subclass of Object. In this case almost anything. Consider
重点是 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
At Runtime, same as compile time, the reference variable obj has type Byte.
在运行时,与编译时相同,引用变量 obj 的类型为 Byte。
The static/dynamic type of an object, for me, has to do with inheritance. More specifically the overriding mechanism. Also known as Dynamic Polymorphism and Late Binding.
对我来说,对象的静态/动态类型与继承有关。更具体地说,是覆盖机制。也称为动态多态性和后期绑定。
Consider overriding the equals() in class Object:
考虑覆盖类 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
}
}
Now we know that the type of the reference variable typ is Types.
现在我们知道引用变量 typ 的类型是 Types。
Object typ = new Types();
When it comes to
到那个时刻
typ.equals("Hi");
This is how I think the compiler thinks.
这就是我认为编译器的想法。
If the equals() is
如果 equals() 是
1.NOT static and final, which it is.
1.NOT 静态和最终,它是。
2.Referenced from a base class (more on this soon).
2.从基类引用(稍后会详细介绍)。
then the compiler defers which method gets called to the JVM. The exact method that is invoked depends on the Dynamic Type(more soon) of the variable that calls the method. In our case the reference variable is typ. This is known as Dynamic Method Invocation.
然后编译器将调用哪个方法推迟到 JVM。调用的确切方法取决于调用该方法的变量的动态类型(更多)。在我们的例子中,引用变量是 typ。这称为动态方法调用。
Now Referenced from a base class: From the above code
现在从基类引用:从上面的代码
Object typ = new Types();
typ.equals("Hi");
Type Object could be regarded as the base type of typ, also known as the Static Typeof a reference variable and the equals() is referenced from the base type, in this case Object.
类型 Object 可以看作是 typ 的基类型,也称为 引用变量的静态类型,equals() 是从基类型引用的,在这种情况下是 Object。
if we had
如果我们有
Types typ = new Types();
There would be no reference from a base type and hence no Dynamic Method Invocation.
没有来自基类型的引用,因此没有动态方法调用。
Now to the Dynamic Typeof a reference variable.
现在到引用变量的动态类型。
Object typ = new Types();
typ.equals("Hi");
The Dynamic Typeof typ is Types and according to Dynamic Method Invocation, the equals() in class Types would be called at runtime.
typ的动态类型是 Types,根据动态方法调用,类 Types 中的 equals() 将在运行时调用。
Also lets say we had another class that extends Types, TypesSubClass. And TypesSubClass also had a overridden equals(). Then
也可以说我们有另一个扩展类型的类,TypesSubClass。TypesSubClass 也有一个被覆盖的 equals()。然后
Object typ = new TypesSubClass();
typ.equals("Hi");
Would make the Dynamic Typeof typ TypesSubClass and TypesSubClass's equals() would be called at runtime.
会使typ TypesSubClass的Dynamic Type和 TypesSubClass 的 equals() 在运行时被调用。
To be honest, I personally didn't know why we needed all of this and have posted a question regarding this. check
老实说,我个人不知道为什么我们需要所有这些,并发布了一个关于此的问题。查看
What is the reason behind Dynamic Method Resolution in a staticlly typed language like Java