1.继承(重中之重 20遍)
人类:
特征:姓名、年龄
行为:吃饭、娱乐
学生类 吸收 人类:
特征:学号
行为:学习
教师类 吸收 人类:
特征:工号
行为:讲课
工人类 吸收 人类:
特征:薪水
行为:工作
…
1.1 基本概念
当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类的内部编写自己独有特征和行为的方式,叫做继承。
使用继承可以提高代码的复用性和扩展性以及可维护性。
在Java语言中使用extends(扩展)关键字来表达继承关系。
如:
public class Worker extends Person {} - 表示Worker类继承自Person类
其中Person类叫做基类、父类、超类
其中Worker类叫做派生类、子类、孩子类
父类Person
/*
编程实现Person类的封装
*/
public class Person {
// 1.私有化成员变量,使用private关键字修饰
private String name;
private int age;
// 3.在构造方法中调用set方法进行合理值的判断
public Person() {
System.out.println("Person()");
}
public Person(String name, int age) {
System.out.println("Person(String, int)");
setName(name);
setAge(age);
}
// 2.提供公有的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) {
if(age > 0 && age < 150) {
this.age = age;
} else {
System.out.println("年龄不合理!!!");
}
}
public void show() {
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了!");
}
// 自定义成员方法描述吃饭的行为
public void eat(String food) {
System.out.println(food + "真好吃!");
}
// 自定义成员方法描述娱乐的行为
public void play(String game) {
System.out.println(game + "真好玩!");
}
public static void test() {
System.out.println("父类的静态方法");
}
}
子类Worker
/*
编程实现Worker类的封装
*/
public class Worker extends Person {
// 1.私有化成员变量,使用private关键字修饰
private int salary;
// 3.在构造方法中调用set方法进行合理值的判断
public Worker() {
super(); //调用父类的无参构造方法
System.out.println("Worker()");
}
public Worker(String name, int age, int salary) {
super(name, age); //调用父类的有参构造方法
System.out.println("Worker(String, int, int)");
//setName(name);
//setAge(age);
setSalary(salary);
}
// 2.提供公有的get和set方法,并在方法体中进行合理值的判断
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
if(salary >= 2120) {
this.salary = salary;
} else {
System.out.println("薪水不合理!!!");
}
}
// 自定义成员方法描述工作的行为
public void work() {
System.out.println("正在努力地搬砖!!!");
}
//标注,说明下面的方法是对父类中方法的重写,若没有构成重写则编译报错
@Override
public void show() {
// 表示调用父类中的show方法
super.show();
System.out.println("我的薪水是:" + getSalary());
}
public static void test() {
System.out.println("子类的静态方法");
}
}
测试类WorkerTest
/*
编程实现Worker类的测试
*/
public class WorkerTest {
public static void main(String[] args) {
Worker w1 = new Worker();
w1.show(); //null 0
System.out.println("---------------------------");
Worker w2 = new Worker("zhangfei", 30, 3000);
//当子类没有show方法时,这里调用从父类中继承下来的版本
//当子类有show方法时,这里调用子类重写的版本
w2.show(); //zhangfei 30
w2.eat("豆芽");
w2.play("王者荣耀");
w2.work();
}
}
运行代码:
1.2 注意事项
(1)子类可以继承父类的成员变量和成员方法,其中私有成员变量可以继承但不可以直接 使用,子类不可以继承父类的构造方法和私有方法。
(2)无论使用何种方式构造子类对象时,都会自动调用父类中的无参构造方法来初始化从 父类中继承下来的成员变量,相当于在子类构造方法第一行增加代码:super()的效果
(3)使用继承必须满足 子类 is a 父类 的逻辑关系,也就是不能滥用继承。
(4)Java语言中只支持单继承不支持多继承,也就是一个子类只能有一个父类,但一个父类可以有多个子类。
1.3 方法的重写(override)
(1)基本概念
若从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个与父类中一样的方法来覆盖从父类中继承的版本,这种方式就叫做重写。
(2)重写的原则(笔试题)
a.要求方法名相同、参数列表相同、返回值类型相同,从jdk1.5开始允许返回子类类型
b.要求方法的访问权限不能变小,可以相同或者变大。
c.要求不能抛出更大的异常(异常机制)。
练习:
自定义Pet类实现封装,特征有:名字和年龄,要求实现打印所有特征的行为。
自定义Dog类继承Pet类实现封装,特征有:毛色,要求实现打印所有特征的行为。
Pet类:
//自定义Pet类实现封装,特征有:名字和年龄,要求实现打印所有特征的行为。
public class Pet
{
//私有化成员变量
private String name;
private int age;
//析构,获取get
public Pet(){
System.out.println("Pet()");
}
public Pet(String name,int age){
setname(name);
setage(age);
}
//get和set方法
public void setname(String name){
this.name=name;
}
public void setage(int age){
if (age>0&&age<150)
{
this.age=age;
}
else{
System.out.println("大兄弟,你的年龄有问题,我有点慌!!!");
}
}
public String getname(){
return name;
}
public int getage(){
return age;
}
//要求实现打印所有特征的行为
public void show(){
System.out.println("宠物"+getname()+"今年"+getage()+"岁了!!");
}
}
Dog类:
//自定义Dog类继承Pet类实现封装,特征有:毛色,要求实现打印所有特征的行为。
public class Dog extends Pet
{ //特征
private String Coatcolor;
//析构
public Dog(){
System.out.println("Dog()");
}
public Dog(String name,int age ,String Coatcolor){
super(name,age);
setCoatcolor(Coatcolor);
}
//get和set方法
public void setCoatcolor(String Coatcolor){
this.Coatcolor=Coatcolor;
}
public String getCoatcolor(){
return Coatcolor;
}
//打印所有特征
@Override
public void show(){
super.show();
System.out.println("它的毛色是:"+getCoatcolor());
}
}
DogTest类:
public class DogTest
{
public static void main(String[] args){
Dog dd=new Dog("大黄",4,"蓝色");
dd.show();
}
}
运行结果:
2.2 包的定义
package 包名;
package 包名1.包名2…包名n; - 便于管理,避免命名冲突的问题
3.final关键字(重点)
3.1 基本概念
final本意为"最终的,不可更改的",该关键字可以修饰类、成员方法、成员变量等。
3.2 使用方式
final关键字修饰类表示该类不能被继承。
-
为了防止滥用继承带来的危害
如:java.lang.String类等final关键字修饰成员方法表示该方法不能被重写但可以被继承。
-
为了防止不经意间造成的方法重写
-
如:java.text.DateFormat类中的format方法等
final关键字修饰成员变量表示该成员变量必须初始化而且不能更改。
-
为了防止不经意间造成数值的更改。
-
如:java.lang.Thread类中的MAX_PRIORITY等
扩展:
在以后的开发中很少单独使用static关键字或final关键字修饰成员变量,通常都是 使用public static final共同修饰成员变量来表达常量的含义
常量的命名规则是:要求所有字母大写,不同单词之间采用下划线连接,如:
public static final double PI = 3.14;
eclipse快捷方式:
Alt+/:自动补全
Ctrl+Shift+/:多行注释被选中
继承实例:
Shape类:
package Test;
public abstract class Shape {
public static int x;
public static int y;
public Shape(int x){
}
public Shape(int x,int y){
setX(x);
setY(y);
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int x){
this.x=x;
}
public void setY(int y){
this.y=y;
}
public void show(){
System.out.println("横坐标:"+getX()+"纵坐标:"+getY());
}
}
Circle类:
package Test;
//自定义圆形(Circle)类,特征有:横纵坐标、半径,要求实现封装并提供打印方法;
public class Circle extends Shape{
private int radius;
public Circle(){
super(x);
}
public Circle(int x,int radius){
super(x);
setRadius(radius);
}
public void setRadius(int radius){
this.radius=radius;
}
public int getRadius(){
return radius;
}
@Override
public void show(){
super.show();
System.out.println("半径:"+getRadius());
}
}
Rect类:
package Test;
//.自定义矩形(Rect)类,特征有:横纵坐标、长度及宽度,要求实现封装并提供打印方法;
public class Rect extends Shape{
private int len;
private int wide;
public Rect(){
super(x,y);
}
public Rect(int x ,int y ,int wide,int len){
super(x,y);
setWide(wide);
setLen(len);
}
public void setWide(int wide){
this.wide=wide;
}
public void setLen(int len){
this.len=len;
}
public int getWide(){
return wide;
}
public int getLen(){
return len;
}
@Override
public void show(){
super.show();
System.out.println("长度为:"+getLen()+"宽度为:"+getWide());
}
}
TestShape类:测试:
package Test;
public class TestShape {
// Circle tt=new Circle(1,2);
// tt.show();
// Rect tt1=new Rect(1,2,1,3);
// tt1.show();
/*
//自定义成员方法,实现指定矩形特征的打印
//矩形类型的引用指向自己的对象,没有多态
Rect r=new Rect(1,2,3,4);
public static void draw(Rect r){
//最终调用矩形类中自己的show方法
r.show();
}
//自定义成员方法实现参数指定圆形特征的打印
//圆形类型的指引圆形的对象,没有多态
Circle c=new Circle(5,6);
public static void draw(Circle c){
c.show();
}*/
//自定义成员方法实现既能打印矩形也能打印圆形的方法
Shape s=new Rect(1,2,3,4);
//父类类型的引用,指向了子类类型的对象,形成了多态
Shape s1=new Circle(5,6);
//多态的使用场合之一
public static void draw(Shape s){
//编译阶段调用父类的版本,运行阶段调用子类重写以后的版本
s.show();
}
public static void main(String[] args) {
TestShape.draw(new Rect(1,2,1,3));
System.out.println("---------------");
TestShape.draw(new Circle(56,6));
}
}