在java中,我们可以通过传递超类方法中使用的参数的子类来重写方法吗?

在java中,我们可以通过传递超类方法中使用的参数的子类来重写方法吗?,java,overloading,overriding,Java,Overloading,Overriding,根据规则,在重写子类中的方法时,参数不能更改,必须与超类中的参数相同。 如果我们在重写方法时传递参数的子类会怎么样? 它将被称为重载还是重写 根据我的查询,我在下面编写了一些代码。 我原以为输出是“狗吃肉”,但出乎意料的是输出是“动物吃肉” 如果有人能解释一下当分配的对象是Dog类型时如何调用Animal方法,我将不胜感激 class Food { public String toString(){ return "Normal Food";

根据规则,在重写子类中的方法时,参数不能更改,必须与超类中的参数相同。 如果我们在重写方法时传递参数的子类会怎么样? 它将被称为重载还是重写

根据我的查询,我在下面编写了一些代码。
我原以为输出是“狗吃肉”,但出乎意料的是输出是“动物吃肉” 如果有人能解释一下当分配的对象是Dog类型时如何调用Animal方法,我将不胜感激

    class Food {
        public String toString(){
            return "Normal Food";
        }
    }

    class Flesh extends Food {
        public String toString(){
            return "Flesh Food";
        }
    }

    class Animal {
        public void eat(Food food){
            System.out.println("Animal eats "+ food);
        }
    }

    class Dog extends Animal{

        public void eat(Flesh flesh){
            System.out.println("Dog eats "+ flesh);
        }
    }

    public class MyUtil {

        public static void main(String[] args) {

            Animal animal = new Dog(); 

            Flesh flesh = new Flesh();

            animal.eat(flesh);
        }
    }

不,我们不能在这种情况下,您可以通过在Dog类中的eat方法上方添加@Override进行检查,因此编译错误将如下所示:

@Override
public void eat(Flesh flesh){
   System.out.println("Dog eats "+ flesh);
}

确保在override中,参数的类型和顺序应为父类。

Dog
中的方法
eat
不会覆盖
Animal
中的方法
eat
。这是因为参数不同(一个需要
,另一个需要
食物

eat
方法是重载

重载之间的选择发生在编译时,而不是运行时。它不是基于调用方法的对象的实际类,而是基于编译时类型(变量的声明方式)

animal
具有编译时类型
animal
。我们之所以知道这一点,是因为变量
animal
的声明是
animal-animal=…
。事实上,它实际上是一只
是不相关的-必须调用
动物
中的

另一方面,
中的
toString
方法确实
覆盖了
食品
中的
toString
方法

当一个方法重写另一个方法时,调用该方法的对象的实际类决定运行哪个版本

Animal
eat
方法中,即使参数具有编译时类型
Food
,如果您将
肉体
的实例传递给它,将执行
肉体
中的
toString
方法


因此,您会收到信息“动物吃肉食”

您可以使用
@override
注释通知编译器您正试图重写超类中的方法

e、 g

在您的代码中,现在编译器将生成一个错误,因为此方法不重写
eat
,所以您需要具有相同的参数类型

但是,将
果肉
参数更改为
食品
类型将解决以下问题:

class Dog extends Animal{

    @Override
    public void eat(Food food){
        System.out.println("Dog eats "+ food);
    }
}
现在,您可以执行以下操作:

public class MyUtil {

    public static void main(String[] args) {

        Animal animal = new Dog(); 

        Food food = new Flesh();

        animal.eat(food);
    }
}
执行此操作时:
Animal=newdog()它正在向上投射

并且不重写该方法

public void eat(Flesh flesh){
    System.out.println("Dog eats "+ flesh);
}

因此,它在java中调用
Animal

eat(Food-Food)
方法,我们可以通过传递超类方法中使用的参数的子类来重写方法吗

没有

举例说明:

假设我们可以通过传递超类方法中使用的参数的子类来重写方法。

class A {
    public void print(Oject obj) 
    {
      System.out.println(obj.toString());
     }
}

class B extends A {
    @Override
     public void print(String str) 
     {
        System.out.println(str.toString());
     }
}

class C extends A {
   @Override
   public void print(Integer in) {
      System.out.println(in.toString());
   }
}

class MainTest {
   public static void main(String args[]) 
   {
      Integer in = new Integer(3);
      A a = new B(); // developer by mistake types new B() instead of new C()
      a.print(in);  // compiler will allow this because class A has print method which can take any subclass of Object type(in this case any class because Object is superclass of all classes in java).
    }
}
但想想运行时会发生什么

在运行时,对引用所指向的实际对象调用方法。在我们的例子中,它指向B类。 所以JVM将研究类B以执行方法,这对JVM来说是一个巨大的冲击,因为类B没有重写 方法的签名为public void print(in中的整数),它将在运行时失败

其结果是应用程序将在运行时而不是编译时崩溃

Java中的重写规则:

  • 参数必须相同&返回类型必须兼容
  • 这种方法不可能不那么容易获得
=============================

在您的示例中,发生的情况是:

在编译时执行:编译器确保可以对引用类型(即Aniaml类)调用eat方法。 因为动物类有一种方法,可以吃任何类型的食物和动物的子类 食物类型作为输入参数(多态性),编译通过

通常,编译器保证特定的方法可以为特定的引用类型调用

在运行时:调用的实际方法是该对象类型(Dog类)方法的最具体版本。自 JVM无法找到被重写的方法,即声明了相同方法名和参数类型的方法 在子类(Dog类)中,它检查其超类(Animal类),找到方法并执行

公共空吃(食物)公共空间吃(肉) 从重写方法的角度来看,它们是不同的

通常,当您在对象引用上调用方法时,您正在为此调用该方法的最特定版本 运行时期间的对象类型。但如果它找不到,它将上升到层次结构。最坏的情况下,超类肯定会有 否则编译将无法通过方法实现。

为了能够“在运行时动态加载子类”,使用泛型可以使其完美工作。
To be able to "dynamically load the subclass at runtime", use of generics makes it work perfectly.


public class HelloWorld{

     public static void main(String []args){
        Animal animal = new Dog(); 

        Food flesh = new Flesh();

        animal.eat(flesh);
     }
}

 class Food {
        public String toString(){
            return "Normal Food";
        }
    }

    class Flesh extends Food {
        public String toString(){
            return "Flesh Food";
        }
    }

    class Animal<T extends Food> {
        public void eat(T food){
            System.out.println("Animal eats "+ food);
        }
    }

    class Dog extends Animal<Flesh>{
        
        public void eat(Flesh flesh){
            System.out.println("Dog eats "+ flesh);
        }
    }
公共类HelloWorld{ 公共静态void main(字符串[]args){ 动物=新狗(); 食物肉=新肉(); 动物。吃(肉); } } 等级食品{ 公共字符串toString(){ 返回“正常食物”; } } 类肉延伸食物{ 公共字符串toString(){ 还“肉食”; } } 类动物{ 公共食品(T食品){ System.out.println(“动物吃”+食物); } } 狗类动物{ 公共空吃(肉){ 系统
To be able to "dynamically load the subclass at runtime", use of generics makes it work perfectly.


public class HelloWorld{

     public static void main(String []args){
        Animal animal = new Dog(); 

        Food flesh = new Flesh();

        animal.eat(flesh);
     }
}

 class Food {
        public String toString(){
            return "Normal Food";
        }
    }

    class Flesh extends Food {
        public String toString(){
            return "Flesh Food";
        }
    }

    class Animal<T extends Food> {
        public void eat(T food){
            System.out.println("Animal eats "+ food);
        }
    }

    class Dog extends Animal<Flesh>{
        
        public void eat(Flesh flesh){
            System.out.println("Dog eats "+ flesh);
        }
    }