一、基础知识
1.this与super关键字的使用
a.this关键字
* 区分成员变量和局部变量
- 方法中出现局部变量和成员变量重名,可以在成员变量名前面加
this.
加以区分; - this代表的是实例(对象),哪个实例(对象)调用了this所在的方法,this就代表哪个实例(对象);
- this可以代表任何对象,当this出现在某个方法体中,它所代表的对象是不确定的,但它的类型是确定的,它所代表的只能是当前类的实例;只有当这个方法被调用时,他所代表的对象才被确定下来;
- 举例:
public class Dog { private String name; // 姓名 public void setName(String name) { this.name = name; }}复制代码
- 构造器中应用该构造器正在初始化的对象
- 调用其他构造方法的语句必须定义在构造方法的第一行,因为初始化动作要最先执行;
- 使用this调用重载的构造器时,系统根据this后的实参列表调用与形参列表相匹配的构造器; * 举例:
public class Employee { private String name; private String id; public Employee() {} public Employee(String name) { this.name = name; } public Employee(String name, String id) { this(name); this.id = id; }}复制代码
b.super关键字
- 子类方法中调用父类方法
- 需要在子类方法中调用父类被覆盖的实例方法,可以使用super限定来调用;
- 如果子类里没有包含和父类同名的成员变量,在子类实例方法中访问该成员变量时,则无须显示使用super或父类名作为调用者。 * 举例:
public class Fruit { public String shape = "圆形";}复制代码
public class Banana extends Fruit { public String shape = "浅弓形"; public void getShape() { System.out.println(shape); System.out.println(super.shape); }}复制代码
public class Test { public static void main(String[] args) { Banana b = new Banana(); b.getShape(); }}复制代码
- 子类构造器调用父类构造器
- 不管是否使用super调用的方法执行父类构造器的初始化代码,子类构造器总会调用父类构造器一次。 * 子类构造器执行体的第一行使用super显式调用父类构造器,系统将根据super调用传入的实参列表调用父类对应的构造器。 * 子类构造器执行体的第一行代码使用this显式调用本类中重载的构造器,系统将根据this调用传入的实参列表调用本类中的另一个构造器。执行本类中另一个构造器时即会调用父类构造器。 * 子类构造器执行体中既没有super调用,也没有this调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器。
- 由于创建子类对象必须先调用父类的构造器,所以创建任何实例,最先执行的总是Object类。
- 举例:
public class Person { public String name; public int age; public Person() { this("张三",22); } public Person(String name, int age) { this.name = name; this.age = age; }}复制代码
public class Worker extends Person{ public Worker(String name,int age) { super(name,age); }}复制代码
c.静态方法中不能使用this、super
- 因为this代表的是调用这个函数的对象的引用,而静态方法是属于类的,不属于对象,静态方法成功加载后,对象还不一定存在,所以无法使用this关键字;
- super的用法跟this类似,this代表对本类对象的引用,指向本类已经创建的对象;而super代表对父类对象的引用,指向父类对象;
- 因为静态优先于对象存在,所以方法被静态修饰之后方法先存在,而方法里面要用到super指向的父类对象,但是所需的父类引用对象晚于该方法出现,也就是super所指向的对象没有,当然就会出错。综上,静态方法中不可以出现super关键字。
2.方法重写(override)
a.方法重写的要求
- 子类包含与父类同名方法等现象可以说成子类重写了父类的方法;
- 方法名、形参列表必须相同;
- 子类方法返回值类型应比父类方法返回值类型更小或相等;
- 子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
- 子类方法的访问权限应比父类方法的访问权限更大或相等;
- 父类被覆盖方法与子类覆盖方法要么都是静态的(static),要么都是实例方法;
- 当父类方法被private修饰时,则该方法对子类是隐藏的,即使子类定义了一个与父类方法具有相同的方法名、形参列表、返回值类型的方法,也不是重写。 * 父类方法
public class Father { public void show() { System.out.println("父类方法"); }} 复制代码
* 子类重写方法
public class Son extends Father{ public void show() { System.out.println("子类同名方法"); }}复制代码
b.与方法重载(overload)的区别
多个同名函数同时存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。 方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
3.抽象类(abstract)与接口(interface)
A.抽象类
a.抽象类的特点
1. 抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中; 2. 抽象类有构造器,但是不可以用于创建实例,主要用于被子类调用; 3. 只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类; 4. 抽象类一定是父类; 5. 抽象类可以不定义抽象方法,这个类不可以创建实例,但是子类可以使用该类的方法;
b.关键字abstract不可以与一些关键字共存
- private: 私有的方法子类是无法继承到的,也不能重写,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
- final: 使用abstract修饰的方法表明子类必须重写,而final修饰的类不能被继承,final修饰的方法不能被重写,两者矛盾。
- static: static表示非静态,可以通过
类名.方法
调用,而abstract修饰的方法没有方法体,不能被直接调用。
B.接口(interface)(基于Java7)
a.接口的特点
- 接口是暴露在外面的规范,体现的是规范和实现分离的设计哲学;
- 接口中的所有成员,包括常量、方法、内部类、和内部枚举都是public访问权限;
- 接口中的每个成员变量都默认使用public static final修饰,并且必须显示赋值;
- 接口的实现类的重写方法的访问权限都必须是public。
C.抽象类与接口共同点与区别
a.相同点:
- 都位于继承的顶端,用于被其他类实现或继承;
- 都不能直接实例化对象;
- 都包含抽象方法,其子类都必须覆写这些抽象方法;
b.区别:
- 抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
- 一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承) 单继承多实现;
- 抽象类是这个事物中应该具备的你内容, 继承体系是一种 is..a关系; 4. 接口是这个e事物中的额外内容,继承体系是一种 like..a关系;
c.二者的选用:
- 优先选用接口,尽量少用抽象类;
- 需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
4.类和类,类与接口,接口与接口之间的关系
- 类与类之间:继承关系,单继承,可以是多层继承
- 类与接口之间: 实现关系,单实现,也可以多实现
- 接口与接口之间:继承关系,单继承,也可以是多继承
- Java中的类可以继承一个父类的同时,实现多个接口
5.权限修饰符
public | protected | default | private |
---|---|---|---|
同一类中 | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ |
不同包的子类 | √ | √ | |
不同包中的无关类 | √ |
二、按需求完成指定功能:
* 形状类: 功能:求面积,求周长 * 圆形类: 属性:常量圆周率,半径 功能:求面积,求周长 * 长方形类: 属性:长和宽 功能:求面积,求周长 * 定义测试类,在测试类的main方法中使用上面的类创建对象,并调用方法计算: 半径为3的圆形的周长和面积 长度为9,宽度为8的长方形的周长和面积
- Shape类
public abstract class Shape { public abstract double area(); public abstract double perimeter(); public Shape() { }}复制代码
- Cricle类
public class Circle extends Shape { private final double PI = 3.1415926; //π的值 private double r; //半径 public Circle() { } public Circle(double r) { this.r = r; } @Override public double area() { //面积 return PI * r * r; } @Override public double perimeter() { //周长 return 2 * PI * r; } public double getR() { return r; } public void setR(double r) { this.r = r; } public double getPI() { return PI; }}复制代码
- Rectangle类
public class Rectangle extends Shape { private double width; //宽 private double length; //长 //空参构造 public Rectangle() { } //有参构造 public Rectangle(double width, double length) { this.width = width; this.length = length; } @Override public double area() { //面积 return width * length; } @Override public double perimeter() { //周长 return (width + length) * 2; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getLength() { return length; } public void setLength(double length) { this.length = length; }}复制代码
- Test类
public class Test { public static void main(String[] args) { //圆形的周长及面积计算 Circle c = new Circle(); c.setR(3); System.out.println("圆的周长: " + c.perimeter()); System.out.println("圆的面积: " + c.area()); //长方形的周长及面积计算 Rectangle r = new Rectangle(); r.setLength(9); r.setWidth(8); System.out.println("长方形的周长: " + r.perimeter()); System.out.println("长方形的面积: " + r.area()); }}复制代码
- 运行结果:
三、按需求完成指定功能,题目如下:
- 动物类: * 行为: 1. 吼叫:没有具体的吼叫行为 2. 吃饭:没有具体的吃饭行为
- 缉毒接口 * 行为: 缉毒 * 缉毒犬:犬的一种 * 行为: 吼叫:汪汪叫 吃饭:狗啃骨头 缉毒:用鼻子侦测毒品
- 测试类: 使用多态的形式创建缉毒狗对象,调用缉毒方法
- Animal类
public abstract class Animal { public abstract void bark(); // 抽象方法,吼叫 public abstract void eat(); // 抽象方法,吃饭 public Animal() { }}复制代码
- 缉毒接口
public interface NoDrug { public abstract void noDrug(); // 接口中抽象方法,缉毒}复制代码
- 犬类
//抽象狗类继承动物类public abstract class Dog extends Animal { public Dog() { }}复制代码
- 缉毒犬类
//缉毒犬继承抽象狗类,并实现缉毒接口public class NoDrugDog extends Dog implements NoDrug { public NoDrugDog() { } public void bark() { // 吼叫 System.out.println("汪汪叫"); } public void eat() { // 吃饭 System.out.println("狗啃骨头"); } public void noDrug() { // 缉毒 System.out.println("用鼻子侦测毒品"); }}复制代码
- Test类
public class Test { public static void main(String[] args) { NoDrug n = new NoDrugDog(); // 多态调用 n.noDrug(); }}复制代码
- 运行结果
四、按需求完成指定功能,题目如下:
-
USB接口: 开启USB功能 关闭USB功能
-
笔记本类: 开机功能 关机功能 使用USB设备的功能 要求:既能使用鼠标也能使用键盘,使用USB功能内部调用USB开启和USB关闭功能
-
鼠标类: 要符合USB接口
-
键盘类: 要符合USB接口
-
测试类: 创建电脑对象,依次调用开机方法,使用USB设备, 关机方法
-
USB接口
//USB接口public interface USB { public abstract void openUSB(); //抽象方法,使用USB public abstract void closeUSB(); //抽象方法,关闭USB}复制代码
- Computer类
public class Computer { public Computer() { } public void openComputer() { System.out.println("笔记本开机"); } public void closeComputer() { System.out.println("笔记本关机"); } //使用USB接口 public void useUSB(USB usb) { usb.openUSB(); //开启USB功能 usb.closeUSB(); //关闭USB功能 }}复制代码
- Mouse类
public class Mouse implements USB { public Mouse() { } @Override public void openUSB() { System.out.println("开启鼠标"); } @Override public void closeUSB() { System.out.println("关闭鼠标"); }}复制代码
- Keyboard类
public class Keyboard implements USB { public Keyboard() { } @Override public void openUSB() { System.out.println("开启键盘"); } @Override public void closeUSB() { System.out.println("关闭键盘"); }}复制代码
- Test类
public class Test { public static void main(String[] args) { //创建笔记本实例 Computer c = new Computer(); USB u1 = new Mouse(); //创建鼠标实例 USB u2 = new Keyboard(); //创建键盘实例 c.openComputer(); //开启笔记本 c.useUSB(u1); //调用USB功能 c.useUSB(u2); //调用USB功能 c.closeComputer(); //关闭笔记本 }}复制代码
- 运行结果
五、饲养动物
- 动物类: 属性:年龄 行为:喝水,吃东西(吃什么不确定) 游泳接口: 行为:游泳方法
- 狗类: 行为:吃饭(啃骨头)和 游泳(狗刨)
- 羊类: 行为:吃饭(羊啃草)
- 青蛙类: 行为:吃饭(吃虫子)和 游泳(蛙泳)
- 饲养员类: 行为:饲养动物:包括吃饭和喝水
- 测试类: 创建饲养员对象,饲养员调用三次饲养方法:饲养狗,饲养羊,饲养青蛙
- Animal类
//动物类public abstract class Animal { private int age; //年龄 //空参构造 public Animal() { } //有参构造 public Animal(int age) { this.age = age; } public void drink(){ System.out.println("喝水"); } //抽象方法,吃饭 public abstract void eat(); public int getAge() { return age; } public void setAge(int age) { this.age = age; }}复制代码
- 游泳接口
//游泳接口public interface Swim { public abstract void swim();}复制代码
- 狗类
//狗类,继承动物类,实现游泳接口public class Dog extends Animal implements Swim { public Dog() { } @Override public void swim() { System.out.println("游泳方式: 狗刨"); } @Override public void eat() { System.out.println("狗啃骨头"); }}复制代码
- 羊类
//养类继承动物类public class Sheep extends Animal { @Override public void eat() { System.out.println("羊啃草"); }}复制代码
- 青蛙类
//青蛙类继承动物类,实现游泳接口public class Frog extends Animal implements Swim { @Override public void swim() { System.out.println("游泳方式: 蛙泳"); } @Override public void eat() { System.out.println("吃虫子"); }}复制代码
- 饲养员类
//饲养员类public class Breeder { public Breeder() { } public void feeding(Animal a) { System.out.println("饲养的内容: "); a.drink(); a.eat(); }}复制代码
- Test类
public class Test { public static void main(String[] args) { //创建饲养员实例 Breeder b = new Breeder(); //创建狗类实例 Animal a1 = new Dog(); Swim s1 = new Dog(); b.feeding(a1); s1.swim(); //创建羊实例 Animal a2 = new Sheep(); b.feeding(a2); //创建青蛙实例 Animal a3 = new Frog(); Swim s3 = new Frog(); b.feeding(a3); s3.swim(); }}复制代码
- 运行结果