抽象类:并不是所有对象的类都是用来描述对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类叫做抽象类。比如:Animal类,他是一个动物类,而动物有很多中,有猫有狗,你不知道他到底是具体哪一种动物。
//抽象类:被abstract修饰的类
public abstract class Animal {
//抽象方法:被abstract修饰的方法,没有方法体
// 如果一个方法你不想写具体的实现可以使用抽象方法
public abstract void eat();
abstract public void play();
//第二种方法,abstract写在访问权限符前面,可能编译器不会报错,但可读性不好,推荐第一种
//普通方法
public void sleep(){
System.out.println("在睡觉");
}
//属性
public String name;
}
1.抽象类不可以实例化自己;
虽然抽象类不可以实例化自己,但是他和普通类一样依然可以进行向上转型
public class Test {
public static void Eat(Animal animal){
animal.eat();
}
public static void main(String[] args) {
Dog dog1 = new Dog();
Animal animal=dog1;
Dog dog2 = new Dog();
Eat(dog2);
Eat(dog2);
//匿名对象
Eat(new Dog());
Eat(new Dog());
}
}
2.抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则编译器会报错,但如果子类也是抽象类,那么其子类可以不对父类中的抽象类进行重写
3.抽象类和抽象方法不能被private,抽象类就是用来被继承的并且子类要对抽象方法进行重写,如果被private修饰,那么抽象类将无法被继承,这没有意义,子类也不能重写抽象方法;
4.同理,抽象类和抽象方法也不能被static和final修饰,但抽象类中的普通方法可以被这些修饰
5. 抽象类中不一定包含抽象方法,但是有抽象方法一定是抽象类;
6.抽象类中可以有构造方法,供子类对象时,初始化父类成员变量。
既然抽象类本身不可以实例化,那么他有什么作用?
但是普通类也是可以被继承的?为什么还要用抽象类和抽象方法呢?
接口:公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。例如:电源插座插孔上,可以插:电脑、电风扇、充电器等所有符合规范的设备。
语法规则
将class关键字换成interface来定义一个接口
public interface 接口名称{ ..... }
接口不能直接使用,必须要有一个“实现类”来“实现”该接口,实现该接口的所有抽象方法。
通过implements来实现类与接口的关系
public class 类名称 implements 接口名称{ .... }
代码示例:
实现笔记本电脑使用USB鼠标、USB键盘: 1.USB接口:包含打开、关闭设备; 2.鼠标接口:实现USB接口,并具备点击功能; 3.键盘类:实现USB接口,并具备输入功能; 4.笔记本类:包含开机、关机功能,使用USB设备。
//USB接口
public interface USB {
void openDevice();
void closeDevice();
}
//鼠标类,实现接口
public class Mouse implements USB{
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("点击鼠标");
}
}
//键盘类,实现接口
public class KeyBoard implements USB{
@Override
public void openDevice() {
System.out.println("打开键盘");
}
@Override
public void closeDevice() {
System.out.println("关闭键盘");
}
public void inPut(){
System.out.println("输入键盘");
}
}
//笔记本类,使用接口
public class Computer {
public void open(){
System.out.println("开机");
}
public void close(){
System.out.println("关机");
}
//使用USB功能
public void useUSBDevice(USB usb){
usb.openDevice();
//使用鼠标功能
if(usb instanceof Mouse){
//向下转型
Mouse mouse=(Mouse)usb;
mouse.click();
} else{//使用键盘
KeyBoard keyBoard=(KeyBoard)usb;
keyBoard.inPut();
}
usb.closeDevice();
}
}
//测试
public class Test {
public static void main(String[] args) {
Computer computer=new Computer();
computer.open();
computer.useUSBDevice(new KeyBoard());
computer.useUSBDevice(new Mouse());
computer.close();
}
}
public interface IAnimal {
int a=3;
public static final int b=3;
}
public abstract void eat();
abstract void eat2();
public void eat1();
void eat4();//推荐这一种,更简洁
default void sleep(){
System.out.println("在睡觉");
}
static void sleep1(){
System.out.println("在睡觉");
}
public class Cat implements IAnimal {
@Override
public void eat4() {
System.out.println("吃猫粮");
}
}
abstract class KeyBoard implements USB{
}
为什么要实现多个接口?
在下面的代码中,有父类:动物类,子类:狗类和鸟类。我们知道狗会跑,鸟会飞。那我们是否可以将跑和飞这项特性写到动物类中呢?
答案是:不可以。父类是他们共性的集合,而鸟不会跑,而狗又不会飞。那应该怎么办呢?
//父类:动物类
public abstract class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
}
//子类:狗类
public class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"吃狗粮");
}
public void run(){
System.out.println(this.name+"会跑");
}
}
//子类:鸟类
public class Bird extends Animal{
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"吃虫子");
}
public void fly(){
System.out.println(this.name+"会飞");
}
}
我们知道,在Java中,类和类之间是单继承,一个类只能有一个父类,无法实现多继承,但是一个类可以实现多个接口。
//父类
public abstract class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
}
//子类
public class Dog extends Animal implements IRun{
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"吃狗粮");
}
@Override
public void run(){
System.out.println(this.name+"会跑");
}
}
public class Bird extends Animal implements IFly{
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"吃虫子");
}
public void fly(){
System.out.println(this.name+"会飞");
}
}
public class Duck extends Animal implements IRun,IFly{
public Duck(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"吃鸭食");
}
@Override
public void fly() {
System.out.println(this.name+"会飞");
}
@Override
public void run() {
System.out.println(this.name+"会跑");
}
}
//接口
public interface IFly {
void fly();
}
public interface IRun {
void run();
}
测试类
上述代码展现了一个类继承一个父类实现多个接口。
实现多个接口的好处:其解决了不能多继承的问题。有了接口之后,可以不必再关注类的使用者具体类型,而只关注某个类是否具备某种能力就好。
接口与接口之间也可以实现extends(扩展)关系
在Java中,类和类之间是单继承的,一个类可以实现多个接口,而接口与接口可以是多继承的,用接口可以达到多继承的目的。
interface IA{
void a();
}
interface IB{
void b();
}
interface IC extends IA,IB{
void c();
}
class ID implements IC{
@Override
public void a() {
}
@Override
public void b() {
}
@Override
public void c() {
}
}
作用:自定义类的比较
public class Test {
public static void main1(String[] args) {
Student stu1=new Student(16,"张三");
Student stu2=new Student(20,"李四");
//compareTo的调用
//stu1相当于compareTo中的this,stu2相当于o
System.out.println(stu1.compareTo(stu2));
}
}
public class Student implements Comparable<Student> {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
//对Compareable接口中的compareTo方法进行重写
//年龄的比较
@Override
public int compareTo(Student o) {
/* //比较年龄
//大于返回1;
if(this.age>o.age){
return 1;
}
//小于返回-1
else if(this.age<o.age){
return -1;
}
//等于返回o
else{
return 0;
}*/
//简化
return this.age-o.age;
}
===========================================
//如果进行姓名的比较,对上述重写方法需要进行改写
@Override
public int compareTo(Student o) {
//姓名是引用类型
return this.name.compareTo(o.name);
}
}
缺陷:比较固定的比较,不够灵活
这是用于两个自定义类之间的比较,如果是多个对象呢?
数组中有一个sort方法,是否可以直接使用?
public class Student implements Comparable<Student> {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
public class Test {
public static void main(String[] args) {
Student[] stus=new Student[3];
stus[0]=new Student(16,"a");
stus[1]=new Student(20,"b");
stus[2]=new Student(14,"c");
//排序
Arrays.sort(stus);
//打印排序后的数组内容
System.out.println(Arrays.toString(stus));
}
出现了类型转换异常的情况
sort需要进行Comparable强制类型转换,并用到其中的compareTo方法
正确代码如下:
public class Test {
public static void main(String[] args) {
Student[] stus=new Student[3];
stus[0]=new Student(16,"b");
stus[1]=new Student(20,"c");
stus[2]=new Student(14,"a");
//排序
Arrays.sort(stus);
//打印排序后的数组内容
System.out.println(Arrays.toString(stus));
}
}
public class Student implements Comparable<Student> {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
//比较名字
return this.name.compareTo(o.name);
}
}
作用: 解决CompareTo缺陷,可以根据不同属性进行比较,不用重新修改。
public class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
public class Test {
public static void main(String[] args) {
Student stu1=new Student(16,"张三");
Student stu2=new Student(20,"李四");
//两个之间
//年龄
AgeComparator age=new AgeComparator();
System.out.println(age.compare(stu1,stu2));
//姓名
NameComparator name=new NameComparator();
System.out.println(name.compare(stu1,stu2));
//数组
Student[] stus=new Student[3];
stus[0]=new Student(16,"b");
stus[1]=new Student(20,"c");
stus[2]=new Student(28,"a");
//年龄排序
Arrays.sort(stus,age);
System.out.println(Arrays.toString(stus));
//姓名排序
Arrays.sort(stus,name);
System.out.println(Arrays.toString(stus));
}
}
作用:对对象进行拷贝
//实现Cloneable接口
public class Animal implements Cloneable{
public int age;
public String name;
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Animal{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
//重写clone方法
@Override
protected Object clone()
throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String[] args)
//处理异常
throws CloneNotSupportedException{
Animal animal=new Animal(2,"动物");
Animal animal2=(Animal) animal.clone();
System.out.println(animal2.toString());
}
}
克隆的实现: