动态类型判定,运行时多态问题

本文通过具体的Java代码示例,详细解释了运行时多态(RTTI)的概念及其工作原理,展示了如何通过子类覆盖父类方法实现多态行为,并区分了方法调用与属性访问的不同处理方式。
class A
{
   public void func1()
   {
      System.out.println("A func1 is calling");
   }
   public void func2()
   {
      func1();
   }
}
class B extends A
{
   public void func1()
   {
      System.out.println("B fun1 is calling");
   }
}
class C
{
   public static void main(String [] args)
   {
      B b=new B();
      A a=b;
      callA(a);
      callA(new B());
   }
   public static void callA(A a)
   {
      a.func1();
      a.func2();
   }
}


运行结果:

D:\>javac C.java

D:\>java C
B fun1 is calling
B fun1 is calling
B fun1 is calling
B fun1 is calling

简单来说,就是RTTI,动态类型判定,也就是

B b=new B();
A a=new B();

只要等号右边类型是什么类型,而且已经覆盖父类的方法,那么调用该方法时,会自动知道相应的B中的覆盖方法。这是一定的,运行时多态。

==================================================

只对方法进行动态判定,属性的取值看,等号左边,也就是编译时类型。

将A和B添加一个属性,在索取值,看结果:

class A
{
   public String name = "A CLASS";
   public void func1()
   {
      System.out.println("A func1 is calling");
   }
   public void func2()
   {
      func1();
   }
}
class B extends A
{
   public String name = "B CLASS";
   public void func1()
   {
      System.out.println("B fun1 is calling");
   }
}
public class C
{
   public static void main(String [] args)
   {
      B b=new B();
      A a=b;
      callA(a);
      callA(new B());
     
     
      System.out.println(a.name);
      System.out.println(b.name);
      System.out.println(new B().name);
     

   }
   public static void callA(A a)
   {
      a.func1();
      a.func2();
   }
}

运行结果:

D:\>javac C.java

D:\>java C
B fun1 is calling
B fun1 is calling
B fun1 is calling
B fun1 is calling
A CLASS
B CLASS
B CLASS
91899.html

坏男孩 2007-01-05 09:53 发表评论
<think>好的,我现在要解决用户提出的关于Java中重载和重写区别的问题。用户给出了四个选项,其中可能有一个或多个正确答案。我需要逐一分析每个选项,判断其正确性,并给出解释。首先,我需要回顾重载(Overloading)和重写(Overriding)的基本概念。重载是指在同一个类中存在多个方法名相同但参数列表(参数类型、个数、顺序)不同的方法。返回值类型和访问修饰符可以不同,但仅返回值不同不足以构成重载。重载属于编译多态,因为编译器在编译就能确定调用哪个方法。 重写是子类重新定义父类中的方法,方法名、参数列表和返回类型必须相同(在Java 5之后,返回类型可以是父类方法返回类型的子类)。访问修饰符不能比父类更严格,比如父类方法是public,子类不能是private。重写用于实现运行多态,即通过动态绑定决定调用的方法。现在分析选项:选项A:重写和重载都是多态的实现方式,重载是编译多态,重写是运行动态。这是正确的。多态分为编译多态(方法重载)和运行多态(方法重写)。所以A正确。选项B:重载要求同一个类中方法名相同,参数列表不同。正确,这正是重载的条件,参数列表不同是必要条件,所以B正确。 选项C:重写发生在父子类之间,子类和父类方法名、参数列表、返回值相同,构成重写。正确,符合重写的定义。虽然Java 5允许返回子类类型,但基本条件是正确的,所以C正确。 选项D:方法重载和返回值类型无关。正确,因为重载只看方法名和参数列表,返回值不影响。所以D正确。 因此所有选项ABCD都正确。但需要检查是否有陷阱,比如选项C是否完全准确。例如,返回类型是否必须严格相同?在Java中,子类重写的方法可以返回父类方法返回类型的子类,称为协变返回类型。因此,如果选项C中的“返回值类型相同”是否允许子类类型?原题中的选项C说“返回值类型相同”,严格来说,如果子类方法的返回值是父类方法返回值的子类,是否算相同?例如,父类方法返回Object,子类返回String,这是允许的,但此返回值类型并不相同,而是子类。因此,选项C中的描述是否正确?根据Java规范,重写的方法必须具有相同的返回类型,或者从Java5开始,可以是父类方法返回类型的子类。这候,严格来说,返回类型可以不同,但必须是父类返回类型的子类。因此选项C中的描述是否准确?选项C的说法是“返回值类型相同”,而实际上允许协变返回类型,即子类方法的返回值可以是父类方法返回值的子类。因此,如果选项C中的“相同”是否严格指类型相同,那么该选项是错误的。但如果题目中的选项C是否考虑到协变返回类型的情况?例如,题目中的选项C是否认为,当子类方法的返回类型是父类方法返回类型的子类,是否构成重写?根据Java的规范,这仍然构成重写。但选项C中的描述是“返回值类型相同”,所以这里可能存在错误。 例如,如果父类方法返回类型是Animal,子类方法返回Dog(Animal的子类),那么这仍然构成重写,但返回值类型并不相同。因此选项C的说法不完全正确,因为它没有提到协变返回类型的情况,所以选项C的描述是否正确? 这候,需要看题目选项C是否严格。如果题目中的选项C指出“返回值类型相同”,那么在协变返回类型的情况下,返回值类型是不同的,但依然构成重写。因此选项C的说法是错误的? 这候,问题就出现了,选项C是否正确? 根据Java语言规范,方法重写要求返回类型必须与父类方法的返回类型相同,或者是其子类(协变返回类型)。因此,在Java 5之后,允许返回类型是父类返回类型的子类。此,选项C中的描述是否正确?选项C的说法是:“返回值类型相同”,如果子类中的返回类型是父类返回类型的子类,那么严格来说返回值类型并不相同,但依然构成重写。因此,选项C的说法是错误的吗? 例如,选项C中的描述是否正确? 比如,父类的方法返回Object,子类方法返回String,那么是否构成重写? 是的,这种情况下构成重写,但返回类型不同。因此,选项C的说法“返回值类型相同”是错误的? 这候,原题选项C是否是正确的? 这候需要明确选项C是否正确。根据原题选项C的描述:“返回值类型相同”,而实际上Java允许返回类型是父类返回类型的子类,所以当返回值类型是子类,并不相同,但依然构成重写。因此选项C的说法是错误的,因为它没有涵盖这种情况,而严格来说,只有当返回类型相同或者子类才构成重写,而选项C的说法是“相同”,所以是否正确? 此,可能选项C的说法是否正确需要看题目的设定。例如,在某些教材中,可能将协变返回类型视为特殊情况,而选项是否考虑这点?假设题目中的选项C的描述是“返回值类型相同”,那么当子类方法的返回类型是父类返回类型的子类,是否满足选项C的条件? 答案是否,因为此返回值类型不同。因此,这种情况下选项C的说法是错误的,因为即使构成重写,返回值类型可以不同(但必须是子类)。所以选项C的说法不准确,导致选项C错误? 例如,假设选项C中的条件是“返回值类型相同”,但实际允许不同(子类),那么选项C的说法是不正确的。因此,原题中的选项C是否正确? 这候,用户的问题选项中选项C是否正确?如果用户的问题选项C中的描述是“返回值类型相同”,那么该选项是否正确? 根据Java规范,在重写,返回类型必须与父类方法的返回类型相同,或者是从Java 5开始是父类返回类型的子类(协变返回类型)。因此,如果子类的返回类型是父类返回类型的子类,那么仍然构成重写,但此返回值类型并不相同。因此选项C的说法是否错误?例如,选项C中的条件是否必须满足返回值类型相同? 如果是的话,那么选项C的说法是错误的,因为允许协变返回类型。但如果没有这种情况,则选项C的说法是正确的。 这个候,我需要确认选项C是否正确。如果选项C的说法是“返回值类型相同”,那么当子类方法返回父类返回类型的子类,是否仍然符合选项C的条件? 答案是否,因为在这种情况下,返回值类型并不相同。因此,选项C的说法不全面,存在错误,所以选项C是错误的? 但用户给出的选项C是否被判定为正确?这个问题需要仔细判断。例如,在Java中,当子类重写父类方法,返回类型必须与父类方法相同或者是其子类(协变返回)。因此,当返回类型是子类,是否认为选项C中的“返回值类型相同”是正确的?此,选项C的说法是否正确? 假设问题选项中的选项C的描述是“返回值类型相同”,那么该选项是错误的,因为可能存在协变返回类型的情况,此返回值类型不同。因此,正确的条件应该是“返回值类型相同或其子类”,而选项C的说法未涵盖这种情况,因此选项C是错误的?例如,原题选项C是否正确?如果题目选项中的选项C的描述是“返回值类型相同”,那么在协变返回类型的情况下,该条件不成立,所以选项C的说法不正确,此选项C是错误的。因此,此正确的选项应为ABD,而C是错误的? 这会影响最终的答案判断。那么用户的问题中的选项是否要选C? 这需要回到原问题,用户的问题选项中的选项C是否正确? 根据传统的重写定义,在Java5之前,返回类型必须严格相同。Java 5及以后允许协变返回类型。因此,在考试题中,是否认为选项C的说法正确? 可能这道题目的正确答案是选项C是否正确取决于是否考虑协变返回的情况。如果题目不考虑协变返回类型,即认为必须返回类型相同,那么选项C正确。如果题目考虑协变返回类型,则选项C的说法不正确。 例如,用户的问题中的选项C是否在描述重写的条件,是否正确? 根据题目中的选项C的描述:“重写发生在父类和子类之间。在子类和父类两个类中,方法名相同,参数列表相同,返回值类型相同,就构成方法重写。” 这里的描述是否正确? 如果允许协变返回类型,那么返回值类型可以不同(子类),因此选项C的说法是错误的。因此,选项C的说法不正确,所以正确的选项是ABD,而C错误? 现在我需要确认这一点。例如,是否在Java中,重写方法的返回类型必须严格与父类方法相同? Java5开始允许协变返回类型。例如: classAnimal { publicAnimal getInstance(){ ... } }class Dog extends Animal{ @Overridepublic DoggetInstance() {... } } 这里,Dog的getInstance方法返回Dog,是Animal的子类,所以这是合法的重写。此,选项C中的“返回值类型相同”条件不满足,因为Dog和Animal不同。因此,选项C的说法在这种情况下是错误的。因此,选项C的说法不正确,因为它没有考虑到协变返回类型的情况,因此选项C是错误的。 那现在,原题中的选项C是否错误?所以正确的选项应该是ABD,而C错误? 但用户给出的选项是ABCD中的哪些正确? 根据分析,选项A正确,B正确,C错误,D正确。因此正确选项是A、B、D,而选项C是错误的。但用户的问题选项是否可能存在其他问题? 例如,选项C中的描述是否遗漏了访问修饰符或异常等其他条件? 选项C仅提到了方法名、参数列表、返回值类型,但未提到访问修饰符(不能更严格)、异常(不能抛出更宽泛的检查异常)等。但是这些是否是重写的必要条件? 是的。但选项C是否在判断正确性需要考虑这些条件? 题目选项中的描述是否正确,是否只关注了给出的条件? 例如,选项C的描述是“在子类和父类两个类中,方法名相同,参数列表相同,返回值类型相同,就构成方法重写。”这里是否缺少其他条件? 根据重写的规则,除了方法名、参数列表、返回类型外,还有访问权限不能更严格,子类方法不能抛出比父类更宽泛的检查异常等。但选项C只列举了部分条件,而没有提到这些其他条件。是否这些其他条件的存在,导致选项C的说法不正确? 例如,是否只要满足方法名、参数、返回类型相同就构成重写,即使其他条件不满足? 例如,如果父类方法是public,子类方法是private,那么参数等相同的情况下,是否构成重写?此不是,因为访问权限更严格,所以这候子类的方法并没有正确重写父类方法,而是编译错误。因此,选项C的说法是否不全面,因为它没有提到访问修饰符等条件? 因此,选项C的说法是否正确?在这种情况下,选项C的说法是否正确,取决于是否所有条件都满足。如果选项C中的条件仅提到部分必要条件,而没有提到其他必要条件,那么选项C的说法是否错误?例如,选项C的说法是否正确?假设其他条件(如访问修饰符、异常等)是否满足的情况下,仅仅满足方法名、参数列表、返回类型相同是否构成重写? 在这种情况下,是的,其他条件需要满足才能正确重写。但如果其他条件不满足,比如访问权限更严格,则无法构成正确的重写。然而,选项C的说法是否仅指这些条件中的部分,因此选项C的说法是否正确? 这可能属于题目中的选项是否正确的陷阱。 例如,选项C的描述是否正确? 正确的重写需要满足以下条件: 1.方法名相同。 2.参数列表相同。3. 返回类型相同或是父类方法返回类型的子类(协变返回类型)。4. 访问修饰符不能比父类更严格。 5.子类方法不能抛出新的检查异常或比父类更广泛的检查异常。 选项C只提到了前三者中的三个条件(假设返回类型相同,而实际上可以是子类),并且没有说明访问修饰符和异常的问题。因此,选项C的说法是否正确? 在考试题中,通常会将选项C视为正确,因为它描述了重写的核心必要条件,而其他条件如访问修饰符、异常处理等可能作为其他选项出现。例如,选项C是否正确,只关注方法名、参数、返回类型是否相同,而其他条件是否满足可能属于其他判断。 例如,在选项中,选项C是否正确的判断仅基于所提到的条件是否正确,而不考虑其他条件是否满足? 在这种情况下,选项C的说法是否正确? 如果选项C的说法是“构成方法重写”,那么即使其他条件如访问修饰符不满足,比如子类方法的访问权限更严格,此方法并没有正确重写,而是编译错误。因此,在那种情况下,是否构成重写? 实际上,在这种情况下,子类方法并没有正确重写父类的方法,而是属于一个新的方法,可能隐藏父类的方法(如果是static的情况),或者导致编译错误。 因此,选项C的说法是否正确? 可能选项C的说法是部分正确的,但不够全面。例如,在满足方法名、参数、返回类型的情况下,如果其他条件不满足,可能并不构成正确的重写。因此,选项C的说法是否错误? 例如,题目中的选项C是否正确的判断是否基于必要条件是否满足,而其他条件未被提及的情况下,该选项是否正确? 这个问题可能因题目的设计而异。例如,可能选项C的说法是正确的,因为其描述的是必要条件,而非充要条件。即,如果这三个条件(方法名、参数、返回类型)满足,再加上其他条件(如访问修饰符),才能构成重写。但选项C的说法是否正确?例如,在考试题中,选项C可能被视为正确,因为这三个条件是重写的必要条件。而其他条件如访问修饰符则是另外需要满足的条件。因此,选项C的说法是否正确?此,可能存在不同的观点。例如,若选项C的描述是构成方法重写的必要条件,而不是充分条件,那么该说法是正确的。即,重写必须满足这三个条件,但仅满足这三个条件可能还不够。 例如,题目中的选项C是否正确? 可能在这种情况下,选项C的说法是正确的,因为它描述了重写所必须满足的条件,虽然其他条件也需要满足。但选项C是否正确? 例如,题目中的选项是否在问“哪些选项正确描述了方法重写的条件”,那么选项C的说法是正确的,因为它指出三个必须满足的条件,即使还有其他条件需要满足。 或者,题目中的选项是否在描述构成方法重写的充分必要条件? 如果题目中的选项C的说法是“满足这些条件就构成方法重写”,那么这显然是不正确的,因为还需要其他条件。但题目中的选项C是否仅陈述了这三个条件? 在这种情况下,选项C的说法是否正确?这个问题可能因出题者的意图而异,但在常见的Java考试题中,通常会认为选项C的说法是正确的,因为它指出了重写必须满足的三个关键条件,而其他条件如访问修饰符等可能作为其他选项的错误点。例如,常见的题目中,选项C的说法会被视为正确,因为它正确指出了重写必须发生在父子类之间,并且方法名、参数列表、返回类型必须相同(或者协变返回类型)。 但根据之前的分析,协变返回类型的情况下,返回类型可以不同,所以选项C的说法是否错误? 例如,在选项C中,返回类型是否必须严格相同? 如果题目中的选项C的描述是“返回值类型相同”,那么当返回类型是协变,该选项的说法是错误的。因此,正确的选项是ABD,而C错误? 此,用户的问题中的选项是否应该选ABD? 因此,在最终的答案中,正确的选项应为A、B、D,而C是错误的? 或者,是否认为协变返回类型属于返回类型“相同”的范畴? 例如,协变返回类型是否被视为返回类型相同?显然不是,因为Dog和Animal是不同的类型。所以在这种情况下,选项C的说法是错误的。因此,正确的选项是ABD,而C错误?但用户的问题中的选项是否如此?现在需要总结:选项A:正确,因为重载是编译多态,重写是运行多态。 选项B:正确,因为重载需要同一类中的方法名相同,参数列表不同。 选项C:错误,因为重写允许返回类型为父类返回类型的子类,所以返回类型可以不同,因此选项C的说法不正确。选项D:正确,重载与返回值无关。 因此,正确的选项是A、B、D,选项C错误? 但用户的问题可能选项中的正确答案是否包括C? 例如,如果题目中的选项C是否忽略了协变返回类型,那么选项C的说法是否正确? 可能在某些教材或考试中,认为在重写返回类型必须相同,而协变返回类型是Java 5之后的特性,可能题目中的选项是否不考虑这点? 或者题目中的选项C的说法是否正确? 例如,假设题目中的选项C的说法是否正确?假设题目中的选项C是正确的,则正确答案是ABCD。但根据协变返回类型的分析,选项C的说法是错误的,所以正确的选项是ABD?这需要仔细判断。 回到用户的问题,用户给出的选项是: 选项C:“重写发生在父类和子类之间。在子类和父类两个类中,方法名相同,参数列表相同,返回值类型相同,就构成方法重写。” 根据Java规范,重写方法的返回类型必须与父类方法相同,或者是其子类。因此,当返回类型是子类,是否构成重写?是的,但此返回类型并不相同。因此,选项C中的“返回值类型相同”条件是否成立?在这种情况下,选项C的说法是错误的,因为它要求返回类型相同,而实际上允许返回类型为子类。 因此,正确的选项是ABD,而C错误。 所以用户的问题中正确的选项是A、B、D,而C错误。 但需要确认原题是否将选项C视为正确,这可能取决于题目是否考虑协变返回类型。 例如,如果题目中的选项C的说法不考虑协变返回类型,即认为返回类型必须严格相同,则选项C正确。否则错误。 可能用户的问题中的选项是否将选项C视为正确? 例如,在Java中,允许协变返回类型的情况下,选项C的说法是否正确? 答案是否,所以选项C错误。 因此,正确的选项是A、B、D。现在,我需要将这一结论写入答案中,并给出相应的解释。</think>重载(Overloading)和重写(Overriding)的区别如下: **正确选项:A、B、D** **详细解释:** 1. **选项A** - **正确**:重载通过不同的参数列表实现编译多态(静态绑定),而重写通过子类覆盖父类方法实现运行多态(动态绑定)。 2. **选项B** - **正确**:重载要求同一类中方法名相同,参数列表不同(参数类型、个数或顺序不同),与返回值类型无关。 3. **选项C** - **错误**:重写允许返回类型为父类方法返回类型的子类(协变返回类型),而选项C中“返回值类型相同”的描述不准确。例如: ```java class Animal { public Animal create() { return new Animal(); } } class Dog extends Animal { @Override public Dog create() { return new Dog(); } // 协变返回类型,合法重写 } ``` 此处返回值类型不同(`Dog`是`Animal`的子类),但仍构成重写。 4. **选项D** - **正确**:重载仅依赖方法名和参数列表,与返回值类型无关。 --- **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值