简体   繁体   English

Java对象赋值是什么意思?

[英]What does Java object assignment mean?

I have the following 2 classes : 我有以下两个班级:

class Animal {
    public static void staticMethod(int i) {
        System.out.println("Animal : static -- " + i);
    }

    public void instanceMethod(int i) {
        System.out.println("Animal : instance -- " + i);
    }
}

class Cat extends Animal {
    public static void staticMethod(int i) {
        System.out.println("Cat : static -- " + i);
    }

    public void instanceMethod(int i) {
        System.out.println("Cat : instance -- " + i);
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        myCat.staticMethod(1);                       // Cat : static -- 1
        myCat.instanceMethod(2);                     // Cat : instance -- 2
        System.out.println("");

        Animal myAnimal = myCat;
        Animal.staticMethod(3);                      // Animal : static -- 3 
        myAnimal.staticMethod(4);                    // Animal : static -- 4 [ ? ]
        System.out.println("");

        myAnimal.instanceMethod(5);                  // Cat : instance -- 5
    }
} 

And when I run Cat, I got the following results : 当我运行Cat时,我得到了以下结果:

Cat : static -- 1
Cat : instance -- 2

Animal : static -- 3
Animal : static -- 4

Cat : instance -- 5

I can understand 1,2,3 and 5, but why #4 is not : " Cat : static -- 4 " ? 我能理解1,2,3和5,但为什么#4不是:“Cat:static - 4”? My understanding would be like this : 我的理解是这样的:

myAnimal=myCat means "myAnimal" is now exactly the same as "myCat", so anywhere "myAnimal" apears, you can replace it with "myCat" and get the same result, because everything inside myAnimal is the same as everything inside myCat, therefore "myAnimal.staticMethod(4)" should be the same as "myCat.staticMethod(4)" and the output should be : "Cat : static -- 4", similiar to "myCat.staticMethod(1)" above. myAnimal = myCat意味着“myAnimal”现在与“myCat”完全相同,所以任何地方“myAnimal”都会出现,你可以用“myCat”替换它并获得相同的结果,因为myAnimal中的所有内容都与myCat中的所有内容相同,因此“myAnimal.staticMethod(4)”应与“myCat.staticMethod(4)”相同,输出应为:“Cat:static - 4”,与上面的“myCat.staticMethod(1)”类似。

But that doesn't seem to be the case, why ? 但事实并非如此,为什么呢?

You declare myAnimal as Animal . 您将myAnimal声明为Animal Therefore a static method is called from that class too. 因此,也从该类调用静态方法。

You should never call static methods (or access static fields) from an instance to prevent this kind of confusion. 您永远不应该从实例调用静态方法(或访问静态字段)以防止这种混淆。

The reason is that Java resolves static methods based on the type of the reference variable itself, and not polymorphically at run time, as happens with instance methods. 原因是Java根据引用变量本身的类型解析静态方法,而不是在运行时以多态方式解析,就像实例方法一样。

To expand a little bit, when you are doing Animal myAnimal = myCat , you are assigning a Cat reference to an Animal reference. 为了扩展一点,当你做Animal myAnimal = myCat ,你正在为Animal引用分配一个Cat引用。 This is acceptable, because a Cat is also an Animal , so anything that an Animal can do, a Cat can do also. 这是可以接受的,因为Cat也是Animal ,所以Animal可以做任何AnimalCat也可以做。

Furthermore, if you call an instance (that is, non static) method via the myAnimal reference, and the method is overriden in Cat , then the Cat version of the method is called, because that's why the method was overriden in the first place. 此外,如果通过myAnimal引用调用实例(即非静态)方法,并且该方法在Cat被覆盖,则调用该方法的Cat版本,因为这就是首先覆盖该方法的原因。 Static methods, on the other hand, are never overriden. 另一方面,静态方法永远不会被覆盖。 That's why they are "static", as in "non-dynamic". 这就是为什么它们是“静态的”,就像“非动态”一样。 Meaning that static methods can be resolved by the compiler instead of having to rely on the runtime environment. 这意味着静态方法可以由编译器解决,而不必依赖于运行时环境。

From Oracle docs : 来自Oracle文档

8.4.8.2. 8.4.8.2。 Hiding (by Class Methods) 隐藏(按类方法)

If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible to code in C. 如果类C声明或继承静态方法m,则m被称为隐藏任何方法m',其中m的签名是m'的签名的子签名(第8.4.2节),在超类和超接口中。否则C中的代码可以访问的C.

Example 8.4.8.2-1. 例8.4.8.2-1。 Invocation of Hidden Class Methods 隐藏类方法的调用

A class (static) method that is hidden can be invoked by using a reference whose type is the class that actually contains the declaration of the method. 可以使用引用来调用隐藏的类(静态)方法,该引用的类型是实际包含方法声明的类。 In this respect, hiding of static methods is different from overriding of instance methods. 在这方面,隐藏静态方法与覆盖实例方法不同。 The example: 这个例子:

class Super {
            static String greeting() { return "Goodnight"; }
            String name() { return "Richard"; }
        }
        class Sub extends Super {
            static String greeting() { return "Hello"; }
            String name() { return "Dick"; }
        }
        class Test {
            public static void main(String[] args) {
                Super s = new Sub();
                System.out.println(s.greeting() + ", " + s.name());
            }
        }

produces the output: 产生输出:

Goodnight, Dick 晚安,迪克

because the invocation of greeting uses the type of s, namely Super, to figure out, at compile time, which class method to invoke, whereas the invocation of name uses the class of s, namely Sub, to figure out, at run time, which instance method to invoke. 因为greeting的调用使用s的类型,即Super,在编译时弄清楚要调用哪个类方法,而name的调用使用s的类,即Sub,在运行时计算,要调用的实例方法。

Static means exactly that: the call is resolved statically (in your case, it is resolved based on the declared type of the variable , and the variable is a compile-time entity). 静态意味着:静态解析调用(在您的情况下,它基于声明的变量类型进行解析,并且变量是编译时实体)。

The result you expected would require that the call is resolved dynamically (polymorphically, based on the actual type of the referenced instance, and the instance is a runtime entity). 您期望的结果将要求动态解析调用(多态,基于引用实例的实际类型,并且实例是运行时实体)。

设置myAnimal = myCat时,指针myAnimal指向cat对象,但是当您尝试通过myAnimal指针访问静态方法时,它会从myAnimal声明为的类中访问静态方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM