Java中类继承、接口实现的一些要注意的细节问题
1.接口A和接口B有相同的方法,只是返回值不同,则实现类不能同时实现这两个接口中的方法。
接口A有void C()方法,接口B有int C()方法,则无法同时实现这两个接口。
Java为了弥补类单继承的不足,引入了类多实现接口的机制,不过多实现某个接口也是有一定限制的,比如:
public interface A
{
void C();
}
public interface B
{
int C();
}
那么同时实现这两个接口是不可能的:

这个错误是无法被修复的。试想,类AB实现接口A和接口B,那么接口A里面的抽象方法和接口B里面的抽象方法参数列表都相同仅有返回值不同,类AB应该实现哪个呢?实现接口A的"void C()",那么接口B的"int C()"怎么办?实现接口B的"int C()"那么接口A的"void C()"怎么办?因为"void C()"、"int C()"属于方法参数相同,返回值不同,这两个方法是不可以重载的,所以同时实现两个方法也不可能。因此,在这里Java只能报错了。
2.A是接口,B实现A,C继承B,则C也是A的子类
有一个接口A,B实现了A接口,C继承自B类,则C也是A的子类,看一下:
public interface A
{ }
public class B implements A
{ }
public class C extends B
{ }
public static void main(String[] args)
{
C c = new C();
System.out.println(c instanceof A);
}
返回结果是true。这是一个不难理解的结论,想到求证这个结论是因为有一次在研究LinkedHashMap的时候:
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
既然LinkedHashMap已经继承了HashMap了,HashMap是Map的实现类,那为什么LinkedHashMap还要实现Map呢,岂不是多此一举吗?由此想到了会不会是因为继承了HashMap不代表LinkedHashMap是Map的子类所以LinkedHashMap要专门再实现一下Map,做了上面的实验,发现是我多虑了,可能Sun的开发人员就想这么写吧,呵呵。
3.父子类有同名变量和同名方法的处理.
子类不会覆盖父类的同名变量。
class Base {
    int count = 2;
    public void display() {
        System.out.println("Base : " + this.count);
    }
}
class Derived extends Base {
    int count = 20;
    @Override
    public void display() {
        System.out.println("Derived : " + this.count);
    }
}
public class Main {
    public static void main(String[] args) {
        Base bd = new Derived();
        System.out.println(bd.count);
        bd.display();
        Derived d = new Derived();
        Base d2b = d;
        System.out.println(d2b.count);
    }
}
运行结果为:
2
Derived : 20
2
原因如下:
编译器有一条这样的规定:编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
编译器在处理方法和成员变量时存在区别。在子类没有重写父类的方法时,编译器会将父类中的方法copy到子类中,如果子类复写,则无法copy。对于实例变量而言却不存在这样的现象,子类定义的同名变量无法覆盖父类的同名变量,就如同上面“2和20”的例子,两个都存储了,正是由于变量和方法之间的处理存在这样的区别,所以对于一个引用类型的变量而言:
- 访问变量时,按照声明该变量时的类型(编译时类型)
 - 访问方法时,按照实际引用的对象的类型(运行时类型)
 
因此,对于System.out.println(bd.count);而言,bd的编译时类型为Base,因此就会输出Base的count,也就是2;对于bd.display();而言,调用的是方法,bd的运行时类型为Derived,因此也就会调用了子类的display()方法。System.out.println(d2b.count);同理,会输出编译时类型Base的count了
4.注意父子类同名不同参数方法
上面的例子稍微修改一下:
class Father {
    public void foo(Object o) {
        System.out.println("Father.foo()");
    }
}
class Son extends Father{
    public void foo(String s) {
        System.out.println("Son.foo()");
    }
}
public class Main {
    public static void main(String[] args) {
        Son son = new Son();
        son.foo(new Object());
    }
}
运行结果:
Father.foo()
注意这个不是overload(方法重载),虽然方法名称一样,但是方法参数的类型不一样,原则上也属于两个方法,曾经看到有人将上面也归属于方法重写,个人表示有点异议。
不同不同于上面的例子,son从父类中继承到了foo(Object o)方法,son会根据传入的参数不同而决定使用哪个方法。对于本例,传入的是Object,因此son会使用继承的foo方法,而非自己的。
5.一个抽象类继承接口,可以不实现接口的方法。
一个实现类继承自一个抽象类并且实现了多个接口,那么必须实现所有未被实现的抽象方法
举个例子: public interface InterfaceA
{
void A1();
void A2();
}
public interface InterfaceB
{
void B1();
void B2();
} public abstract class AbstractC implements InterfaceA, InterfaceB
{
public void A1(){} // 我实现了InterfaceA的A1()方法
public void B2(){} // 我实现了InterfaceB的B2()方法 abstract void C(); // 我自己定义了一个抽象方法
}
那么要定义一个ClassD继承自AbstractC,则必须:
public class ClassD extends AbstractC{
   public void A2(){} // 我必须实现InterfaceA中未被实现的A2()方法
   public void B1(){} // 我必须实现InterfaceB中未被实现的B1()方法
   void C(){} // 我必须实现AbstractC中未被实现的C()方法
}
Java中类继承、接口实现的一些要注意的细节问题的更多相关文章
- Java中类继承、接口实现的一些细节(长期更新)
		
前言 在Java中,子类继承父类,类实现接口是属于常识性的内容了,作为一个Java程序员应该也比较熟悉.不过子类继承父类,类实现接口中还是有一些小细节值得注意一下,本文就从个人工作.学习中入手,总结一 ...
 - java中类继承,到底继承了什么?
		
继承的最大好处就是为了实现代码的复用.那么,子类到底从父类得到的什么呢? 实例成员 父类的private成员不会被子类继承,子类不能访问.但是子类对象的确包含父类的私有成员. 父类的 包访问成员 继承 ...
 - Java中类和接口
		
很形象的接口的使用——针对初学者 里氏代换原则是什么?听起来很高深,不过我们也不是什么学院派,就不讲大道理了,直接拿个例子来说一下. 我们拿人和程序员举个例子.人是一个大类,程序员是继承自人的子类.看 ...
 - Java中类的继承,属性和方法的四种修饰符的作用范围,final关键字,java的三大特点中的2个:封装和多态,以及多态的一个设计模式,模板方法模式(template method)
		
(一)Java中的继承: 关于继承,在Java中类的继承只能是单继承,不像C+++那样灵活,可以多继承,多继承的后果就是各种关系乱套,就相当于一个孩子有2个母亲一样,社会关系的复杂,不利于程序后期的开 ...
 - Java中类的继承深入剖析
		
在Java开发中,我们常常用到继承这一概念,可以说继承是Java这类面向对象编程语言的基石.正是有了继承这个概念,使得我们可以创建分等级层次的类.今天小编就和大家一起来深入聊聊Java语言的继承. 在 ...
 - Java之继承、抽象类、接口篇
		
一.继承(extends) 什么是继承? 继承是对现实生活中的"分类"概念的一种模拟. 狮子拥有动物的一切基本特性,但同时又拥有自己的独特的特性,这就是"继承" ...
 - java 面对对象(抽象 继承 接口 多态)
		
什么是继承? 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可. 多个类可以称为子类,单独这个类称为父类.超类或者基类. 子类可以直接 ...
 - Java基础10 接口的继承与抽象类
		
链接地址:http://www.cnblogs.com/vamei/archive/2013/03/31/2982240.html 作者:Vamei 出处:http://www.cnblogs.com ...
 - 关于Java中继承多接口同名方法的问题
		
在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样? 动手做实验: interface A{ void fun(); } interface B{ void fun(); ...
 
随机推荐
- Oracle 架构
 - Intellij IDEA自定义类模板和方法模板
			
以Intellij IDEA 2017.3.5为例 定义类模板 依次打开File->Settings->File and Code Templates->Files, 选择class ...
 - Golang教程:循环语句
			
循环语句用于重复执行一段代码. for 语句是 Go 中唯一的循环语句.Go 没有提供其他语言(如 C)中的 while 和 do while 语句. for 语句语法 for 语句的语法如下: fo ...
 - 正排索引(forward index)与倒排索引(inverted index)
			
正常的索引一般是指关系型数据库里的索引. 把不同的数据存放到不同的字段中.如果要实现baidu或google那种搜索,就需要与一条记录的多个字段进行比对,需要 全表扫描,如果数据量比较大的话,性能就很 ...
 - C++Array类模板编写笔记
			
C++Array类模板 函数模板和类模板都属于泛型技术,利用函数模板和类模板来创建一个具有通用功能的函数和类,以支持多种不同的形参,从而进一步简化重载函数的函数体设计. 声明方法:template&l ...
 - C#基础知识-使用XML完成一个小程序(十一)
			
上一篇中讲到XML基本的结构,还有增删改查的方法,这一篇中我们就来利用XML来完成一个简单的订单系统,主要是实现一个简单学生名单的增删改查,如果想要应用到实际的环境中建议考虑数据量的问题,如果数据量大 ...
 - OOP 第一章作业总结
			
程序设计结构分析 类图分析 第一次作业 由于第一次作业完成的功能比较简单,而且出于对面向对象设计理念不熟悉(其实现在也不是很熟悉,逃),整个程序设计的非常简单.通过类图(见下)可以看出,程序只有两个类 ...
 - HttpResponse  Entity的处理(将字符数组转为JSON)
			
1.问题背景 调用高德的IP地址查询接口,获取的返回值为字符串数组(如下); 因为这里只是纯字符串,并不是真正的数组,无法直接取值,所以想到看能不能转为数组或者JSON再进行取值. 2.解决: 通过在 ...
 - Light OJ 1422 - Halloween Costumes(区间DP 最少穿几件)
			
http://www.cnblogs.com/kuangbin/archive/2013/04/29/3051392.html http://www.cnblogs.com/ziyi--caolu/a ...
 - FastJson 常见问题
			
一.场景 在使用序列化的时候,Object里包含了两个一模一样的对象,所以解析的时候,只有第一个能解析出来,另外一个无法显示. 查看了json的序列化源码,发现是DisableCircularRefe ...