稳稳当当学java之继承(10)

第十二章 继承

1.作业回顾

1,定义一个Person类(name,age,sno)进行数据封装,age的年龄范围设置为0到130,使用getAge返回年龄。

//1,定义一个Person类(name,age,sno)进行数据封装,age的年龄范围设置为0到130,使用getAge返回年龄。
public class Person {
	private String name;
	private int age;
	private String sno;
	
	public Person(String name, int age, String sno) {
		super();
		this.name = name;
		this.sno = sno;
		if(age <= 0 || age >=130) {
			System.out.println("数据非法");
			return;
		}
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		if(age <= 0 || age >=130) {
			System.out.println("数据非法");
			return;
		}
		this.age = age;
	}
	public String getSno() {
		return sno;
	}
	public void setSno(String sno) {
		this.sno = sno;
	}
}

public class Day121 {
	public static void main(String[] args) {
		Person p = new Person("张三", 20, "20191101");
		System.out.println(p.getAge()); //20
		p.setAge(-20); //数据非法
		System.out.println(p.getAge()); //20
	}
}

2,编写类Triangle,声明private的两个属性:底边长base和高height,同时提供getter和setter,在 TriangleManager类中定义一个方法public static double getArea(Triangle t)计算三角形的面积,并在main方法中输出。

public class Triangle {
	//2,编写类Triangle,声明private的两个属性:底边长base和高height,同时提供getter和setter
	
	private double base;
	private double height;
	
	public Triangle(double base, double height) {
		super();
		this.base = base;
		this.height = height;
	}

	public double getBase() {
		return base;
	}

	public void setBase(double base) {
		this.base = base;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}	
}
public class TriangleManager {
	//TriangleManager类中定义一个方法public static double getArea(Triangle t)计算三角形的面积,并在main方法中输出。
	
	public static double getArea(Triangle t) {
		return t.getBase() * t.getHeight();	
	}
	
	public static void main(String[] args) {
		Triangle tr = new Triangle(3.0, 2.0);
		double area = getArea(tr);
		System.out.println(area);
	}
}

2.成员变量的初始值

java中,局部变量( 形参、方法内定义的变量、代码块中定义的变量 )没有初始化不能使用。成员变量( 类变量 和 实例变量 )如果没有初始化会有默认值。

public class Day122 {
	public static void main(String[] args) {
		int i;
//		System.out.println(i); //编译错误,i没有被初始化
	}
}
class Foo{
	//成员变量包括 类变量 和 实例变量
	
	//类变量
	static byte b;
	//实例变量
	short s;
	char c;
	int i;
	long l;
	float f;
	double d;
	boolean bool;
	String str;
}
//java中一个类文件可以有多个类,但只能有一个public类
//public类的名称要与文件名相同
public class Day122 {
	public static void main(String[] args) {
		
//		int i; //局部变量
//		System.out.println(i); //编译错误,i没有被初始化
		
		Foo foo = new Foo();
		System.out.println(Foo.b); //0   类变量通过类名访问
		System.out.println(foo.s); //0   实例变量通过对象访问
		System.out.println(foo.c); //
		System.out.println(foo.i); //0
		System.out.println(foo.l); //0
		System.out.println(foo.f); //0.0
		System.out.println(foo.d); //0.0
		System.out.println(foo.bool); //false 
		//null表示它不引用任何对象
		System.out.println(foo.str); //null  String为引用类型,引用类型默认值为null
	}
}

3.对象初始化

java中对象的初始化有三种方式:

1.在变量声明时赋值,

2.使用构造器,

3.使用代码块。

class Bar{
	private String name = setDefaultName(); //声明变量的时候赋值
	private int age = 0; //声明变量的时候赋值
	//类变量
	//记录创建对象的个数
	public static int COUNT;
	
	//静态代码块
	//静态代码块在类被加载时执行
	//每个类只被加载一次,因此静态代码块只执行一次
	//静态代码块用来初始化静态字段(类变量)
	//不能访问实例字段(实例变量)
	static {
		COUNT = 0;
		System.out.println("1静态代码块执行");
	}
	
	//非静态代码块
	//非静态代码块在每次创建对象的时候执行
	//非静态代码块用来初始化实例字段(实例变量)
	{
		System.out.println("3非静态代码块执行");
		COUNT++;
	}
	
	public Bar() {
		System.out.println("4默认构造器执行");
	}
	
	private String setDefaultName() {
		System.out.println("2setDefaultName()");
		return "setDefaultName";
	}
	
	public Bar(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}	
}

public class Day123 {
	public static void main(String[] args) {
		//1.加载类,执行静态代码
		//2.执行成员变量的赋值语句
		//3.执行非静态代码块
		//4.调用构造器
		
		//ctrl + f查找和替换
		Bar bar1 = new Bar();
		System.out.println(bar1.getAge()); //0
		System.out.println(bar1.getName()); //setDefaultName
		System.out.println(Bar.COUNT); //1
		
		//2.执行成员变量的赋值语句
		//3.执行非静态代码块
		//4.调用构造器
		Bar bar2 = new Bar(); 
		System.out.println(bar2.getAge()); //0
		System.out.println(bar2.getName()); //setDefaultName
		System.out.println(Bar.COUNT); //1	
	}	
}

4.继承

java中通过继承一个类,来继承此类的所有功能。java中的每一个类都继承于Object类,当创建一个类时,会自动的继承Object类的所有方法。

//java中的所有类都继承于Object类
//类F继承于Object
class F{
	
}

public class Day124 {
	public static void main(String[] args) {
		//ctrl + shift + t 打开一种类型
		//Ctrl + o 打开类的列表信息(属性和方法)
		
		F f = new F();
		//toString方法继承于Object
		System.out.println(f.toString()); //day12.F@53bd815b
		
		//hashCode方法继承于Object
		//hashCode方法是本地方法,没有方法体
		//native方法会调用底层的c语言的函数
		//hashCode方法将返回对象的哈希码
		System.out.println(f.hashCode()); //1404928347
		
		//instanceof关键字用于判断一个对象是否是这个类型
		//f是F类的实例
		System.out.println(f instanceof F); //true
		
		//f是Object类的实例
		System.out.println(f instanceof Object); //true
		
		//动物(Object)
		//哺乳动物(F)
		//f是某一只具体的哺乳动物(我家的狗——小黑)
	}
}

Object类位于java.lang包中,它定义和实现了所有类的通用功能。在java中所有的类都继承于Object类。因此Object类是所有类的超类。

在这里插入图片描述

下面是继承的例子

//Person没有写继承,那么就自动继承Object类
class Person {
	String name;
	int age;

	public void info() {
		System.out.println("我叫" + name + ",我今年" + age + "岁了");
	}
}

// extends 关键字用来继承一个类
// Student类是Person的子类,Person类是Student类的父类
// Student类继承了Person类中定义的属性和方法
// Student类有三个属性,两个方法
class Student extends Person {
	// 学号
	int sno;

	public void study() {
		System.out.println("好好学习,天天向上");
	}
}

//Actor类继承于Person,一个父类可以有多个子类,一个子类只能有一个父类
class Actor extends Person {
	// 薪水
	double salary;

	public void act() {
		System.out.println("我热爱表演");
	}
}

public class Day125 {
	public static void main(String[] args) {
		Student s = new Student();
		//name和age属性继承于Person
		s.name = "小明";
		s.age = 10;
		//sno是Student类中定义的属性
		s.sno = 20191101;
		//info方法继承于Person
		s.info();
		//study方法是Student类中定义的方法
		s.study();
		
		Actor a = new Actor();
		//name和age属性继承于Person
		a.name = "梁朝伟";
		a.age = 50;
		//salary是Student类中定义的属性
		a.salary = 10000000;
		//info方法继承于Person
		a.info();
		//act方法是Student类中定义的方法
		a.act();	
	}
}

5.子类对象的实例化过程

子类对象创建之前必须先有父类对象 ,子类对象的构造器默认会调用父类的无参构造器,以便创建父类的对象。

class Person {
	String name;
	int age;
	
	public Person() {
		super(); //调用父类的无参构造器
		System.out.println("Person构造器");	
	}
	
	public void info() {
		System.out.println("我叫" + name + ",我今年" + age + "岁了");
	}
}

class Student extends Person {
	//学号
	int sno;
	
	public Student( int sno) {
		//子类对象创建之前必须先有父类对象
		//子类对象的构造器默认会调用父类的无参构造器,以便创建父类对象
		//super()调用父类的无参构造器
		super(); //写不写都一样,默认会调用父类的无参构造器
		System.out.println("Student构造器");
		this.sno = sno;
	}
	
	public void study() {
		System.out.println("好好学习,天天向上");
	}
}

public class Day126 {
	public static void main(String[] args) {
		Student s = new Student(20191101); //创建两个对象,父类对象和子类对象		
	}
}

在这里插入图片描述

上面的例子中,子类的属性被初始化,但是父类的属性没有被初始化。

有个两种方式可以解决父类的属性初始化。

第一种:在子类的构造器中直接初始化从父类继承的属性。

class Person {
	String name;
	int age;
	
	public Person() {
		super(); //调用父类的无参构造器
		System.out.println("Person构造器");	
	}
	
	public void info() {
		System.out.println("我叫" + name + ",我今年" + age + "岁了");
	}
}

class Student extends Person {
	//学号
	int sno;
	
	public Student(String name, int age, int sno) {
		//子类对象创建之前必须先有父类对象
		//子类对象的构造器默认会调用父类的无参构造器,以便创建父类对象
		//super()调用父类的无参构造器
		super(); //写不写都一样,默认会调用父类的无参构造器
		System.out.println("Student构造器");
		this.name = name;
		this.age = age;
		this.sno = sno;
	}
	
	public void study() {
		System.out.println("好好学习,天天向上");
	}
}

public class Day1261 {
	public static void main(String[] args) {
		Student s = new Student("小明", 10, 20190001); //创建两个对象,父类对象和子类对象	
		System.out.println(s.name); //张三
		System.out.println(s.age); //30
		System.out.println(s.sno); //20191101
	}
}

第二种:调用父类的有参构造器进行初始化。(推荐)

class Person4 {
	String name;
	int age;
	
	public Person4(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("Person4构造器");	
	}
	
	public void info() {
		System.out.println("我叫" + name + ",我今年" + age + "岁了");
	}
}

class Student4 extends Person4 {
	//学号
	int sno;
	
	public Student4(String name, int age, int sno) {
        //调用父类的有参构造器,对name和age进行赋值
		super(name, age);
		this.sno = sno;
		System.out.println("Student构造器");
	}
	
	public void study() {
		System.out.println("好好学习,天天向上");
	}
}

public class Day1262 {
	public static void main(String[] args) {
		Student4 s = new Student4("小明", 10 , 20190001); //创建两个对象,父类对象和子类对象		
		System.out.println(s.name);
		System.out.println(s.age);
		System.out.println(s.sno);
	}
}

在这里插入图片描述

class Person5 {
	String name;
	int age;
	
	public Person5(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("Person5构造器");	
	}
	
	public void info() {
		System.out.println("我叫" + name + ",我今年" + age + "岁了");
	}
}

class Student5 extends Person5 {
	//学号
	int sno;
	
	public Student5(String name, int age, int sno) {
		//调用父类的有参构造器,对name和age进行赋值
		super(name, age);
		this.sno = sno;
		System.out.println("Student构造器");
	}
	
	public void study() {
		System.out.println("好好学习,天天向上");
	}
}

public class Day1263 {
	public static void main(String[] args) {
		Student5 s1 = new Student5("张三", 30, 20191101); //创建两个对象,父类对象和子类对象		
		System.out.println(s1.name);
		System.out.println(s1.age);
		System.out.println(s1.sno);
		
		Student5 s2 = new Student5("李四", 10, 20191102); //创建两个对象,父类对象和子类对象		
		System.out.println(s2.name);
		System.out.println(s2.age);
		System.out.println(s2.sno);
		
		//一共四个对象
	}
}

6.继承的规则一

静态成员(静态变量,静态常量,静态方法)不考虑继承问题,静态成员不能被继承。

子类不能继承父类的private 成员(属性和方法)。

protected成员包括包访问权限,protected成员可以被同一个包下的所有类访问。

protected成员可以被子类访问,不管这个子类和父类是否在同一个包下。

子类可以继承对它可见的成员。

子类可以继承父类的public,protected成员。

如果子类和父类在同一个包下,子类还可以继承父类的default成员。

构造器不是类的成员,因此无法被继承,但是子类可以使用super关键字调用其超类的构造器。 子类可以声明和超类同名的字段,这将导致隐藏其超类的字段。

class Person6 {
	String name;

	public Person6(String name) {
		super();
		this.name = name;
	}
}

class Student6 extends Person6{
	//子类的将隐藏超类的同名字段
	private String name;
	private int sno;
	
	public Student6(String name1, String name2, int sno) {
		super(name1);
		//访问的是子类的name
		name = name2;
		this.sno = sno;
	}
	
	public void showInfo() {
		//super代表父类的对象
		System.out.println("父类对象的名字:" + super.name);
		System.out.println("子类对象的名字:" + this.name);
		//访问的是子类的name
		System.out.println("我的名字:" + name + "我的学号" + sno);
	}	
}

public class Day127 {
	public static void main(String[] args) {
		Student6 s = new Student6("1", "2", 20191101);
		s.showInfo(); 	//父类对象的名字:1
						//子类对象的名字:2
						//我的名字:2我的学号20191101
	}	
}

7.练习

1,编写一个Person类,包括属性(name、age),有参构造器、方法say(返回自我介绍的字符串)。

2.编写一个 Student类,继承Person类,增加sno、score属性,以及有参构造器,在子类中调用父类的构造器。

3.编写一个方法showInfo(返回自我介绍的字符串)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年之伴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值