A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 韦念欣 黑马帝   /  2012-6-22 01:56  /  4100 人查看  /  16 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 韦念欣 于 2012-6-23 07:56 编辑

JAVA中有重载,也有重写,到底什么情况下才是重载,什么情况下才是重写?

16 个回复

倒序浏览
重载表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。

重写表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报
    (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。

重载Overloading是一个类中多态性的一种表现。


    (2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。

调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。


    (3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。


    下面是重载的例子:
    package c04.answer;//这是包名
    //这是这个程序的第一种编程方法,在main方法中先创建一个Dog类实例,然后在Dog类的构造方法中利用this关键字调用不同的bark方法。

不同的重载方法bark是根据其参数类型的不同而区分的。

    //注意:除构造器以外,编译器禁止在其他任何地方中调用构造器。
    package c04.answer;

    public class Dog {
         Dog()
         {
                this.bark();
         }
         void bark()//bark()方法是重载方法
         {
                System.out.println(\"no barking!\");
                this.bark(\"female\", 3.4);
         }
         void bark(String m,double l)//注意:重载的方法的返回值都是一样的,
         {
                System.out.println(\"a barking dog!\");
                this.bark(5, \"China\");
         }
         void bark(int a,String n)//不能以返回值区分重载方法,而只能以“参数类型”和“类名”来区分
         {
                System.out.println(\"a howling dog\");
         }

         public static void main(String[] args)
         {
                Dog dog = new Dog();
                //dog.bark(); [Page]
                //dog.bark(\"male\", \"yellow\");
                //dog.bark(5, \"China\");




  然后我们再来谈谈 重写(Overriding)


    (1) 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。

但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。

方法重写又称方法覆盖。


    (2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。

如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。


    (3)子类函数的访问修饰权限不能少于父类的;
    下面是重写的例子:


    概念:即调用对象方法的机制。



    动态绑定的内幕:

    1、编译器检查对象声明的类型和方法名,从而获取所有候选方法。试着把上例Base类的test注释掉,这时再编译就无法通过。



    2、重载决策:编译器检查方法调用的参数类型,从上述候选方法选出唯一的那一个(其间会有隐含类型转化)。

如果编译器找到多于一个或者没找到,此时编译器就会报错。试着把上例Base类的test(byte b)注释掉,这时运行结果是1 1。



    3、若方法类型为priavte static final ,java采用静态编译,编译器会准确知道该调用哪
    个方法。



    4、当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用对象的实际类型相匹配的方法版本。

在例子中,b所指向的实际类型是TestOverriding,所以b.test(0)调用子类的test。

但是,子类并没有重写test(byte b),所以b.test((byte)0)调用的是父类的test(byte b)。

如果把父类的(byte b)注释掉,则通过第二步隐含类型转化为int,最终调用的是子类的test(int i)。



学习总结:

    多态性是面向对象编程的一种特性,和方法无关,
    简单说,就是同样的一个方法能够根据输入数据的不同,做出不同的处理,即方法的
    重载——有不同的参数列表(静态多态性)

  而当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法,

    即在子类中重写该方法——相同参数,不同实现(动态多态性)



    OOP三大特性:继承,多态,封装。

    public class Base
    {
        void test(int i)
        {
            System.out.print(i);
        }
        void test(byte b)
        {
            System.out.print(b);
        }
    }
    public class TestOverriding extends Base
    {
        void test(int i)
        {
            i++;
            System.out.println(i);
        }
          public static void main(String[]agrs)
        {
            Base b=new TestOverriding();
            b.test(0)
            b.test((byte)0)
        }
    }


    这时的输出结果是1     0,这是运行时动态绑定的结果。



重写的主要优点是能够定义某个子类特有的特征:

public class Father{

   public void speak(){

       System.out.println(Father);

    }

}

public class Son extends Father{

    public void speak(){

        System.out.println("son");

   }

}

这也叫做多态性,重写方法只能存在于具有继承关系中,重写方法只能重写父类非私有的方法。

当上例中Father类speak()方法被private时,Son类不能重写出Father类speak()方法,此时Son类speak()方法相当与在Son类中定义的一个speak()方法。

Father类speak()方法一但被final时,无论该方法被public,protected及默认所修饰时,Son类根本不能重写Father类speak()方法,

试图编译代码时,编译器会报错。例:

public class Father{

   final public void speak(){

       System.out.println("Father");

    }

}

public class Son extends Father{

    public void speak(){

       System.out.println("son");

    }

}       //编译器会报错;



Father类speak()方法被默认修饰时,只能在同一包中,被其子类被重写,如果不在同一包则不能重写。

Father类speak()方法被protoeted时,不仅在同一包中,被其子类被重写,还可以不同包的子类重写。


评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 熬夜不容易啊!

查看全部评分

回复 使用道具 举报
方法重载是指方法名和方法的返回类型都相同,但方法参数不一样;参数不一样体现在参数个数和参数类型不一样。Test.java
--------------
public class Test
{
public static void main(String[] args){
  Test ts = new Test() ;
  System.out.println(ts.ss("s1","s2")) ;
  System.out.println(ts.ss("s1")) ;
}
public String ss(String s1,String s2){
  return s1+s2 ;
}
public String ss(String s1){
  return s1 ;

}
}
方法重写:方法重写是相对继承而言的,重写的方法名.返回类型,参数类型和参数个数都要求和父类中的一样。这是重载和重写形式上的区别。
回复 使用道具 举报
重载:
在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法。

重写:
(1)父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
譬如:
class Bar extends Foo{
      /*
              void kk(){
       }
       这个方法是从Foo这个类里继承而来
      */
      void kk(String x){   //重载
      }
}
因此bar类里面有两个方法同名,但是参数类型不一样。
如果
class Bar extends Foo{
      /*
              void kk(){
       }
       这个方法是从Foo这个类里继承而来
      */
      void kk(){    //重写
      }
}

回复 使用道具 举报
重写的主要好处是具有能够定义某个子类型特定行为的能力。
        以下是重写方法的规则:
        1. 参数列表必须与被重写的方法的参数列表完全匹配,或者就成重载了;
        2. 返回类型必须与超类中被重写方法原先声明的返回类型或其子类型相同;
        3. 访问级别的限制性一定不能比被重写方法的更严格(如public->private);
        4. 访问级别的限制性可以比被重写方法的弱;
        5. 仅当实例方法被子类继承时,它们才能被重写。(与超类位于相同包内的子类可以重写未标识为private或final的任何超类方法;不同包中的子类只能重写那些标识为public或protected的非final方法。)
        6. 重与方法可以抛出任何示检验(运行时)异常,无论被重写方法是否声明了该异常;
        7. 重与方法一一不能抛出比被重写方法声明的检验异常更新或更广的检验异常。(例如,一个声明FileNotFoundException异常的方法不能被一个声明SQLException、Exception或任何其他非运行时异常的方法重写,除非它是FileNotFoundException的一个子类;
         8. 重写方法能够抛出更少或更有限的异常。仅仅因为被重写方法“承担风险”,并不意味着重写子类的异常会承担同样的风险。关键之处是:不管被重写方法声明了什么异常,重写方法都不必声明它从不会抛出的任何异常;
         9. 不能重写标识为final或static的方法;
        10. 如果方法不能被继承,就不能被重写。

        二、重载方法允许在类中复用相同的方法名称,但是具有不同的参数(并可以选择不同的返回类型)。重载一个方法往往意味着对那些调用方法的人更加友好,因为你的代码承担起处理不同参数类型的责任,而不用强制要求调用程序在调用方法之前进行了转换。
         重载的规则相对简单:
        1. 重载方法必须改变参数列表;
        2. 重载方法可以改变返回类型;
        3. 重载方法可以改变访问修饰符;
        4. 重载方法可以声明新的或更广的检验异常;
        5. 方法能够在同一个类或者一个子类中被重载。
        三、重写和重载的区别:
        1. 参数: 重载方法:必须改变 ,重写方法:一定不能改变
        2. 返回类型: 重载方法:可以改变 ,重写方法:除协变式返回外,不能改变。
        3. 异常: 重载方法:可以改变 ,重写方法:可以减小或消除。一定不能抛出新的或更广的检验异常。
        4. 访问级别: 重载方法:可以改变 ,重写方法:一定不能执行更严格的限制(可以降低限制)。
        5. 调用: 重载方法:引用类型决定了选择哪个重载版本(基于声明的参数类型)。在编译时做出决定。调用的实际方法仍然是一个运行时发生的虚拟方法调用,但是编译器总是知道所调用方法的签名。因此在运行时,不仅是方法所在的类,而且参数匹配也已经明确。重写方法:对象类型(也就是堆上实际的实例类型)决定了调用哪个方法在运行时做出决定。
回复 使用道具 举报
重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。
重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。
回复 使用道具 举报
刘笑 中级黑马 2012-6-22 10:03:56
8#
重写是子类的方法覆盖父类的方法,要求方法名和参数都相同

重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数,可以参考API帮助文档看看类的构造方法
回复 使用道具 举报
简单点:重载就是类内部方法多态的体现;重写就是子类与父类间多态性的体现

建议看看,“张孝祥java就业面试宝典”  上面有很多类似问题 解释的也很详细,咱不面试也可以学习嘛
回复 使用道具 举报
重载是表示在同一类中把原来的方法重新写一次,只不过是方法的参数不一样(参数的类型或参数的个数不一样)其他的都一样(方法的返回值和方法的权限都一样)。
重写是表示子类把父类的原有方法覆盖掉,重新写了一个和父类一模一样的方法(方法的返回值和方法的参数完全一样),覆写时子类的方法权限必须大于等于父类的方法访问权限。
回复 使用道具 举报
  Overload是重载的意思,Override是覆盖的意思,也就是重写。

     重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。

     重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。




     override可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点:

1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;

2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;

3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;

4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。

     overload对我们来说可能比较熟悉,可以翻译为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。在使用重载要注意以下的几点:

1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int,float),但是不能为fun(int,int));

2、不能通过访问权限、返回类型、抛出的异常进行重载;

3、方法的异常类型和数目不会对重载造成影响;

4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
回复 使用道具 举报
一般情况下在同一个类里面有相同的方法,但是参数不同,可以重载,比如相加方法:add(int a,int b)和add(int a,int b,int c)在同一个类里面就是重载。
一般子类继承父类,子类里面的某个方法和和父类相同,但是实现方式内容不同,就需要覆盖,覆盖的时候方法的返回值,方法名和参数列表与父类的必须一模一样。
回复 使用道具 举报
下面是我自己对重载和覆盖的一点总结,你可以参考下,希望对你有用。
方法重载:类中完成同一种功能的方法有多种不同的表现形式,而这些方法的名称相同,但是调用哪一个方法,取决于方法给定的形式参数。
方法重载的规则:
1.方法名称一定要相同。不一样,就是两个不同的方法,不能称之为重载。
2.传入的参数类型一定要不同。包括参数的类型或者参数的个数,至少有一项不同。
3.方法重载和方法的返回值类型和方法的修饰符没关系。

方法覆盖:对于子父类而言的,子类中的某一个方法的名称,返回值类型,形式参数的类型和个数刚好和其父类的某个方法相同,就称之为方法覆盖。
方法覆盖的规则:
1.方法名称一定要相同。不一样,就是两个不同的方法,不能称之为覆盖。
2.返回值类型一定要相同。不一样就是重载而不是覆盖。
3.方法的形式参数要一样。包括参数的个数和每个参数的类型。
4.修饰符的使用权限只能越来越开放,不能越来越封闭。
回复 使用道具 举报
其实挺简单的,当定义的功能相同,但参与运算的未知内容不同,那么这时可以定义同一个函数名称,以表示功能,方便阅读,而通过参数列表的不同来区分多个同名函数,就是重载,重载只看同名函数的参数列表。当子类继承了父类,沿袭了父类的功能到子类中,但子类虽具有该功能,功能的内容却和父类不一样,这时可以可以用重写功能来保留父类的功能 定义,只需重写功能内容,重写时子类和父类方法要一模一样。
回复 使用道具 举报
简单点说吧!重写与重载都是java的多态技术

所谓“重载”,即是方法名称相同,但却可以在不同的场合做不同的事(返回值类型,参数类型,个数可以不同)。

所谓“重写”,即是当一个子类继承一个父类,而子类中的方法与父类中的方法的名称,参数个数,类型等都完全一致时,就称子类中的这个方法覆写了父类中的方法。同理,如果子类中重复定义了父类中已有的属性,则称此子类中的属性覆写了父类中的属性。
回复 使用道具 举报
在java里面重载 即为方法重载指的是同一个方法有着多种不同的表现形式,具体有方法参数的类型不同,个数不同,注意和方法的返回值没有关系。
而重写必须有继承,没有继承不谈重写,还有我们在重写之前一定要弄清除我们为什么要重写?重写的具体意义是什么? 我个人的理解是即当子类对父类的某些成员变量或成员方法不满意时我们就需要重写父类的成员方法或成员变量。
public String toString(); 是Object类里的一个方法,Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示.
我们都知道Object是所有java 类的父类,当我们在定义了一个自己的类比如说Student
public class Student // 相当于 extends Object
{
        private String name;
        private String sex;
        public Student()
        {
       
        }
        public Student(String name, String sex)      //这里对构造方法进行了重载
        {
                 this.name = name;
                this.sex = sex;
        }
        public String toString()
        {
                return this.name + " " + this.sex;
        }
        public static void main(String[ ] args)
        {
                Student student = new Student("Tanliwen", "Man");
                System.out.println(student);
        }
}
如果我们没有重写父类的方法public String toString();方法当我们在执行System.out.println(student); //相当于是System.out.println(student.toString());
输出的是Student@(对象哈希码的无符号十六进制)请问你对这个输出结果感兴趣吗,是否有觉得晦涩,反正我是觉得很晦涩?
这个时候我们就可以来重写父类的public String toString();方法来输出Student实例的属性,姓名以及性别。
也许你会说我完全可以不重写父类的public String toString();方法而重新定义一个方法:
public String getInformation()
{
                return this.name + " " + this.sex;
}
是的,完全可以,而我们为什么要选择重写呢?java在输出一个对象名时是默认调用的toString方法,这样我们在重写父类的方法之后可以给我们的程序带来便利,你觉得是写System.out.println(studnet.getInformation());更方便还是直接System.out.println(student);更简洁。
这些只是我在学完java基础后一点个人的理解,若有错误,欢迎拍砖,共同学习。


回复 使用道具 举报
我明白了,谢谢大家。
15楼说的简单明了,我简单总结一下吧:
重载就是:函数名相同,参数不同。
重写就是:在继承的时候,子类的函数名、函数参数、函数返回值都和父类一样;只是函数体内容不一样。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马