详解Java抽象类与普通类的区别

浅谈抽象类

在面向对象概念中,所有的对象都是通过类来描述的,但是反过来,并不是所有的类都是用来描述对象的.如果一个类中没有足够多的信息来描述一个具体的对象,这样的类就是抽象类。

看到这里可能还是觉得有些难以理解,举个例子说明一下:说到动物你会想到什么?猫,狗,鸡鸭鹅?当然这些都可以.那么动物这两个字,你能确定一个具体的对象吗?显然不能.甚至更严格意义上讲,说到猫你会想到什么?橘猫,短美…

毕竟:

一千个人心中有一千个哈姆雷喵.

所以我们在设计中,动物类可以设计成为抽象类,而某一种特定的物种可以采用通过继承动物类实现.

多态这部分我理解了好久,有一天突然就会用了,也明白所谓的父类引用指向子类对象是什么意思了.但是写完前面发现,自己明白了讲出来还是很模糊.多态真的是很重要很重要的一个点,要好好体会这部分.

抽象类和普通类的区别是什么?

抽象类的语法规则

抽象类的语法规则:abstract关键字修饰

1.抽象类不可以被实例化.

2.抽象类不定有抽象方法.

3.一个类中如果有抽象方法,那么这个类一定是抽象类.

4.抽象类中可以存在普通属性、方法、静态属性和静态方法.

5.抽象类中可以存在构造方法.

public abstract class AbstractObject{
	// 普通属性
    String name;
	// 构造方法
    public AbstractObject(String name) {
        this.name = name;
    }
    // 静态方法 - 类名访问
    public static void staticMethod(){
        System.out.println("抽象类可以有静态方法.");
    }
	// 抽象方法
    public abstract void move();
	// 普通方法
    public void commonMethod(String food){
        System.out.println("抽象类可以有普通方法.");
    }
}

抽象类不可以实例化

这部分可以直接暂时记住结论,整个过程可以暂时先跳过后面补,按照我的学习经历(基础差到爆),这部分直接看会很懵.

定义一个动物的抽象类,动物总得动吧(并不!)所以定义一个共性的move()方法.

public abstract class Animal {
    String name;
    public Animal(String name) {
        this.name = name;
    }
    public abstract void move();
}

当我使用IDEA写示例的时候直接出现了第二种情况!见鬼了抽象类new出来了!

public class Test {
    public static void main(String[] args) {
    	// 抽象类不能实例化!会直接报编译期错误!
        //标红信息: 'Animal' is abstract; cannot be instantiated
        Animal animal = new Animal("小猫");
        // 第二种情况
        Animal animalObjcet = new Animal("小猫") {
            @Override
            public void move() {
                System.out.println("我开始移动了!");
            }
        };
    }
}

关于第二种情况的解释 - 扩展知识:匿名内部类(可跳过)

这里涉及到了一个知识点叫做匿名内部类.
匿名内部类的格式如下:

new 类名或者接口名(){
	重写方法;
}
// 放到一起对比看,很明显后面的是一个匿名内部类
new Animal("小猫") {
    @Override
    public void move() {
        System.out.println("我开始移动了!");
    }
};

匿名:这个类没有名字
内部类:存在于某个类的内部的类.

它实际上是继承并实现了Animal抽象类的一个子类.也就是说这里并不是实例化出了Animal类,这个简便的写法相当于我们进行了如下的写法.

public class AnimalObject extends Animal{
    public AnimalObject(String name) {
        super(name);
    }
    @Override
    public void move() {
        System.out.println("我是一只能动的动物!");
    }
}

public class Test {
    public static void main(String[] args) {
        AnimalObject animalObject = new AnimalObject("我是动物抽象类的子类");
        animalObjcet.move();	// 我是一只能动的动物!
    }
}

抽象类的子类

注意:这里有一个需要强调的地方,对于抽象类中的方法我们的用词应该是实现.对于已经实现了的方法,我们的用词才可以是重写.写到后面发现了前面描述过程中我用词都是重写这里进行了修正.
错误写法:不重写(Override)抽象类中的抽象方法
正确写法:不实现(Implement)抽象类中的抽象方法
再次补充:好像说成重写也不能算错误,IDEA自动生成的里面也加了 @Override 注解.就不继续修改了.

1.不实现抽象类中的抽象方法

当不对抽象类中的抽象方法进行重写的时候,子类一定也是抽象类.(有抽象方法的类一定是抽象类)

public abstract class AbstractCat extends Animal{
    Integer weight;
    public AbstractCat(String name, Integer weight) {
        super(name);    // 继承父类的名称
        this.weight = weight; // 猫咪的年龄
    }
    // 这个是没有重写,依旧是了抽象方法
    public abstract void move();
    // 注意:下面这种写法是重写过之后的!只是方法体为空.
    // public void move(){};
}

2.实现抽象类中的抽象方法

当对抽象类中的所有抽象方法进行实现之后,现在的猫咪类可以是一个普通类了.

public class Cat extends AbstractCat{
    public Cat(String name, Integer weight) {
        super(name, weight);
    }
    @Override
    public void move() {
        System.out.println("一只奔跑的重达" + weight + "kg的" + name);
    }
}

测试一下:

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("橘猫", 20);
        cat.move();	// 一只奔跑的重达20kg的橘猫
    }
}

好了到这里,属于你的橘猫终于跑起来了!

关于实现抽象方法的延伸

我看很多文章都说要子类要重写(重写是错误的!这里更正为实现)父类的抽象方法,抽象方法.那我如果只实现部分抽象方法呢?
第一步:改造Animal类

public abstract class Animal {
    String name;
    public Animal(String name) {
        System.out.println("我是动物的构造方法!");
        this.name = name;
    }
    // 多添加几个抽象方法
    public abstract void move();
    public abstract void eat();
    public abstract void sleep();
}

第二步:AbstractCat 类中实现部分抽象方法

// 不添加 abstract 关键字会报错
// Class 'AbstractCat' must either be declared abstract or implement abstract method 'move()' in 'Animal'
public abstract class AbstractCat extends Animal{
    Integer weight;
    public AbstractCat(String name, Integer weight) {
        super(name);
        System.out.println("我是抽象猫咪的构造方法!");
        // 继承父类的名称
        this.weight = weight; // 猫咪的年龄
    }
    @Override
    public void eat() {
        System.out.println(this.name + "在吃猫粮");
    }
    @Override
    public void sleep() {
        System.out.println(this.name + "睡觉了!");
    }
}

第三步:Cat类登场

public class Cat extends AbstractCat{

    public Cat(String name, Integer weight) {
        super(name, weight);
    }
    /*
    sleep方法和eat方法已经在父类中实现过了,所以这里只剩下最后一个 move 是需要实现的抽象方法.
	*/
    @Override
    public void move() {
        System.out.println("重达" + weight + "kg的" + this.name + "在懒洋洋的跑");
    }
}

小结

1.普通类可以实例化调用,但是抽象类不可以,因为抽象类只是一种概念,无法映射为具体的对象.

2.普通类和抽象类都可以被继承,但是抽象类被继承之后,子类需要重写抽象类中的全部抽象方法,否则子类必须是一个抽象类.

参考和扩展阅读

Java基础系列第一弹之方法重载和方法重写的区别
Java基础系列第二弹之Java多态成员访问的特点
Java基础系列第三弹之操作字符串的类都有哪些?区别是什么?

到此这篇关于详解Java抽象类与普通类的区别的文章就介绍到这了,更多相关Java抽象类与普通类内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java抽象类和抽象方法定义与用法实例详解

    本文实例讲述了Java抽象类和抽象方法定义与用法.分享给大家供大家参考,具体如下: 一.Java抽象类 参考资料:Java抽象类 详解 1.抽象类的说明 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量.成员方法和构造方法的访问方式和普通类一样. 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用.也是因为这

  • Java抽象类与接口区别详解

    很多常见的面试题都会出诸如抽象类和接口有什么区别,什么情况下会使用抽象类和什么情况你会使用接口这样的问题.本文我们将仔细讨论这些话题. 在讨论它们之间的不同点之前,我们先看看抽象类.接口各自的特性. 抽象类 抽象类是用来捕捉子类的通用特性的 .它不能被实例化,只能被用作子类的超类.抽象类是被用来创建继承层级里子类的模板.以JDK中的GenericServlet为例: public abstract class GenericServlet implements Servlet, ServletC

  • 详解JAVA 抽象类

    在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量.成员方法和构造方法的访问方式和普通类一样. 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用.也是因为这个原因,通常在设计阶段决定要不要设计抽象类. 父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法. 在Java中抽象类表示的是

  • Java中的对象、类、抽象类、接口、继承之间的联系

    正文: 举个例子:如果现在要想定义一个动物,那么动物肯定是一个公共的标准,而这个公共标准就可以通过接口来完成. 在动物中又分为两类:哺乳动物.卵生动物,而这个标准属于对动物的标准进一步细化,应该称为子标准,所以此种关系可以使用接口的继承来表示. 而哺乳动物可以继续划分为人.狗.猫等不同的类型,由于这些类型不表示具体的事物标准,所以可以使用抽象类进行表示. 如果要表示出工人或者学生这样的概念,则肯定是一个具体的定义,则使用类的方式. 然后每个学生或者每个工人都是具体的,那么就通过对象来表示: 由下

  • Java 的抽象类原理与用法分析

    本文实例讲述了Java 的抽象类原理与用法.分享给大家供大家参考,具体如下: Java 的抽象类 用abstract关键字来修饰一个类时,这个类叫做抽象类: 用abstract来修饰一个方法时,该方法叫做抽象方法. 抽象方法:只有方法的声明,没有方法的实现.以分号结束:abstract int abstractMethod(int a ); 含有抽象方法的类必须被声明为抽象类. 抽象类不能被实例化.抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体.若没有重写全部的抽象方法,

  • Java 抽象类与接口的对比

    其实说实话,没有多大的可比较性,它们是完全不同的两个东西,它们的抽象不在同一个层级上.但是为了让大家更好的理解,还是做一个比较吧,毕竟它们都很抽象(233). 首先是语法层面上的对比 1)抽象类跟接口都不能被实例化,因为它们都很虚嘛.但是在访问权限上,两者有一定的区别. a.抽象类中的抽象方法(其前有abstract修饰)不能用private.static.synchronized.native访问修饰符修饰.理由很简单,容我慢慢道来. 抽象方法是没有方法体的,它的目的就是用来继承的,所以如果使

  • Java接口和抽象类有什么区别

    接口(interface)和抽象类(abstract class)是支持抽象类定义的两种机制. 接口是公开的,不能有私有的方法或变量,接口中的所有方法都没有方法体,通过关键字interface实现. 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念.类描述对象的属性和方法.接口则包含类要实现的方法. 除非实

  • 详解Java抽象类与普通类的区别

    浅谈抽象类 在面向对象概念中,所有的对象都是通过类来描述的,但是反过来,并不是所有的类都是用来描述对象的.如果一个类中没有足够多的信息来描述一个具体的对象,这样的类就是抽象类. 看到这里可能还是觉得有些难以理解,举个例子说明一下:说到动物你会想到什么?猫,狗,鸡鸭鹅?当然这些都可以.那么动物这两个字,你能确定一个具体的对象吗?显然不能.甚至更严格意义上讲,说到猫你会想到什么?橘猫,短美- 毕竟: 一千个人心中有一千个哈姆雷喵. 所以我们在设计中,动物类可以设计成为抽象类,而某一种特定的物种可以采

  • 详解JAVA 时间处理相关类

    时间处理相关类: 1.java.util.Date:时间类 2.java.text.DateFormat:时间格式化类(抽象类),实现类:java.text.SimpleDateFormat 3.java.util.Calendar:日历类(抽象类),实现类:java.util.GergorianCalendar 1.java.util.Date 时间就是一个数轴,在计算机中,1970年1月1日00:00:00定位基准时间,也就是数轴的原点,每个度量单位是毫秒(1000毫秒=1秒) java中我

  • 详解Java中的日期类

    Java 编程语言中时间的处理类有 Date类与 Calendar类.目前官方不推荐使用 Date类,因为其不利于国际化:而是推荐使用 Calendar类,并使用 DateFormat 类做格式化处理. 一.Date 类介绍 Date 表示特定的瞬间,精确到毫秒. 在 JDK 1.1 之前,类 Date 有两个其他的函数.它允许把日期解释为年.月.日.小时.分钟和秒值.它也允许格式化和解析日期字符串. 不过,这些函数的 API 不易于实现国际化.从 JDK 1.1 开始,应该使用 Calenda

  • 一文详解Java抽象类到底有多抽象

    目录 抽象类 1.引出抽象类 2.认识抽象类 接口 1.抽象类和接口的区别 2.认识接口 3.具体实现 USB接口 接口表示能力 抽象类 1.引出抽象类 向上转型带来的最大的好处就是参数统一化,使用共同的父类引用,就可以接收所有的子类实例. 多态非常依赖方法覆写,但是子类可以选择性的覆写父类的方法,若需要强制要求子类覆写方法,就会用到抽象类其实显示生活中就有很多的抽象类,这些类都是概念化的,没法具体到某个实例,但是能描述这一类对象的共同属性和方法,比如人类,就没法具体到某一类人,世界上有很多类人

  • 详解Java 中的嵌套类与内部类

    详解Java 中的嵌套类与内部类 在Java中,可以在一个类内部定义另一个类,这种类称为嵌套类(nested class).嵌套类有两种类型:静态嵌套类和非静态嵌套类.静态嵌套类较少使用,非静态嵌套类使用较多,也就是常说的内部类.其中内部类又分为三种类型: 1.在外部类中直接定义的内部类. 2.在函数中定义的内部类. 3.匿名内部类. 对于这几种类型的访问规则, 示例程序如下: package lxg; //定义外部类 public class OuterClass { //外部类静态成员变量

  • 详解java JDK 动态代理类分析(java.lang.reflect.Proxy)

    详解java JDK 动态代理类分析(java.lang.reflect.Proxy) /** * JDK 动态代理类分析(java.lang.reflect.Proxy使用) * * @author 张明学 * */ public class ProxyStudy { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { // 动态代理类:通用指定类加载器,和接

  • 详解java 对象锁与类锁

    一.什么是对象锁 对象锁也叫方法锁,是针对一个对象实例的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,而并不会对其他对象实例的锁产生任何影响,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞, 例如: public class MyObject { private synchronized void method1(){ try { System.out.println(Thread.currentThread().getName());

  • 详解Java的构造方法及类的初始化

    目录 一. 利用构造方法给对象初始化 1. 构造方法的概念 2. 构造方法的特性 3. 子类构造方法 4. 避免在构造方法中调用重写的方法 二. 对象的默认初始化 三. 就地初始化对象 四. 类的初始化顺序 1. 普通类(没有继承关系) 2. 派生类( 有继承关系) 一. 利用构造方法给对象初始化 1. 构造方法的概念 构造方法(也称为构造器)是一个特殊的成员方法,其名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次. 构造方法的作用就是给对象中的成员进行初

  • 详解JAVA中implement和extends的区别

    详解JAVA中implement和extends的区别 extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,Java中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了比如class A extends B implements C,D,E implements是一个类实现一个接口用的关键字,他是用来实现接口中定义的抽象方法. 还有几点需要注意: (1

随机推荐