5.1 类、超类和子类
5.1.1 定义子类
public class Manager extends Employee
{
// added methods and fields(字段)
}
Employee类:超类、基类、父类
Manager类:子类、派生类、孩子类
子类拥有比父类更多的字段和功能
5.1.2 覆盖方法
Manager类继承自Employee类
要重新实现getSalary方法 -> 重写(Override)
class Employee{
private String name;
private double salary;
public Employee(String name,double salary){
this.name = name;
this.salary = salary;
}
public double getSalary(){
return salary;
}
}
class Manager extends Employee{
private double bonus;
public Manager(String name, double salary) {
super(name, salary);
}
// public double getSalary(){
// return getSalary()+bonus; 调用自己,无限递归
// }
@Override
public double getSalary(){
return super.getSalary()+bonus;
}
}
super的使用方法:
用于子类去访问父类
- 调用父类的构造函数:在子类的构造函数中使用super()来调用父类的构造函数。这样可以执行父类的初始化操作。如果子类构造函数没有显式调用
super()
,则会默认调用父类的无参数构造函数。 - 调用父类的方法:使用
super
关键字可以在子类中调用父类的方法 - 访问父类的成员变量:在子类中使用
super
关键字可以访问父类中的成员变量
this的使用方法:
用于类自己访问自己
- 引用当前对象的实例变量:可以使用
this
关键字来引用当前对象的实例变量。这在构造函数中经常用到,用于区分实例变量和局部变量 - 引用当前对象的方法:在类的方法内部,可以使用
this
调用当前对象的其他方法。这对于确保在方法内部使用的是当前对象的方法是很有用的
public class MyClass {
public void method1() {
// 调用method2方法
this.method2();
}
public void method2() {
// 方法2的实现
}
}
- 返回当前对象:在方法中可以使用
this
返回当前对象的引用
public class MyClass {
private int num;
public MyClass setNum(int num) {
this.num = num;
return this; // 返回当前对象
}
}
5.1.3 SOLID设计原则
SOLID设计原则是面向对象设计的五大基本原则
-
单一职责原则(Single Responsibility Principle,SRP):一个类应该只有一个引起变化的原因。换句话说,一个类应该只有一个责任。这个原则强调了类的高内聚性,即一个类应该只关注一件事情。
-
开放-封闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着当需要改变或扩展系统时,应该通过添加新的代码来实现,而不是修改现有的代码。
-
里氏替换原则(Liskov Substitution Principle,LSP):已经在前面提到了。子类应该能够替换父类并且表现出相同的行为,而不引起任何意外或异常。
-
接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖于它不使用的接口。这意味着一个类不应该强迫依赖于它不需要的接口。相反,应该为不同的客户端提供特定的接口。
-
依赖反转原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,两者都应该依赖于抽象。换句话说,代码应该依赖于抽象接口,而不是具体的实现。
5.1.4 多态
多态(Polymorphism)指的是同一个方法调用可以在不同的对象上产生不同的行为。在Java中,多态性可以通过方法重写(Override)和方法重载(Overload)来实现。
abstract class Animal {
public abstract void makeSound();
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
5.1.5 阻止继承
在声明类时使用关键字 final 可以避免这个类被继承:
public final class Manager extends Employee{
}
在一个类中可以对方法使用关键字 final
这样这个方法不允许覆盖
public class Employee{
private String name;
public final String getName(){
return name;
}
}
5.1.6 抽象类
可以在Employee类上面再抽象一个Person类,这个Person类很“抽象”,很复杂,不需要具体说每个人到底是什么样的,只需要说每个人都有什么
用关键字 abstract 声明一个抽象类,这个类只能被继承,而不能实例化
用关键字 abstract 声明一个抽象方法,这个方法在子类必须实现
public abstract class Person {
public abstract String getDescription();
}
5.1.7 受保护访问
4个访问控制修饰符:
- 仅对本类可见 -> private
- 对外部完全可见 -> public
- 对本包和所有子类可见 -> protected
- 对本包可见 -> 默认,不需要修饰符
5.2 对象包装器与自动装箱
包装器(wrapper)类:
- Integer
- Long
- Float
- Double
- Short
- Byte
- Character
- Boolean
自动装箱(autoboxing)
允许将基本数据类型自动转换为对应的包装类对象,反之亦然
5.3 参数数量可变的方法
变参(varargs)方法
如:
System.out.printf("%d",n);
System.out.printf("%d %s",n,"widgets");
可以自定义变参方法:
public static double max(double... values) {
double largest = Double.NEGATIVE_INFINITY;
for (double v : values) {
if (v > largest) {
largest = v;
}
}
return largest;
}
public static void main(String[] args) {
double ans = max(1, 18.3, 9, 23.7, 2.98, 2, 5, 8);
System.out.println(ans); // print 23.7
}
5.4 枚举类
public enum Day {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY;
}
枚举类与普通的类有一些区别:
- 枚举类可以通过
enum
关键字定义。 - 枚举类默认继承自
java.lang.Enum
类 - 枚举常量必须在枚举类的最开始部分声明
- 枚举常量之间用逗号分隔,以分号结束