Java面向对象
完整代码
在干货开始前写一些无关的牢骚。在Java中一切被人们熟知且常用的技术、特性、技巧都是为了解决需求而存在的!在学习Java的时候一定要理解其解决了什么需求,而不是对其进行简单的记忆。
同理作为Java三大特性(封装、继承、多态)之一的继承自然也是为了解决需求而诞生的。
那么继承解决了什么需求呢?
我们的需求是制作一个后宫模拟器。在此之前我们已经创建了一个后宫群妃的对象。但是后宫并不仅仅只有群妃、还有宦官、侍卫、医生、厨师、宫女等等。当我们创建这个对象的时候发现他们会有一些共有的属性和方法,比如身高、年龄、性别、体重、吃饭、走动等等。继承的存在就是为了解决这些共有属性在创建对象时多次书写代码重复和修改问题。
因此我们可以创建一个父类设置共有的属性、方法用于被需要的类进行继承。
如何使用?
第一步 找出共有的属性、方法创建父类(对象)
以后宫模拟器为例 创建一个人的父类 此时需要使用
package com.qingsu.personnel;
public class Person {
protected String name;//姓名
protected int age;//年龄
protected boolean sex;//true 代表男 false 代表女
protected String weight;//体重
//自动生成的get/set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
//共有的方法
protected void eat() {
System.out.println("吃的方法!");
}
protected void sleep() {
System.out.println("这是一个睡觉的方法");
}
}
第二步 编写继承于父类的子类 群妃、宦官、医生
继承关键字为extends 具体句法为 子类 extends 父类
示例
修改WifeConcubine类 删除继承的属性及方法
package com.qingsu.personnel;
public class WifeConcubine extends Person{
//我们将对象的特征称之为对象的属性 将对象的行为称之为对象的方法
//后宫佳丽的共有属性 (对象的属性)
private String position;//位份
private int appearance;//颜值
private String hobby;//爱好
private String familyBackground;//家庭背景
private String address;//住址
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getAppearance() {
return appearance;
}
public void setAppearance(int appearance) {
this.appearance = appearance;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String getFamilyBackground() {
return familyBackground;
}
public void setFamilyBackground(String familyBackground) {
this.familyBackground = familyBackground;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
//构造方法
public WifeConcubine() {
}
public WifeConcubine(String name) {
this.name=name;
System.out.println(name+"对象已被创建");
}
//后宫佳丽的共有方法 (对象的方法)
//赏花
public void flowerViewing() {
System.out.println("这是一个赏花的行为");
}
//跳舞
public void dancing() {
System.out.println("这是一个跳舞的方法");
}
//侍寝
public void waiter() {
System.out.println("这是一个侍寝的方法");
}
}
宦官 Eunuch 类
package com.qingsu.personnel;
public class Eunuch extends Person{
//属性
private String department;//部门 十二监、四司、八局 司礼监、内官监、司设监、御马监、神宫监、尚膳监、尚宝监、印绶监、直殿监、尚衣监、都知监、
//惜薪司、钟鼓司、宝钞司、兵仗局、银作局、浣衣局、巾帽局、针工局、内织染局、酒醋面局、司苑局
private String position;//级别
//get、set
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}//职级
//方法
//采购方法
public void purchase() {
System.out.println(name+"正在进行采购!");
}
//养马方法
public void raiseHorses() {
System.out.println(name+"正在养马!");
}
}
医生 Doctors类
package com.qingsu.personnel;
public class Doctors extends Person{
private String department;//院使、左、右院、御医、吏目、医士、食粮、切造医生
private String specialty;//特长
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getSpecialty() {
return specialty;
}
public void setSpecialty(String specialty) {
this.specialty = specialty;
}
//方法
//治病
public void cure() {
System.out.println(name+"正在治病");
}
//煎药
public void decoction() {
System.out.println(name+"正在煎药");
}
}
第三步 创建子类对象时可以直接使用父类的属性及方法
此时 姓名 吃饭等属性和方法在子类中并没有书写却可以直接使用
在Simulation类中新建对象及对对象赋值
package com.qingsu.personnel;
public class Simulation {
public static void main(String[] args) {
//创建一个嫔妃对象 王梦竹 同时会调用无参的构造方法 构造方法中this同时会调用有参构造对其进行赋值
WifeConcubine mengzhu= new WifeConcubine();
//创建一个嫔妃对象 李秀影
WifeConcubine xiuying; //创建一个数据类型为 WifeConcubine 我们自己定义的一个类 可以当作数据类型来用
xiuying= new WifeConcubine("李秀影");//将李秀影对象进行实例化 取得对象所需要的属性及方法 可以理解为对对象进行赋值
//对群妃 李秀影对象内的属性进行赋值
xiuying.setAge(19); //对年龄进行赋值
xiuying.setHeight(1.66);//对身高进行赋值、
xiuying.setPosition("美人");//对位份进行赋值
xiuying.setAppearance (7); //颜值
xiuying.setHobby("弹琴"); //爱好
xiuying.setFamilyBackground("父亲为户部侍郎"); //家世
xiuying.setAddress("钟粹宫");
System.out.println(xiuying.getName()+"是后宫模拟器的一员,年龄"+xiuying.getAge()+"岁,身高"+xiuying.getHeight()+",在后宫的位份是"+xiuying.getPosition()+",她的爱好是"+xiuying.getHobby()+",她的家世"+xiuying.getFamilyBackground()+",她的住址是"+xiuying.getAddress());
//继续创建一个嫔妃对象 季凌菲
WifeConcubine lingfei = new WifeConcubine("季凌菲");//直接对姓名进行赋初值
lingfei.setAge(21); //对年龄进行赋值
lingfei.setHeight(1.71);//对身高进行赋值
lingfei.setPosition("妃");//对位份进行赋值
lingfei.setAppearance (7); //颜值
lingfei.setHobby("舞蹈");
lingfei.setFamilyBackground("父亲为兵部尚书");
lingfei.setAddress("景仁宫");
System.out.println(lingfei.getName()+"是后宫模拟器的一员,年龄"+lingfei.getAge()+"岁,身高"+lingfei.getHeight()+",在后宫的位份是"+lingfei.getPosition()+",她的爱好是"+lingfei.getHobby()+",她的家世"+lingfei.getFamilyBackground()+",她的住址是"+lingfei.getAddress());
//调用对象的方法 实现对象的行为
xiuying.dancing();
xiuying.eat();
xiuying.waiter();
xiuying.flowerViewing();
//创建一个医生张晖对象
Doctors zhanghui = new Doctors();
zhanghui.setName("张辉");
zhanghui.setSex(true);//性别男
zhanghui.setDepartment("院使");//部门
zhanghui.setSpecialty("跌打伤");//特长
zhanghui.cure();//调用治病方法
zhanghui.decoction();//调用煎药方法
//创建一个宦官李黑对象
Eunuch lihei = new Eunuch();
lihei.setName("李黑");
lihei.setDepartment("御马监");
lihei.purchase();
lihei.raiseHorses();
}
}
控制台输出
Object类
Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。
当我们不选择继承的类时 会自动继承Object类
整理和注意点
☀ 子类继承父类就拥有了父类的成员属性和方法
☀ 继承单继承 一个子类只能拥有一个父类 但是一个父类可以有多个子类
☀ 继承可以连续继承 子类也可以继续作为另一个类的父类
☀ 父类的构造方法不会被子类继承
重写
当我们继承父类的方法不能满足现有需求时,我们可以重写继承的属性和方法
重写需要满足以下原则
☀ 子类方法必须和父类方法具有相同的方法名称、参数列表和返回值类型
☀ 子类方法的访问权限只能比父类的更大或相同
☀ 子类方法抛出的异常不能大于父类被重写方法的异常
示例:
我们在宦官类中重写性别的isSex()方法使其只能为男性
public boolean isSex() {
return true;
}
当我们错误赋值为女性时我们也可以确保调用时为男性
//创建一个宦官李黑对象
Eunuch lihei = new Eunuch();
lihei.setName("李黑");
lihei.setDepartment("御马监");
lihei.setSex(false);
lihei.purchase();
lihei.raiseHorses();
System.out.println(lihei.isSex());
控制台输出
super
super关键字和this关键字有很多相通的地方 this用于调用本类的属性方法 super则是用于调用父类的属性和方法
因此super关键字只能出现在子类中
目的一般是用于特殊性指向 比如在重写方法时
具体使用方式如下
访问父类构造方法
super();
super(name);
注意: 只能放在第一行
•访问父类属性
super.name
•访问父类方法
super.print();
注意:就算在子类重写了父类的方法 super访问的依然是父类的原方法
示例 重写吃饭的方法
父类中原方法
//共有的方法
public void eat() {
System.out.println(name+"正在吃饭!");
}
子类
//吃饭方法
@Override
public void eat() {
// TODO 自动生成的方法存根
System.out.println("重写了吃饭的方法并且调用父类吃饭方法中的代码");
super.eat();
}
主方法
//创建一个宦官李黑对象
Eunuch lihei = new Eunuch();
lihei.setName("李黑");
lihei.setDepartment("御马监");
lihei.setSex(false);
lihei.purchase();
lihei.raiseHorses();
lihei.eat();
System.out.println(lihei.isSex());
控制台输出
在继承中对象的创建过程
☀JVM会先加载父类,再加载子类
☀在栈内存中为定义的变量分配内存空间,同时在堆内存中为真正的对象分配内存空间
☀调用构造器来为创建出的对象进行初始化:
•子类中所有的构造方法,默认都会先调用父类中无参的构造方法
•Object类的构造器是最先被执行的
重点
如果在父类中我们书写了一个有参的构造函数 那么默认的无参构造就不给了
因此在执行时就会出现没有父类无参构造的错误 因为在子类的构造函数中默认含有super()无论写不写
因此解决方法一般有两种
在父类里书写一个无参构造
在子类中的无参构造函数中主动调用有参构造即:super(x);
重点
我们默认父类里必须有无参构造 这是规范 你好我好大家好事情干嘛不做呢
final
作用
为了提高程序的安全性,Java中提供了fianl修饰符,来修饰类、变量、方法等。
用法
•final修饰类:表示该类不能被继承
•final修饰变量:表示该变量只能被赋值一次 必须手工为变量赋值一次(包括成员变量,如果赋默认值,没有任何意义)
•final修饰方法:表示该方法不能被覆盖