java重载和重写及类的加载顺序

Posted Heavy sea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java重载和重写及类的加载顺序相关的知识,希望对你有一定的参考价值。

一、方法重载(Overload)

重载概念同一个类中,同名不同参的方法称为重载方法
多数程序语言要求为每个方法(函数)提供一个独一无二的方法名,不存在方法重载的概念。
在java中,规定方法签名是解析方法的规则而不是方法名,为方法重载开创了条件。
方法重载使得在一个类中,方法名相同而参数列表不同的方法可同时存在,代表相似的行为或功能

注意:仅有返回值不同的方法不能称为重载

public class Overloading {
    public int test(){
        System.out.println("test1");
        return 1;
    }
 
    public void test(int a){
        System.out.println("test2");
    }   
 
    //以下两个参数类型顺序不同
    public String test(int a,String s){
        System.out.println("test3");
        return "returntest3";
    }   
 
    public String test(String s,int a){
        System.out.println("test4");
        return "returntest4";
    }   
}

二、方法重写(Override)

方法重写是指子类可以根据需要对从父类继承来的方法进行改写,是多态机制的前奏。

注意点:

  • 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值
  • 重写方法不能比被重写方法有更严格的访问权限
  • 父类中的私有方法 不能被重写
  • 在子类重写的方法中继续调用父类被重写的方法可以通过 super. 函数名获取
class Person
{
	String name;
	int score;

	public void eat()
	{
		System.out.println("人吃饭!");
	}
	
	public void drink()
	{
		System.out.println("人喝水!");
	}
	
	public void printData()
	{
		System.out.println("name="+name + "  score="+score);
	}
}

class Student extends Person
{	
	
	// 方法重写
	@Override 
	public void printData()
	{   
		super.printData();    // 使用父类的方法
		System.out.println("子类打印!");
		System.out.println("name="+name);
	}
}

public class Demo {
	public static void main(String[] args) {

		Student s = new Student();
		s.name = "haha";
		s.score = 14;
		s.printData();
	}
}

三、类的加载顺序

对于一个类,类有静态属性、静态代码块、构造方法…那么值得思考的是这些类中的成员在初始化时的顺序是怎样的?
先给出结论:
类中各成员初始化的顺序是

父类的静态字段——>父类静态代码块——>子类静态字段——>子类静态代码块——>

父类成员变量(非静态字段)——>父类非静态代码块——>父类构造器——>子类成员变量——>子类非静态代码块——>子类构造器

接下来用代码验证:
Father.java

package com.heavysea.l;

/**
 * @author heavysea
 * @date 2021/6/20
 */
public class Father {
    private String hobby = "喝酒";
    private static String NAME = "隔壁老王";

    static {
        System.out.println("父亲的静态属性:"+Father.NAME);
        System.out.println("父亲的静态代码块!");
    }

    {
        System.out.println("父亲成员变量:"+hobby);
        System.out.println("父类非静态代码块");
    }

    public Father(String hobby) {
        System.out.println("父类的构造方法");
        this.hobby = hobby;
    }

    public String getHobby() {
        return hobby;
    }

    public void smoke()
    {
        System.out.println("父亲来根华子");
    }
}

Son.java

package com.heavysea.l;

/**
 * @author heavysea
 * @date 2021/6/20
 */
public class Son extends Father {

    private String hobby = "游戏";
    private static String NAME = "老王的孩子";

    static {
        System.out.println("孩子的静态属性:"+Son.NAME);
        System.out.println("孩子的静态代码块!");
    }

    {
        System.out.println("儿子成员变量:"+hobby);
        System.out.println("孩子非静态代码块");
    }

    // 方法重写

    public Son(String hobby) {
        // 调用父类构造方法
        super(hobby);
        System.out.println("子类的构造方法");
    }

    @Override
    public void smoke()
    {
        System.out.println("儿子表示华子来不了,来根黄山!");
    }

    public void swim()
    {
        // 调用父类的方法
        super.smoke();
        System.out.println("儿子去游泳");
    }
}

Test.java

package com.heavysea.l;

/**
 * @author heavysea
 * @date 2021/6/20
 */
public class Test {
    public static void main(String[] args) {
        Son son = new Son("打游戏");
        son.smoke();
        son.swim();
        System.out.println(son.getHobby());

    }
}

运行结果:
在这里插入图片描述
运行结果非常nice,足以看出结论中类中成员的初始化顺序是正确的

四、继承中有关构造方法的问题

我们知道在子类继承父类时,如果 子类构造方法中未显式指定父类构造方法,那么将会默认执行父类的无参构造。 当然此时父类中同时实现有参构造和无参构造,子类仍然会默认执行父类的无参构造,即便仍未在子类当中指定父类构造方法。
例如:
Father.java

public class Father {
    private String hobby ;
	// 默认调用无参构造
    public Father(){
        System.out.println("父类的无参构造");
    }

    public Father(String hobby) {
        System.out.println("父类的构造方法");
        this.hobby = hobby;
    }
}

此时一切正常。但如果我们重载了一个父类的有参构造而没有指定无参构造,把上面的代码注释掉,程序会报错!!!
这时候就需要在子类当中指定父类构造方法了。

Father.java

public class Father {
    private String hobby ;
	//  默认调用无参构造
    // public Father(){
   //     System.out.println("父类的无参构造");
	//    }

    public Father(String hobby) {
        System.out.println("父类的构造方法");
        this.hobby = hobby;
    }
}

Son.java

public class Son extends Father {

    private String hobby;

    public Son(String hobby) {
        // 调用父类构造方法
        super(hobby);
        System.out.println("子类的构造方法");
    }
}

以上是关于java重载和重写及类的加载顺序的主要内容,如果未能解决你的问题,请参考以下文章

Java构造方法及类的初始化

重写和重载的区别

Java中的重载和重写的区别

笔记2---初始化及类的加载

java中重写重载的区别

java中重载和重写的区别是啥?