文章目录
抽象类
抽象类的定义
抽象类:在普通类的基础上扩充了一些抽象方法
抽象方法:只声明而没有实现的方法(即没有方法体)
抽象方法和抽象类使用abstract关键字来定义
范例:定义一个抽象类
abstract class Person{
private String name ; // 属性
public String getName(){ // 普通方法
return this.name;
}
public void setName(String name){
this.name = name ;
}
// {}为方法体,所有抽象方法上不包含方法体
public abstract void getPersonInfo() ; //抽象方法
}
抽象类中包含有抽象方法,而抽象方法不包含方法体,即没有具体实现,因此抽象类不能直接产生实例化对象。
对于抽象类的使用原则
1.所有的抽象类必须有子类
2.抽象类的子类覆写抽象类的所有抽象方法(子类不是抽象类),如果子类没有覆写抽象类的所有方法,那么子类也必须是抽象类,否则会报错。【方法覆写一定要考虑权限问题,权限尽量都用public】
3.抽象类的对象可以通过对象多态性利用子类为其实例化
private与abstract不能同时使用。
范例:使用抽类
abstract class Person{
private String name ; // 属性
public String getName(){ // 普通方法
return this.name;
}
public void setName(String name){
this.name = name ;
}
// {}为方法体,所有抽象方法上不包含方法体
abstract void getPersonInfo() ; //抽象方
}
class Student extends Person{
@Override
public void getPersonInfo() {
System.out.println("我是一名学生");
}
}
public class Interview {
public static void main(String[] args) {
Person p=new Student(); //实例化子类,向上转型
p.getPersonInfo();//被子类所覆写的
}
}
范例:抽象类静态方法内部类实现抽象类
abstract class Person{
private String name ; // 属性
public String getName(){ // 普通方法
return this.name;
}
public void setName(String name){
this.name = name ;
}
// {}为方法体,所有抽象方法上不包含方法体
abstract void getPersonInfo() ; //抽象方法
public static Person getIntace(){
class Student extends Person{
@Override
public void getPersonInfo() {
System.out.println("我是一名学生");
}
}
return new Student();
}
}
public class Interview {
public static void main(String[] args) {
Person p=Person.getIntace();
p.getPersonInfo();
}
}
抽象类中允许提供构造方法
范例:这是一个奇怪的代码
abstract class A{
public A(){
this.Print();
}
public abstract void Print();
}
class B extends A{
private int num=10;
public B(){
super();
num=100;
}
@Override
public void Print() {
System.out.println(num);
}
}
public class Interview {
public static void main(String[] args) {
new B();//0
}
}
抽象类中允许不定义抽象方法
抽象类中允许不定义任何的抽象方法,但是此时抽象类依然无法直接创建实例化对象
抽象类一定不能使用final声明
抽象类一定不能使用final声明,因为使用final声明的类不允许有子类;而抽象类必须有子类;相应的,抽象方法也不能使用private定义,因为抽象方法必须要被覆写
内部抽象类和外部抽象类
范例:观察内部抽象类
abstract class A{
public abstract void PrintA();
abstract class B{
public abstract void PrintB();
}
}
class X extends A{
@Override
public void PrintA() {
System.out.println("I am A...");
}
class Y extends B{
@Override
public void PrintB() {
System.out.println("I am B...");
}
}
}
public class Interview {
public static void main(String[] args) {
A a=new X();
a.PrintA();
X x=new X();
X.Y y= x.new Y();
y.PrintB();
}
}
如果现在外部抽象类中使用了static那么就是语法错误,但是内部抽象类允许使用static
接口
在以后的开发过程之中:接口优先(在一个操作既可以使用抽象类又可以使用接口的时候,优先考虑使用接口)
接口的定义
接口是一个抽象方法和全局常量的集合
范例:实现一个接口
interface A{
public static final int i=1;
public abstract void Print();
}
一个子类可以实现多个接口,【可以使用接口来实现多继承的概念】对于接口的子类(不是抽象类)必须覆写接口中的全部抽象方法。随后可以利用子类的向上转型通过实例化子类来得到接口的实例化对象.
范例:一个子类实现多个接口
interface IMessage{
public static final String MSG = "I am a biter" ; // 全局常量
public abstract void print() ; // 抽象方法
}
interface INews {
public abstract String getNews() ;
}
class MessageImpl implements IMessage,INews {
public void print() {
System.out.println(IMessage.MSG) ;
}
public String getNews(){
return IMessage.MSG ; // 访问常量都建议加上类名称
}
}
public class Interview {
public static void main(String[] args) {
IMessage m = new MessageImpl() ; //子类向上转型,为父接口实例化对象
m.print() ; // 调用被子类覆写过的方法
INews n = (INews) m ;
System.out.println(n.getNews()) ;
}
}
接口使用限制
1.接口中只允许public权限。(不管是属性还是方法,其权限都是public)
阿里编码规约:接口中的方法和属性不要加任何修饰符号,public也不要加,保持代码的简洁性.
2.当一个子类即需要实现接口又需要继承抽象类时,请先使用extends继承一个抽象类,而后使用implements实现多个接口。
3.一个抽象类可以使用implements实现多个接口,但是接口不能继承抽象类。
4.一个接口可以使用extends继承多个父接口。
范例:一个接口继承多个接口
interface A {
public void printA() ;
interface B {
public void printB() ;
}
interface C extends A,B { // 接口多继承
public void printC() ;
}
class Impl implements C{
public void printA() {}
public void printB() {}
public void printC() {}
}
public class Test{
public static void main(String[] args) {
}
}
5.接口可以定义一系列的内部结构,包括:内部的普通类,内部抽象类,以及内部接口,其中使用static定义的内部接口就相当于是一个外部接口!
范例:使用static定义的内部接口
interface A {
public void printA() ;
static interface B {
public void printB() ; // 使用static定义,描述一个外部接口
}
}
class Impl implements A.B {
public void printB() {}
}
public class Test{
public static void main(String[] args) {
}
}
抽象类和接口的区别
编程角度
抽象类:是一种类的继承关系,一个子类只能继承一个父类
接口:是一种实现关系,一个类可以实现多个接口
设计角度
抽象类:是一种继承关系,要想使继承关系合理,父类和子类概念基本一致,存在“is-a”关系。(模板模式)
接口:接口和子类之间不要求概念一致,类只要实现与接口之间定义的契约。(工厂模式)
语法角度
1.抽象类由普通方法和抽象方法组成,接口由抽象方法和全局常量组成(接口中只有public权限,抽象方法不能是静态的和私有的,因为要被实现)
2.一个抽象类可以实现若干个接口,接口不能继承抽象类,但是接口可以使用extends关键字继承多个父接口
3.一个子类只能继承一个抽象方法,一个子类可以继承多个接口
4.抽象方法既可以做方法申明也可以实现方法,接口只能申明方法
4.都不可以实例化对象,但是可以指向实现它们类的实例化
JDK8 接口定义加强
- 可以使用default来定义普通方法,需要通过对象调用
- 可以使用static来定义静态方法,通过接口名就可以调用。
范例:定义普通方法
package www.bit.java.testdemo;
interface IMessage {
public default void fun() { // 追加了普通方法,有方法体了
System.out.println("Hello IMessage");
}
public void print() ;
}
class MessageImpl implements IMessage {
@Override
public void print() {
System.out.println("Hello MessageImpl");
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage message = new MessageImpl() ;
message.print();
message.fun();
}
}
范例:定义static方法
package www.bit.java.testdemo;
interface IMessage {
public default void fun() { // 追加了普通方法,有方法体了
System.out.println("Hello IMessage");
}
// 可以直接由接口名称直接调用
public static IMessage getInstance() {
return new MessageImpl() ;
}
public void print() ;
}
class MessageImpl implements IMessage {
@Override
public void print() {
System.out.println("Hello MessageImpl");
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage message = IMessage.getInstance() ;
System.out.println(message);
message.print();
message.fun();
}
}