抽象类 
什么是抽象类 
被abstract修饰的类就是抽象类。抽象类是类的进一步抽象,抽象类中的方法可以不做具体的实现(抽象方法,由abstract修饰)。抽象类中也可以有普通方法。
抽象方法不能由static和final修饰,因为抽象方法要被子类重写。
抽象类中不一定要有抽象方法,但是有抽象方法的类一定是抽象类。
抽象类不能实例化,但可以引用其子类对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 abstract  class  Animal   {    public  String name;          public  Animal (String name)   {         this .name = name;     }          public  abstract  void  eat ()  ; } class  Dog  extends  Animal   {    public  Dog (String name)   {         super (name);     }     @Override      public  void  eat ()   {         System.out.println(this .name+"正在吃狗粮" );     } } public  class  Demo1   {    public  static  void  main (String[] args)   {                  Animal animal = new  Dog("旺旺" );                  animal.eat();     }      } 
 
执行结果:旺旺正在吃狗粮
为什么需要抽象类 
抽象类中的方法可以不做具体实现,为了子类能够继承该抽象类。使用抽象类能够多一层编译器校验,增加了安全性。就像常量用final修饰,不小心修改时编译器会报错提醒。
像上面的代码main方法中new Dog改成new Animal,编译器就会报错:‘Animal’ is abstract; cannot be instantiated。
接口 
什么是接口 
接口是多个类的公共规范,是一种引用数据类型。接口可以理解为一种功能、特性,类实现某个接口,便可以具备某种功能。
接口中的方法默认是由public abstract修饰,接口中的属性默认是public final static。建议接口中的方法和属性不加任何修饰符号, 保持代码的简洁性.
接口不能实例化。
接口中不能有静态代码块和构造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 interface  Running  {    void  run ()  ;  } interface  Flying  {    void  fly ()  ; } abstract  class  Animal   {    public  String name;          public  Animal (String name)   {         this .name = name;     }          public  abstract  void  eat ()  ; } class  Dog  extends  Animal  implements  Running   {    public  Dog (String name)   {         super (name);     }     @Override      public  void  eat ()   {         System.out.println(this .name+"正在吃狗粮" );     }          @Override      public  void  run ()   {         System.out.println(this .name+"正在扑向他的主人" );     } } class  Bird  extends  Animal  implements  Flying  {         public  Bird (String name)   {         super (name);     }          @Override      public  void  eat ()   {         System.out.println(this .name+"正在觅食" );     }          @Override      public  void  fly ()   {         System.out.println(this .name+"正在天空中自由地翱翔" );     } } public  class  Demo1   {    public  static  void  main (String[] args)   {         Dog dog = new  Dog("旺旺" );         dog.eat();         dog.run();         Bird bird  = new  Bird("飞儿" );         bird.eat();         bird.fly();              } } 
 
执行结果:
旺旺正在吃狗粮 
旺旺正在扑向他的主人 
飞儿正在觅食 
飞儿正在天空中自由地翱翔
为什么需要接口 
Java不允许多重继承,通过接口可以提供多重继承的大部分好处,同时还能避免多重继承的复杂性和低效性。
接口的使用实例 
Comparable接口 
对数组元素按年龄排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import  java.util.Arrays;class  Student  implements  Comparable <Student >  {    public  String name;     public  int  age;     public  Student (String name, int  age)   {         this .name = name;         this .age = age;     }     @Override      public  String toString ()   {         return  "Student{"  +                 "name='"  + name + '\''  +                 ", age="  + age +                 '}' ;     }          @Override      public  int  compareTo (Student o)   {                  return  this .age-o.age;     } } public  class  Compare   {    public  static  void  main (String[] args)   {         Student[] students = new  Student[]{                 new  Student("panghu" ,20 ),                 new  Student("xiaofu" ,18 ),                 new  Student("daxiong" ,19 ),                 new  Student("jingxiang" ,16 )         };         Arrays.sort(students);         System.out.println(Arrays.toString(students));     } } 
 
执行结果:
[Student{name=‘jingxiang’, age=16}, Student{name=‘xiaofu’, age=18}, Student{name=‘daxiong’, age=19}, Student{name=‘panghu’, age=20}]
上面代码有一个问题,只能按年龄排序,如果想按姓名排序就要修改compareTo方法,修改后又只能按姓名排序。有没有一种办法,可以实现按不同的属性进行排序。利用比较器可以实现该要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import  java.util.Arrays;import  java.util.Comparator;class  Student1   {    public  String name;     public  int  age;     public  Student1 (String name, int  age)   {         this .name = name;         this .age = age;     }     @Override      public  String toString ()   {         return  "Student{"  +                 "name='"  + name + '\''  +                 ", age="  + age +                 '}' ;     } } class  AgeComparator  implements  Comparator <Student1 >  {    @Override      public  int  compare (Student1 o1, Student1 o2)   {         return  o1.age-o2.age;     } } class  NameComparator  implements  Comparator <Student1 >  {    @Override      public  int  compare (Student1 o1, Student1 o2)   {         return  o1.name.compareTo(o2.name);     } } public  class  Compare1   {    public  static  void  main (String[] args)   {         Student1[] students = new  Student1[]{                 new  Student1("panghu" ,20 ),                 new  Student1("xiaofu" ,18 ),                 new  Student1("daxiong" ,19 ),                 new  Student1("jingxiang" ,16 )         };         AgeComparator ageComparator = new  AgeComparator();         NameComparator nameComparator = new  NameComparator();                  Arrays.sort(students,ageComparator);         System.out.println("按年龄" +Arrays.toString(students));                  Arrays.sort(students,nameComparator);         System.out.println("按姓名" +Arrays.toString(students));     } } 
 
执行结果:
按年龄[Student{name=‘jingxiang’, age=16}, Student{name=‘xiaofu’, age=18}, Student{name=‘daxiong’, age=19}, Student{name=‘panghu’, age=20}] 
按姓名[Student{name=‘daxiong’, age=19}, Student{name=‘jingxiang’, age=16}, Student{name=‘panghu’, age=20}, Student{name=‘xiaofu’, age=18}]
Clonable接口 
实现Clonable接口需要重写Object类的clone()方法,在方法中使用super关键字调用Object类的clone()方法,然后调用该方法即可实现克隆。
浅拷贝:仅仅拷贝当前对象本身,不拷贝引用类型。 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class  Phone  {    public  String phone; } class  Person  implements  Cloneable  {    public  int  age;     Phone p = new  Phone();     @Override      protected  Object clone ()  throws  CloneNotSupportedException  {         return  super .clone();     }     @Override      public  String toString ()   {         return  "Person{"  +                 "age="  + age +                 ", p.phone="  + p.phone +                 '}' ;     } } public  class  Demo   {    public  static  void  main (String[] args)  throws  CloneNotSupportedException  {         Person person = new  Person();         person.age=20 ;         person.p.phone="xiaomi" ;         Person person2 = (Person)person.clone();         person2.age=10 ;         person2.p.phone="iphone" ;         System.out.println(person);         System.out.println(person2);     } } 
 
深拷贝:不仅拷贝当前对象,还拷贝其引用类型。
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class  Phone  implements  Cloneable  {    public  String phone;     @Override      protected  Object clone ()  throws  CloneNotSupportedException  {         return  super .clone();     } } class  Person  implements  Cloneable  {    public  int  age;     Phone p = new  Phone();     @Override      protected  Object clone ()  throws  CloneNotSupportedException  {         Person tmp = (Person) super .clone();         tmp.p= (Phone) this .p.clone();         return  tmp;     }     @Override      public  String toString ()   {         return  "Person{"  +                 "age="  + age +                 ", p.phone="  + p.phone +                 '}' ;     } } public  class  Demo1   {    public  static  void  main (String[] args)  throws  CloneNotSupportedException  {         Person person = new  Person();         person.age=20 ;         person.p.phone="xiaomi" ;         Person person2 = (Person)person.clone();         person2.age=10 ;         person2.p.phone="iphone" ;         System.out.println(person);         System.out.println(person2);     } }