java接口的抽象方法,Java抽象类和接口
这篇文章给大家带来了一些关于java的知识,包括关于抽象类和接口的相关问题,包括什么是抽象类,抽象类在实现多态性中的意义等等。来看看吧,希望对你有帮助。
如何解决写爬虫IP受阻的问题?立即使用。
什么是抽象类
我们之前学过什么是类,那么抽象类也是类的一种吗?
听名字就感觉好抽象呀!说对了,他就是抽象的,不是具体的。在类中没有包含足够的信息来描绘一个具体的对象,这样的类称为抽象类。
看一个抽象类的例子。
//抽象类和抽象方法需要用抽象关键字来修饰
抽象类形状{
//抽象类中的方法一般需要抽象方法,抽象方法没有方法体。
抽象void draw();
}大家觉得这个抽象类是不是什么也没干,他唯一的方法draw()还是空的。
如果像这样的类没有包含足够的信息来描述一个特定的对象,自然就不能实例化该对象。不要相信我:
既然那个类不能实例化,那么这个抽象类存在的意义是什么?
抽象类在实现多态中的意义
抽象类存在的一个最大意义就是被继承,当被继承后就可以利用抽象类实现多态。
看一段代码。
//抽象类和抽象方法需要用抽象关键字来修饰
抽象类形状{
//抽象类中的方法一般需要抽象方法,抽象方法没有方法体。
抽象void draw();
}
//当普通类继承抽象类时,普通类必须重写抽象类中的方法。
课程循环扩展形状{
@覆盖
Void draw() {//重写抽象类中的draw方法
System.out.println(画圆);
}
}
公共类测试4 {
公共静态void main(String[] args) {
//Shape Shape=new Shape();尽管抽象类不能被直接实例化
//但是可以将普通类对象传递给抽象类引用,即父类引用指向子类对象。
Shape shape=新循环();//这叫:向上转化
/*Cycle循环=new Cycle();
shape=cycle//这是向上转换的另一种写法
*/
shape . draw();//通过父类引用调用被子类重写的方法
}
}跑完之后,你会发现一个神奇的场景:
看完代码,你可能会有很多疑问。别急,我们一个一个说。
什么是向上转化:一句话,概括为“父类引用子类对象”
向上转型后的变化
关于方法:父类引用可以调用子类和父类公用的方法(如果子类重写了父类的方法,则调用子类的方法),但子类特有的方法无法调用。关于属性: 父类引用可以调用父类的属性,不可以调用子类的属性向上转型的作用
减少一些重复性的代码对象实例化的时候可以根据不同需求实例化不同的对象这样的话就我们上面的代码就可以理解了
好像可以通过子类继承重写抽象类,抽象类真的很有用!
但这和多态有什么关系呢,抽象类用起来这么麻烦,我还不如直接用普通类,也能达到这样的效果,还不用再写一个子类呢?
好了,再看下面这段代码,你就知道抽象类在实现多态性上的好处了。
抽象类形状{
公共抽象void draw();//抽象方法中不能有具体的语句。
}
//当普通类继承抽象类时,抽象类中的抽象方法必须在这个子类中被覆盖。
课程循环扩展形状{
@Override //如果不重写会出错,但是如果继承了一个通用类就不会出错。使用抽象类更安全。
公共void draw() {
System.out.println(画圆);
}
}
Class Flower extends Shape {//不同的子类以不同的方式重写父类的draw方法。
@覆盖
公共void draw() {
System.out.println(画一朵花);
}
}
类方形扩展形状{
@覆盖
公共void draw() {
System.out.println(画一个正方形);
}
}
公共类测试4 {
公共静态void main(String[] args) {
周期Cycle=new Cycle();//子类引用循环
花花=新花();//子类引用花
Square Square=new Square();
//数组的类型是Shape,即数组中的每个元素都是父类引用。
//在这个过程中,实际上有一个向上的转化,重写抽象类中的方法。
shape[]shapes={周期,花朵,正方形};//父类引用引用不同的子类对象
for(int I=0;一.形状.长度;i ) {
shape shape=shapes[I];//父类引用形状指向—当前对应的子类对象。
shape . draw();//通过父类引用调用被子类覆盖的draw方法。
}
}
}
调用同一个方法竟然打印出了不同的结果,这难道就是所谓的多态
是不是有点懵,下面我们来解释一下
//补充上面的代码。
//也许你对shape [] shapes={cycle,flower,square}感兴趣;不太明白
//但是上面的代码相当于
Shape[] shapes1=新形状[3];//有三个不同的子类对象!数组大小为3。
//是不是相当于把子类引用赋给父类对象,父类对象指向对应的子类对象-?
//这是向上转换的另一种写法,应该是之前已经实例化了子类对象Cycle Cycle=new Cycle();
shapes1[0]=循环;//如果子类对象之前没有实例化,应该写成shape1[0]=new Cycle。
shapes1[1]=花;
shapes1[2]=正方形;对于多态性,他有这三个要素。
继承(我们刚才的Cycle类继承Shape抽象类)重写(我们子类对draw方法的重写)父类指向子类对象(就是shape1[0] = cycle --也可以称作向上转型)回头看看我们的代码,是不是刚好符合多态性的三个要素。
当我们的父类引用指向不同的子类对象时,当我们调用同一个draw方法时却输出了不同的结果。(其实就是该方法再子类中被重写成了不同形式)这就叫做多态 。
嘻嘻,其实多态性只要结合例子就没那么难理解了。
那为啥一定要用抽象类呢?我一个普通类继承普通类来实现多态不可以吗
当然,但是它不安全。有风险。
但如果是抽象类的话,就不一样了
由此也可以看出,在使用抽象类时,编译器会自动检查我们是否重写了它们,在实际开发中充分利用编译器的检查是非常有意义的。所以抽象类是有用的。
好了,我相信你在这里对抽象类有了一个大概的了解。这里简单总结一下。
使用abstract修饰的类或方法,就抽象类或者抽象方法抽象类是不能具体的描述一个对象,不能用抽象类直接实例化对象抽象类里面的成员变量和成员方法,都是和普通类一样的,只不过就是不能进行实例化了当一个普通类继承这个抽象类后,那么这个普通类必须重写抽象类当中的所有的抽象方法(我们之前说过抽象类是不具体的,没有包含足够的信息来描述一个对象,所以我们需要把他补充完整)但当一个抽象类A继承了抽象类B,这是抽象类A就可以不重写抽象类B当中的抽象方法final不能修饰抽象类和抽象方法(因为抽象类存在的最大意义就是被继承,而被final修饰的不能被继承,final和抽象,他们两个是天敌)抽象方法不能被private修饰(抽象方法一般都是要被重写的,你被private修饰了,还怎么重写)抽象类当中不一定有抽象方法,但如果一个类中有抽象方法,那么这个类一定是抽象类。
接口是什么
抽象类是从多个类中抽象出来的模板,如果将这种抽象进行的更彻底,则可以提炼出一种更加特殊的“抽象类”——接口(Interface)。
接口是Java中最重要的概念之一。可以理解为特殊阶层。不同的是接口的成员没有执行器,由全局常量和公共抽象方法组成。
如何定义一个接口?我们来看一个栗子。
//接口的定义格式和定义类的基本相同。如果将class关键字改为interface关键字,就定义了一个接口。
公共接口名称{
//定义变量
int a=10//接口中的成员变量默认都是public static final。
//抽象方法
公共抽象void method 1();//public abstract是固定搭配,可以不填。
void方法2();//接口中的成员方法默认都是公共抽象,建议用第二种方法定义方法。
}你可以看到接口和类其实有很多相似之处:
接口也包含抽象方法,所以不能直接实例化接口。那么我们如何使用界面呢?
哈哈,很简单,我们再用一个普通类实现这个接口不就行了吗,不同的是抽象类是被子类来继承而实现的,而接口与类之间则是用关键字implements来实现。
就像普通类实现实现抽象类一样,一个类实现某个接口则必须实现该接口中的抽象方法,否则该类必须被定义为抽象类。
通过接口实现多态
铁汁!刚才我们用抽象类来实现多态性,那么现在我们可以尝试用接口来实现多态性。
Interface可以看作是一个特殊的类,只能用interface关键字来修饰。
接口IShape {
int a=10默认情况下,接口的成员变量都是public static final。
int b=23
void draw();一般来说,接口的成员方法只能是抽象方法,默认是公共抽象(JDK 1.8之前)
默认void show() {
System.out.println(接口中的其他方法);//接口中的其他方法也可以实现,但应该用default来修饰
}
公共静态void测试(){
System.out.println(这是接口中的静态方法);
}
}
//如果普通类要实现接口,可以使用implement,
//因为接口也是抽象的,所以这个实现接口的类也必须重写抽象方法。
类循环实现IShape {
@覆盖
公共void draw() {
System.out.println(画圆);
}
}
类Square实现IShape {
@覆盖
公共void draw() {
System.out.println(画一个正方形);
}
}
班花器IShape {
@覆盖
公共void draw() {
System.out.println(画一朵花);
}
}
公共类测试4 {
公共静态void main(String[] args) {
//IShape IShape=new IShape();也不能直接实例化接口。
周期Cycle=new Cycle();
Square Square=new Square();
花花=新花();
//这里的IShape接口相当于抽象类中的父类,接口类型也是引用类型。
IShape[]iShapes={循环,正方形,花};//这个过程其实是向上转化的。
For (IShape iShape: iShapes) {//增强For—each循环,也可以写成普通for循环。
ishape . draw();//多态性是通过重写实现的
}
}
}
参考变量cycle和square都被分配给shape类型的参考变量Shape,
但是当执行shape.draw()时,其draw方法被java虚拟机覆盖,
要看这个时候界面是不是指那个物体,是形状还是周期的 看一下运行结果。
看完代码你可能会有点晕,但是没关系。一般我们不会这样使用接口,就用抽象类吧(我只是在演示用接口可以实现多态性)。
下面我们来总结一下Java中接口的几个主要特点
接口中可以包含变量和方法,变量被隐式指定为 public static final,方法被隐式指定为 public abstract(JDK 1.8 d一个类可以同时实现多个接口,一个类实现某个接口则必须实现该接口中的抽象方法,否则该类必须被定义为抽象类接口支持多继承,即一个接口可以继承(extends)多个接口,间接解决了 Java 中类不能多继承的问题。那么接口一般用在什么地方呢?
一般实现类和它的抽象类之前有一个‘是-a’的关系,但是如果我们想达到同样的目的,但是没有这样的关系,我们就要使用接口。由于Java单一继承的特性,一个类只能继承一个类,但可以实现一个或多个接口。在这种情况下,您可以使用接口。下面就让我们来看看接口的正确用法:帮助java实现“ 多继承 ”
由于Java单一继承的特性,一个类只能继承一个类,但可以实现一个或多个接口。在这种情况下,您可以使用接口。
动物类{
字符串名称;//private不能用,后面的子类也要用。
公共动物(字符串名){//父类的自定义构造方法
this.name=name
}
}
界面显示{//自定义各种界面
void fly();
}
界面运行{
空运行();
}
接口正在消失{
虚空泳();
}
//鸭子,不仅会跑,还会游泳,会飞。
一个类继承其父类,实现多个接口,间接解决了java不能继承更多的问题。
鸭子类扩展动物工具奔跑,行走,如果{
Public Duck(String name) {//子类构造方法
超级(名);//必须在子类构造方法的第一行
//在给构造函数实现子类之前,要用super()调用构造函数实现父类。先有父母后有孩子更好!
//由于父类定义了自己的构造函数,编译器不会自动将super()添加到子类的构造函数中;要实现父类的构造方法,需要我们自己实现。
}
//重写接口中的抽象方法
@覆盖
公共void fly() {
System.out.println(this.name 用翅膀飞翔);
}
@覆盖
公共无效运行(){
System.out.println(this.name 两条腿走路);
}
@覆盖
公共无效游泳(){
System.out.println(this.name 浮在水面);
}
}
公共类接口的使用{//我不需要学习中文名字作为类名,我这样做只是为了方便演示。
公共静态void main(String[] args) {
鸭鸭鸭=新鸭(第一只小鸭);//实例化duck对象
duck . fly();//通过引用变量名输出重写的方法。方法名称
duck . run();
duck . swimming();
}
}
有人可能会说,为什么要用接口?我直接在父类Animal中实现了fly、run和swimming属性。
然后不同的动物子类继承父类。这些方法不行吗?
但问题是,鸭子会飞,会游泳。猫会飞会游泳吗?你就不能再写一个其他动物的子类吗?
而有了接口呢?我们只是抽象出了飞行和游泳的行为,
只要一个子类有这个行为,就可以实现相应的接口,更加灵活。
上面的代码展示了 Java 面向对象编程中最常见的用法:个类继承一个父类, 同时实现多个接口。
继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性 ,能实现接口的类和该接口并不一定有is_a的关系,只要该类有这个接口的特性就行
这样的设计有什么好处?时刻牢记多态性的好处,让程忘记了类型。有了接口,类的用户就不必关注具体的类型,只要类有这个特性就可以了。
给我一个栗子
类机器人实现IRunning {
私有字符串名称;
公共机器人(字符串名称){
this.name=name
}
//重写run方法
@覆盖
公共无效运行(){
system . out . println( robot this . name 正在运行);
}
}
公共类测试4 {
公共静态void main(String[] args) {
机器人robot1=新机器人(‘图图’);
robot 1 . run();
}
}
//执行结果
图图正在运行只要能跑就行,管他是机器人还是动物呢。
推荐:《java视频教程》以上是全面掌握Java中抽象类和接口的细节。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。