当前位置: 代码网 > it编程>编程语言>Java > Java继承和多态怎么理解?从基础到实例的完整讲解

Java继承和多态怎么理解?从基础到实例的完整讲解

2026年08月25日 Java 我要评论
继承只能存在一个父类,可以存在多个子类。父类的私有成员(访问权限为private的成员)不能被子类继承。子类继承父类的成员,同时可以定义其他的成员。允许存在多重继承,即子继承父,父继承爷。继承实现cl

继承

  • 只能存在一个父类,可以存在多个子类。
  • 父类的私有成员(访问权限为private的成员)不能被子类继承。
  • 子类继承父类的成员,同时可以定义其他的成员。
  • 允许存在多重继承,即子继承父,父继承爷。

继承实现

class 子类名称 extends 父类名称 {
}

实例

class person {
	int age;
	public char gender;
	protected string name;
	private string dream;
	
	void msgprintf(){
		system.out.println("age is " + age);
		system.out.println("gender is " + gender);
		system.out.println("name is " + name);
	}
	
	//私有方法
	private void myprintf(){
		system.out.println("hello");
	}
	
}  //父类(只能存在一个父类,可以存在多个子类):人

//子类:老师
class teacher extends person {
	void teacherdream(){
		system.out.println("become teacher");
	}
}

//子类:学生
class student extends person {
	void studentdream(){
		system.out.println("become programmer");
	}
}

public class text {

	public static void main(string[] args) {
		
		teacher t1 = new teacher();
		t1.age = 25;
		t1.gender = '女';
		t1.name = "jiangxiaoya";
		//t1.dream = "become teacher";  由于父类person中的dream是私有成员,因此无法被子类teacher继承
		//t1.myprintf();  由于父类person中的myprintf()是私有方法,因此无法被子类teacher继承
		t1.msgprintf();
		t1.teacherdream();
		system.out.println();
		
		student s1 = new student();
		s1.age = 19;
		s1.gender = '男';
		s1.name = "haozige";
		//s1.dream = "become programmer";  由于父类person中的dream是私有成员,因此无法被子类student继承
		//s1.myprintf();  由于父类person中的myprintf()是私有方法,因此无法被子类teacher继承
		s1.msgprintf();
		s1.studentdream();
		
	}
}

方法重写

  • 当子类与父类有相同的方法时(即方法名相同、返回值类型相同、参数列表相同),此时使用创建的子类对象使用该方法时,使用的是子类的方法,即方法重写。
  • 当子类和父类的方法名相同,参数列表不同时,此时使用创建的子类对象使用该方法时,使用的是子类的方法,但属于方法重载。
  • 方法重写发生在继承类中,被重写的方法不能有更严格的权限,而方法重载发生在一个类中,对权限没有要求。
  • 当子类存在与父类相同的数据成员时,优先使用子类的数据成员。

实例

class person {
	int age = 99;
	public char gender;
	protected string name;
	private string dream;
	
	void msgprintf(){
		system.out.println("age is " + age);
		system.out.println("gender is " + gender);
		system.out.println("name is " + name);
	}
}  //父类:人


//子类:学生
class student extends person {
	
	//方法重写,与父类的方法名相同,参数列表相同
	void msgprintf(){
		system.out.println("my dream is become programmer");
	}	
}


class teacher extends person {
	
	int age = 40;  //当子类存在与父类相同的数据成员时,优先使用子类的数据成员
	
	//方法重载,与父类的方法名相同,参数列表不同
	void msgprintf(string name){
		system.out.println(age);
		system.out.println(name);
	}
}

public class text {

	public static void main(string[] args) {
		
		student s1 = new student();
		s1.msgprintf();
		system.out.println();
		
		teacher t1 = new teacher();
		t1.msgprintf("jiangxiaoya");
		
	}
}

继承的构造方法的执行顺序

  • 当执行子类的构造方法时,父类以及父类的上一级结构的构造方法都会被执行,执行顺序是从最年老的到最年轻的。
  • 当子类有多个构造方法时,无论子类创建的对象使用哪个构造方法,父类以及父类的上一级结构都只会执行默认的构造方法(无参数的构造方法)。 

典例

class person {
	
	//构造方法
	person() {
		system.out.println("我是人");
	}
	
	person(string name) {
		system.out.println(name);
	}
}  //父类:人


//子类:学生
class student extends person {
	
	//构造方法
	student() {
		system.out.println("我是学生");
	}
	
	student(string name) {
		system.out.println(name);
	}
}

class haozige extends student {
	
	//构造方法
	haozige() {
		system.out.println("我是浩子哥");
	}
	
	haozige(string name) {
		system.out.println(name);
	}
}


public class text {

	public static void main(string[] args) {
		new haozige("haozige");  //执行匿名对象haozige的构造方法
		
	}
}

super关键字

 用途:

  • 在子类的构造方法中调用父类的构造方法。(子类创建对象时,部分数据成员使用父类的数据成员的值)
  • 当子类调用构造方法时,父类也会调用默认的构造方法,因此super关键字应用场景是调用父类有参数的构造方法
  • 在子类中调用父类的数据成员或者方法。(调用父类数据成员,当给子类的数据成员赋值之后,即使使用super关键字调用父类数据成员时,使用的也是子类成员的值)

实例

class student  {
	int age;
	char gender;
	string name = "学生名字未知";
	string greet;
	
	student() {
		this.greet = "i am a student";
	}
	
	void studentprintf(){
		system.out.println("hello teacher");
	}
}


class haozige extends student {
	
	public haozige(int age,char gender,string name) {
		super();  //调用父类的构造方法
		this.age = age;
		this.gender = gender;
		this.name = name;
	}
	
	void msgprintf(){
		
		system.out.println(super.name);  //调用父类数据成员,当给子类的数据成员赋值之后,即使使用super关键字调用父类数据成员时,使用的也是子类成员的值
		super.studentprintf();  //调用父类方法
		
		system.out.println(age);
		system.out.println(gender);
		system.out.println(greet);
	}
	
	
}

class jiangxiaoya extends student {
	void msgprintf(){
		system.out.println(super.name);  //调用父类数据成员
	}
}

public class text {

	public static void main(string[] args) {
		
		new haozige(19,'男',"haozige").msgprintf();
		system.out.println();
		
		new jiangxiaoya().msgprintf();
	}
}

final关键字

  • 当使用final关键字修饰数据成员时,声明该数据成员是一个常量(定义常量时应该进行初始化),常量的值不能改变。
  • 当使用final关键字修饰父类的方法时,子类继承时不能进行该方法的方法重写,但可以进行该方法的方法重载。
  • 当final关键字修饰类时,声明该类不能由其他类继承,即不能拥有孩子。

实例

class person  {
	int age;
	char gender;
	string name = "jiangxiaoya";
	final string greet = "i am a person";
	
	final void msgprintf(){
		system.out.println("hello");
	}
	
	void changemsg(){
		name = "haozige";
		//greet = "i am student";  数据成员常量不能被改变
	}
	
}


final class student extends person {
	
	//void msgprintf(){}  由于父类的msgprintf方法添加了final关键字,因此子类继承时不能进行方法重写,但能进行方法重载。
	void msgprintf(string name){
		system.out.println(name);
	}
	
}

//class jiangxiaoya extends student{}  由于类student添加了final关键字,因此不能生产孩子
	
	
public class text {

	public static void main(string[] args) {
		
		new student().msgprintf("zhutoucai");
		
	}
}

static关键字

  • static修饰数据成员时称为静态成员,static修饰方法时称为静态方法,类的静态成员和静态方法不需要创建对象就能使用。
  • 静态方法只可以使用静态成员和调用静态方法。
  • 如果父类有静态方法,那么子类不能进行该方法的方法重写,但可以进行方法重载,或者使用相同的方法名也定义为静态方法。

实例

class student  {
	static int age;  
	char gender;
	string name;

	static void initage(){
		age = 99;  //如果age不是静态成员,则会报错,静态方法只可以使用静态成员和调用静态方法
	}
	
	void initname(){
		name = "student";
	}
	
}


class haozige extends student {
	
	//不能进行方法重写,但可以对父类的静态方法进行方法重载
	void initage(int age){
		system.out.println(age);
	}
	
}


class jiangxiaoya extends student {
	
	//使用与父类相同的方法名也定义为静态方法,不知道是不是属于方法重写
	static void initage(){
		age = 19;
		system.out.println(age);
	}
	
}
	
	
public class text {

	public static void main(string[] args) {
		
		new haozige().initage(21);
		system.out.println();
		
		jiangxiaoya.initage();  //调用静态方法时,可以不用创建对象
		
	}
}

抽象类与抽象方法

  • 使用abstract关键字定义抽象类。
  • 抽象类是一个模板父类,让继承的子类实现模板父类的抽象方法,因此抽象类不能使用new关键字创建对象,只能被其他类继承。
  • 抽象类里面允许存在普通方法和数据成员和构造方法,但必须存在一个或一个以上的抽象方法,即主体内容都是抽象方法。
  • 抽象类被子类继承后,子类必须对抽象方法进行方法重写(即抽象方法的具体化)。
  • 继承抽象类的子类可以在构造方法中使用super关键字调用抽象类的构造方法,或者使用super关键字调用普通方法。

定义抽象类

abstract class 类名称 {
        数据成员;
        普通方法{
        }
        修饰符 abstract 抽象方法;
}

实例

//使用abstract关键字定义抽象类
abstract class student {
	//数据成员
	int age;
	char gender;
	string name;
	string greet;
	
	//构造方法1
	student() {
		this.greet = "父类构造方法1";
	}
	
	//构造方法2
	student(int age) {
		this.greet = "父类构造方法2";
	}
	
	//普通方法
	void myprintf(){
		system.out.println("hello");
	}
	
	//抽象方法
	abstract void msgprintf();
	
	
}

//继承抽象类
class haozige extends student {

	//子类的构造方法
	haozige(int age,char gender,string name){
		super(99);  //使用super关键字调用父类的构造方法2,注释掉该行时,会调用父类的构造方法1
		this.age = age;
		this.gender = gender;
		this.name = name;
	}
	
	//实现抽象方法
	public void msgprintf() {
		system.out.println(name);
		system.out.println(age);
		system.out.println(gender);
		system.out.println(greet);
		
		super.myprintf();  //调用父类的普通方法
	}
	
	
}


public class text {

	public static void main(string[] args) {	
		haozige h1 = new haozige(20, '男', "haozige");
		h1.msgprintf();
		
	}
}

接口

接口和抽象类的区别

  • 接口类似于抽象类,只提供方法的定义,让使用接口的类实现接口定义的方法
  • 一个类只能继承一个父类,而一个类能实现多个接口  ,处于不同层次的类可以实现同一个接口
  • 抽象类有数据成员、常量、普通方法和抽象方法,而接口只有常量和抽象方法
  • 接口内的方法在编译时,自动变成public和abstract类型,即变成公有抽象方法,而接口内的数据成员在编译时,自动变成public和final类型,即变成公有常量。

接口的定义和使用

  • 使用interface关键字定义接口,类使用implements实现接口
  • 接口的数据成员必须赋值,编译时会变成常量
  • 不能将接口方法声明为私有接口方法

定义接口

interface 接口名称 {
        修饰符 数据成员
        修饰符 普通方法;
}

实例

//定义接口1
interface haozige {
	int age = 20;  //接口内定义的数据成员必须进行初始化,因为他们编译后会变成公有常量
	string name = "haozige";
	
	//接口方法
	void haozigeprintf();  //接口方法在编译时会变成公有抽象方法
	
}

//定义接口2
interface jiangxiaoya {
	int age = 19;  
	string name = "jiangxiaoya";
	
	//接口方法
	void jiangxiaoyaprintf();  
	
}

//实现接口的类
class teacher implements haozige{
	
	//实现接口方法
	public void haozigeprintf(){
		system.out.println(age);  //使用接口的常量
		system.out.println(name);  
		
	}
}

//一个类可以同时实现多个接口
class student implements haozige,jiangxiaoya {
	
	//实现haozige接口的接口方法
	public void haozigeprintf(){
		system.out.println(haozige.age);  //使用接口的常量,如果实现了多个接口,接口的常量名重合时,使用接口名来区分常量
		system.out.println(haozige.name);
	}
	
	//实现jiangxiaoya接口的接口方法
	public void jiangxiaoyaprintf(){
		system.out.println(jiangxiaoya.age);
		system.out.println(jiangxiaoya.name);  
	}
	
}

public class text {

	public static void main(string[] args) {	
		
		new teacher().haozigeprintf();
		system.out.println();
		new student().haozigeprintf();
		system.out.println();
		new student().jiangxiaoyaprintf();
	}
}

接口继承

  • 接口也可以像类一样继承,即子接口使用extends关键字继承父接口
  • 实现子接口的类不仅要实现自子接口的接口方法,还要实现父接口或更上层接口的接口方法

实例

//定义接口person
interface person {
	
	void personprintf();

}

//定义子接口继承父接口person
interface student extends person {
	
	void studentprintf();

}

//定义一个类实现子接口
class haozige implements student {
	
	//实现子接口接口方法
	public void studentprintf(){
		system.out.println("我是子接口");
	}

	//如果父接口或者更上层接口的接口方法没有实现就会报错
	public void personprintf() {
		system.out.println("我是父接口");
		
	}

}

public class text {

	public static void main(string[] args) {	
		
		new haozige().studentprintf();
		new haozige().personprintf();
	}
}

多态

多态能让不同对象执行相同的方法却能实现不同的结果

抽象类实现多态

抽象类对象能够引用子类的对象,当引用成功后,能使用子类对象的数据成员和方法。

实例

import java.util.scanner;

//定义一个抽象类
abstract class dayindian {
	string dname = "谢谢惠顾,你购买的打印机是";
	abstract void myprintf();//
}

class heibaidayinji extends dayindian {
	string hname = "黑色打印机";
	void myprintf() {	
		system.out.println("黑白打印机");
		system.out.println(hname);
	} 
}

class caishedayinji extends dayindian {
	string cname = "彩色打印机";
	void myprintf() {
		system.out.println("彩色打印机");
		system.out.println(cname);
	}
}

public class text {
	
	public static void main(string[] args) {	
		
		//让一个抽象类对象,根据不同的程序逻辑引用不同的子对象,来使用子对象的方法
		
		dayindian d;//声明抽象类对象
		heibaidayinji h = new heibaidayinji();//创建黑白打印机对象
		caishedayinji c = new caishedayinji();//创建彩色打印机对象
	
		scanner sc = new scanner(system.in);  //使用输入类
		int tmp;
		while(true){
			system.out.println("欢迎光临");
			system.out.println("请选择打印机:1.黑白打印机    2.彩色打印机    3.不买了");
			
			tmp = sc.nextint();
			
			if(tmp == 1){
				d = h;  //让抽象类对象引用黑白打印机对象
			}else if(tmp == 2){
				d = c;  //让抽象类对象引用彩色打印机对象
			}else{
				break;
			}
		
		system.out.println(d.dname);  //使用抽象类的数据成员
		d.myprintf();  //当对象类引用子类对象成功后,使用抽象类方法时,将会调用子类方法
		
		}
		
	}
}

实例分析

没引用对象前的内存分配

dayindian d;        //声明抽象类对象
heibaidayinji h = new heibaidayinji();        //创建黑白打印机对象
caishedayinji c = new caishedayinji();        //创建彩色打印机对象 

 d = h;        //让抽象类对象引用黑白打印机对象

d = c;        //让抽象类对象引用彩色打印机对象 

接口实现多态

当某个子类已经继承一个父亲时,该子类无法通过继承一个抽象类来完成多态(即该子类同时只能拥有一个父亲),因此只能选择用接口完成多态。

实例

接口实现多态跟抽象类实现多态大同小异

import java.util.scanner;

//定义一个接口
interface dayindian {
	string dname = "谢谢惠顾,你购买的打印机是";
	void myprintf();
}

class heibaidayinji implements dayindian {
	string hname = "黑色打印机";
	public void myprintf() {	
		system.out.println("黑白打印机");
		system.out.println(hname);
	} 
}

class caishedayinji implements dayindian {
	string cname = "彩色打印机";
	public void myprintf() {
		system.out.println("彩色打印机");
		system.out.println(cname);
	}
}

public class text {
	
	public static void main(string[] args) {	
		
		dayindian d;//声明接口对象
		heibaidayinji h;  //声明黑白打印机对象
		caishedayinji c;  //声明彩色打印机对象
	
		scanner sc = new scanner(system.in);  //使用输入类
		int tmp;
		while(true){
			system.out.println("欢迎光临");
			system.out.println("请选择打印机:1.黑白打印机    2.彩色打印机    3.不买了");
			
			tmp = sc.nextint();
			
			if(tmp == 1){
				//h = new heibaidayinji(); 
				//d = h;
				d = new heibaidayinji();  //让接口对象引用黑白打印机对象
			}else if(tmp == 2){
				//c = new caishedayinji();
				//d = c;
				d = new caishedayinji();  //让接口对象引用彩色打印机对象
			}else{
				break;
			}
		
		system.out.println(dayindian.dname);  //使用接口的数据成员
		d.myprintf();  
		
		}
		
	}
}

包的功能及介绍

包的功能

  • 解决命名冲突的问题,同一个包中的类名不能相同
  • 将同一个类型的类集中在一个包中,让项目整体架构更清晰

包的介绍

  • 一个包中能存在多个.java文件。
  • 一个.java文件中只能存在一个公有类,该公有类名字与.java文件的名字必须一样,可以存在多个默认类。

包的定义

包的创建

在src目录下->new->package

在包中创建类

在包目录下->new->class

类和类成员权限的设定

类的权限

类的权限只有public和默认,即类按权限分为公有类和默认类

  • 公有类:能在同一个包中或者不同的包中使用该公有类。
  • 默认类:只能在同一个包中使用该默认类。

类成员的权限

  • private(私有成员):只有同一个类可以使用
  • 默认(默认成员):同一个包中的类可以使用
  • protected(保护成员):同一个包中的类都可以使用,以及不同包中的非子类可以使用
  • public(公有成员):任何包中的类都可以使用

包的引用

引用包中某个公有类

import 包名称.类名

引用包中所有的公有类

import 包名称.* 

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com