Java 将实例化分配给父类和派生类之间的区别

Java 将实例化分配给父类和派生类之间的区别,java,Java,如果我声明这两个类: public class A { // attributes } public class B extends A { // attributes } A obj1 = new B(); B obj2 = new B(); 这两个实例化之间有什么区别?在实例化中没有区别。在这两种情况下,您都是在堆上为B对象分配空间 差异在于参考变量的赋值和类型 A obj = new B(); 在这种情况下,参考变量obj的类型为A(父变量)。因此,在obj上调用行为时,只能

如果我声明这两个类:

public class A {
  // attributes
}
public class B extends A {
  // attributes
}

A obj1 = new B();
B obj2 = new B();

这两个实例化之间有什么区别?

实例化中没有区别。在这两种情况下,您都是在堆上为
B
对象分配空间

差异在于参考变量的赋值类型

A obj = new B();
在这种情况下,参考变量
obj
的类型为
A
(父变量)。因此,在
obj
上调用行为时,只能调用
A
中存在的方法

B obj = new B();

在这种情况下,参考变量
obj
的类型为
B
(child)。因此,当在
obj
上调用行为时,可以调用子
B
从其父
A
继承的方法,也可以调用仅存在于
B
中的方法。在实例化中没有区别。在这两种情况下,您都是在堆上为
B
对象分配空间

差异在于参考变量的赋值类型

A obj = new B();
在这种情况下,参考变量
obj
的类型为
A
(父变量)。因此,在
obj
上调用行为时,只能调用
A
中存在的方法

B obj = new B();
在这种情况下,参考变量
obj
的类型为
B
(child)。因此,当在
obj
上调用行为时,可以调用子
B
从其父
A
继承的方法,也可以调用仅存在于
B
中的方法。实例化是相同的。在这两种情况下,您都在创建一个
新B()

作业是不同的。由于
B
a
,因此可以将
B
类型的任何表达式指定给
a
类型的变量。无需执行显式强制转换即可执行此操作,因此:

允许将表达式的值指定给变量;表达式的类型必须转换为变量的类型

在您的示例中,如果
S
T
的子类型,则执行一个允许将引用类型
S
转换为引用类型
T
。编译器会自动为您执行此操作,因为这是一个扩展的转换:即,在没有
ClassCastException
的情况下,它将始终成功

Java需要考虑到这一点才能做到这一点,这允许您将类型
S
视为其超类型
T
(例如,将
Cat
Dog
视为
动物
);这反过来又允许您将通用行为(或通用契约——有关接口的注释,请参见下文)放入超类型

在运行时,实际类型是已知的,并且调用实际类型的方法而不是超类型方法。因此,对于
动物a=新猫()a
Cat
,并在
Cat
上调用
sleep
的实现,而不是在
Animal
上调用

public class Animal { public void sleep() { /* close eyes */ } }
public class Cat extends Animal { public void sleep() { /* curlUpAndSleep */ } }
public class Dog extends Animal { public void sleep() { /* stretchOutAndSleep */ } }
...
public void putToBed(Animal a) { a.sleep(); }
...
Animal a1 = new Cat(); // curls up and sleeps
Animal a2 = new Dog(); // stretches out and sleeps - my dog obviously thinks he's a cat
putToBed(a1); putToBed(a2);
整个概念也适用于允许您将通用约定应用于不共享超类型关系的对象的接口:

public interface Sleepable { public void sleep(); }
public class Cat implements Sleepable { public void sleep() { /* curlUpAndSleep */ } }
public class Dog implements Sleepable { public void sleep() { /* stretchOutAndSleep */ } }
...
public void putToBed(Sleepable a) { a.sleep(); }
实例化是相同的。在这两种情况下,您都在创建一个
新B()

作业是不同的。由于
B
a
,因此可以将
B
类型的任何表达式指定给
a
类型的变量。无需执行显式强制转换即可执行此操作,因此:

允许将表达式的值指定给变量;表达式的类型必须转换为变量的类型

在您的示例中,如果
S
T
的子类型,则执行一个允许将引用类型
S
转换为引用类型
T
。编译器会自动为您执行此操作,因为这是一个扩展的转换:即,在没有
ClassCastException
的情况下,它将始终成功

Java需要考虑到这一点才能做到这一点,这允许您将类型
S
视为其超类型
T
(例如,将
Cat
Dog
视为
动物
);这反过来又允许您将通用行为(或通用契约——有关接口的注释,请参见下文)放入超类型

在运行时,实际类型是已知的,并且调用实际类型的方法而不是超类型方法。因此,对于
动物a=新猫()a
Cat
,并在
Cat
上调用
sleep
的实现,而不是在
Animal
上调用

public class Animal { public void sleep() { /* close eyes */ } }
public class Cat extends Animal { public void sleep() { /* curlUpAndSleep */ } }
public class Dog extends Animal { public void sleep() { /* stretchOutAndSleep */ } }
...
public void putToBed(Animal a) { a.sleep(); }
...
Animal a1 = new Cat(); // curls up and sleeps
Animal a2 = new Dog(); // stretches out and sleeps - my dog obviously thinks he's a cat
putToBed(a1); putToBed(a2);
整个概念也适用于允许您将通用约定应用于不共享超类型关系的对象的接口:

public interface Sleepable { public void sleep(); }
public class Cat implements Sleepable { public void sleep() { /* curlUpAndSleep */ } }
public class Dog implements Sleepable { public void sleep() { /* stretchOutAndSleep */ } }
...
public void putToBed(Sleepable a) { a.sleep(); }
万一

A a = new B()
已创建类型为B的Instance,但引用为父类型。使用它,您无法访问特定于B类型的字段或调用方法。

A a = new B()

已创建类型为B的Instance,但引用为父类型。使用它,您无法访问特定于B类型的字段或调用方法。

让我在您的问题中添加一些代码

public class A{
void base(){
 print("base method");
}
}
public class B extends A{
void child(){
 print("child method");
}
}
.......

A obj1 = new B(); 
B obj2 = new B();
现在按对象调用这两个方法

obj1.base();   //base method

obj1.child();   //create compile time error 
因为obj1是B类的对象,但引用是A类的….
obj1只能调用类A中的方法

//but obj2 can call both methods as it inherits Class A and also having reference of its own.

obj2.base();   //base method

obj2.child();   // child method

让我在你的问题中添加一些代码

public class A{
void base(){
 print("base method");
}
}
public class B extends A{
void child(){
 print("child method");
}
}
.......

A obj1 = new B(); 
B obj2 = new B();
现在按对象调用这两个方法

obj1.base();   //base method

obj1.child();   //create compile time error 
因为obj1是B类的对象,但引用是A类的….
obj1只能调用类A中的方法

//but obj2 can call both methods as it inherits Class A and also having reference of its own.

obj2.base();   //base method

obj2.child();   // child method

多态性和接口编程。开始。在
B
中创建一个在
a
中不存在的全新方法。在这两种情况下都试着调用它。接下来创建一个具有相同属性的方法