接口与抽象类,全解

(学习留存,如有侵权,请告知,立刻删除!)

1. Java抽象类可以有构造函数吗?

可以有,抽象类可以声明并定义构造函数。因为你不可以创建抽象类的实例,所以构造函数只能通过构造函数链调用(Java中构造函数链指的是从其他构造函数调用一个构造函数),例如,当你创建具体的实现类。现在一些面试官问,如果你不能对抽象类实例化那么构造函数的作用是什么?好吧,它可以用来初始化抽象类内部声明的通用变量,并被各种实现使用。另外,即使你没有提供任何构造函数,编译器将为抽象类添加默认的无参数的构造函数,没有的话你的子类将无法编译,因为在任何构造函数中的第一条语句隐式调用super(),Java中默认超类的构造函数。

2. Java抽象类可以实现接口吗?它们需要实现所有的方法吗?

可以,抽象类可以通过使用关键字implements来实现接口。因为它们是抽象的,所以它们不需要实现所有的方法。好的做法是,提供一个抽象基类以及一个接口来声明类型 。这样的例子是,java.util.List接口和相应的java.util.AbstractList抽象类。因为AbstractList实现了所有的通用方法,具体的实现像LinkedList和ArrayList不受实现所有方法的负担,它们可以直接实现List接口。这对两方面都很好,你可以利用接口声明类型的优点和抽象类的灵活性在一个地方实现共同的行为。Effective Java有个很好的章节,介绍如何使用Java的抽象类和接口,值得阅读。

3. Java抽象类可以是final的吗?

不可以,Java抽象类不能是final的。将它们声明为final的将会阻止它们被继承,而这正是使用抽象类唯一的方法。它们也是彼此相反的,关键字abstract强制继承类,而关键字final阻止类被扩张。在现实世界中,抽象表示不完备性,而final是用来证明完整性。底线是,你不能让你的Java类既abstract又final,同时使用,是一个编译时错误。

4. Java抽象类可以有static方法吗?

可以,丑娘类可以声明并定义static方法,没什么阻止这样做。但是,你必须遵守Java中将方法声明为static的准则,因为在面向对象的设计中是不受欢迎的,因为Java中的static方法是不可以被重载的。在抽象类中看到static方法是罕见的,但正如我所说的,如果你有很好的理由这样做的话,那没有什么可以阻止你。

5. 可以创建抽象类的实例吗?

不可以,你不能创建Java抽象类的实例,它们是不完全的。即使你的抽象类不包含任何抽象方法,你也不能对它实例化。将类声明为abstract的,就等你你告诉编译器,它是不完全的不应该被实例化。当一段代码尝试实例化一个抽象类时Java编译器会抛错误。

6. 抽象类必须有抽象方法吗?

不需要,抽象类有抽象方法不是强制性的。你只需要使用关键字abstract就可以将类声明为抽象类。编译器会强制所有结构的限制来适用于抽象类,例如,现在允许创建一些实例。是否在抽象类中有抽象方法是引起争论的。我的观点是,抽象类应该有抽象方法,因为这是当程序员看到那个类并做假设的第一件事。这也符合最小惊奇原则。

7. Java抽象类和接口有何不同?

这是最重要的经典Java面试题之一。我已经记不清多少次看到这个问题了。这个问题有趣的原因是可以举出例子。很容易回答核心OOPS的概念,如抽象,封装,多态和继承,但是,当涉及到微妙点就是这样,候选人往往失手。你可以从本文看出抽象类和接口之间的所有语法的差异。

8. 何时选用抽象类而不是接口?

这是对之前抽象类和接口对比问题的后续。如果你知道语法差异,你可以很容易回答这个问题,因为它们可以令你做出抉择。当关心升级时,因为不可能在一个发布的接口中添加一个新方法,用抽象类会更好。类似地,如果你的接口中有很多方法,你对它们的实现感到很头疼,考虑提供一个抽象类作为默认实现。这是Java集合包中的模式,你可以使用提供默认实现List接口的AbstractList。

9. Java中的抽象方法是什么?

抽象方法是一个没有方法体的方法。你仅需要声明一个方法,不需要定义它并使用关键字abstract声明。Java接口中所有方法的声明默认是abstract的。这是抽象方法的例子

public void abstract printVersion();

现在,为了实现这个方法,你需要继承该抽象类并重载这个方法。

10. Java抽象类中可以包含main方法吗?

是的,抽象类可以包含main方法,它只是一个静态方法,你可以使用main方法执行抽象类,但不可以创建任何实例。

 

1)成员的区别:
        成员变量:
            抽象类:成员变量可以是常量,也可以是变量
            接口:成员变量只能是一常量:存在默认修饰符:public static final
        构造方法:
            抽象类:可以有无参构造,有参构造方法。作用:通过子类进行数据初始化(通过子类创建对象,调用父类的构造方法)
            接口:没有构造方法的
        成员方法的区别:
            抽象类:可以有抽象方法,也可以有非抽象方法
            接口:只能是抽象方法:存在默认修饰符:public abstract

    2)关系的区别:
        类与类的关系:
            继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!
        类与接口的关系:
            实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口
                (class 子实现类名  enxtends Object implements 接口名1,接口名2...)

       接口与接口的关系
            继承关系:extends,可以支持单继承,也可以多继承!

    3)设计理念的区别:
            抽象类:
                体现的是一种"is a"的关系,存在继承关系!(抽象类多态)
            接口:
                体现的是一种"like a"的关系,由于接口的一种扩展功能

 

final和abstract不可以同时修饰一个类。 

final:修饰类代表不可以继承,修饰方法不可重写。

abstract:修饰类就是用来被继承的,修饰方法就是用来被重写的。

static修饰的方法可以用类名调用。对于abstract修饰的方法没有具体的方法实现,所有不能直接调用,也就是说abstract不可以与static共存。

private修饰的只能在本类中使用,abstract方法是用来被子类进行重写的,有矛盾。所有不能共存。

有抽象函数的类,该类一定是抽象类。

抽象类可以没有抽象函数。抽象类可以继承普通类与抽象类。

抽象类不能使用new创建对象。

抽象类中一定有构造函数。主要为了初始化抽象类中的属性。通常由子类实现。

 

接口中的所有属性,默认的修饰符是  public static final。抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认为public static final。抽象类中可以有普通成员变量,而接口中不能有普通成员变量。接口更多的是在系统框架设计方法发挥作用,主要定义模块之间的通信;而抽象类在代码实现方面发挥作用,可以实现代码的重用。

接口中的属性存储在接口的静态存储区域内,不属于该接口。是静态常量。

接口中的所有方法,默认的修饰符是  public abstract。不能用static修饰。也只能是public修饰。

接口中不能含有静态方法。

类实现接口可以通过implements实现,实现接口的时候必须把接口中的所有方法实现,一个类可以实现多个接口。

接口中定义的所有的属性默认是public static final的,即静态常量既然是常量,那么定义的时候必须赋值。

接口中定义的方法可以有参数列表和返回值类型,但是不能有方法体。接口中定义的方法默认添加public abstract。

有抽象函数的不一定是抽象类,也可以是接口类。

由于接口中的方法默认都是抽象的,所以不能被实例化。

对于接口而言,可以使用子类来实现接口中未被实现的功能函数。

如果实现类中要访问接口中的成员,不能使用super关键字。因为两者之间没有显示的继承关系,况且接口中的成员成员属性是静态的。可以使用接口名直接访问。

接口没有构造方法。

类与类之间的关系是继承,接口与类之间是实现关系。接口与接口之间的关系是继承。接口可以多继承接口。接口的作用是拓展。

非抽象类实现接口时,必须把接口里面的所有方法实现。类实现接口用关键字implments,类与接口之间是可以多实现的(即一个类可以实现多个接口)。

多态就是一个对象的多种状态。多态的前提是要有继承关系,要有方法重写,要有父类引用指向子类的对象。父 f = new 子();

当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量。

当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量。

所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。

当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。

当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。

最后说明一点:

很重要啊!

静态方法只能访问静态成员,不可以访问非静态成员。因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。

静态方法中不能使用this,super关键字。因为this代表对象,而静态存在时,有可能没有对象,所以this无法使用;

成员变量是对象的特有属性,静态变量是对象的共享属性,所以成员变量随对象而存在,静态变量随类而存在,成员变量存储在堆内存,静态变量存储在静态方法区内;

一个类在使用之前需要经过:类加载 / 类验证 / 类准备 / 类解析 / 类初始化等工作;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值