Java基础学习-方法重载、构造函数重载、方法重写与多态

一、方法以及方法重载

  首先我们要明确什么是方法,方法其实就是一段经过封装的有特定功能的代码段。你可以用它来做特定的动作,比如在控制台输出一行字符串,给它两个整数然后让这段代码替你将两个整数进行相加。
  其次我们应该需要理解两个概念。【形参】和【实参】。【形参】就是定义方法上的,用来接收外界传给它的信息。在java中,你需要指定信息的类型,如果是整数就是int,如果是字符串类型就是String。字符串类型为什么是大写字母开头呢,因为字符串其实是一个类,在java中类的名称约定为大写首字母开头。你给一段代码传递的信息可能不止一个呀,如果需要传两个整数类型怎么办,这个时候就用逗号隔开。比如:
1  public  int add(int a,int b){}

  这个时候就传递了两个整数类型进去了,分别命名为a和b。这个时候方法里面就可以直接拿a和b开始用了。

  我们调用的时候就可以直接:

1 add(5,6);

  这样我们就把整数5和整数6传递给了名字叫add方法的这个方法。5和6就是实际传给add方法的参数,也就是【实参】。通常情况下,我们可能传入的是两个变量。例如:

1 int x=6;
2 int y=7;
3 add(x,y);

  这个时候x和y就是实参了。分别对应的是add()方法的形参a和b。要注意一点,a和b跟x、y有什么关系呢?其实从名字上看是一点关系都没有的,唯一有关系的就是他们的数据类型必须要一一对应。逗号前面,方法要求传的是整数型,你调用这个方法的时候就必须传递一个整数,后面如果要求传递一个数组,你就必须传递一个数组类型进去,否则就调用错误了。

  形参的命名a、b就是的意义就是给传入的两个信息命个名字。第一个我叫a,第二个我叫b。在方法体内部我就可以直接调用了这两个参数了。仅此而已。比如实参传来的两个整数型变量叫a、b形参也叫a、b,这个时候传入的a、b和方法内部的a、b一样吗?表面看一样,其实传入的a和b是方法外的两个变量,方法内部也把重新命名了两个变量叫a和b来接收方法外的两个变量。方法外的方法内部的a和b占用了不同位置的内存的。所以不是同一个东西。

  接着说,如果我需要把若干个整数进行相加。有的时候是两个,有的时候是3个,有的时候我还要把5个数进行相加。这个时候我们需要命名不同的函数名吗?Java提供了方法重载的功能。我们就用同一个函数名,需要传两个整数在函数名的小括号里面传入两个整数形参,需要传三个就传入三个整数形参。函数被调用的时候,你传入了几个实参,java就会去寻找能传入几个实参的那个函数,然后把实参挨个传过去就可以了。

  这样在调用的时候会很方便。一个函数名就对应一种功能。如果是两个都需要传入两个整数类型的函数,他们的区别只是返回值不同,这是不算方法重载的,这样会报错。因为java会认为他们是同一个功能的函数。简单的说,java看两个方法是不是重复只看形参的类型和个数,不管该方法的返回值。

  下面是一个完整的代码实例:

 1 package blog;
 2 
 3 public class Overloaddemo {
 4     
 5     public  int add(int a,int b){ //传入两个整数形参
 6         return a+b;
 7     }
 8     
 9     public int add(int a,int b,int c){  //传入三个整数形参
10         System.out.println(add(a,b));  //重载的方法中调用了两个整数形参的同名方法
11         return a+b+c;
12     }
13     
14     public static void main(String[] args) {
15         Overloaddemo test=new Overloaddemo();
16         int result=test.add(1,2);
17         System.out.println(result);
18         
19         int result2=test.add(1,3,4);
20         
21         //System.out.println(result);
22         System.out.println(result2);
23     }
24 
25 }

  结果是:

 3
 4
 8

 二、构造方法及构造方法重载

  构造方法是用于完成对象属性的初始化工作的。你在调用一个类的方法或者变量,如果不是类的静态成员的话,你首先需要new一个对象,也就是根据这个类初始化一个对象。只要你new了一个对象,构造方法就运行了。如果你没有在类文件中写该类的构造方法,java编译器会自动给这个类加上构造方法,该构造方法的形参为空切方法体也是空的。
  但是你自己主动在类中创建了一个该类的构造方法,那么java编译器就不会再添加这个空的构造方法了。
  现在自己怎么在类中主动创建一个构造方法呢?
  先来段标准的代码:
 
1  class Demo{
2       public Demo(int i){}
3   }

  可以看出:【1】构造方法的名字必须和类名完全一样。因为java是区分大小写的,所以大小写也不能写错。

       【2】构造函数没有返回值,也不能写void。

  我们是无法像调用类其他成员方法一样调用类的构造构造方法的。构造方法的运行是通过new关键字创建一个对象的时候,java会自动调用它为对象进行初始化。

  构造函数的重载其实跟方法重载差不多,也是在同一个类中因构造函数的形参类型和个数不同构成了重载。new该对象的时候,根据new class()括号中的参数类型和个数不同,调用不同的构造函数。一个类中不同的构造函数之间是可以互相调用的。也就是只要能遵循初始化一个对象只能一开始就初始化,且只能一次的原则就可以了。

  我们如果在一个构造方法中调用另一个构造方法,那么可以使用this()的方式,this()括号中的参数为构造方法的参数。也可以省略写。从用this可以看出,构造函数不是类的静态成员。

  对构造方法进行调用时,对new的使用特点:

    【1】调用时,后面的小括号()表示构造方法的参数列表,如果构造方法不接收参数,那么小括号可以为空;
    【2】如果构造方法接收参数,那么小括号中的实际参数就需要和构造方法定义中的形式参数保持一致(一致条件为:参数数量一致、参数类型一致、按相应的顺序排列逐一赋值)。
  下面是完整的代码:
 1 package blog;
 2 
 3 public static void main(String[] args) {
 4         //通过new初始化一个对象调用了空参的构造函数
 5         new Gouzaofangfa();
 6     }
 7     
 8     public Gouzaofangfa(){
 9           //空参的构造函数调用了一个参数的构造函数
10         this(3);    
11     System.out.println("test");
12    } 
13 
14    public Gouzaofangfa(int i){
15      System.out.println(++i); 
16    } 
17 
18  }

结果是:

4
test

 三、方法重写与多态

  在java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。也常叫做方法覆盖。

  多态有两种表现形式,分为重载和覆盖。现在讲的就是方法覆盖。

  先看看代码:

 1 package blog;
 2 
 3 public class DemoPolymorphism{    //演示多态
 4     public static void main(String[] args){
 5         Son s1=new Son();
 6         s1.work();
 7         
 8         // 子类继承父类,子类拥有父类所有的功能,因此可以把子类传给父类
 9         Dad s2=new Son();
10         s2.work();            //调用了父类的工作方法,但是传递的是儿子对象,儿子对象既是父类对象也是子类对象,儿子的工作是码代码
11         
12         Dad s3=(Dad)s1;
13         s3.work();            //把子类对象强转成父类对象,就相当于化妆成了父亲,但是让其工作还是只会码代码
14         
15         s1.show();            //调用了子类的show方法,展示的是其父类的工作方法,设计房子
16         
17     }
18     
19 
20 }
21 
22 class Son extends Dad{
23     //儿子继承了父类,因为儿子的工作是写代码,所以重写了父类的work方法。这个叫方法重写
24     public void work(){
25         System.out.println("儿子在工作:码代码");
26     }
27     
28     public void show(){
29         super.work();    //调用了父类的工作方法,会输出了父类的工作方法,设计房子
30     }
31 }
32 
33 class Dad{
34     //爸爸的工作内容是设计房子
35      void work(){
36         System.out.println("爸爸在工作:设计房子");
37     }
38 }

   子类重写了父类的工作方法,因为子类的工作是码代码,父类是设计房子。子类的对象属于子类类型也属于父类类型。

  再来一个多态的例子。

 1 abstract class Animal
 2 {
 3     abstract void eat();
 4 }
 5 
 6 class Cat extends Animal
 7 {
 8     public void eat()
 9     {
10         System.out.println("吃鱼");
11     }
12     public void catchMouse()
13     {
14         System.out.println("抓老鼠");
15     }
16 }
17 
18 class Dog extends Animal
19 {
20     public void eat()
21     {
22         System.out.println("吃骨头");
23     }
24     public void kanJia()
25     {
26         System.out.println("看家");
27     }
28 }
29 
30 class DuoTaiDemo
31 {
32     public static void main(String[] args)
33     {
34         function(new Cat());
35         function(new Dog());
36         
37         Animal a = new Cat();//向上转型
38         a.eat();
39         
40         Cat c = (Cat)a;//向下转型
41         c.catchMouse();
42         
43         
44     }
45     
46     public static void function(Animal a)
47     {
48         a.eat();
49         //用于子类型有限
50         //或判断所属类型进而使用其特有方法
51         if(a instanceof Cat)
52         {
53             Cat c = (Cat)a;
54             c.catchMouse();
55         }
56         else if(a instanceof Dog)
57         {
58             Dog c = (Dog)a;
59             c.kanJia();
60         }
61     }
62     
63     
64 }    

  这个例子就把多态用途展现得很充分了。其中定义了一个方法,只要抛入的是动物类型,我就会调用其吃的方法。抛入狗就会啃骨头,抛入猫就会吃鱼。但是要注意的是,这个方法不能含有直接调用动物类型非公有的方法,也就是抽象类中不存在的方法。否则就会出错误。就好像抛入猫,就不能在方法中调用其看家的方法,否则就会出错,即使是狗也不行,因为动物类型没有这个共性的方法,你要调用,你必须强制转型成狗的类型。这个时候你就可以调用看家的方法了。

原文地址:https://www.cnblogs.com/soongkun/p/4882947.html