day12 Final、多态、抽象类、接口、Object

1.Final
    1.是什么
        是个修饰符,表示最终的,不可修改的。
    2.能做什么
        final修饰的类不能被继承
        final修饰的成员方法不能被覆写
        final修饰的变量不能二次赋值,没有默认值,必须显式赋值
        一般我们把final修饰的静态变量叫做 常量 ,也就是public static final 数据类型 变量名 = 值;
        注: final、static、public没有先后顺序,都是修饰符
    
    3.怎么用
        final修饰的类不能被继承
            final class A{
            }
            class B extends A{                  //此时A报错
            }
        final修饰的成员方法不能被覆写
            class A {
                public final void m1(){
                }
            }
            class B extends A{
                public void m1(){            //此时m1报错 
                }
            }
        final修饰的变量,不能二次赋值
            final int i = 2;
            i = 3;
        final修饰的成员变量没有默认值,并且不能二次赋值

        final修饰的静态变量没有默认值,不能二次赋值,一般pfs会一起出现,简称常量
            public final static int AGE = 18;
    
    4.修饰引用类型
        public class Final {
            //常量名建议全部大写
            public final static int AGE = 18;
            final static public void main(String[] args){
            int AGE = 0;  
            final Customer c = new Customer("张三",18);
            c.age = 19;
            c.name = "李四";
            }
        }
        class Customer{
            String name;
            int age;
            
            public Customer(String name,int age){
                super();
                this.name = name;
                this.age = age;
            }
        }

2.多态
    1.是什么
        父类引用指向子类对象

        父类引用:指的是用父类型声明的引用类型变量
        指向:通过内存地址可以找到哪个对象
        子类对象:new子类 创建的堆内存对象
        子类 变量 = new 子类();
        Cat c = new 子类();
        多态调用方法:父类.类名 = new 子类();
        Animal a = new Cat();
        注:只继承成员方法

    2.相关知识
        软件设计六大原则:
            1.单一职责原则:功能单一,只拥抱一种变化
            2.里氏替换原则:能使用父类的情况下,一定可以使用子类
            3.依赖倒置原则:细节应该依赖抽象,而抽象不应该依赖细节
            4.接口隔离原则:先不管
            5.迪米特法则:最少知识原则,和其他类或对象尽可能有更少的了解
            6.开闭原则:对修改关闭,对扩展开放
    
    3.优点
        同一操作,作用于不同对象,可以有不同的解释,产生不同的结果,这就是多态性

        当一件事会有多种不同实现的方式的时候,我们选择依赖高层,来拥抱多种变化(曹操问文官)
        本质还是降低类和细节之间的耦合度    
    
        多态的缺点 : 丢失子类特有的属性

        多态进行属性调用 : 
            1 如果父类没有 ,直接报错,不管子类有没有      
            2 如果父类有,子类没有, 直接执行父类  
            3 父类和子类都有, 成员方法执行子类,因为成员方法可以覆写,其他的都执行父类 
        
         多态又叫向上转型

        public class Poly_03 {
            public static void main(String[] args) {
                // 多态
                SupClass sup = new SubClass();
                // 父类和子类都有的成员方法 , 执行子类
                sup.m1();
                // 父类没有,子类有,报错,访问不了
                // sup.m2();
                // 父类有,子类没有,执行父类
                sup.m3();
                // 父类和子类都有的 静态方法  执行父类
                sup.m4();
                // 成员变量,也是执行父类
                System.out.println(sup.i);
                
                // 此时 由于多态原因,子类特有属性访问不到,想要访问也行,先进行向下转型
                // 必须先发生向上转型,才能发生向下转型
                SubClass sub = (SubClass) sup;
                sub.m2();
                
                // 没有发生向上转型,如果直接使用向下转型 会报错
                SupClass sup1 = new SupClass();
                // 类型转换异常
                // SubClass sub1 = (SubClass) sup1;
                
                // instanceof : 判断 某个对象是否由某个类实例化而来
                if ( sup1 instanceof SubClass) {
                    // 如果是 在向下转型,不是就不转,可以避免类型转换异常
                    SubClass sub1 = (SubClass) sup1;
                }
            }
        }

        class SupClass {
            int i = 1;

            public static void m4() {
                System.out.println("父类静态方法m4");
            }

            public void m1() {
                System.out.println("父类成员m1");
            }

            public void m3() {
                System.out.println("父类成员m3");
            }
        }

        class SubClass extends SupClass {
            public static void m4() {
                System.out.println("子类静态方法m4");
            }

            int i = 2;

            public void m1() {
                System.out.println("子类成员m1");
            }

            public void m2() {

            }
        }

    
    6.多态的几种形式
        父类引用指向子类对象

        1.直接多态
            Sup sup = new Sub();
        2.形参和实参,方法参数列表为父类类型,调用方法传入子类对象
            m1(new Sub());
        3.返回值多态,返回值类型是父类类型,但是返回子类对象
            Sup result = m2();
    
    7.Instanceof
        判断某个对象是否由某个类实例化而来
            if(sup instanceof SubClass){           SupClass sup1 = new SupClass(); //sup1由SupClass实例化而来
                SubClass sub1 = (SubClass)sup1;
            }

3.abstract
    1.是什么
        修饰符,修饰的类 是抽象类,修饰的方法是抽象方法
        抽象类不能实例化
        抽象方法,没有方法体,只定义功能,没有功能的实现,并且抽象方法必须在抽象类中
        反之,抽象类中,可以没有抽象方法
        
        abstract不能和final同时出现

    2.使用方法
        //动物吃饭的功能
        abstract class Animal{
            public abstract void eat();
            public void m1(){
            
            }
        }
        //实现
        class Cat extends Animal{
            public void eat(){

            }
        } 
    
4.Interface
    1.是什么
        接口,可以理解为完全抽象的一个类,里面只有抽象方法和常量
        但是1.8开始,允许出现静态方法和默认方法

        语法   修饰符 interface 接口名 {}
        接口中的抽象方法不需要加abstract修饰,方法默认都是 public  abstract
        接口中,没有变量,只有常量,并且 public static final 可以省略

        类和接口之间,不再是继承关系,变成了实现关系,由 extends 换成了implements

        接口名 变量 = new 子实现类() 也是会发生多态的

        一个类 只能继承一个类,但是可以实现N个接口,以 逗号 隔开,可以解决单继承功能变弱问题

            class 类名 implements 接口1,接口2……{}

        接口和接口之间是多继承,多个 逗号 隔开
            interface 接口名 extends 父接口名1,父接口名2……

        一个类如果实现了一个接口,那么必须实现接口中所有的抽象方法,否则该类需要加abstract修饰
        一个抽象类,实现一个接口,可以实现0~N个抽象方法

        1.7 只能有抽象方法
        1.8 可以有静态方法,也可以有default方法(就理解为成员方法即可)
                静态方法,用接口名调用即可
                 default 方法需要同过子实现类调用,同时也可以覆写
        1.9 开始 支持 private方法

    2.使用方法
        interface A{
            public static final String name ="xx";
            // psf可以省略
            int age = 2;
            
            public abstract void m1();
            // public和abstract可以省略
            void m2();
            public default void m3(){
                System.out.println("默认方法");
            }
            public static void m4(){
                System.out.println("静态方法");
            }
            }
            interface B{
                
            }
            // 多继承
            interface C extends B,A{
                
            }
            // 多实现,需要实现所有的抽象方法
            class D implements A,B,C{
                @Override
                public void m1() {
                    
                }
                @Override
                public void m2() {
                    
                }
            }
            // 抽象类,可以实现0~N个抽象方法
            abstract class E implements A,B,C{
                
            }

5.Object
    1.概述
        所有类的祖类
        一个类没有显示继承另一个类的时候,默认继承object
        Object xx = new xxx():是可以发生多态的

    2.Equals
        ==:比较基本类型的时候,比较值的大小,比较引用类型的时候,比较的是内存地址
        而比较内存地址是没有任何价值的,我们一般会比较两个对象的属性值,是否一致,而不是比较两个对象地址是否一致
        equals():该方法设计目的是用来比较两个对象是否相等,但是默认比较地址
        java中Object里面的equals方法默认比较内存地址(==)需要我们根据需求进行重写

        //需求:如果两个学生ID和姓名相同,则认为这两个是同一个学生
        public boolean equals(Object obj){
            if(obj instanceof Srudent){
                Student s2 = (Student) obj;
                if(this.id == s2.id && this.name.equals(s2.name){
                ruturn true;
            }
            }
            return false;
        }

    3.finalize
        该方法会在垃圾被回收的时候自动调用,无须程序员手动调用
        垃圾:当一个对象没有更多引用指向它的时候,该对象被视为垃圾数据(就是创建了一个对象,谁也找不到它)
        
        protected void finalize() throws Throwable()
        Object中的finalize方法什么也没有做,需要自己根据需求进行重写

    4.toString
        代表了当前对象的字符串表示形式
        当我们打印一个引用类型变量的时候会自动调用该方法的toString方法
        而Object中默认的toString方法是打印该对象的内存地址(hash值)
   
    
  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值