Rumah > Java > javaTutorial > Cara menggunakan kelas dan antara muka abstrak Java

Cara menggunakan kelas dan antara muka abstrak Java

WBOY
Lepaskan: 2023-05-16 09:58:12
ke hadapan
973 orang telah melayarinya

Apakah kelas abstrak?

Apakah kelas abstrak? Seperti namanya, kelas abstrak adalah sangat abstrak, iaitu, apabila kita tidak mempunyai maklumat yang mencukupi untuk menerangkan kelas ini, kita tidak perlu menerangkan kelas tersebut.

Gunakan kod untuk memberi contoh:

class Shape {
    public void draw() {
        System.out.println("我要画图形!!");
    }
}
class circle extends Shape {
    @Override
    public void draw() {
        System.out.println("我要画圆形!!!");
    }
}
class rect extends Shape {
    @Override
    public void draw() {
        System.out.println("我要画矩形!!!");
    }
}
public class TestDemo3 {
    public static void drawShape(Shape shape) {
        shape.draw();
    }
    public static void main(String[] args) {
        drawShape(new circle());
        drawShape(new rect());
    }
}
Salin selepas log masuk

Hanya gunakan kes kecil ini untuk menyemak polimorfisme Kami mencipta kelas induk Shape, dan kemudian mencipta dua subkelas yang dipanggil kelas rect dan kelas bulatan gunakan kaedah yang sama menggunakan dua kelas ini, bentuk yang terhasil adalah berbeza Ini adalah polimorfisme, tetapi

kita dapati bahawa saya hanya menggunakan dua subkelas ini untuk melukis grafik, iaitu bulatan Untuk bentuk dan segi empat tepat, I tidak memanggil kelas induk untuk melaksanakan kaedah ini. ? ? Oleh kerana kelas induk ini tidak dapat melukis grafik, maka pelaksanaan kaedah cabutan kelas induk ini tidak berguna saya hanya memerlukan kelas induk untuk mempunyai kaedah ini dan menulis semula melalui subkelas Tidak perlu untuk kelas induk pelaksanaan tertentu.

Ya, ini memperkenalkan kita kepada kelas abstrak tema hari ini

Kaedah cabutan kelas induk di atas tidak berguna kerana pelaksanaannya yang khusus, jadi kita tidak perlu menulisnya, iaitu mengapa Selaras dengan definisi kelas abstrak, apabila tidak ada maklumat yang mencukupi untuk menerangkannya, maka kami memanggilnya kelas abstrak.

Sintaks kelas abstrak

Jika kaedah cabutan kelas induk di atas tidak mempunyai pelaksanaan khusus, kita boleh memanggilnya kaedah abstrak. Gunakan abstrak untuk mengubah suai

public abstract void draw();
Salin selepas log masuk

Cara menggunakan kelas dan antara muka abstrak Java

, tetapi mengapa ralat akan dilaporkan? ?

Sebabnya kaedah yang diubah suai oleh abstrak dipanggil kaedah abstrak Jika terdapat kaedah abstrak dalam kelas, maka kelas itu mestilah kelas abstrak, jadi kelas itu juga mesti diubah suai dengan abstrak.

Cara menggunakan kelas dan antara muka abstrak Java

Tetapi sebaliknya, adakah sudah pasti kaedah abstrak dalam kelas abstrak? ? ?

Cara menggunakan kelas dan antara muka abstrak Java

Pengkompil tidak akan melaporkan ralat, jadi jawapannya tidak semestinya kelas abstrak boleh mempunyai kaedah abstrak atau tidak.

Bolehkah kelas abstrak dijadikan instantiated? ? ?

Cara menggunakan kelas dan antara muka abstrak Java

Jadi, kelas abstrak tidak boleh dibuat seketika.

Bolehkah kelas abstrak mentakrifkan pembolehubah ahli, kaedah dan pembina seperti kelas biasa? ? ?

Cara menggunakan kelas dan antara muka abstrak Java

Perbezaan antara kelas abstrak dan kelas biasa ialah kelas abstrak tidak boleh dibuat instantiated takrifan lain bagi pembolehubah ahli, kaedah ahli, pembina, dsb.

Memandangkan kelas abstrak tidak boleh dijadikan instantiated, apakah maksud kewujudannya? ? ?

Pemikiran Lao Tie masuk akal Sebenarnya, makna terbesar kelas abstrak adalah untuk diwarisi, kerana kelas abstrak tidak boleh membuat instantiat objek dan hanya boleh bergantung pada subkelas untuk mengatasi kaedah kelas induk (iaitu, abstrak. kelas).

Bagaimana untuk mewarisi kelas abstrak? ? ? Apakah perkara yang perlu diberi perhatian? ? ?

Cara menggunakan kelas dan antara muka abstrak Java

Mengapa pewarisan menjadi salah seperti ini? ? Sebabnya ialah apabila subkelas mewarisi kelas abstrak, subkelas perlu mengatasi semua kaedah kelas induk atau subkelas perlu diubah suai dengan abstrak (kelas abstrak diwarisi oleh kelas abstrak atau subkelas mengatasi semua kaedah kelas abstrak (kelas induk)) .

Cara menggunakan kelas dan antara muka abstrak Java

Itu sahaja.

Cara menggunakan kelas dan antara muka abstrak Java

Juga ambil perhatian di sini bahawa apabila kita tidak mengatasi kaedah kelas induk tetapi menggunakan abstrak untuk mengubah suainya, inilah yang berlaku apabila anda mewarisi subkelas ini semula menjadi kelas induk, dan subkelas seterusnya mesti terus menulis semula kaedah kelas induk ini dan kaedah kelas induk kelas induk ini.

Bolehkah kaedah abstrak diubah suai secara statik dan muktamad? ? ?

Cara menggunakan kelas dan antara muka abstrak Java

Kaedah abstrak tidak boleh diubah suai secara statik dan muktamad, kerana subkelas mesti mengatasi kaedah kelas induk dan kelayakan pengubahsuaian akses boleh diabaikan .

Ringkasan kelas abstrak:

  • Kami memanggil kelas yang tidak dapat menerangkan objek dengan cukup jelas sebagai kelas abstrak.

  • Kaedah yang diubah suai oleh abstrak dipanggil kaedah abstrak, dan kelas yang diubah suai oleh abstrak dipanggil kelas abstrak

  • Kaedah abstrak mestilah dalam kelas abstrak , maksudnya, selagi terdapat kaedah abstrak, nama kelas juga mesti diubah suai dengan abstrak Sebaliknya, kelas abstrak mungkin tidak mempunyai kaedah abstrak, atau ia mungkin mempunyai kaedah abstrak.

  • 抽象类不能实例化,除了不能实例化之外其他与普通类一样可以定义成员变量,成员方法,构造方法等。同时构造方法和类方法(被static修饰的方法)不能被abstract来修饰

  • 抽象方法的访问修饰限定符不能是private,如果省略默认是public,同时抽象方法不能被final修饰。

  • 子类继承抽象类的时候,子类必须重写抽象类的所有方法并且要有方法的具体实现,如果重写那子类还是抽象类,必须用abstract来修饰。

  • 抽象类中的方法没有具体实现,要通过子类重写在子类中实现。

  • 一个类只能继承一个抽象类

接口

说到接口我们会想到什么呢???我一开始想到的就是充电接口插排等等,比如充电接口,只要符合那个插口的标准,我们都可以使用那个接口来进行充电。这就是把标准进行统一起来,然后大家就可以根据不同的标准来使用不同的接口,比如苹果手机与安卓手机的手机接口就是不一样的,他们就是两种不同的标准,安卓手机用安卓的接口,苹果用苹果的接口这就将标准统一起来。

而在Java中也是一样的,我们把这个标准或者可以说是一种公共的规范叫做接口,只要符合这一接口的标准我们就可以使用它。

听着这抽象的概念你可能现在还是不太明白这到底是什么,我在来拿代码举个例子:

class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"吃饭***!");
    }
}
Salin selepas log masuk

这里我定义了一个动物类,这个动物有名字,年龄,还有吃饭的行为。

class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println(this.name+"吃饭***!");
    }
    public void swim() {
        System.out.println("我要游泳~~~~");
    }
}
class Fish extends Animal {
}
Salin selepas log masuk

接着我又定义了一个鱼类(子类)继承这个动物类(父类),我想让这个鱼有这个游泳的行为,但是这就会有一个问题,在父类定义了一个swim方法,接着我还要定义很多类,难道所有的类都要有这个游泳的行为么???答案是不可以的。所以我们就不能把这个swim方法定义在父类里面,那我们就可以把这个方法定义在子类(鱼类)里面,这样就符合了,但是如果我还要定义1000个动物都会游泳难道都要在自己类中写这个游泳的方法么??这样做显然是不可行的。那我们该怎么做呢??

我们可以就提供一个公共的接口,这也是一种标准,只要符合这一标准都可以使用这个接口或者可以说可以实现这一功能。

看了上面的引例我们应该接口是干什么的了,接下来我们来学一下接口的语法。

怎么定义接口

定义接口要使用interface关键字:

//创建一个接口
//创建接口要是用interface关键字  接口的命名最好是形容词其他的也可以
interface IFlying{
    //这就是一个flying接口
}
Salin selepas log masuk

接口中的成员变量:

Cara menggunakan kelas dan antara muka abstrak Java

这样会报错,接口中的成员变量都是常量,所以必须初始化,接口中的成员变量会被隐式指定为public static final 修饰的。

interface IFlying{
    //接口中的成员变量默认都是被public static final修饰的常量
    //这里的成员变量不可改变
   public static final int a =10;
}
Salin selepas log masuk

接口中的成员方法:

Cara menggunakan kelas dan antara muka abstrak Java

interface IFlying{
    //接口中的成员方法都是抽象方法,默认是public abstract 
    //其中public abstract 可以被省略
    //接口中的成员方法不能有具体的实现
    public abstract void eat();
    //一般就写成:
    //void eat();
    default void sleep(){
        //接口中的方法想要具体实现,要加上default修饰
    }
    //接口中可以有静态方法的具体实现
    public static void method() {
        System.out.println("我是静态的方法!!");
    }
}
Salin selepas log masuk

接口能否实例化???

Cara menggunakan kelas dan antara muka abstrak Java

接口是不能被实例化的。

怎么使用接口???

实现的接口如下:

interface IFlying{
    void eat();
}
interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}
interface IClimbing{
    void climb();
}
Salin selepas log masuk
//创建一个Ant类 
//利用implements关键字来实现接口
//一个类可以实现多个接口,接口之间利用逗号连接
//实现了接口必须要在接口中重写接口中的方法
//重写方法快捷键:鼠标移动到implements关键字上然后 alt+enter
class Ant implements IClimbing,IRunning{
    public String name;
    @Override
    public void run() {
        System.out.println(this.name+"要跑步");
    }
    @Override
    public void climb() {
        System.out.println(this.name+"爬山");
    }
}
Salin selepas log masuk
  • 接口的使用时利用implements关键字与类连接,类与接口之间使用implements连接的。

  • 一个类可以实现多个接口,多个接口之间利用逗号连接。

  • class Ant implements IClimbing,IRunning.的意思是类Ant可以实现两个功能,既可以爬又可以跑。

  • 类实现接口时,必须要重写接口中的方法。如果不重写该类还是抽象类,要用abstract来修饰。

接口能否有静态方法和代码块呢???

Cara menggunakan kelas dan antara muka abstrak Java

接口中是不能有静态代码块和构造方法的。

接口间的继承

我们这里总结一下类与接口之间的联系

  • 类与类之间是继承关系利用extends来连接 代表子类继承了父类

  • 类与接口之间是利用implements来连接, 代表类能实现某个功能

  • 接口与接口之间也可以进行联系,利用extends 接口A和接口B interface A enxtends B 代表接口A拓展了接口B的功能。

这里来讲一下接口与接口之间的继承

我们利用extends关键字将两个接口连接起来,这样就实现了接口之间的继承。

例如:

interface IRunning extends IFlying{
    //类IRunning拓展了IFlying的功能
    void run();
    //接口与接口之间继承后IRunning拓展了IFlying功能
    //有了IRunning的功能的类也要重写IFlying这个方法
}
Salin selepas log masuk
  • 类IRunning拓展了IFlying的功能

  • 接口与接口之间继承后IRunning拓展了IFlying功能

  • 有了IRunning的功能的类也要重写IFlying这个方法

几个重要的接口

接口comparable

我们这里举一个例子:

比如我们要进行给一个学生进行排序,我们之前学过Arrays的sort方法,好我们来尝试一下这个方法对学生进排序。

class Student{
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Student[] student = new Student[4];
        student[0] = new Student("张三",18,88);
        student[1] = new Student("李四",98,98);
        student[2] = new Student("王二麻子",8,18);
        student[3] = new Student("赵老八",58,38);
        System.out.println(Arrays.toString(student));
        Arrays.sort(student);
        System.out.println(Arrays.toString(student));
    }
}
Salin selepas log masuk

Cara menggunakan kelas dan antara muka abstrak Java

从这里发现Arrays.sort方法是比较具体的数字大小的,而我们这里比较学生这个对象并没有指定,我们究竟依靠什么来比较这个学生对象,目前这个学生有名字,分数,年龄,我们到底依靠什么比较是根据我们的需求来定,那我们要具体的比较学生对象的某一个学生怎么比较呢·???看报错信息也就是这个异常,我们需要提供这个comparable这个接口然后重写这个comparable方法。

怎样提供接口????

Cara menggunakan kelas dan antara muka abstrak Java

我们根据类要实现一个接口是利用关键字implements来连接的。

Cara menggunakan kelas dan antara muka abstrak Java

然后使用comparable这个接口,尖括号里面写上你要排序的类。

好这样我们就实现了这个接口,当然看前面那个红线就知道会有报错,这也就是当我们实现一个接口我们必须重写这个接口中的方法,然后Alt+enter重写这个接口中的方法。

Cara menggunakan kelas dan antara muka abstrak Java

好,我们就重写了这样的一个方法,比如我们要比较年龄按照升序排列:

Cara menggunakan kelas dan antara muka abstrak Java

然后调用Arrays.sort方法就可以进行排序了。

Cara menggunakan kelas dan antara muka abstrak Java

同样我们还可以根据名字排序:

Cara menggunakan kelas dan antara muka abstrak Java

由于,名字是String类型也就是引用类型所以我们要调用compareTo方法来进行比较。

同样的我们还可以根据分数来排序这个学生对象。

Cara menggunakan kelas dan antara muka abstrak Java

comparator接口-比较器

我们刚才使用comparable这个接口会有一个缺陷,就比如当我们已经实现按照年龄排序好了,但是有个人突然把他改成了名字比较,如果是未来做项目开发的时候,那就会给程序猿造成很大的困扰,就怕有一天别人修改了那段代码,所以我们就有了这个comparator这个比较器,我们还是把他封装起来,不用在去学生这个类中去修改。

对学生年龄排序:

class AgeComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
Salin selepas log masuk

对学生分数排序:

class ScoreComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score - o2.score);
    }
}
Salin selepas log masuk
对学生名字排序:
Salin selepas log masuk
class NameComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
Salin selepas log masuk

我们还是利用Arrays.sort方法里面再加一个比较器的这个参数就可以比较了。

 public static void main(String[] args) {
        Student[] student = new Student[4];
        student[0] = new Student("张三",18,88);
        student[1] = new Student("李四",98,98);
        student[2] = new Student("王二麻子",8,18);
        student[3] = new Student("赵老八",58,38);
        System.out.println(Arrays.toString(student));
        AgeComparator ageComparator = new AgeComparator();
        Arrays.sort(student,ageComparator);
        System.out.println(Arrays.toString(student));
    }
Salin selepas log masuk

这样我们将根据什么排序,实例化对应的对象,通过对象调用重写comparator的方法就可以进行比较,不需要担心类中被修改。

cloneable接口深入理解深拷贝与浅拷贝

我们之前学过数组中的克隆方法,就是把一个数组中的内容全部拷贝到另外一个数组中去。

今天我们学的cloneable接口可以将一个对象的属性拷贝到另外一个对象里面去。

怎么使用cloneable接口

我们创建一个人这个类,人这个类中有两个属性,一个是分数,一个是smartphone这个对象(引用类型)。

class SmartPhone{
    public int money = 9999;
}
class Person{
    public int score = 96;
    SmartPhone smartPhone = new SmartPhone();
}
public class TestDemo {
    public static void main(String[] args){
        Person person1 = new Person();
    }
}
Salin selepas log masuk

我们现在要将这个person这个类实现cloneable接口,利用implements连接,同样的我们要重写这个cloneable这个接口中的方法。

Cara menggunakan kelas dan antara muka abstrak Java

这里我们要注意·重写cloneable这个方法,它的返回类型是object,object是Java中所有类的父类。

好,完成了接口的操作,我们接下来完成克隆的工作,我们怎么使用clone这个方法来进行克隆呢???

浅拷贝:
//浅拷贝
class SmartPhone{
    public int money = 9999;
}
class Person implements  Cloneable{
    public int score = 96;
    SmartPhone smartPhone = new SmartPhone();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Person{" +
                "score=" + score +
                ", smartPhone=" + smartPhone +
                &#39;}&#39;;
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
        person1.smartPhone.money=9;
        System.out.println("===============拷贝之后=================");
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
    }
}
Salin selepas log masuk

Cara menggunakan kelas dan antara muka abstrak Java

原因是什么呢??画一下图理解一下

Cara menggunakan kelas dan antara muka abstrak Java

这就是浅拷贝,对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此

为浅拷贝。只要将money值进行修改两个对象的money的值都改变,没有彻底的拷贝。

深拷贝
//深拷贝
class SmartPhone implements  Cloneable{
    public int money = 9999;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "SmartPhone{" +
                "money=" + money +
                &#39;}&#39;;
    }
}
class Person implements  Cloneable{
    public int score = 96;
    SmartPhone smartPhone = new SmartPhone();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person)super.clone();
        tmp.smartPhone= (SmartPhone) this.smartPhone.clone();
        return tmp;
    }
    @Override
    public String toString() {
        return "Person{" +
                "score=" + score +
                ", smartPhone=" + smartPhone +
                &#39;}&#39;;
    }
}
public class TestDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
        person1.smartPhone.money=9;
        System.out.println("===============拷贝之后=================");
        System.out.println(person1.smartPhone.money);
        System.out.println(person2.smartPhone.money);
    }
}
Salin selepas log masuk

Cara menggunakan kelas dan antara muka abstrak Java

 此时为深拷贝,进行了彻底的拷贝。对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

Cara menggunakan kelas dan antara muka abstrak Java

Atas ialah kandungan terperinci Cara menggunakan kelas dan antara muka abstrak Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan