96SEO 2026-02-19 17:23 13
抽象类如果一个类没有足够的信息来描述一个对象(这个类通常是父类)那么这个类可以用abstract修饰成为抽象类。

抽象方法抽象类中被abstract修饰的方法称为抽象方法抽象方法可以不具体实现。
抽象类也是类内部可以有成员和构造方法等也可以发生向上转型方法重写多态。
abstract不能修饰被private、static、final修饰的方法因为抽象方法要被子类重写(被重写的方法要满足能被重写的条件)
如果一个类中包含抽象方法那么这个类必定是抽象类但抽象类中不一定有抽象方法。
抽象类不能实例化对象只能被继承(和被final修饰的类效果相反)并且继承抽象类的子类A必须要重写抽象类中的抽象方法如果不重写得将子类A也得写成抽象类那么当子类B继承子类A后就得重写子类A的父类和子类A中所有没被重写的方法(出来混总是要还的)。
{/*重写Fa***r类中的抽象方法*/Overridepublic
{System.out.println(我是爷爷的第一个孙子);}/*重写Son类中的抽象方法*/Overridepublic
{System.out.println(我是爸爸的第一个儿子);}
{/*重写Fa***r类中的抽象方法*/Overridepublic
{System.out.println(我是爷爷的第二个孙子);}/*重写Son类中的抽象方法*/Overridepublic
{System.out.println(我是爸爸的第二个儿子);}
{//向上转型成Fa***r类只能调用Fa***r类有的成员fa***r.funcA();}public
{//向上转型成Son类由于Son类继承了Fa***r类//此时能调用Fa***r类和Son类有的成员//所以无论在抽象类有没有继承抽象类的情况下//记住向上转型成最后一个抽象类即可son.funcA();son.funcB();}public
GrandSon2();//Test01.funcDemo1(grandSon1);//Test01.funcDemo1(grandSon2);Test01.funcDemo2(grandSon1);Test01.funcDemo2(grandSon2);}
抽象类本身不能被实例化要想使用只能创建该抽象类的子类然后让子类重写抽象类中的抽象方法。
有些人可能会说了,
确实如此但是使用抽象类相当于多了一重编译器的校验。
使用抽象类的场景就如上面的代码,
而应由子类重写的方法完成那么如果不小心忘记在子类中重写父类中的方法了在方法调用的过程中父类使用普通类编译器是不会报错的但是父类是抽象类就会在子类继承父类后提示需要重写父类中的方法,
概念接口英文Interface在JAVA编程语言中是一个抽象引用数据类型是抽象方法的集合接口用interface关键字来定义。
接口的命名一般以大写字母I开头并且命名一般使用形容词性的单词。
接口中的成员可以有成员变量和成员方法但成员变量必须是public
abstract修饰的(也就是说接口中的成员变量必须是公开可以使用的常量接口中的成员方法必须是抽象方法)阿里编码规范中约定接口中的方法和属性不要加任何的修饰符号因此我们在写接口中的成员时可以不写前面的修饰编译器会自动修饰。
接口前面不要用abstract修饰因为接口本身比抽象类更抽象。
抽象类和接口都不能实例化对象抽象类用来被类继承接口用来被类实现。
当一个类实现一个接口时意味着要在这个类中重写接口中所有抽象方法如果在这个类中不想重写则这个类必须定义成抽象类继承这个抽象类的类得重写接口和这个抽象类中的所有抽象方法。
接口也可以发生向上转型动态绑定多态(动态绑定是原理多态是思想)。
接口定义好后也会有一个单独的Java文件编译完成后生成的字节码文件的后缀也是(.class)。
重写接口中的方法时方法只能是public修饰的(因为重写方法的权限要大于等于重写前的权限而接口中的成员方法默认是public的)。
修饰的方法要写清楚具体实现的语句且被实的接口中default成员方法可以不重写也可以被重写并不会像接口中的抽象方法一样强制要重写。
在Java中类和类之间只能是单继承的也就是说一个类只能有一个父类但一个类可以实现多个接口从而间接达到实现多继承的目的。
一个类实现多个接口时每个接口中的抽象方法都要实现否则类必须设置为抽象类。
例如根据我们当前掌握的知识当我们想要描述狗、鱼、鸭这三种动物时我们会定义狗、鱼、鸭这三个类并且由于它们之间共属于动物我们可以定义一个父类Animal从而达到代码复用的效果。
但是在定义的过程中我们会发现一个问题游泳、跑步、飞行这三个行为如果我们把它们定义在父类Animal中并不稳妥因为继承是对子类共性的抽取并不是所有的动物都同时具备这三个行为如果我们把它们定义在狗、鱼、鸭的各自类中这又会造成代码冗余如果我们把它们定义在一个新的类A中当我们定义狗、鱼、鸭类时又会发现类是不支持多继承的继承了Animal类就不能再继承A类了。
在这种场景下我们把游泳、跑步、飞行这三个行为定义在一个接口中最为合适这样子类既可以继承Animal类也可以根据需要拥有游泳/跑步/飞行这三个行为而且不会造成代码冗余。
于是我们可以写下如下图代码该代码展示了
使用接口的好处让程序员忘记类型。
例如下图中用绿色方框框起来的方法参数部分采用了向上转型传参数的方式在调用该方法传参时程序员可以不用考虑传入的参数是什么类只需要关心传入的参数的类中是否实现了对应的接口。
一个接口可以继承多个接口从而达到复用的效果关键字也是extends。
下图代码中接口C继承了接口A、B实现接口C的TestNew类要重写接口A、接口B、接口C中所有的抽象方法否则TestNew类得定义成抽象类。
关系运算符只能比较基本数据类型数据的大小引用数据类型的数据比较大小要用到Comparable接口中的compareTo方法。
具体做法为将要比较大小的引用数据类型的对象它对应的类实现Comparable接口在类中重写接口中的compareTo方法compareTo方法的内部自定义根据类的哪一种成员变量进行比较。
我们在比较该引用数据类型的对象的大小时直接用对象的引用调用compareTo方法并传参即可不用定义一个新的方法使用向上转型(这样写有点多此一举了)举例代码如下图所示。
Arrays.sort方法在排序装有引用数据类型的数组时会先将数组中的元素强制转换成Comparable类型然后调用compareTo方法比较两个相邻数据的大小最后根据比较的结果对数组中相邻两个元素进行位置调整。
这也就是说使用Arrays.sort方法对装有引用数据类型数据的数组进行排序时也得先让对应引用数据类型的类实现Comparable接口并在类中重写了compareTo方法后才能正常进行排序且值得注意的是也就是说Arrays.sort排序的逻辑与compareTo内部实现比较大小的依据有着极大的关联当compareTo内部根据年龄、姓名等比较大小时可能会造成不同的排序结果。
使用Comparable接口中的compareTo方法来比较两个引用数据类型的大小的局限性在于一旦把compareTo中的内容写下了之后以后在比较该引用数据类型对象的大小时调用compareTo方法只能按照compareTo方法中依据的东西判断大小了。
写一个自己的sort方法实现和Arrays.sort方法一样的功能(采用冒泡排序)
针对Comparable接口的局限性在比较某个类实例化的两个对象的大小时我们可以采用实现Comparator接口对里面的compare方法进行重写而不去采用实现Comparable接口。
具体做法重新定义新的类(A)去实现Comparator接口里面写上要比较的类使用时直接new一个A类的对象a使用a调用compare方法并传参即可我们可以按照这种方式写多个比较器来达到目的如果Comparator接口由比较对象的类实现则会达不到想要的效果如下图二所示。
我们在调用Arrays.sort方法时也可以将比较器作为参数传递给sort方法使得sort方法在排序装有引用数据类型的数组时比较相邻的两个元素的大小采用比较器中的compare方法而不再采用Comparable中的compareTo方法。
给该对象对应的类实现Clonable接口但并不用重写Cloneable中的接口因为这个接口里面并没有抽象方法此时这个接口叫做空接口/标记接口这种接口的意义在于只有实现了该接口才能证明你有该功能除此之外没有什么特殊的意义。
调用Object类中的clone方法。
但我们不能直接调用因为Object类中的clone方法被protected修饰了此时是不能在不同包的非子类中使用的
于是我们可以先在子类中重写Object的克隆方法在这个重写的克隆方法内部直接返回原来克隆方法的返回值即可因为我们调用克隆方法的目的本来就是得到克隆后对象的地址在不同包的子类中是可以调用Object的clone方法的。
由于clone方法的返回值是Object类型的因此在接收clone方法的返回值时要强制类型转换一下(Object类是所有类的父类这里要发生向下转型)。
当上面的步骤都做好后代码运行时还会报错此时是由于异常原因解决的方法是在main方法参数列表的后面加上clone方法参数列表后的“throws
CloneNotSupportedException”即可异常问题后面的文章中会讲到。
浅拷贝修改上文Cloneable接口中的代码即给Student类增加一个成员变量(该成员变量是Money类创建的一个对象)并保持其他的代码不变。
代码和代码在内存中的示意图如下图所示。
我们会发现一个问题克隆出的student2中成员变量m指向的对象和student1中成员变量m指向的对象一样当我们在修改student1/student2中m对象的money值时student1和student2中m对象的money值都会变这种现象被称为浅拷贝(并没有实现真正的拷贝效果)。
深拷贝为了实现真正的拷贝效果我们可以修改上述代码中重写的clone方法来达到目的。
具体操作是在Student类重写的clone方法中先调用Object类中的clone方法克隆一下this所指向的对象并让临时的Student类对象tmp来接收然后为Money类实现Cloneable接口并重写clone方法接着克隆一下this中的m对象并让tmp中的m接收最后返回tmp即可达到真正的拷贝效果代码和代码在内存中的分析如下图所示。
对于整个Object类中的方法需要实现全部掌握本小节当中我们主要来熟悉这几个方法toString()方法equals()方法hashcode()方法。
items并在搜索框中搜索Object点击第一个Object然后在ideal页面的左下角点击Structure即可看到Object类中的所有的方法。
如果要打印对象的信息可以通过重写Object类中的toString()方法在打印时对于单个对象直接用sout打印对象的名称即可对于装有多个对象的数组来说用sout打印Arrays.toString的返回值即可具体示例代码如下图所示。
Object类中的equals方法的功能是比较两个引用所指向的对象是否为同一个对象如果是就返回true否就返回false并且Object类中的equals方法是用public修饰的哦~。
也就是说当我们想比较两个对象中的内容是否相同时得重写Object类中的equals方法。
并且ideal提供了快捷方式具体做法单机右键Generate点击equals()
toString方法的源码中有一个hashCode()方法它可以帮我们算一个具体的对象位置(我们可以暂时理解为内存地址)。
Integer.toHexString()方法可以将这个地址以16进制输出。
hashCode()方法是一个native方法底层是由C/C代码写的所以我们看不到。
如果在某个业务场景中我们需要实现如果对象的成员变量都一致我们就认为是同一个人的话我们可以通过重写hashCode方法来达到目的。
ideal提供了快捷方式具体做法单机右键Generate点击equals()
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback