• 大数据学习--day11(抽象类、接口、equals、compareTo)


    抽象类、接口、equals、compareTo

    什么是抽象方法  ?

        区分于正常的方法  
        1.使用了 abstract 修饰符 
            该修饰符修饰方法 则该方法就是抽象方法 该修饰符修饰类 , 则该类就是抽象类
        2. 没有方法体 
        3. 小括号之后用 分号 作为结尾 

    什么是抽象类  ?

            abstract 修饰的类就是抽象类  
            抽象类可以认为是 部分抽象的类 
            后期还有 完全抽象
            这里的抽象 指的是内部中无法描述的部分  -> 抽象方法

    抽象类 可以包含什么成员  ?

            1. 属性
            2. 静态字段 类变量 
            3. 构造器
            4. 正常方法 
            5. 静态方法
            6. 抽象方法

    抽象类的特性  

            1. 必须 abstract 修饰
            2. 可以有构造器 , 但是不能 实例化对象  不能     new 构造器([实参]);
            3. 抽象类也是类  比较特殊的一种类  , 可以继承正常类 也可以继承抽象类    单继承
            4. 抽象类可以被继承 但是继承抽象类 和 继承普通的类有所不同
            5. 抽象类中 可以没有抽象方法

    抽象类的应用场景

            经常作为底层的抽象基类存在 
            例如在集合家族中  , 扮演了 接口(完全抽象) 和 正常类 中间的 缓冲环节
            抽象类是 完全抽象  -> 部分抽象  -> 正常类 , 中间的过渡

    接口

    接口中 可以包含什么成员  ?    

            1. 公共的public  静态的static  常量final
                不写的话 默认就是 public static final 修饰的
                如果更改权限 那么报错
            2. 公共的抽象方法
                不写的话 默认就是 public abstract 修饰的
                规定其他的修饰符 例如 static final 会报错

    接口的特性 : 

            1. 接口不可以实例化对象
            2. 接口可以继承接口 接口是多继承 , 多个父接口用 逗号 隔开  关键字仍然用 extends
                    接口继承接口之后  会继承父接口的抽象方法 , 即继承了 规范和要求
            3. 类 可以实现接口 , 实现和继承会有所不同
                    继承指的是 类继承类 , 接口继承接口     extends 
                    实现指的是 类 实现 接口    implements
                    类实现接口之后 , 接口类型也是类的父类型 , 也可以方法重写  , 也可以多态
                    类和接口是多实现的 , 一个类可以实现多个接口  , 多个父接口用逗号隔开    
            4. 接口是引用数据类型 接口类型引用可以存储子类对象 

    抽象类 和 接口的 异同

    你选择使用接口和抽象类的依据是什么?

    接口和抽象类的概念不一样。
    接口是对动作的抽象,抽象类是对根源的抽象。
     抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。 人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它. 
    所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。
     
     当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。 
     抽象类的功能要远超过接口,但是,定义抽象类的代价高。
    因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的 所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。
     
     下面看一个网上流传最广泛的例子:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:
    abstract class Door {
        public abstract void open();
        public abstract void close();
    }

    或者:

    interface Door {
        public abstract void open();
        public abstract void close();
    }

    但是现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?下面提供两种思路:

      1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;

      2)将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的open( )和close( ),也许这个类根本就不具备open( )和close( )这两个功能,比如火灾报警器。

      从这里可以看出, Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口

    interface Alram {
        void alarm();
    }
     
    abstract class Door {
        void open();
        void close();
    }
     
    class AlarmDoor extends Door implements Alarm {
        void oepn() {
          //....
        }
        void close() {
          //....
        }
        void alarm() {
          //....
        }
    }

    equals、Comparable

    两个类比较,比较的是地址

    重写equals方法,每个属性比较相等。要比较大小,实现接口。

    public class Person implements Comparable{
        public String name;
        private int age ;
        private boolean sex;
        public Person() {
            // TODO Auto-generated constructor stub
        }
        public Person(String name , int age, boolean sex) {
            super();
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public boolean isSex() {
            return sex;
        }
        public void setSex(boolean sex) {
            this.sex = sex;
        }
        
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
        }
        
        
        
        /**
         * 如果有属性是引用数据类型 , 一定不能 == 来比较
         * 而是调用属性对象的 equals 方法 
         */
        
        /**
         *     instanceof    关系运算符  
         *  使用格式 : 
         *      对象 instanceof 类名 ; 
         *  返回 布尔值
         *  如果 对象是该类的对象 , 那么返回true  反之false
         *  
         */
        /**
         * 基本数据类型强转 : 可能会丢失数据
         * 引用数据类型强转 : 可能会有类型不匹配异常  java.lang.ClassCastException
         *                       如果没有继承关系 不能强转
         */
        
        @Override
        public boolean equals(Object obj) {
            if( this == obj)
                return true;
            
            // 判断 obj 是本类对象
            if( !(obj instanceof Person) )
                return false;
                
            // 引用数据强转  经过判断之后可以放心的强转了
            Person p = (Person)obj;
            
            // 接下来是 具体的判断是否相等的 业务逻辑
            if( this.age == p.age)
                if(this.sex == p.sex)
                    if(this.name.equals(p.name)) 
                        return true;
            
            return false;
        }
        
        
        /**
         * 1. 判断参数是不是本类对象
         * 2. 书写具体的比较规则
         */
    //    @Override
    //    public int compareTo(Object o) {
    //        if( !(o instanceof Person) )
    //                return 0 ; // 类型不一样 没办法比 直接给结果
    //        
    //        // 强转
    //        Person p = (Person)o;
    //        
    //        // 此次比较完全按照 age 比较
    //        int result = this.age - p.age;
    //        System.out.println("Person.compareTo("+result+")");
    //        return result;
    //    }
        
        
    //    @Override
    //    public int compareTo(Object o) {
    //        if( !(o instanceof Person) )
    //            return 0 ; // 类型不一样 没办法比 直接给结果
    //        
    //        // 强转
    //        Person p = (Person)o;
    //        
    //        // 此次比较完全按照 sex 比较
    //        // 先规定 true = 0  false = 1 ;
    //        int result = (this.sex ? 0 : 1)  - (p.sex ?  0 : 1);
    //        System.out.println("Person.compareTo("+result+")");
    //        return result;
    //    }
        
        
    //    @Override
    //    public int compareTo(Object o) {
    //        if( !(o instanceof Person) )
    //            return 0 ; // 类型不一样 没办法比 直接给结果
    //        
    //        // 强转
    //        Person p = (Person)o;
    //        
    //        // 此次比较按照 age sex 比较    规定 true = 0  false = 1 
    //        // 先按照age比较 , age 相等 按照 sex 比
    //        
    //        int result = this.age - p.age ;
    //        if( result == 0 ) // 相等
    //            return (this.sex ? 0 : 1)  - (p.sex ?  0 : 1); // age 相等 return sex 的结果
    //        
    //        return result;// age 不等 , 直接 return age 的比较结果
    //    }
        
        
        @Override
        public int compareTo(Object o) {
            if( !(o instanceof Person) )
                return 0 ; // 类型不一样 没办法比 直接给结果
            
            // 强转
            Person p = (Person)o;
            
            // 此次比较按照 age sex  name比较    规定 true = 0  false = 1 
            // 先按照age比较 , age 相等 按照 sex 比  , sex 相等按照 name
            
            int result = this.age - p.age ;// age 的结果
            if( result == 0 ){ // 相等
                result = (this.sex ? 0 : 1)  - (p.sex ?  0 : 1); // sex 的结果
                if(result ==  0)
                    return this.name.compareTo(p.name);
            }
            return result;
        }
    }
    
    
    
    
    
    import java.util.Arrays;
    
    public class Test {
        public static void main(String[] args) {
            Person p = new Person("张三a",18, true);
            Person p2 = new Person("张三c",18, true);
            Person p3 = new Person("张三2",20, true);
            Person p4 = new Person("张三3",18, false);
            Person p5 = new Person("张三b",18, true);
            
            Person[] ps = {p , p2 , p3 , p4 , p5};
            
            // 直接把 Person 数组给Arrays 排序
            Arrays.sort(ps);
            // java.lang.ClassCastException: com.equals.Person cannot be cast to java.lang.Comparable
            
            System.out.println("=============================");
            for (Person person : ps) {
                System.out.println(person);
            }
        }
    }

      

  • 相关阅读:
    004-spring cache-声明性的基于XML的缓存
    003-spring cache-JCache (JSR-107) annotations
    002-spring cache 基于注解的缓存-02详细-Cacheable 、CachePut、CacheEvict、Caching、CacheConfig、EnableCaching、自定义
    002-spring cache 基于注解的缓存-01-关键注解概述、spel、缓存Key 与 缓存解析器
    001-springboot cache 简介、基础使用
    tools-eclipse-004-UML图安装
    001-Spring的设计理念和整体架构
    java-信息安全(十八)java加密解密,签名等总结
    005-java的Annotation
    002-原始jpa以及基本加载过程,基本sql使用
  • 原文地址:https://www.cnblogs.com/symkmk123/p/9688641.html
Copyright © 2020-2023  润新知