前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 中的 "extends" 关键字

Java 中的 "extends" 关键字

作者头像
架构探险之道
发布2019-07-25 15:59:23
5200
发布2019-07-25 15:59:23
举报
文章被收录于专栏:架构探险之道

Java 中的 extends 关键字

手机用户请横屏获取最佳阅读体验,REFRENCES中是本文参考的链接,如需要链接和更多资源,可百度”Yiyuery”获取

  • CSDN
  • 简书
  • 个人博客地址 同步更新,文章中有对应的参考资源链接。

概要

  • Java中的继承实现方式与执行顺序 本文主要探究如何使用Java中的继承(extends)?以及子父类中,static{}{}和构造器执行顺序。
  • 子父类的equals重写注意事项

Java中的继承实现方式与执行顺序

A:

代码语言:javascript
复制
/*
* @ProjectName: 编程学习
* @Copyright:   2018 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
* @address:     http://xiazhaoyang.tech
* @date:        2018/9/17 22:28
* @email:       xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.chapter.extend;import java.util.Date;/**
* <p>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/9/17 22:28
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/9/17
* @modify reason: {方法名}:{原因}
* ...
*/public class A {    public A() {
       System.out.println("Class A");
   }
   {
       System.out.println("{} A");
       overrideMe("{}");
   }    static{
       System.out.println("static A");
       overrideMeStatic("static");
   }    public void overrideMe(String area){
       System.out.println("overrideMe A - " + area);
   }    public static void overrideMeStatic(String area){
       System.out.println("overrideMeStatic A - " + area);
   }    public static void main(String[] args) {        new A();        //static A
       //overrideMeStatic A - static
       //{} A
       //overrideMe A - {}
       //Class A
   }
}

分析

  • 类在初始化时,方法块{}、静态方法块static{}、构造器className()的执行顺序依次是:static{} > {} > className()
  • 静态方法只能在静态方法块中执行,所以静态方法的执行顺序和静态方法块一样,是最高的(除非静态方法快中并没有使用该静态方法)。

B:

代码语言:javascript
复制
/*
* @ProjectName: 编程学习
* @Copyright:   2018 HangZhou xiazhaoyang Dev, Ltd. All Right Reserved.
* @address:     http://xiazhaoyang.tech
* @date:        2018/9/17 22:29
* @email:       xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.chapter.extend;/**
* <p>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/9/17 22:29
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/9/17
* @modify reason: {方法名}:{原因}
* ...
*/public class B extends A{    public B() {
       System.out.println("Class B");
   }
   {        //方法快中无论什么方法都可以执行
       System.out.println("{} B");
       isStatic();
       notStatic();
   }    static{        //静态方法块中只能执行静态方法
       System.out.println("static B");        //notStatic(); 报错
       isStatic();//不报错,使用的是静态方法
   }    public static void isStatic(){
       System.out.println("is static method B");
   }    public void notStatic(){
       System.out.println("not static method B");
   }    public static void overrideMe(){
       overrideMeStatic("static method B");//父类静态方法
       System.out.println("overrideMe B");
   }    public static void main(String[] args) {
       B b = new B();
       b.overrideMe();
       B.overrideMe();        //---父类static{}
       //static A
       //overrideMeStatic A - static
       //---子类static{}
       //static B
       //is static method B
       //---父类方法块
       //{} A
       //overrideMe A - {}
       //---父类构造器
       //Class A
       //---子类方法块
       //{} B
       //is static method B
       //not static method B
       //---子类构造器
       //Class B
       //--- 实例方法调用
       //overrideMeStatic A - static method B
       //overrideMe B
       //--- 子类静态方法调用
       //overrideMeStatic A - static method B
       //overrideMe B
   }}

分析

  • 子类初始化时,父类static{}和其中的静态方法 > 子类static{}和其中的静态方法 > 父类方法块{} > 父类构造方法 > 子类方法块 > 子类构造器
  • static{}方法块执行优先级最高(父>子)
  • 单个类中,方法块调用在类初始化构造器之前,子父类中,子类方法块的执行在父类构造器方法之后执行

Java中的继承实现方式与执行顺序 注意事项

要么为继承而设计,并提供文档说明,要么就禁止继承

  • 继承对于final变量域的修改

Super:

代码语言:javascript
复制
/*
* @ProjectName: 编程学习
* @Copyright:   2018 HangZhou Yiyuery Dev, Ltd. All Right Reserved.
* @address:     http://xiazhaoyang.tech
* @date:        2018/9/12 08:50
* @email:       xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.chapter.extend;/**
* <p>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/9/12 08:50
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/9/12
* @modify reason: {方法名}:{原因}
* ...
*/public class Super {    public Super() {
       overrideMe();
   }    public void overrideMe(){
       System.out.println("Super overrideMe!");
   }
}

Sub:

代码语言:javascript
复制
/*
* @ProjectName: 编程学习
* @Copyright:   2018 HangZhou Yiyuery Dev, Ltd. All Right Reserved.
* @address:     http://xiazhaoyang.tech
* @date:        2018/9/12 08:52
* @email:       xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.capsule.chapter.extend;import java.util.Date;/**
* <p>
*
* </p>
*
* @author xiazhaoyang
* @version V1.0
* @date 2018/9/12 08:52
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018/9/12
* @modify reason: {方法名}:{原因}
* ...
*/public class Sub extends Super{    private final Date date;   Sub(){
       date = new Date();
   }    @Override
   public void overrideMe(){
       System.out.println(date);
   }    public static void main(String[] args) {
       Sub sub = new Sub();
       sub.overrideMe();        //null
       //Wed Sep 12 08:55:57 CST 2018
   }}

继承之后,子类实例化之前会先执行被重载的父类方法overrideMe(),此时子类的实例化尚未完成,静态块也未执行,所以虽然是final修饰的字段,date变量仍然是null,实例化时打印null,实例化之后打印复制后的新时间。

继承父类,子类重写equals方法如何正确使用instance of

基类 Lombok自动生成

代码语言:javascript
复制
/*
* @ProjectName: 编程学习
* @Copyright:   2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address:     http://xiazhaoyang.tech
* @date:        2018/7/29 22:24
* @email:       xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.example.chapter3.extend;/**
* <p>
*
* </p>
*
* @author xiachaoyang
* @version V1.0
* @date 2018年11月02日 10:11
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018年11月02日
* @modify reason: {方法名}:{原因}
* ...
*/public class EqualsSuper {    private Integer count;    private String superName;    public EqualsSuper() {
   }    public Integer getCount() {        return this.count;
   }    public String getSuperName() {        return this.superName;
   }    public void setCount(Integer count) {        this.count = count;
   }    public void setSuperName(String superName) {        this.superName = superName;
   }    public boolean equals(Object o) {        if (o == this) return true;        if (!(o instanceof EqualsSuper)) return false;        final EqualsSuper other = (EqualsSuper) o;        //此处o针对的是实际类型,如果是EqualsSub, other.canEqual 进入的是子类的canEqual方法
       //判断equalsSuper.equals(equalsSub)    return other instanceof EqualsSub;
       //(Object) this) 指向 EqualsSuper
       // new EqualsSuper() instanceof EqualsSub; //false
       if (!other.canEqual((Object) this)) return false;        final Object this$count = this.count;        final Object other$count = other.count;        if (this$count == null ? other$count != null : !this$count.equals(other$count)) return false;        final Object this$superName = this.superName;        final Object other$superName = other.superName;        if (this$superName == null ? other$superName != null : !this$superName.equals(other$superName)) return false;        return true;
   }    public int hashCode() {        final int PRIME = 59;        int result = 1;        final Object $count = this.count;
       result = result * PRIME + ($count == null ? 0 : $count.hashCode());        final Object $superName = this.superName;
       result = result * PRIME + ($superName == null ? 0 : $superName.hashCode());        return result;
   }    public boolean canEqual(Object other) {        return other instanceof EqualsSuper;
   }    public String toString() {        return "com.example.chapter3.extend.EqualsSuper(count=" + this.count + ", superName=" + this.superName + ")";
   }
}

子类 Lombok自动生成

代码语言:javascript
复制
/*
* @ProjectName: 编程学习
* @Copyright:   2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
* @address:     http://xiazhaoyang.tech
* @date:        2018/7/29 22:24
* @email:       xiazhaoyang@live.com
* @description: 本内容仅限于编程技术学习使用,转发请注明出处.
*/package com.example.chapter3.extend;/**
* <p>
*
* </p>
*
* @author xiachaoyang
* @version V1.0
* @date 2018年11月02日 10:12
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify By: {修改人} 2018年11月02日
* @modify reason: {方法名}:{原因}
* ...
*/public class EqualsSub extends EqualsSuper{    private String subName;    public EqualsSub() {
   }    public String getSubName() {        return this.subName;
   }    public void setSubName(String subName) {        this.subName = subName;
   }    public boolean equals(Object o) {        if (o == this) return true;        if (!(o instanceof EqualsSub)) return false;        final EqualsSub other = (EqualsSub) o;        if (!other.canEqual((Object) this)) return false;        final Object this$subName = this.subName;        final Object other$subName = other.subName;        if (this$subName == null ? other$subName != null : !this$subName.equals(other$subName)) return false;        
       return true;
   }    public int hashCode() {        final int PRIME = 59;        int result = 1;        final Object $subName = this.subName;
       result = result * PRIME + ($subName == null ? 0 : $subName.hashCode());        return result;
   }    public boolean canEqual(Object other) {        return other instanceof EqualsSub;
   }    public String toString() {        return "com.example.chapter3.extend.EqualsSub(subName=" + this.subName + ")";
   }    public static void main(String[] args) {
       EqualsSub equalsSub = new EqualsSub();
       equalsSub.setSubName("sub2");
       equalsSub.setCount(2);
       equalsSub.setSuperName("super2");
       EqualsSuper equalsSuper = new EqualsSuper();
       equalsSuper.setCount(2);
       equalsSuper.setSuperName("super2");
       System.out.println(equalsSub.equals(equalsSuper));//false
       System.out.println(equalsSuper.equals(equalsSub));//false
   }
}

备注

equals方法通过lombok插件delombok生成,可见lombok插件在自动生成eauls方法时不会去考虑父类属性。

写法调整 V1 子父类Equals判断

EqualsSub

代码语言:javascript
复制
public boolean equals(Object o) {    if (o == this) return true;    if (o instanceof EqualsSub){        final EqualsSub other = (EqualsSub) o;        if (!other.canEqual((Object) this)) return false;        final Object this$subName = this.subName;        final Object other$subName = other.subName;        if (this$subName == null ? other$subName != null : !this$subName.equals(other$subName)) return false;
   }else if(o instanceof EqualsSuper){        return super.equals(o);
   }    return false;
}//...public static void main(String[] args) {
   EqualsSub equalsSub = new EqualsSub();
   equalsSub.setSubName("sub2");
   equalsSub.setCount(2);
   equalsSub.setSuperName("super2");
   EqualsSuper equalsSuper = new EqualsSuper();
   equalsSuper.setCount(2);
   equalsSuper.setSuperName("super2");
   System.out.println(equalsSub.equals(equalsSuper));//true
   System.out.println(equalsSuper.equals(equalsSub));//false}

子父类 instance of 比较区别

代码语言:javascript
复制
new EqualsSuper() instanceof EqualsSub //falsenew EqualsSub() instanceof EqualsSuper //true

写法调整 V2 IDEA 默认实现方式

EqualsSuper

代码语言:javascript
复制
@Override
public boolean equals(Object o) {     if (this == o) return true;     if (!(o instanceof EqualsSuper)) return false;
    EqualsSuper that = (EqualsSuper) o;     return Objects.equals(count, that.count) &&
            Objects.equals(superName, that.superName);
} @Override
public int hashCode() {     return Objects.hash(count, superName);
}

EqualsSub

代码语言:javascript
复制
@Overridepublic boolean equals(Object o) {    if (this == o) return true;    if (!(o instanceof EqualsSub)) return false;    if (!super.equals(o)) return false;
   EqualsSub equalsSub = (EqualsSub) o;    return Objects.equals(subName, equalsSub.subName);
}@Overridepublic int hashCode() {    return Objects.hash(super.hashCode(), subName);
}public static void main(String[] args) {
   EqualsSub equalsSub = new EqualsSub();
   equalsSub.setSubName("sub2");
   equalsSub.setCount(2);
   equalsSub.setSuperName("super2");
   EqualsSuper equalsSuper = new EqualsSuper();
   equalsSuper.setCount(2);
   equalsSuper.setSuperName("super2");
   System.out.println(equalsSub.equals(equalsSuper));//false
   System.out.println(equalsSuper.equals(equalsSub));//true}

写法调整 V2 + V1 调整判断一致性

EqualsSub

代码语言:javascript
复制
@Overridepublic boolean equals(Object o) {   if (this == o) return true;   if (o instanceof EqualsSub){       if (!super.equals(o)) return false;
      EqualsSub equalsSub = (EqualsSub) o;       return Objects.equals(subName, equalsSub.subName);
  }else if(o instanceof EqualsSuper){       return super.equals(o);
  }   return false;
}//...public static void main(String[] args) {
     EqualsSub equalsSub = new EqualsSub();
     equalsSub.setSubName("sub2");
     equalsSub.setCount(2);
     equalsSub.setSuperName("super2");
     EqualsSuper equalsSuper = new EqualsSuper();
     equalsSuper.setCount(2);
     equalsSuper.setSuperName("super2");
     System.out.println(equalsSub.equals(equalsSuper));//true
     System.out.println(equalsSuper.equals(equalsSub));//true}

总结

  • 比对lombok和idea模板两种比较方法,各有优点和缺点
  • lombok不对父类进行属性比较,idea模板不具有一致性,只支持Super.equals(Sub)

REFRENCES

  1. equals方法在父类与子类之间进行比较时的情况

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构探险之道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java 中的 extends 关键字
    • 概要
      • Java中的继承实现方式与执行顺序
        • Java中的继承实现方式与执行顺序 注意事项
          • 继承父类,子类重写equals方法如何正确使用instance of
            • REFRENCES
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档