Java学习04-继承与多态

继承与多态

1.1继承

Java中不支持多继承,子类只能有一个父类或者没有父类。

1.1.1Java继承的实现

定义类时通过extends关键字指明其要继承的父类。
子类可以访问:

  1. 子类中直接定义的成员
  2. 父类中的非私有成员(除构造方法)

【注意】 子类无法继承父类的私有属性,也无法直接访问父类的私有属性,但如果父类中有public修饰的对私有属性的get和set的方法,子类便可以通过该方法间接访问父类的私有属性。
【例如】

class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

class Student extends Person{

}

public class Test{
    public static void main(String[] args) {
        Student s = new Student();
        s.setAge(18);
        s.setName("张三");
        System.out.println(s.getName()+":"+s.getAge()+"岁");    //张三:18岁
    }
}

1.1.2构造方法在类继承中的作用

构造方法不能继承。由于子类对象要对继承自父类的成员进行初始化,因此,在创建子类对象时除了执行子类的构造方法外,还需要调用父类的构造方法。

子类调用父类构造方法时的注意事项:

  1. 子类可以在自己构造方法中使用关键字super来调用父类的构造方法,但super调用语句必须是子类构造方法中第一个可执行语句。
  2. 子类在自己定义构造方法中如果没有用super明确调用父类的哪个构造方法,则在创建对象时,系统会默认首先自动执行父类的无参构造方法,然后再执行自己定义的构造方法。

【例如】以下程序在编译时出错,原因在于父类不含无参构造方法。

public Parent{
	String my;
	public parent(String x){
		my = x;
	}
}
public class Child extends Parent{
}

【说明】在Parent类中定义了一个有参构造方法,所以系统不会自动产生无参构造方法,而在子类Child中,没有自己调用super方法,所以系统会默认自动执行父类的无参构造(相当于在子类中的第一行默认添加了:super()),但是父类中并没有无参构造,所以会出错。如果将有参构造方法注释掉,编译可通过。
鉴于上述情形,一个类在设计时如果有构造方法,最好手动提供一个无参构造方法。

【例】

import java.awt.*;

class Point{
    private int x, y;

    public Point(int x, int y) {    //有参构造
        this.x = x;
        this.y = y;
    }

    public Point() {    // 无参构造
        this(0,0);  //在这里this在一个构造方法中调用同类的另一个构造方法,即在无参构造中调用有参构造
    }

    @Override
    public String toString() {  //重写toString()方法
        return "点:"+x+","+y;
    }
}

public class Pixle extends Point{
    Color c;

/*该方法也 alt+insert 可自动生成*/
    public Pixle(int x, int y, Color c) {      //用super调用父类的有参构造
        super(x, y);
        this.c = c;     //在这里this来访问实例变量
    }

    @Override
    public String toString() {
        return super.toString()+"颜色:"+c;    //用super访问父类方法
    }

    public static void main(String[] args) {
        Pixle x = new Pixle(3,24,Color.black);
        System.out.println(x);      //点:3,24颜色:java.awt.Color[r=0,g=0,b=0]
    }
}

【说明】本例中出现super关键词,super与this在使用上类似,super表示当前对象的直接父类对象的引用,通过super除了可以调用父类的构造方法外,还可以通过super引用访问父类的属性和方法。
【注意】

  • 使用this查找匹配的方法时首先在本类查找,在找不到时再到其父类和祖先类查找。
  • 使用super查找匹配方法时,首先到直接父类查找,若不存在,则继续到其祖先类查找

1.2多态

一般地,面向对象的多态性体现在以下两个方面:

  1. 方法的重载:在同一个类中定义多个方法名相同,参数列表不同(参数类型不同 ∪ 参数个数不同)的方法。
  2. 子类对父类方法的覆盖:子类中可对父类定义的方法重新定义,这样在子类中将覆盖来自父类的同形态方法。

1.2.1方法的重载

方法的重载就是在同一个类中定义多个方法名相同,参数列表不同(参数类型不同 ∪ 参数个数不同)的方法。
方法调用的匹配处理原则是:

  1. 按精确匹配原则去查找匹配方法。
  2. 如果精确匹配找不到,则按自动类型转换匹配原则去查找能匹配的方法。

1.2.2方法的覆盖

子类将继承父类的非私有方法,在子类中也可以对父类定义的方法重新定义,这时产生方法的覆盖。
方法覆盖的注意事项:

  1. 方法名、参数列表完全相同才会产生方法覆盖。返回类型通常也要一致,只有返回类型为引用类型时,允许子类方法的返回类型时父类方法返回类型的子类型。
  2. 方法覆盖不能改变方法的静态与非静态属性。
  3. 不允许子类中方法的访问修饰符比父类有更多的限制,通常应将子类中方法访问修饰与父类中的保持一致。

1.2.3访问继承的成员

如果子类中定义了与父类同名的属性,在子类中将隐藏来自父类的同名属性变量。这里也是“就近原则”,自己类中有就不会去找父类的。

【例】

class ParentShow{
	int y = 8;
	int m = 2;

	void show(){
		System.out.println("Parent.show,y="+y);
	}
}

public class ChildShow extends ParentShow{
	int y = 20;
	int z = 1;

	void show(){
		System.out.println("Child.show,y="+y);
	}

	public static void main(String args[]){
		ChildShow chid = new ChildShow();
		ParentShow parent = child;//父类引用指向子类对象
		System.out.println("Child.y="+child.y);
		System.out.println("Parent.y="+parent.y);
		child.show();
		parent.show();
		System.out.println("z="+child.z+",m="+child.m);
	}

【运行结果】
Child.y=20
Parent.y=8
Child.show,y=20
Child.show,y=20
z=1,m=2

[说明]

  1. 当子类与父类有相同成员时,通过子类引用访问的成员均是子类定义的。
  2. 父类引用指向子类对象时,只有实例方法会是子类定义的,对象属性、静态属性、静态方法均是指父类定义的。

1.3Object类

Object类包含了所有Java类的公共属性和方法,以下给出了几个常用的方法:

  • public boolean equals(Object obj):比较运算符"=="在比较两对象引用变量时,只有当两个对象引用指向统一对象时才为真。但在Object类中,equals()方法采用==运算进行比较,其他类如果没有定义equals()方法,则继承object类的equals()方法。因此,在类设计时,需要进行对象数据的比较时,一般要重写equals()方法。
  • public String toString:该方法返回对象的字符串描述,其他类通常会重写该方法。
  • public final Clsaa getClass():返回对象的所属类,而且利用Class类提供的getName()方法可以获取对象的类名称。
  • protected void finalize():该方法在Java垃圾回收程序删除对象前自动执行。一个对象没有任何一个引用变量指向它时,Java垃圾回收成句将自动释放对象空间。

1.4访问控制修饰符

1.公共访问控制符:public
public可用于两个地方:作为类的修饰符,作为类的成员的访问修饰符。
2.默认访问控制符:defaul
默认的访问控制指在属性或方法定义前没有给出访问控制符的情形。
3.私有访问控制符:private
通常,出于系统设计的安全性考虑,将类的成员属性定义为private形式保护起来,而将类的成员方法定义为public形式对外公开,这是类封装特性的一个体现。
保护访问控制符:protected

在这里插入图片描述

1.5 final修饰符

可用于修饰:成员变量,非抽象类(不能与abstract同时出现),非抽象的成员方法,以及方法参数。
1.final修饰类:
表示该类不能被继承,没有子类;final类中的方法也无法被继承。
2.final修饰方法
不能被子类的方法重写,但可以被继承。final不能用于修饰构造方法。
3.final定义常量
用final标记的变量也就是常量,并且final标记的常量系统不会默认给其赋初值,所以必须定义初始化。final定义常量的初始化,可以在定义时初始化,也可以在其对应类的构造方法中初始化。
如果将引用类型的变量标记为final,那么该变量只能固定指向一个对象,不能修改,但可以改变对象内容,因为只有引用本身是final的。

猜你喜欢

转载自blog.csdn.net/qq_42145862/article/details/88925842