面向对象的三大特征:继承、封装、多态。
继承
继承使用要点:
- 1.父类也称作超类、基类、派生类
- 2.java中只有单继承,没有C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
- 3.java的接口可以多继承,类只有单继承。
- 4.子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如 父类私有的属性和方法)
- 5.如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object
方法的重写 override
子类通过重写父类的方法,可以用自身的行为替换父类的行为
方法的重写需要符合下面的三个要点:
1.“==”:方法名、形参列表相同
2.“<=”: 返回值类型和声明异常类型,子类小于等于父类
3.“>=”: 访问权限,子类大于等于父类
测试方法的重写
package cn.yishan.oo2;public class TestExtends {
public static void main(String[] args) { Horse h = new Horse(); h.run(); h.stop(); }
}
class Vehicle {
public void run(){ System.out.println("跑..."); } public void stop(){ System.out.println("停止!"); } public Person whoIsPsg(){ return new Person(); }
}
class Horse extends Vehicle{
@Override public void run(){ System.out.println("得得得得得"); } @Override public Student whoIsPsg(){//返回值类型小于等于父类的类型 return new Student(); }
}
Object类
Object类时所有java类的根基类,也就意味着所有的java对象都拥有Object类的属性和方法
toString方法
toString方法的重写
测试Object
package cn.yishan.oo2;public class TestObject {
public static void main(String[] args) { //Object obj; TestObject to = new TestObject(); System.out.println(to.toString()); } @Override public String toString(){ return "测试对象"; }
}
==与equals方法
“==”代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。
“equals”Object类中定义有:public boolean equals(Object obj)方法,提供定义“对象内容相等”的逻辑。
测试重写equals
package cn.yishan.oo2;
import java.util.Objects;
public class TestEquals {
public static void main(String[] args) {
Object obj;
String str;
User u1 = new User(1000,"亦山","123");
User u2 = new User(1000,"一闪","123");
System.out.println(u1==u2);
System.out.println(u1.equals(u2));
String str1 = new String("sxt");
String str2 = new String("sxt");
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
}
}
class User{
int id;
String name;
String pwd;
public User(int id, String name, String pwd) {
super();
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
User user = (User) obj;
return id == user.id;
}
}
super
super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。
构造方法调用顺序:
构造方法第一局总是:super(…)来调用父类对应的构造方法。所以,流程就是:先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。
子类中所有的构造方法默认都会访问父类中无参的构造方法
因为在初始化的时候,子类有可能会用到父类中的数据,所以,子类初始化之前,首先会完成父类数据的初始化。因此,每一个构造方法的第一局语句默认的都是:super();
注:静态初始化快调用顺序,与构造方法调用顺序一样,不再重复。
封装
封装的具体优点:
- 1.提高代码的安全性
- 2.提高代码的复用性
- 3.“高内聚”:封装细节,便于修改内部代码,提高可维护性。
- 4.“低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。
封装的实现–使用访问控制符
- 1.private表示私有,只有自己类能访问
- 2.default表示没有修饰符修饰,只有同一个包的类能访问
- 3.protected表示可以被同一个包的类以及其他包中的子类访问
- 4.public表示可以被该项目的所有包中的所有类访问
封装的使用细节
类的属性的处理: - 1.一般使用private访问权限
- 2.提供相应的get/set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!)
- 3.一些只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰。
多态
多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。
多态的要点:
- 1.多态是方法的多态,不是属性的多态(多态与属性无关)
- 2.多态的存在要有3个必要条件:继承/实现关系,方法重写,父类引用指向子类对象。
- 3.父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
多态中成员访问特点
- 构造方法:同继承一样,子类对通过super访问父类构造方法
- 成员变量:编译看左边(父类),运行看左边(父类)
- 成员方法;编译看左边(父类),运行看右边(子类)
多态的好处和弊端
- 多态的好处:提高了程序的扩展性
- 具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接受者父类的任意子类对象
- 多态的弊端:不能使用子类的特有功能
1 | package com.yishan.myduotai03; |
多态中的转型
- 向上转型:从子到父,父类引用指向子类对象
- 向下转型:从父到子,父类引用转为子类对象
1 | package com.yishan.myduotai04; |
多态中的转型存在的风险
- 概述;如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
instanceof 运算符
instanceof是二元运算符,左边是对象,右边是类;当对象时右面类或子类所创建对象时,返回true;否则,返回false.
1
2
3
4if(animal instanceof Dog){
Dog dog = (Dog) animal;
dog.show();//加入instanceof判断,可以避免ClassCastException 类型转换错误
}
final
作用:
- 1.修饰变量:被它修饰的变量不可改变。一旦赋了初值,就不能被重新赋值
- 基本数据类型变量:其值不能被更改
- 引用数据类型变量:其地址值不能被更改,但是可以修改对象的属性值
- 成员变量(要注意初始化时机):1.在创建的时候,直接复制 2.在构造方法结束之前,完成赋值
- 2.修饰方法:该方法不可被子类重写,但是可以被重载!
- 3.修饰类:修饰的类不能被继承。比如:Math、String等
抽象方法
使用abstract修饰的方法,没有方法体,只有声明。定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现。抽象类
包含抽象方法的类就是抽象类,通过abstract 方法定义规范,然后要求子类必须定义具体实现。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。使用要点
- 1.有抽象方法的类只能定义成抽象类,但是抽象类中不一定有抽象方法
- 2.抽象类不能实例化,即不能new来实例化抽象类
- 3.抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用
- 4.抽象类只能用来被继承
抽象类的意义就在于:为子类提供统一的,规范的模板。子类必须实现相关的抽象方法!
package cn.yishan.oop;
1 | public abstract class Animal { |
1 | class Dog extends Animal{ |
接口
声明格式
[访问修饰符] interface 接口名 [extends 父接口1.父接口2...]{
常量定义;
方法定义;
}
定义接口的详细说明
1.访问修饰符:只能是public或默认
2.接口名:和类名采用相同命名机制
3.extends: 接口可以多继承
4.成员变量:接口中的属性只能是常量!总是:public static final 修饰。不写也是
5.成员方法:只能是抽象方法!接口中的方法只能是:public abstract。省略的话。也是public abstract
6.构造方法:没有,super();访问的是Objict的构造方法
Java8中的接口方法(默认方法、静态方法)
默认方法:default关键字
- 作用:解决接口升级的问题
注意事项
- 默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
- public可以省略,default不能省略
- 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写
静态方法:static关键字
注意事项
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public可以省略,static不能省略
Java9中的接口方法(私有方法)
私有方法产生原因
- Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性
注意事项
- 默认方法可以调用私有的静态方法和非静态方法
- 静态方法只能调用私有的静态方法
类和接口的关系
- 类和类的关系
- 继承关系,只可以单继承,但是可以多层继承
- 类和接口的关系
- 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
- 接口和接口的关系
- 继承关系,可以单继承,也可以多继承