javaSE---抽象类和接口

javaSE---抽象类和接口,第1张

javaSE---抽象类和接口

目录

抽象类

接口

接口

接口的实现类

三个常用接口

comparable

comparator

cloneable接口

 深浅拷贝


抽象类

抽象方法:一个没有具体实现的方法,被abstract关键字修饰

关键类:包含抽象方法的类

   abstract class Draw{
        public  abstract void draw() ;
}

抽象方法不能有主体

抽象方法不能实例化

 抽象类中可以包括普通成员

   abstract class Draw{
       int age;
       String name;

    public void print() {
        System.out.println("hi");
    }
        public  abstract void draw() ;
}

抽象类只能被继承,子类必须重写父类里的所有抽象方法(子类如果是抽象类,可以只实现一部分)

 abstract class Draw {
    public abstract  void draw();
}
class Fun extends Draw{
    @Override
    public void draw() {
        System.out.println("hehe");
    }
}
  public class text {
      public static void main(String[] args) {
          Fun fun=new Fun();
          fun.draw();
      }
}

Fun类继承了这个抽象类,并且对这个抽象类的抽象方法进行了重写,实例化子类调用子类中重写的方法

抽象类也可以发生向上转型和动态绑定

abstract class Draw {
    public abstract void draw();
}
class Flower extends Draw{
    @Override
    public void draw(){
        System.out.println("❀");
    }
}
class Square extends Draw{
    @Override
    public void draw(){
        System.out.println("■");
    }
}
class Triangle extends Draw{
    @Override
    public void draw(){
        System.out.println("");
    }
}
public class text {
    public static void Draw(Draw Draw) {
        Draw.draw();
    }
    public static void main(String[] args) {
        Draw(new Flower());
        Draw(new Square());
        Draw(new Triangle());
    }
}

抽象类不能被final修饰

final类是最终类,被final修饰的类不能被继承,而抽象类的作用就是被继承

接口 接口

如果一个类中全部的方法都是抽象的,那么可以将这个类定义为接口

接口是一种特殊的抽象类,它不能包含普通方法,其内部的所有方法都是抽象的

JDK8中,对接口进行了重新定义,接口中除了抽象方法外,还可以有默认方法和静态方法,默认方法使用default修饰,静态方法用static修饰,并且这两个方法都允许有方法体

定义接口,要用interface关键字

interface AI{
        public abstract void fun();
}
 interface AI{
        public abstract void fun();
        default public void print(){//默认方法
            System.out.println("hi");
        }
       public static void sub(){//静态方法
            
        }
}

接口里的所有方法都是public的接口不可以使用new来创建对象接口内部有3种方法,抽象方法,静态方法,默认方法借口内部的成员变量默认类型:public static final,一定要初始化

静态方法可以通过接口名.静态方法名来调用

 interface AI{
        public abstract void fun();
        default public void print(){
            System.out.println("hi");
        }
       public static void sub(){
           System.out.println("ok");
        }
}
public class text {
    public static void main(String[] args) {
        AI.sub();
    }
}

默认方法和抽象方法要通过类的实例化调用

接口的实现类

接口的实现类通过implements关键字实现当前接口,并重写接口的所有抽象方法

 interface AI{
        public abstract void fun();
        default public void print(){
            System.out.println("hi");
        }
       public static void sub(){
           System.out.println("ok");
        }
}
class A implements AI{
    @Override
    public void fun() {
        System.out.println("❀");
    }
}
public class text {
    public static void main(String[] args) {
       A a=new A();
       a.fun();
    }
}

A类实现了AI口,并对AI接口的抽象方法进行了重写,通过对A类的实例化对象可以引用AI接口的成员(除了静态方法)

1.一个类可以实现多个接口

interface AI{
     public abstract void  funA();
}
interface BI{
        public abstract void funB();
}
class A implements AI,BI{
    @Override
    public void funA() {
        System.out.println("❀AI");
    }
    @Override
    public void funB() {
        System.out.println("❀BI");
    }
}

A类继承了AI,BI接口,要对AI,BI的所有抽象方法进行重写  

2.一个类可以继承一个类同时实现多个接口

 interface AI{
     public abstract void  funA();
}
interface BI{
        public abstract void funB();
}
abstract class B{
        abstract void fun();
}
class A extends B implements AI,BI{
    @Override
    public void funA() {
        System.out.println("❀AI");
    }
    @Override
    public void funB() {
        System.out.println("❀BI");
    }
    @Override
    void fun() {
        System.out.println("hi");
    }
}

A类继承了抽象类B,并继承了AI,BI接口,要对B,AI,BI的所有抽象方法进行重写 

3.接口可以扩展一个接口(extends)

 interface AI{
     public abstract void  funA();
}
interface BI extends AI{
        public abstract void funB();
}
class C implements BI{
    @Override
    public void funB() {
        
    }
    @Override
    public void funA() {
        
    }
}

BI接口扩展了AI接口,那么BI接口就会包含了AI接口的成员,C类继承了BI接口,要对BI接口的所有抽象方法重写

三个常用接口 comparable
public class text {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 1};
        System.out.println(Arrays.toString(arr));
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

sort方法实现了数组排序 

class Student {
    int age;
    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 text {
    public static void main(String[] args) {
        Student []student=new Student[3];
        student [0]=new Student(10,"张三");
        student [1]=new Student(9,"李四");
        student [2]=new Student(3,"王五");
        System.out.println(Arrays.toString(student));
        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
    }

 报错原因:不知道按照什么条件来排序

sort方法的源码:发现数组元素被强制转化为comparable

 如何解决:

使用Comparable接口:让类实现这个接口

 进入Comparable接口

 那么正确的实现方法:

实现这个接口并对public int compareTo(T o)方法重写

  @Override
    public int compareTo(Student o) {
        if (this.age > o.age) {
            return 1;
        } else if (this.age == o.age)
            return 0;
        else
            return -1;
    }
//  return this.age-o.age;可以简化
}

 根据年龄比较:

 根据姓名比较:如果使用equals方法, 字符串比较返回值boolean类型,不能强制转化为int

打开String 的源码:

 发现String也调用了这个接口,那么也一定有compareTo(T o)方法,Alt+7找到这个方法:

调用这个方法就可以来比较了 

class Student implements Comparable {
    int age;
    String name;

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public int compareTo(Student o) {
      return this.name.compareTo(o.name);
 
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + ''' +
                '}';
    }
}
public class text {
    public static void main(String[] args) {
        Student[] student = new Student[3];
        student[0] = new Student(10, "张三");
        student[1] = new Student(3, "王五");
        student[2] = new Student(9, "李四");
        System.out.println(Arrays.toString(student));
        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
    }

 但是我们发现,用这个接口,要重写 compareTo()方法,但是这个方法只能有一个,只能按照一种办法来比较,使用comparator接口可以实现多种比较

comparator

sort有许多种参数不同的实现方法,可以看到其中有一个方法参数是comparator

 打开comparator这个接口

 

使用comparator接口可以实现多种比较

class Student  {
    int age;
    String name;
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + ''' +
                '}';
    }
}
class AgeComparator implements Comparator{//类实现了接口

    @Override
    public int compare(Student o1, Student o2) {
        return o1.age-o2.age;
    }
}
class NameComparator implements Comparator{//类实现了接口

    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
public class text {
    public static void main(String[] args) {
        Student[] student = new Student[3];
        student[0] = new Student(10, "张三");
        student[1] = new Student(3, "王五");
        student[2] = new Student(9, "李四");
        System.out.println(Arrays.toString(student));
        AgeComparator ageComparator = new AgeComparator();//实例化类 按照年龄比较
        Arrays.sort(student, ageComparator);//传入参数有两个
        System.out.println(Arrays.toString(student));
        Arrays.sort(student, new NameComparator());
        System.out.println(Arrays.toString(student));
    }
cloneable接口

object类有一个clone方法,使用这个方法可以进行拷贝,但是要调用这个方法,要先实现cloneable接口,否则会报错

 

 打开clone方法

 发现clone()的返回值类型是object,所以进行强制类型转化

 但是仍然有错误,必须实现cloneable接口

 打开cloneable接口

cloneable接口内没有方法体,不需要对接口的内部方法进行重写

没有方法体的接口称之为标志接口,标志接口代表当前这个类是可以被克隆的

但是规定:要求在类中重写clone方法

class Person implements Cloneable{
    int age;
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

 但是这时候发现,仍然有问题:

 点击以下内容,对异常进行声明:

class Person implements Cloneable{
    int age;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class text {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        Person p=(Person) person.clone();
    }
}
 深浅拷贝

代码1:

class Person implements Cloneable{
    int age=9;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class text {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        System.out.println(person);
        Person p=(Person) person.clone();
        System.out.println(p);
        p.age=109;
        System.out.println(person.age);
        System.out.println(p.age);
        System.out.println(person.age);
    }
}

 对person引用的对象的成员信息拷贝之后产生一个副本,p引用了这个新的对象,所以person和p的地址不相同 ,对p的成员改变不会影响person的成员

 

 代码2:

class A{
    int s=78;
}
class Person implements Cloneable{
    int age=9;
    A a=new A();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class text {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        Person p=(Person) person.clone();
        System.out.println(p.a);
        System.out.println(person.a);
    }

 对person引用的对象的成员信息拷贝之后产生一个副本,p引用了这个新的对象,所以person和p的地址不相同

但是因为person引用的对象中,有一个引用成员变量a,现在的代码导致产生的副本和person引用的成员中的变量a,引用了同一个对象

这是一个浅拷贝

代码3:

class A implements Cloneable{
    int s=78;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    int age=9;
    A a=new A();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person p = (Person) super.clone();//先对person克隆
        p.a = (A) a.clone();//对person中a的克隆
        return p;
    }
}
public class text {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();
        Person p=(Person) person.clone();
        System.out.println(p);
        System.out.println(person);
        System.out.println(p.a);
        System.out.println(person.a);
        System.out.println(p.a.s);
        System.out.println(person.a.s);
        p.a.s=90;
        System.out.println(p.a.s);
        System.out.println(person.a.s);
    }
}

对person和a两个引用变量都进行了拷贝

这是一个深拷贝

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5712685.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存