精华内容
下载资源
问答
  • 多态的好处java
    千次阅读
    2022-03-28 17:46:22

    多态的好处:
     * 1)提高了代码的复用性(由继承保证)
     * 2)提高了代码的扩展性(由多态来保证)

    //动物类
    class Animal{
    	public void eat() {
    		System.out.println("动物需要吃饭");
    	}
    	public void sleep() {
    		System.out.println("动物都需要休息");
    	}
    }
    //定义一个猫类
    class Cat extends Animal{
    	@Override
    	public void eat() {
    		System.out.println("猫吃🐟");
    	}
    	@Override
    	public void sleep() {
    		System.out.println("猫趴着睡");
    	}
    }
    //定义一个狗类
    class Dog extends Animal{
    	@Override
    	public void eat() {
    		System.out.println("狗吃骨头");
    	}
    	@Override
    	public void sleep() {
    		System.out.println("狗躺着睡");
    	}
    }
    //动物类工具
    class AnimalTool{
    	private AnimalTool() {}//构造私有化,外界不能创建该类对象
    	//父类引用指向子类对象
    	public static void useAnimal(Animal a) {//a为形式参数
    		a.eat();
    		a.sleep();
    	}
    }
    //测试类
    public class DouTaiDemo2 {
    	public static void main(String[] args) {
    		Dog d=new Dog();
    		d.eat();
    		d.sleep();
    		System.out.println("---------");
    		Dog d2=new Dog();
    		d2.eat();
    		d2.sleep();
    		System.out.println("---------");
    		//改造---->定义两个静态方法,形参都是对应具体动物,进行测试
    		/*useDog(d);
    		useDog(d2);
    		System.out.println("---------");
    		useCat(new Cat());
    		useCat(new Cat());
    		System.out.println("---------");*/
    		//提供一个动物类:分别产生具体动物对象调用对应的eat()/sleep()
    		AnimalTool.useAnimal(d);//Animal a=new Dog()
    		AnimalTool.useAnimal(new Cat());//Animal a=new Cat()
    	}
    	
    	//定义一些功能
    	/*public static void useDog(Dog d) {
    		d.eat();
    		d.sleep();
    	}
    
    	public static void useCat(Cat c) {
    		c.eat();
    		c.sleep();
    	}*/
    }

     

    更多相关内容
  • 多态 & java泛型

    2021-12-10 00:21:43
    java泛型1、回顾java的多态性1)什么是多态(“多”对1 + 不同“态” => 统一与差异)2)接口和抽象类的比较(同: 抽象方法、继承,异: 多态实现)2、泛型的本质 & 作用1)泛型的本质 - 类型参数化2)泛型的...

    多态 & java泛型

    1、回顾java的多态性

    参考

    1)什么是多态(“多”对1 + 不同“态” => 统一与差异)

    学习Java语言的过程中,对于多态的理解是非常关键的,理解了多态也就意味着打开了理解Java各种“抽象”的大门

    所谓的**“多态”,是指不同类型的对象可以响应相同的消息,从相同的基类派生出来的多个类型可被当作同一种类型对待**,可对这些不同的类型进行同样的处理,由于多态性,这些不同派生类对象响应同一方法时的行为是有所差别的

    java多态性具体体现在定义和功能两个方面,简单的总结一下,多态可以用“三个定义和两个方法”来总结。

    • 三个定义分别是父类定义子类构建、接口定义实现类构建和抽象类定义实体类构建
    • 两个方法分别是方法重载和方法重写(Override)

    我的理解:三种实现形式 + 两种本质方法

    java能够实现多态的形式主要有3种:类继承 & 接口实现 & 泛型

    其中java接口是对java类更高程度的抽象,支持多继承和多实现

    而实现多态的方法有重载和重写(Override)

    类的继承允许子类重写父类方法;接口实现允许实现类重写父类方法;泛型通过对类型参数化,支持函数的重载

    • 1)多种类型继承同一基类 - 同一基类调用不同类型
    public class BaseClass {
    
        private String health;
        private String diploma;
    
        public void makeMoney(){
            System.out.println("makeMoney");
        }
    }
    
    public class AClass extends BaseClass{
    
        private String region_skill_computer;
    
        @Override
        public void makeMoney() {
            System.out.println("make lot of money");
        }
    }
    
    public class BClass extends BaseClass{
    
        private String region_skill_cook;
    
        @Override
        public void makeMoney() {
            System.out.println("make less money");
        }
    }
    
    public static void main(String[] args) {
            BaseClass a = new AClass();
            BaseClass b = new BClass();
            a.makeMoney();
            b.makeMoney();
    }
    
    • 2)多种类型实现相同接口 - 同一接口调用不同实现类
    public interface BaseInterface {
       abstract void makeMoney();
    }
    
    public class AImpl implements BaseInterface {
       @Override
       public void makeMoney() {
           System.out.println("make lot of money");
       }
    }
    
    public class BImpl implements BaseInterface {
       @Override
       public void makeMoney() {
           System.out.println("make less money");
       }
    }
    
    public class Main {
    
       public static void main(String[] args) {
           BaseInterface bi = new AImpl();
           BaseInterface bi1 = new BImpl();
           bi.makeMoney();
           bi1.makeMoney();
       }
    }
    

    3)泛型实现函数重载 跳转至自定义泛型方法

    这样使得多种类型既能满足形式上的统一,又能拥有自身类型特有的属性或方法

    2)接口和抽象类的比较(同: 抽象方法、继承,异: 多态实现)

    抽象类接口
    定义以abstract声明,抽象方法可有可无(!!),相比于普通父类,不能用于实例化。以interface声明,由静态常量和抽象方法组成,abstract,public关键字一般省略。
    组成构造方法、抽象方法、普通方法、常量、变量。静态常量、抽象方法。
    使用子类继承抽象类(extends)。子类实现接口(implements)。
    关系抽象类可以实现多个接口(比如ArrayList,既实现Serializable,又实现Cloneable)。接口不能继承抽象类,但允许继承多个接口。
    对象都通过对象的多态性产生实例化对象。都通过对象的多态性产生实例化对象。
    局限抽象类有单继承的局限。接口可以实现多重继承
    选择如果抽象类和接口都可以使用的话,优先使用接口,可以避免单继承的局限。/

    2、泛型的本质 & 作用

    参考

    1)泛型的本质 - 类型参数化

    • 泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

    • 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。Java语言引入泛型的好处是安全简单
      在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化“带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

    • 泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

    2)泛型的作用

    我的理解:泛型的使用,意味着其他类型可以复用这个泛型方法/泛型接口/泛型类,泛型通过类型的参数化实现函数的重载,它与接口,抽象类实现多态的方式不同,后者是重写

    简单举几个场景:

    • 不想写多个重载函数的场景,如C++的template。
    • 约束对象类型的场景,可以定义边界(T extends …),如JDK集合List,Set。
    • 用户希望返回他自定义类型的返回值场景,如Json返回Java bean。
    • 用反射的应用中,也经常会用到泛型,如Class。
    • 对网页,对资源的分析,返回场景,一般都有泛型。

    3、泛型的使用

    参考熬了个大夜总算把Java中的泛型吃透了

    1)jdk中常见的泛型

    参考

    单独的T 代表一个类型 ,而 Class<T>代表这个类型所对应的类Class<?>表示类型不确定的类

    E - Element (在集合中使用,因为集合中存放的是元素)
    T - TypeJava 类)
    K - Key(键)
    V - Value(值)
    N - Number(数值类型)
    ? -  表示不确定的java类型
    
    举例说明: 
    Set<T> 表示 集合里 是   T类的实例 
    List<E> 表示  集合里 是  E类的实例 
    List<?> 表示 集合里的对象类型不确定,未指定 
    ListList<?> 是一样的。 
    

    在JDK中,常见的泛型接口有:Collection<T>Future<T>

    public interface Collection<E> extends Iterable<E> {...}
    public interface Future<V> {...}
    

    泛型类有:Class<T>WeakReference<T>(弱引用类,和GC有关);而在泛型类和泛型接口中就有泛型方法

    /*********Class<T>**********/
    public final class Class<T> implements java.io.Serializable,
                                GenericDeclaration,
                                Type,
                                AnnotatedElement{
        
         public static Class<?> forName(String name, boolean initialize,
                                       ClassLoader loader)
            throws ClassNotFoundException{
             ...
         }
       
    }
    
    /********ArrayList<E>***********/
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
        ...
    public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    }
    

    2)自定义泛型方法(利用反射调用共有方法)

    假设这里定义了三种不同形式的时间对象:GMT,UTC,CST

    @AllArgsConstructor
    @Data
    public class TimeZoneObj1 {
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT")
        private Date startT;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT")
        private Date endT;
    }
    
    
    @AllArgsConstructor
    @Data
    public class TimeZoneObj2 {
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
        private Date startT;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
        private Date endT;
    }
    
    @AllArgsConstructor
    @Data
    public class TimeZoneObj3 {
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Date startT;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Date endT;
    }
    

    这里假设我创建了GMT对象列表,并保存为json字符串,接着重新将其封装成GMT,UTC,CST对象列表

    /**随机生成GMT日期对象集合,并保存为json文件*/
        public void TimeZoneObjGenerator(int num,String outpath){
            List<TimeZoneObj1> timeZoneObjs = new ArrayList<>();
            for (int i = 0; i < num; i++) {
                try {
                    Date startT = new Date();
                    Thread.sleep(4000);  //时间窗口为4s
                    Date endT = new Date();
                    TimeZoneObj1 tz = new TimeZoneObj1(startT,endT);
                    timeZoneObjs.add(tz);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            String json = JSON.toJSONString(timeZoneObjs);
            IOUtils.writeJsonFile(outpath,json);
        }
    

    这里使用泛型类和泛型方法,对列表中每个GMT,UTC,CST对象进行简单的时间计算和赋值,这里利用反射Class<T>泛型类)来获取泛型类型,以及泛型中的方法

    public class Code001_zoneObjCal<T> {
    	/**
         * 对GMT,UTC,CST对象进行计算: startT变为startT + 1s, endT变为EndT - 1s
         * 泛型的作用:支持三种不同日期对象的时间操作,提高代码的复用
         */
        public List<T> timeCal(List<T> zoneObjs,Class<T> clzz){
    
            /*这里的Class<T> clzz可以直接获取getMethod,而不用将list中取出对象后再getMethod*/
            zoneObjs.stream().forEach(zoneObj->{
                try {
                    Method getStartT = zoneObj.getClass().getMethod("getStartT");
                    Method getEndT = zoneObj.getClass().getMethod("getEndT");
                    Method setStartT = zoneObj.getClass().getMethod("setStartT",Date.class);
                    Method setEndT = zoneObj.getClass().getMethod("setEndT",Date.class);
    
                    Date startT = (Date)getStartT.invoke(zoneObj);
                    Date endT = (Date)getEndT.invoke(zoneObj);
    
                    startT = DateUtils.getEndT(startT,1);  //增加1s
                    endT = DateUtils.getStartT(endT,1);  //减少1s
                    setStartT.invoke(zoneObj,startT);
                    setEndT.invoke(zoneObj,endT);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return zoneObjs;
        }
    }
    
    展开全文
  • java面向对象的三大特征:封装,继承、多态 1.封装 封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也...

    java面向对象【java基础】

    面向对象编程的本质:以类的方式组织代码,以对象的方式(封装)组织数据。
    java面向对象的三大特征:封装,继承、多态

    1.封装

     封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
    

    用通俗的话来说,就是将数据和一些复杂的东西封装起来,保护数据的安全,另外留出一个口,便于用户操纵。

    封装的核心属性私有,get/set
    封装的意义

    • 提高程序的安全性,保护数据
    • 隐藏代码的实现细节
    • 统一接口
    • 提高系统的可维护性

    2.继承

    继承的本质是对一批类的抽象,从而实现对现实世界更好的建模

    • 注意:单根继承原则

    • 方法的重写:重写必须是继承关系,子类重写父类的方法

      • 1.方法名必须相同
      • 2.参数列表必须相同
      • 3.修饰符:范围可以扩大,但不可以缩小
      • 4.抛出异常:范围可以缩小,但不可以扩大
    • 为什莫要重写方法

    • 1.父类的功能,子类不一定需要,或者不够

    3.多态:同一个方法,可以根据发送对象的不同,而采用多种不同的行为方式

    一个对象的实际类型是确定的,但引用类型不一定相同,因为可以使用父类的引用指向子类。

    通俗来说:就是,当子类重写了父类的方法时,父类和子类都有了同一个方法,这个时候,调用该方法,是执行子类的方法还是执行父类中的方法呢。这个就是方法的多态。

    注意:多态是方法的多态,属性没有多态
    多态存在的条件

    • 继承关系:必须是继承关系,否则直接会报错
    • 方法需要重写:如果没有重写,不存在方法的多态
      • 注意:以下关键字修饰的方法不能被重写,也就不存在多态。
        • 1.static方法属于类,不属于实例,不能重写
        • 2.final 常量,不可改变的
        • 3.private方法,是私有的,不能被继承。
    • 父类的引用,指向子类对象:Father f1=new Son();

    对象执行方法的规则

    • 对象能够执行哪些方法,主要看队形左边的类型,和右边关系不大
    • 子类重写了父类的方法,则执行子类的方法。
    展开全文
  • Java多态

    千次阅读 多人点赞 2022-04-07 19:37:12
    java多态中关于重载重写、向上和向下转型的一些解析


    1.🧀 回顾继承

    那么在上一篇博客Java继承中,我们大致分析了继承的概念如何用父类和子类之间的关系来实现,以及各种应用场景,我们也另外分析了super,protected以及final在其中所起到的作用,并且介绍了组合的概念
    image.png
    那么接着上一篇的继承,我们在这一篇博客中介绍多态。

    2.🥗 多态

    2.1🥙 多态的概念

    多态的概念:通俗来说,就是多种形态,那么在Java中,就是去完成某个行为,当不同的对象去完成时会产生不同的状态和表现
    举两个简单的例子
    无标题23.png
    猫和狗.png
    总的来说:同一件事,发生在不同对象身上,就会产生不同的结果

    2.2🥪 多态实现条件

    在Java中要实现多态,那么必须要满足以下几个条件,缺一不可:

    1. 必须在继承体系下
    2. 子类必须要对父类中的方法进行重写
    3. 通过父类的引用调用重写的方法

    多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。

    public class Animal {
        String name;
        int age;
    
        public Animal(String name,int age){
            this.name = name;
            this.age = age;
        }
        public void eat(){
            System.out.println(name+"吃饭");
        }
    }
    
    public class Cat extends Animal{
    
        public Cat(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void eat() {
            System.out.println(name+"吃鱼");
        }
    }
    
    public class Dog extends Animal{
    
        public Dog(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void eat() {
            System.out.println(name+"吃骨头");
        }
    }
    
    分割线/
    public class TestAnimal {
        //编译器在编译代码的时候,并不知道要调用Dog还是Cat中eat的方法
        //等程序运行起来之后,形参a引用的具体对象确定后,才知道调用哪个方法
        //此时要注意:此处的形参类型必须是父类类型才可以,也就是向上转型
        public static void eat(Animal animal){
            animal.eat();
        }
        public static void main(String[] args){
            Cat cat = new Cat("元宝",2);
            Dog dog = new Dog("小七",1);
    
            eat(cat);
            eat(dog);
        }
    }
    

    运行结果👇
    image.png
    在上述代码中,分割线上方的代码是类的实现者 编写的,分割线下方的代码是类的调用者编写的
    当类的调用者在编写eat();这个方法的时候,参数类型为Animal(父类),此时在该方法内部并不知道,也并不关注当前的animal引用指向的是哪个类型(哪个子类)的实例。此时animal这个引用调用eat方法可能会又多种不同的表现(和animal引用的实例对象相关),这种行为就叫做多态

    2.3🌮 重写

    重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等进行重新编写的一个过程,返回值和形参都不能改变即外壳不改变,核心重写
    重写的好处在于子类可以根据需要,定义特定的属于子类自己的行为。
    也就是说子类能够根据需要来实现父类的方法,又和父类的方法不完全一样,实现自己的特色

    2.3.1 🤯 [方法重写的规则]

    • 子类在重写父类的方法时,一般必须与父类方法原型一致:修饰符 返回值类型 方法名(参数列表)要完全一致
    • JDK7以后,被重写的方法返回值类型可以不同,但是必须是具有父子关系
    • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为protected
    • 父类被static、private修饰的方法都不能被重写
    • 子类和父类在同一个包中,那么子类可以重写父类中的所有方法,除了声明为private和final的方法
    • 子类和父类不在同一个包中,那么子类只能够重写父类的 声明为public 和protected的非final方法
    • 重写的方法,可以使用 @Override 注解来显式指定。有了这个注解能够帮我们检查这个方法有没有被正确重写。例如不小心讲方法名拼写错了,此时编译器就会发现父类中并没有这个方法,就会编译报错,构不成重写。

    image.png

    2.3.2 🤯 [generate小技巧]

    我们右击,点击generate,然后发现这个选项
    image.png
    image.png
    这样就可以自动生成重写的方法了
    image.png

    2.3.3 🤯 [重写和重载的区别]

    区别点重载(overloading)重写(override)
    参数列表必须修改一定不能修改
    返回类型可以修改一定不能修改
    访问限定符可以修改不能做出更严格的限制(子类权限大于父类)

    即:方法重载式一个类的多态性的表现,而方法重写式子类与父类的一种多态性表现
    11.png
    image.png

    2.3.4🤯 [重写的设计原则]

    对于已经投入使用的类,我们要做到尽量不去进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。
    例如:若干年前的手机,只能打电话,发短信,来电显示只能显示号码,而今天的手机在来电显示的时候,不仅仅可以显示号码,还可以显示头像,地区等。在这个过程中,我们不应该在原来的老的类上进行修改,因为原来的类可能还有用户在使用,直接修改会影响到这些用户的使用效果,正确做法应该是新建一个手机的类,对来电显示这个方法重写就好了,这样就达到了我们当今的需求
    112.png

    🥫 静态绑定

    也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用哪个方法。
    典型代表函数重载

    🫔 动态绑定

    也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用哪个类的方法

    2.4🌯 向上转型和向下转型

    2.4.1🍠 向上转型

    image.png
    向上转型:实际上就是创建一个子类对象,将其当成父类对象来舒勇
    语法格式: 父类类型 对象名 = new 子类类型();

    Animal animal = new Cat("元宝"2);
    

    animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换

    无标题.png
    猫和狗都是动物,因此将子类对象转化为父类引用时合理的,大范围可以囊括小范围,是安全的
    🐲【使用场景】

    1. 直接赋值
    2. 方法传参
    3. 方法返回
    public class TestAnimal {
        //2.方法传参:形参为父类型引用,可以接受任意子类的
        public static void eatFood(Animal a){
        a.eat();
        }
        
        //3.作为返回值:返回任意子类对象
        public static Animal buyAnimal(String var){
            if("狗"==var){
                return new Dog("狗狗"1);
            }else if("猫"==var){
                return new Cat("猫猫",1);
            }else{
                return null;
            }
        }
        public static void main(String[] args){
            //1.直接赋值:子类对象赋值给父类对象
            Animal cat = new Cat("元宝"2);
            Dog dog = new Dog("小七",1);
            
            eatFood(cat);
            eatFood(dog);
            
            Animal animal = buyAnimal("狗");
            animal.eat();
            
            animal = buyAnimal("猫");
            animal.eat();
        }
    }
    

    向上转型的优点:让代码实现更加简单灵活
    向上转型的缺陷:不能调用到子类特有的方法

    2.4.2🥩 向下转型

    将一个子类对象经过向上转型之后当成父类对象使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。
    image.png

    public class TestAnimal {
        Cat cat = new Cat("元宝",2);
        Dog dog = new Dog("小七",1);
        
        //向上转型
        Animal animal = cat;
        animal.eat();
        animal = dog;
        animal.eat();
        
        //下面这种情况会编译失败
        //编译时编译器将animal当作Animal的对象处理
        //而Animal类中并没有bark方法,因此编译就会失败
        //animal.bark();
        
        //向上转型
        //程序可以通过编译,但是运行的时候还是会抛出异常
        //因为:animal实际上指向的是狗的对象
        //现在要强制还原为猫则无法正常还原,运行时抛出:ClassCastException
        cat = (Cat)animal;
        cat.mew();
        
        //animal本来指向的就是狗,因此将animal还原为狗也是安全的
        dog = (Dog)animal;
        dog.bark();
    }
    

    向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛出异常。Java中为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转换

    public class TestAnimal {
        public static void main(String[] args){
            Cat cat = new Cat("元宝",2);
            Dog dog = new Dog("小七",1);
            
            //向上转型
            Animal animal = cat;
            animal.eat();
            animal = dog;
            animal.eat();
            
            if(animal instanceof Cat){
                cat = (Cat)animal;
                cat.mew();
            }
            
            if(animal instanceof Dog){
                dog = (Dog)animal;
                dog.bark();
            }
        }
    }
    

    2.5🍗 多态的优缺点

    使用多态的好处
    1.能够降低代码的“圈复杂度”,避免使用大量的if-else

    什么叫“圈复杂度”?
    圈复杂度是一种描述一段代码复杂程度的方式。
    一段代码如果平铺直叙,那么就比较简单容易理解。
    而如果有很多的条件分支或者循环语句,就认为理解起来更复杂
    因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数,这个 数就称为“圈复杂度”。如果一个方法的圈复杂度太高,就需要考虑重构
    不同公司对于代码的圈复杂度的规范不一样,一般不会超过10

    例如我们现在需要打印的不是一个形状了,而是多个形状,如果不基于多态,实现代码如下👇

    public class DrawShapes {
        Rect rect = new Rect();
        Cycle cycle = new Cycle();
        Flower flower = new Flower();
        String[] shapes = {"cycle","rect","cycle","rect","flowers"};
    
        public static void main(String[] args) {
            Rect rect = new Rect();
            Cycle cycle = new Cycle();
            Flower flower = new Flower();
            String[] shapes = {"cycle","rect","cycle","rect","flower"};
            for(String shape:shapes){
                if(shape.equals("cycle")){
                    cycle.draw();
                }else if(shape.equals("rect")){
                    rect.draw();
                }else if(shape.equals("flower")){
                    flower.draw();
                }
            }
        }
    }
    

    输出结果为👇
    image.png
    如果使用多态,则不必写出这么多的if-else分支语句,代码将更加简单

        public static void drawShapes(){
            Shapes[] shapes = {new Cycle(),new Rect(),new Cycle(),
                               new Rect(),new Flower()};
            for(Shapes shape = shapes){
                shape.draw();
            }
        }
    

    2.可扩展能力更强
    如果要新增一种新的形状,使用多态的方式代码改动成本也比较低

    class Triangle extends Shape {
        @Override
        public void draw(){
            System.out.println("▲");
        }
    }
    

    对于类的调用者来说,(drawShapes方法),只要创建一个新类的实例就可以了,改动成本很低。
    而对于不用多态的情况,就要把drawShapes中的if-else进行一定的修改,改动成本更高
    多态的缺陷:代码运行的效率降低

    2.6🍖 避免在构造方法中调用重写的方法

    这里介绍一个埋着坑的代码,我们创建两个类,B是父类,D是子类,D中重写了func的方法。并且B的构造方法中调用了func

    class B{
        public B(){
            func();
        }
        public void func(){
            System.out.println("B.func()");
        }
    }
    class D extends B{
        private int num = 1;
        public void func(){
            System.out.println("D.func()"+num);
        }
    }
    public class Test {
        public static void main(String[] args){
            D d = new D();
        }
    }
    

    image.png
    为啥这里的执行结果是0而不是1捏?

    • 构造D对象的时候,会调用B的构造方法。
    • B的构造方法中调用了func方法,此时会触发动态绑定,会调用到D中的func
    • 此时D对象自身还没有构造,此时num处在未初始化的状态,值为0

    结论:“用尽量简单的方式使对象进入可工作状态”,尽量不要在构造器中调用方法(如果这个方法被子类重写,就会触发动态绑定,但是这个时候子类对象还没有构造完成),可能就会出现一些隐藏的且极难被发现的问题。

    多态就介绍到这里
    希望能帮到你
    感谢阅读~

    展开全文
  • 我们都知道在java中,面向对象有三大特征,封装,继承,和多态。封装隐藏实现细节,对外提供享用的访问方式,而且提高了代码的复用性。在事物对象有相同的属性和共同的内容的时候,我们可以把相同的内容的抽取出来,...
  • 当然有些学过java的应该知道,在java中会输出两次in Derived::init() 由于多态的原因。 那为什么在C++中而是一次in Base::init() 一次in Derived::init()呢? 一位大佬解释说 “在基类的构造函数中调用init(),执行...
  • 关于java实现多态的文章早已是非常多了,本文是对我个人过往学习java,理解及应用java实现多态的一个总结。此文内容涉及多态的基本概念,...多态好处: 1、可替换性(substitutability)。 多态对已存在代码具有可
  • 本篇文章给大家带来的内容是什么是java多态?java多态的使用,通过游戏中的一些功能带你掌握多态的使用。下面由动力节点java学院小编为大家一一介绍什么是java多态java多态的使用。希望对大家有帮助。为什么要使用...
  • 继承和多态 一,类的继承 1,继承的实现 语法格式: class 子类名 extends 父类名{ 类体 } 注:extends是关键字,Java中只支持单继承,所以子类只有一个父类,但可以多层继承,子类通过继承可以获得父类的public,...
  • Java多态Java内部类

    2021-08-03 19:56:43
    Java多态Java内部类
  • Java面试题】谈谈对Java多态的理解
  • java多态

    2022-07-29 21:58:40
    使用父类作为方法的形参,是Java中实现和使用多态的主要方式之一。向上转型将父类的引用指向子类对象,称为向上转型,自动进行类型转换。多态同一个引用类型,使用不同的实例而执行不同操作。(3)父类的引用指向...
  • 今天记录一下学习过程中golang与java多态的对比。 一、Golang 在golang中,多态主要是通过接口实现的。 可以按照同一的接口来调用不同的实现,这时接口变量就呈现不同的形态 并且相对于java,少了extends和...
  • Java多态 和 Python多态

    2022-03-18 23:34:59
    Java多态和Python多态 ava中的多态跟Python中的多态是有区别的。 java中的多态定义: 多态存在的三个必要条件 一、要有继承; 二、要有重写; 三、父类引用指向子类对象 java 多态演示 public class Test { public ...
  • 什么是多态JAVA多态 方法必须要被所在类或对象调用才有意义 若方法含有参数: 形参:方法声明时的参数。 实参:方法调用时实际传给形参的参数值。 JAVA里将实参数值传入方法的传递机制只有 值传递 在值...
  • Java继承与多态(多态篇)

    多人点赞 热门讨论 2022-05-17 10:12:43
    写在前面: 博主主页:戳一戳,欢迎大佬指点! 博主秋秋:QQ:1477649017 欢迎志同道合的...多态一,多态概念二,多态的实现条件2.1,向上转型2.2,重写父类方法2.3,通过父类引用调用重写的方法2.4,整体代码三,向..
  • JAVA多态图文详解ppt

    2018-03-20 16:46:02
    JAVA多态图文详解ppt,详细通过各种举例介绍JAVA多态的ppt
  • java多态

    2022-04-26 19:58:03
    多态的概念 多态是面向对象程序设计的一个重要特征,指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。可以理解成,多态就是同一个接口,使用不同的实例而执行...
  • 下面要给大家分享的是一个多态经典案例,一起来看看这个java多态简单例子吧。/*多态好处:提高了代码的维护性和扩展性;弊端:父类不能使用子类的特有功能。要用子类的特有功能,可以:A:创建子类对象,调用方法...
  • Java 多态的实现机制

    2021-03-17 22:33:10
    (给ImportNew加星标,提高Java技能)转自:博客园,作者:crane_practice链接:www.cnblogs.com/crane-practice/p/3671074.html是父类或接口定义的引用变量可以指向子类或实现类的实例对象,而程序调用的方法在运行期...
  • 什么是Java多态?如何实现Java多态

    千次阅读 2021-06-29 10:54:20
    java多态这个概念在同学们深入学习java的时候就会被提出,很多同学并不知道是什么意思,如何实现。今天小千就来给大家介绍一下什么是java多态java如何实现多态。 什么是多态? 指允许不同类的对象对同一消息做出...
  • java继承和多态

    千次阅读 多人点赞 2021-10-08 21:38:20
    继承和多态 文章目录继承和多态继承多态 继承 多态
  • Java多态详解

    2022-04-21 09:52:05
    基本介绍1.1 多态的概念1.2 对象的多态1.3 入门案例2. 具体细节2.1 向上转型2.2 向下转型2.3 instanceOf 比较操作符3. 实现技术:动态绑定4. 应用4.1 多态数组4.2 多态参数5. 多态的优点 1. 基本介绍 1.1 多态的...
  • Java中接口的多态

    2022-02-08 11:11:48
    多态参数 就像我们现实生活中电脑的usb接口,我们既可以接受手机对象,又可以接受相机对象,等等,体现了接口的多态,查看以下代码 接口: package InterfaceM; public interface Interface { public void join...
  • java的编译时多态和运行时多态,保证一看就会
  • java参数多态

    2022-02-02 10:49:16
    /* 多态参数: 方法定义的形参类型为父类类型,实参类型允许为子类类型 */ public class PloyParameter { public static void main(String[] args) { Employee worker = new Worker("worker01",3000); Employee ...
  • 西 安 邮 电 大 学 计算机学院 课内实验报告 实验名称 继承与多态 专业名称 计算机科学...Java 语言的继承和多态特性 掌握变量的隐藏 方法的覆盖 重载掌握抽象类和接口的使用 二实验要求 1.编写体现类的继承性成员变量
  • JAVA中的继承和多态

    2022-04-04 21:33:25
    JAVA中的继承和多态 1.首先,我们先看一段代码 class Parentclass { void pprint() { this.print(); this.print1(0); } void print() { System.out.println("父类:同类型、同名、同参数成员方法!"); } ...
  • Java——封装继承多态

    2022-06-11 20:16:20
    封装 将方法和属性封装到一个对象中,对外提供方法用于改变该对象的属性值。该代码中定义了Person类,...多态顾名思义就是多种形态,代码在运行时可以有多种形态。如果要满足多态,则有一些前置条件。就是必须有子类和

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 263,253
精华内容 105,301
关键字:

多态的好处java