继承
一、面向对象继承性
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.setAge(14);
stu.setName("孙笑川");
stu.tell();
}
}
class Person{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
class Student extends Person{
}
1. 在子类中扩展方法
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.setSchool("平津军官学校");
stu.setAge(14);
stu.setName("孙笑川");
stu.tell();
stu.getSchool();
}
}
class Person{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
class Student extends Person{
private String school;// 扩充方法
public void setSchool(String s){
this.school = s;
}
public void getSchool(){
System.out.println("school is "+ this.school);
}
}
2. 子类对象实例化对象
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student("孙笑川", 14, "平津大学");
stu.tell();
stu.getSchool();
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void tell(){
System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
}
}
class Student extends Person{
private String school;
public Student(String name, int age, String school){
super(name, age); // 调用父类构造方法
this.school = school;
}
public void getSchool(){
System.out.println("school is "+ this.school);
}
}
3. 继承限制
1. 单继承
多层继承:继承层次不要过多
2. 非私有操作
不允许直接访问非私有操作
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student("孙笑川");
System.out.println(stu.getInfo());
}
}
class Person{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class Student extends Person{
private String school;
public Student(String name){
setName(name);
}
public String getInfo(){
return "姓名: "+ getName();
}
}
本程序中Person父类定义的name属性虽然可以被子类继承使用,但是由于private定义,所以在子类中无法直接访问私有属性访问,只能通过getter方法访问,所以该属性属于隐式继承
二、覆写
子类可能会和父类定义名称相同的方法和属性,此时情况被称为覆写
1. 覆写定义
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student("孙笑川");
System.out.println(stu.getInfo());
Person per = new Person();
per.printInfo();
stu.printInfo();
}
}
class Person{
private String name;
public void setName(String name){
this.name = name;
}
public void printInfo(){//父类方法
System.out.println("笑川桑,你还在吗?");
}
public String getName(){
return this.name;
}
}
class Student extends Person{
private String school;
public Student(String name){
setName(name);
}
public void printInfo(){// 覆写方法
System.out.println("平津原来是没有雪的");
}
public String getInfo(){
return "姓名: "+ getName();
}
}
使用super调用父类未覆写方法,使用this调用子类覆写方法
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student("孙笑川");
stu.getInfo();
}
}
class Person{
private String name;
public void setName(String name){
this.name = name;
}
public String printInfo(){
return "笑川桑,你还在吗?";
}
public String getName(){
return this.name;
}
}
class Student extends Person{
private String school;
public Student(String name){
setName(name);
}
public String printInfo(){
return "平津原来是没有雪的";
}
public void getInfo(){
System.out.println("姓名: "+ getName());
System.out.println("父类方法: "+ super.printInfo());// 为覆写的父类方法
System.out.println("子类方法: " + this.printInfo());// 为子类已经覆写的方法
}
}
2. 方法覆写限制
核心问题:被子类所覆写的方法不能拥有比父类更严格的访问控制权限,也就是父类方法是public,子类覆写方法不能是default
No. | 区别 | 重载 | 覆写 |
---|---|---|---|
1 | 英文 | Overloading | Overriding |
2 | 定义 | 方法名称相同,参数的类型和个数不同,返回值按标准要一致,也可以不一致,会强制进行转换 | 方法名称、参数的类型及个数、返回值类型完全相同 |
3 | 权限 | 没有权限要求 | 被子类覆写的方法的访问控制权限不能比父类方法更严格 |
4 | 范围 | 发生在一个类中 | 发生在继承关系类中 |
3. 属性覆盖
子类除了可以对父类进行覆写外,也可以对非private定义的父类属性进行覆盖,至于要定义相同的名称就行
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.getInfo();
}
}
class Person {
String info = "23124"; // 父类属性
}
class Student extends Person{
int info = 123;// 子类覆写属性
public void getInfo(){
System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
}
}
三、final 关键字
实现以下功能:
- 定义不能够被继承的类
final class Channel{}
该类不能被继承
- 定义不能够覆写的方法
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.getInfo();
}
}
class Person {
public final void getInfo(){// 无法被覆写
System.out.println("父类方法");
}
}
class Student extends Person{
public void getInfo(){// IDE 中会报错
System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
}
}
- 定义常量(全局常量)
final int ON = 1
定义全局常量,无法被更改
四、Annotation 注解
1. 准确覆写 Override
用在子类覆写父类方法使用了Override注解,就可以直接分别出哪些是覆写方法,哪些是子类扩充方法。同时利用@Override 注解也可以在编译时检测出因为子类拼写错误所造的方法覆写错误
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.getInfo();
}
}
class Person {
String info = "23124";
public void getInfo(){
System.out.println("父类方法");
}
}
class Student extends Person{
int info = 123;
// 注释
@Override
public void getInfo(){
System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
}
}
2. 过期声明
程序开发是迭代进行的,因此有些不推荐使用的结构,所以就有针对此的注释 @Deprecated
public class ObjectDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.getInfo();
stu.getInfo1();// 函数名称上会出现删除线
}
}
class Person {
String info = "23124";
public void getInfo(){
System.out.println("父类方法");
}
@Deprecated
public void getInfo1(){
System.out.println("aenfasef");
}
}
class Student extends Person{
int info = 123;
@Override
public void getInfo(){
System.out.println("child info is "+this.info+ "、parent info is "+ super.info);
}
}
3. 压制警告
@SuppressWarning(value = {“deprecation”}):可以去除使用@Deprecated注释的函数体发生的Warning
五、面向对象多态性
展现形式1:
- 方法重载
- 方法覆写
展现形式2:
1. 对象向上转型
父类 父类实例 = 子类实例,自动完成转换
public class ObjectDemo {
public static void main(String[] args) {
Person person = new Person();
person.tell();
Person person1 = new Student();// 向上转型
person1.tell();
Person person2 = new Worker();
person2.tell();
}
}
class Person {
public void tell(){
System.out.println("人来了!");
}
}
class Student extends Person{
public void tell(){
System.out.println("学生来了!");
}
}
class Worker extends Person{
public void tell(){
System.out.println("工人来了!");
}
}
统一方法参数
public class ObjectDemo {
public static void main(String[] args) {
Home.tell(new Student()); //不同的实例化对象,但都是一个Person类型
Home.tell(new Worker());
}
}
class Person {
public void tell(){
System.out.println("人来了!");
}
}
class Student extends Person{
public void tell(){
System.out.println("学生来了!");
}
}
class Worker extends Person{
public void tell(){
System.out.println("工人来了!");
}
}
class Home{
public static void tell(Person per){
per.tell();
}
}
2. 对象向下转型
子类 子类实例 = (子类)父类实例,强制完成转换
public class ObjectDemo {
public static void main(String[] args) {
Person per = new Superman(); //先向上转型
per.run();
Superman sup = (Superman) per;// 再向下强制转型
sup.fly();
}
}
class Person {
public void run(){
System.out.println("跑步!");
}
}
class Superman extends Person{
public void fly(){
System.out.println("我会飞翔!");
}
}
4. instanceof 关键字
对象的向下转型有安全隐含,为了保证安全性,可以在转换前通过instanceof队对象所属类型进行判断,语法如下
对象 instanceof 类
返回一个boolean类型的数据
public class ObjectDemo {
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Superman();
System.out.println(per1 instanceof Person);
System.out.println(per1 instanceof Superman); //判断对象所属类型false,未建立联系
System.out.println(per2 instanceof Person);
System.out.println(per2 instanceof Superman);
per2.run();
Superman spm1 = (Superman) per1;// 发生ClassCastException
spm1.fly();
Superman spm2 = (Superman) per2; //向下转型
spm2.fly();
}
}
class Person {
public void run(){
System.out.println("跑步!");
}
}
class Superman extends Person{
public void fly(){
System.out.println("我会飞翔!");
}
}
进行安全的向下转型
public class ObjectDemo {
public static void main(String[] args) {
Person per = new Superman();
if (per instanceof Superman){ // 先判断对象所属类型,再向下转型
Superman spm = (Superman) per;
spm.fly();
} else {
System.out.println("错误");
}
}
}
class Person {
public void run(){
System.out.println("跑步!");
}
}
class Superman extends Person{
public void fly(){
System.out.println("我会飞翔!");
}
}
六、Object类
Object是所有类的父类,所有利用class关键字定义的类全部默认继承自Object类
class Person{}
和class Person extends Object{}
是相同的
public class ObjectDemo {
public static void main(String[] args) {
Object per = new Superman();// 可以直接向上转型到爷爷类
if (per instanceof Superman){
Superman spm = (Superman) per;// 向下转型到孙子类
spm.fly();
} else {
System.out.println("错误");
}
}
}
class Person {
public void run(){
System.out.println("跑步!");
}
}
class Superman extends Person{
public void fly(){
System.out.println("我会飞翔!");
}
}
Object可以接受所有的引用数据类型
1. 获取对象信息
Object提供了toString方法,打印对象信息
public class ObjectDemo {
public static void main(String[] args) {
Person per = new Person("孙笑川", 18);
System.out.println(per.toString());
}
}
class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString(){
return "姓名:" + this.name + "、年龄:" + this.age;
}
}
Object.toString方法的默认实现
public String toString(){
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
2. 对象比较
Object类中的equals方法是基于对象是否相同来建立的,主要是判断两个对象的地址是否相同,”对象.equals(对象)“ 效果等同“对象 == 对象“
String类中覆写了equals方法public boolean equals(Object obj)
覆写equals方法
public class ObjectDemo{
public static void main(String[] args) {
Person per1 = new Person("孙笑川",18);
Person per2 = new Person("孙笑川",18);
System.out.println(per1.equals(per2));
}
}
class Person extends Object{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
// 覆写的目的是为了判断new的两个对象是否创建的是同一人
public boolean equals(Object obj){
if (!(obj instanceof Person)){//判断是否为Person类
return false;
}
if (obj == null){// 判断目标是否为空
return false;
}
if (this == obj){// 判断地址是否相同,地址相同则认为是同一个对象
return true;
}
Person per = (Person) obj;
return this.name.equals(per.name) && this.age == per.age;// 然后判断对象的属性是否相同
}
}