zoukankan      html  css  js  c++  java
  • 抽象类能实例化吗

     抽象类能实例化吗?

               这个问题我想了一个晚上,看了好几篇别人的博客,但结果都各不相同,每个人有每个人的理解,后来我想明白了:

             抽象类不能直接通过new去实例化一个对象,那它就是不能实例化,要获取抽象类的对象, 需要先用一个类继承抽象类,  然后去实例化子类。也可以用匿名内部类,在抽象类中创建一个匿名的子类,继承抽象类,通过特殊的语法实例化子类的对象 。(后面会细说)      

                现在重点来了,要研究这个问题,前提是你要了解抽象类,万变不离其宗,我们从抽象类的根源谈起 , 深化对抽象类的理解。

    首先看这个例子:

         

    package com.my.animal;
    
    //动物类
    public class Animal {
        String name;//名字
        String color;//颜色
    
        public Animal(String name,String color){
            this.name = name;
            this.color = color;
        }
        public void run(){
            System.out.println(name+"四条腿跑的很快!!!");
        }
    }
    //狗类继承动物类
    class Dog extends Animal{
        public Dog(String name,String color){
            super(name,color);
        }
    }
    //鱼类继承动物类
    class Fish extends Animal{
    
        public Fish(String name, String color) {
            super(name, color);
        }
    }
    
    class Test{
        public static void main(String[] args) {
            Dog dog = new Dog("哈巴狗","白色");
            dog.run();
    
            Fish fish = new Fish("锦鲤","红色");
            fish.run();
        }
    }
    运行结果:
    
    哈巴狗四条腿跑的很快!!!
    锦鲤四条腿跑的很快!!!
    

      

            是不是发现问题了,鱼怎么能用腿跑呢,难道是原始鱼?哈哈,开玩笑的,这个问题如何解决,估计大家马上想到了,在子类中重写父类的run方法不就行了,对,确实这样就可以解决,但是大家想过没有,我们是如何发现这个问题的?是不是编译运行之后才看到的,当然,也有大佬能不编译运行就能看到,不抬杠啊,意思是说有发现不了这个问题的风险,对别人可能无所谓,但对我们程序员来说,这种低级错误还是不犯的好,程序员应该有更高的追求,岂能在这被绊倒,我们要把这种风险降为零,那该如何做呢?不急,心急吃不了热豆腐,且看我慢慢分析:

           

            目前存在的问题:

                     1.动物类的run方法描述的不正确

                     2.没有强制要子类一定要重写父类的run方法

             解决方案:(抽象类的应用场景)

                      我们在描述一类事物的时候,发现该种事物确实存在着某种行为,但是这种行为目前是不具体的,那么我们可以抽取这种行为的声明,但是不去实现该种行为,这时候这种行为我们称作为抽象的行为,我们就需要使用抽象类

             先看下面的例子: 

    package com.my.animal;
    //动物类(抽象类)
    public abstract class Animal {
        String name;//名字
        String color;//颜色
           //构造方法
        public Animal(String name,String color){
            this.name = name;
            this.color = color;
        }
    //非抽象方法
    public void eat(){
    System.out.println(name+"吃东西!!!");
    }
    //抽象方法 public abstract void run(); } class Dog extends Animal{ public Dog(String name,String color){ super(name,color); } @Override public void run() { System.out.println(name+"四条腿跑得快!!"); } } class Fish extends Animal{ public Fish(String name, String color) { super(name, color); } @Override public void run() { System.out.println(name+"摇摇尾巴游啊游!!"); } } class Test{ public static void main(String[] args) { Dog dog = new Dog("哈巴狗","白色"); dog.run(); Fish fish = new Fish("锦鲤","红色"); fish.run(); } }
    运行结果:
    
    哈巴狗四条腿跑得快!!
    锦鲤摇摇尾巴游啊游!!
    

      

    这个问题解决了,那还有一个问题就是:抽象类能实例化对象吗?

    看这个例子就知道了:

         

    public abstract class Animal {
        String name;
        String color;
    
        public Animal(String name,String color){
            this.name = name;
            this.color = color;
        }
        public abstract void run();
    }
    
    class Test{
        public static void main(String[] args) {
            Animal a = new Animal();
            a.run();
        }
    }
    运行结果:
    
    Error:(45, 20) java: com.my.animal.Animal是抽象的; 无法实例化
    

      

    抽象类注意的细节:

             1.如果一个函数没有方法体,那么该函数必须要使用abstract修饰,把该函数修饰成抽象的函数。

             2.如果一个类出现了抽象的函数,那么该类也必须使用abstract修饰。

             3.如果一个非抽象类继承了抽象类,那么必须要把抽象类的所有抽象方法全部实现。

             4.抽象类可以存在抽象方法,也可以存在非抽象方法,还可以不存在抽象方法,但是这样没任何意义,Java是不写废话的。

             5.抽象类是不能实例化对象的

             6.抽象类是存在构造函数的,其构造函数是提供给子类创建对象的时候初始化父类的属性的。

                

              

     疑问:为什么抽象类不能实例化对象?

                因为抽象类是存在抽象方法的,如果能让抽象类创建对象的话,那么使用抽象类的对象调用抽象方法是没有任何意义的。

               

    疑问排解了,故事结束了?不,学海本无底,我们来点扩展,就是开头提到的如何用匿名内部类去实例化子类对象。

    看下面的例子:

    package Practice_Anything;
    
    public abstract class Java_Abstract2 {
    
        public void a(){
            System.out.println("我是抽象类中的一个非抽象方法");
        }
    
        public static Java_Abstract2 newIntences(){
            return new Java_Abstract2(){
    
            };
        }
    }
    
    class Test2{
        public static void main(String[] args) {
            Java_Abstract2 java_abstract2 = Java_Abstract2.newIntences();
            java_abstract2.a();
        }
    }
    运行结果:
    
    我是抽象类中的一个非抽象方法
    

      

    这个故事到这就结束了,但是学习还没有停止,比如接口也是一种抽象类型,是抽象方法的集合,由此,我们是不是该联想到学习接口了呢?哈哈,学海本无底,前行莫彷徨!

    此篇为本人原创,花了大概半天时间,找了不知多少相关资料整合而成,如若对你有用,记得推荐,如若哪有不当,感谢指正!

      本文已独家授权给脚本之家(jb51net)公众号独家发布

  • 相关阅读:
    JAVA中的BIO,NIO,AIO
    JAVA通过信号量避免死锁
    java死锁
    ConcurrentHashMap并不是完全的线程安全
    【技术学习】Understand Exit Codes of Docker
    【技术学习】centos7 firewall
    【现场问题】Linux Cache过大问题排查
    【技术学习】postgresql学习笔记--基础篇
    【技术学习】postgresql学习笔记--基础篇
    【监控脚本】利用selenium自动化测试样例一
  • 原文地址:https://www.cnblogs.com/zyx110/p/10648119.html
Copyright © 2011-2022 走看看