继承、重载、重写、多态、抽象类、接口、final、Static
继承
继承就是子类继承父类的属性和方法,实现代码复用。
在父类里面抽取的属性和方法一定是所有子类所共有
Java是单继承,就是一个类只能继承extends(inherit)一个类,而java这种面向对象的语言就是对现实世界的描述,现实世界中是存在很多多继承,但是java里面是支持实现多个接口。
Object是所有类的父类(这个父类不一定是直接父类)
Java里面new子类对象时候首先把父类对象new出来。
//一个类不继承任何一个类,默认继承Object
public class Person/* extends Object*/{
//如果希望子类继承 protected
protected int id;
protected String name;
protected int age;
public Person() {
//Java里面new子类对象时候首先new父类对象
super();//new Object();
}
public Person(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public void show() {
System.out.println("Person.show");
}
}
//实体类:和数据库表一一对应
public class Student extends Person{
// private int id;
// private String name;
// private int age;
private String className;
public Student() {
super();//new Person();
}
public Student(int id, String name, int age, String className) {
x'cxc super(id, name, age);//new Person(id,name,age)
this.className = className;
}
// public void show() {
// System.out.println("Student.show");
// }
public void study() {
System.out.println(className + "班的"+name+"正在学习");
}
}
this、super总结:
1. this:代表当前类的对象 this.id=id
2. super:代表父类对象,在子类里面想调用父类属性或者方法
3. this():调用当前类的其他构造方法
4. super():调用父类构造方法
public class Student extends Person {
protected int className;
public int getClassName() {
return className;
}
public void setClassName(int className) {
//this 代表本类的对象
this.className = className;
}
public Student() {
//调用父类的构造方法
//super();
//调用本类的构造方法
this(1,"1",1,"1",1);
//代表父类的对象
super.age=className;
this.className = className;
}
public Student(int id, String name, int age, String gender, int className) {
//调用父类的构造方法
super(id, name, age, gender);
this.className = className;
}
}
不写,Java默认加上:
1. 无参构造方法
2. 一个类不继承任何一个类默认继承extends Object
3. 在类的构造方法第一句默认会加上super()
重载
重载(Overload)是指在同一个类中可以有多个方法拥有相同的名称,但是它们的参数列表不同。
Java通过方法的参数类型、个数或顺序来区分不同的重载方法。
最典型的重载:构造方法重载(无参构造方法、有参构造方法)
方法重载特点:与返回值无关,只看参数列表。
void show(int a, char b, double c){}
1. void show(int x, char y, double z){} 不是重载,是同一个方法
2. int show(int a, double c, char b){} 是重载,参数顺序不一样,和返回值无关
3. void show(int a, double c, char b){} 是重载,参数顺序不一样
4. boolean show(int c, char b){} 是重载
5. void show(double c){ } 是重载
6. double show(int x, char y, double z){} 不是重载
重写(覆盖)@Override
父类中定义的方法子类不满意,子类重新定义这个方法,最典型的重写就是toString()
重写的规则:
1. 方法名必须相同
2. 参数列表必须完全相同
3. 返回值类型必须相同(或是其子类)
4. 访问权限不能比父类更严格(可以更宽松)
5. 不能抛出比父类更多的异常
public class Object {
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
}
public class Student {
@Override
public String toString() {
return "Student{" +
"className='" + className + '\'' +
", id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
重写 vs 重载:
| 重写 Override | 重载 Overload |
|---|---|
| 发生在父子类之间 | 发生在同一个类中 |
| 方法名相同,参数相同 | 方法名相同,参数不同 |
| 返回值必须相同 | 返回值无关 |
多态
Java 多态(Polymorphism)是面向对象编程的一项核心概念,它允许对象以多种形式出现。
多态性在Java中有两个主要的表现形式:
- 编译时多态(也称为静态多态)
- 运行时多态(也称为动态多态)
编译时多态是通过方法重载(Method Overloading)实现的。这意味着在同一个类中可以定义多个方法,这些方法具有相同的名字但参数列表不同。编译器在编译时根据参数列表来决定调用哪个具体的方法。
这里大家只要知道多态还有编译时多态这种形式就可以,重点还是运行时多态。
多态存在的三个必要条件:
1. 继承
2. 重写
3. 父类引用指向子类对象 Cal cal = new Add();
// 父类 Animal
public class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗啃骨头");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
// 测试多态
public class Test {
public static void main(String[] args) {
// 父类引用指向子类对象
Animal a1 = new Dog();
a1.eat(); // 输出:狗啃骨头,调用子类的方法
Animal a2 = new Cat();
a2.eat(); // 输出:猫吃鱼,调用子类的方法
}
}
抽象方法、抽象类
抽象类和接口都是用来实现抽象,规范子类行为,是面向接口编程的基础。
抽象方法
如果一个方法只有声明,没有实现(没有方法体),那么这个方法就是抽象方法,用 abstract 修饰。
public abstract void eat();
抽象类
包含抽象方法的类必须是抽象类,用 abstract 修饰。
public abstract class Animal {
// 抽象方法,没有方法体
public abstract void eat();
// 抽象类可以有普通成员变量和普通方法
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
特点:
- 抽象类不能创建对象,因为抽象方法没有实现,创建对象调用抽象方法没有意义
- 抽象类必须被子类继承,子类必须重写所有抽象方法,才能创建对象;如果子类没有重写所有抽象方法,子类也必须是抽象类
示例:
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal {
@Override
public void eat() {
// 必须实现抽象方法
System.out.println("狗吃骨头");
}
}
// 使用
public class Test {
public static void main(String[] args) {
// Animal animal = new Animal(); // 错误,抽象类不能创建对象
Animal a = new Dog(); // 多态,没问题
a.eat();
}
}
如果这个类是抽象类,并不要求这个类一定要有抽象方法
抽象类里面可以有普通方法,也可以有抽象方法。
如果一个类是抽象类,那么这个类就不能被new实例化,只能被其他类继承。
抽象方法可以理解为父类(抽象类)定义的一个模板或者规范(自己本身不实现),子类必须实现这个抽象方法,如果子类不想实现这个方法,那么这个子类也必须要变成抽象类。
接口
接口是一个纯粹的抽象类(接口里面所有的方法都是抽象方法)
接口就是一个规范(标准),他没有提供任何是实现,具体的功能由实现接口的子类去实现。
接口就是一个规范,可插拔(可以被替换,首先定义一个标准(接口),大家都遵守这个标准,就可以实现互相之间替换)
面向接口编程
接口有广义和狭义:
- 狭义:就是Java里面接口这个技术 interface
- 广义:声明成父类类型,指向不同的子类对象。
这里的父类可以是:接口、抽象类、普通父类
接口也是父类的一种
接口的使用
接口是一种更彻底的抽象,接口中所有方法都是抽象方法(Java 8 之前)。
接口用 interface 关键字定义:
修饰符 interface 接口名 {
// 常量
// 抽象方法
}
示例:
// 定义接口
public interface Flyable {
// 接口中的属性默认是 public static final
double MAX_SPEED = 1200;
// 接口中的方法默认是 public abstract
void fly();
}
类实现接口使用 implements 关键字:
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟儿用翅膀飞");
}
}
public class Airplane implements Flyable {
@Override
public void fly() {
System.out.println("飞机用引擎飞");
}
}
特点:
- 接口不能创建对象
- 一个类可以实现多个接口,弥补 Java 单继承的不足
- 实现类必须重写接口中所有抽象方法,否则实现类也必须是抽象类
final总结:修饰变量、类、方法
1. final变量:这个变量就不能被修改,就是常量 public static final double PI = 3.1415;
2. final类:这个类就不能被继承
3. final方法:这个方法就不能被重写
4. 接口和抽象类不能使用,没有意义
静态属性、静态方法
static void main(String[] args) {
//Math math = new Math();
//int max = math.max(3, 5);
//静态方法调用,不需要new对象,直接: 类名.方法名()
int max = Math.max(3, 5);
System.out.println(max);
}
如何理解静态属性、静态方法
小区里面业主的房子可以看成一个一个的对象,这些都是属于特定的业主所独有。但是小区里面也有一些公共设施(健身器材、绿地),这些公共设施是属于这个小区的。但是是可以被所有的业主对象所使用的。
非静态的属性和方法(实例属性和方法)必须通过new对象访问,而静态的属性和方法是属于类的,在类加载到内存中就可以访问,不需要new对象就可以使用,但是可以被所有对象所共享。
使用时候注意点:
1、静态的方法只能访问静态的方法和静态的属性(因为当前对象的实例可以没有创建,所以静态的方法是没办法调用非静态的方法和属性的)
2、静态的方法中不能写this、super关键字(因为当前的对象实例可能还没有创建,代表当前类对象的this还有代表父类对象的super可能都还没有创建)
public class Student {
//属性、成员变量、实例变量
public int id;
private String name;
//静态变量
public static String country = "中国";
//成员方法、实例方法、非静态方法
public void show() {
System.out.println("Student.show");
print();
}
//静态方法
public static void print() {
System.out.println("Student.print");
//Non-static method 'show()' cannot be referenced from a static context
//show();
//this.name = "lisi";
country = "zhongguo";
//this.name = "ss";
}
public static void test() {
test();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}