zoukankan      html  css  js  c++  java
  • Java基础(五)

    1、笔记

    1、抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
    抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。
    
    如何使用抽象类和抽象方法:
        1. 不能直接创建new抽象类对象。
        2. 必须用一个子类来继承抽象父类。
        3. 子类必须覆盖重写抽象父类当中所有的抽象方法。 ---> 类似Python中abc.py中的一个方法
        覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
        4. 创建子类对象进行使用。
    
    2、注意事项
    关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。
        1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
        理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
        2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
        理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
        3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
        理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
        4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类(此时可以重写抽象父类的部分方法,剩下的方法给继承它的子类重写)。
        理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义
    
    3、接口就是多个类的公共规范。
    
    接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么
    接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法
    (JDK 9)。
    接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并
    不是类,而是另外一种引用数据类型。
    引用数据类型:数组,类,接口。
    接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做
    是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象
    类。
    
    接口是一种引用数据类型,最重要的内容就是其中的:抽象方法。
    
    如何定义一个接口的格式:
    public interface 接口名称 {
        // 接口内容
    }
    
    备注:换成了关键字interface之后,编译生成的字节码文件仍然是:.java --> .class。
    
        如果是Java 7,那么接口中可以包含的内容有:
        1. 常量
        2. 抽象方法
    
        如果是Java 8,还可以额外包含有:
        3. 默认方法
        4. 静态方法
    
        如果是Java 9,还可以额外包含有:
        5. 私有方法
    
    4、接口使用步骤:
        1. 接口不能直接使用,必须有一个“实现类”来“实现”该接口。
        格式:
        public class 实现类名称 implements 接口名称 {
            // ...
        }
        2. 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。
        实现:去掉abstract关键字,加上方法体大括号。
        3. 创建实现类的对象,进行使用。
    
        注意事项:
        如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
    
    5、在任何版本的Java中,接口都能定义抽象方法。
    格式:
    public abstract 返回值类型 方法名称(参数列表);
    
        注意事项:
        1. 接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
        2. 这两个关键字修饰符,可以选择性地省略。(今天刚学,所以不推荐。)
        3. 方法的三要素,可以随意定义。
    
    6、从Java 8开始,接口里允许定义默认方法。
    格式:
    public default 返回值类型 方法名称(参数列表) {
        方法体
    }
    
    备注:接口当中的默认方法,可以解决接口升级的问题。 ---> 原来继承它的类不用重写该方法
    
    71. 接口的默认方法,可以通过接口实现类对象,直接调用。
        2. 接口的默认方法,也可以被接口实现类进行覆盖重写。
        3. 可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。
    
    8、从Java 8开始,接口当中允许定义静态方法。 ---> 跟python中的类方法一样,只跟类有关
    格式:
    public static 返回值类型 方法名称(参数列表) {
        方法体
    }
    提示:就是将abstract或者default换成static即可,带上方法体。
    
    9、注意事项:不能通过接口实现类的类名或对象来调用接口当中的静态方法。
    正确用法:通过接口名称,直接调用其中的静态方法。
    格式:
    接口名称.静态方法名(参数);
    
    10、
    问题描述:
    我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。
    但是这个共有方法不应该让实现类使用,应该是私有化的。
    解决方案:
    从Java 9开始,接口当中允许定义私有方法。
        1. 普通私有方法,解决多个默认方法之间重复代码问题
        格式:
        private 返回值类型 方法名称(参数列表) {
            方法体
        }
    
        2. 静态私有方法,解决多个静态方法之间重复代码问题
        格式:
        private static 返回值类型 方法名称(参数列表) {
            方法体
        }
    
    11、接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
    从效果上看,这其实就是接口的【常量】。
    格式:
    public static final 数据类型 常量名称 = 数据值;
    备注:
    一旦使用final关键字进行修饰,说明不可改变。
    
        注意事项:
        1. 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
        2. 接口当中的常量,必须进行赋值;不能不赋值。
        3. 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
    
    12、小结
    在Java 9+版本中,接口的内容可以有:
    
        1. 成员变量其实是常量,格式:
        [public] [static] [final] 数据类型 常量名称 = 数据值;
        注意:
            常量必须进行赋值,而且一旦赋值不能改变。
            常量名称完全大写,用下划线进行分隔。
    
        2. 接口中最重要的就是抽象方法,格式:
        [public] [abstract] 返回值类型 方法名称(参数列表);
        注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。
    
        3. 从Java 8开始,接口里允许定义默认方法,格式:
        [public] default 返回值类型 方法名称(参数列表) { 方法体 }
        注意:默认方法也可以被覆盖重写
    
        4. 从Java 8开始,接口里允许定义静态方法,格式:
        [public] static 返回值类型 方法名称(参数列表) { 方法体 }
        注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
    
        5. 从Java 9开始,接口里允许定义私有很乏,格式:
        普通私有方法:private 返回值类型 方法名称(参数列表) { 方法体 }
        静态私有方法:private static 返回值类型 方法名称(参数列表) { 方法体 }
        注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。
    
    13、使用接口的时候,需要注意:
    
        1. 接口是没有静态代码块或者构造方法的。
        2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
        格式:
        public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
            // 覆盖重写所有抽象方法
        }
        3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
        4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
        5. 如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
        6. 一个类中如果父类当中的成员方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
    
    14、接口与接口之间多继承的关系
        1. 类与类之间是单继承的。直接父类只有一个。
        2. 类与接口之间是多实现的。一个类可以实现多个接口。
        3. 接口与接口之间是多继承的。
    
        注意事项:
        1. 多个父接口当中的抽象方法如果重复,没关系。
        2. 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】。
        小贴士:
        1. 子接口重写默认方法时,default关键字可以保留。
        2. 子类重写默认方法时,default关键字不可以保留。
        其他成员特点
        1. 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
        2. 接口中,没有构造方法,不能创建对象。
        3. 接口中,没有静态代码块。
    
    15、多态
    小明是一个对象,这个对象既有学生形态,也有人类形态。
    一个对象拥有多种形态,这就是对象的 多态性。
    
    16、代码当中体现多态性,其实就是一句话:父类引用指向子类对象。
    
    格式:
    父类名称 对象名 = new 子类名称(); ---> 子类被当做父类来使用。eg.一只猫被当做动物来使用
    或者:
    接口名称 对象名 = new 实现类名称();
    
    多态的好处
    定义父类:
    public abstract class Animal {
    public abstract void eat();
    }
    定义子类:
    class Cat extends Animal {
    public void eat() {
    System.out.println("吃鱼");
    }
    }
    class Dog extends Animal {
    public void eat() {
    System.out.println("吃骨头");
    }
    }
    定义测试类:
    public class Test {
    public static void main(String[] args) {
    // 多态形式,创建对象
    Cat c = new Cat();
    Dog d = new Dog();
    // 调用showCatEat
    showCatEat(c);
    // 调用showDogEat
    showDogEat(d);
    /*
    以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代
    而执行效果一致
    */
    showAnimalEat(c);
    showAnimalEat(d);
    }
    public static void showCatEat (Cat c){
    c.eat();
    }
    public static void showDogEat (Dog d){
    d.eat();
    }
    public static void showAnimalEat (Animal a){
    a.eat();
    }
    }
    由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当
    然可以把Cat对象和Dog对象,传递给方法。
    当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致,
    所以showAnimalEat完全可以替代以上两方法。
    不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用
    showAnimalEat都可以完成。
    所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。
    
    17、成员方法才能覆盖重写,成员变量不行
    
    18、多态中访问成员变量的两种方式:
    
        1. 直接通过对象名称访问【成员变量】:看等号【左边】是谁,优先用谁,没有则向上找。 ---> 如果想访问子类的成员变量,可以通过在子类中重写成员方法,间接访问子类的成员变量
        2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
    
    19、在多态的代码当中,成员方法的访问规则是:
        看new的是谁,就优先用谁,没有则向上找。
    
    口诀:编译看左边,运行看右边。
    
    对比一下:
    成员变量:编译看左边,运行还看左边。
    成员方法:编译看左边,运行看右边。
    
    20、
    向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:
    对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
    
    解决方案:用对象的向下转型【还原】。
    
    为什么要转型
    当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。
    
    21、如何才能知道一个父类引用的对象,本来是什么子类?
    格式:
    对象 instanceof 类名称
    这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。
    
    22、final关键字代表最终、不可改变的。
    
        常见四种用法:
        1. 可以用来修饰一个类
        2. 可以用来修饰一个方法
        3. 还可以用来修饰一个局部变量
        4. 还可以用来修饰一个成员变量
    
    23、
    当final关键字用来修饰一个类的时候,格式:
    public final class 类名称 {
        // ...
    }
    
    含义:当前这个类不能有任何的子类。(太监类)
    注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子。)
    
    24、
    当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
    格式:
    修饰符 final 返回值类型 方法名称(参数列表) {
        // 方法体
    }
    
    注意事项:
    对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
    
    25、局部变量
    对于基本类型来说,不可变说的是变量当中的数据不可改变
    对于引用类型来说,不可变说的是变量当中的地址值不可改变
    
    26、成员变量
    对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。
        1. 由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了。
        2. 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一。
        3. 必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。
    
    27、Java中有四种权限修饰符:
                        public  >   protected   >   (default)   >   private
    同一个类(我自己)        YES         YES             YES             YES
    同一个包(我邻居)        YES         YES             YES             NO
    不同包子类(我儿子)       YES         YES             NO              NO
    不同包非子类(陌生人)      YES         NO              NO              NO
    
    注意事项:(default)并不是关键字“default”,而是根本不写。
    
    28、类取名的时候可以有下划线"_"和美元符"$",但是不推荐用"$",因为在定义内部类和外部类的时候,编译器编译后取名会自动带上"$",所以为了避免混淆,自己定义类名称的时候就不要用"$"28、内部类
    如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。
    例如:身体和心脏的关系。又如:汽车和发动机的关系。
    
    分类:
    1. 成员内部类
    2. 局部内部类(包含匿名内部类)
    
    成员内部类的定义格式:
    修饰符 class 外部类名称 {
        修饰符 class 内部类名称 {
            // ...
        }
        // ...
    }
    
    注意:内用外,随意访问;外用内,需要内部类对象。
    
    ==========================
    如何使用成员内部类?有两种方式:
        1. 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
        2. 直接方式,公式:
        类名称 对象名 = new 类名称();
        【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】
    
    29、内部类访问外部类成员变量的方法
    如果出现了重名现象,那么格式是:外部类名称.this.外部类成员变量名
    public class Outer {
    
        int num = 10; // 外部类的成员变量
    
        public class Inner /*extends Object*/ {
    
            int num = 20; // 内部类的成员变量
    
            public void methodInner() {
                int num = 30; // 内部类方法的局部变量
                System.out.println(num); // 局部变量,就近原则
                System.out.println(this.num); // 内部类的成员变量
                System.out.println(Outer.this.num); // 外部类的成员变量
            }
    
        }
    }

     2、使用多态的好处

    3、对象的上下转型

  • 相关阅读:
    Springboot+shiro配置笔记+错误小结(转)
    Shiro的Filter机制详解---源码分析(转)
    最快最简单的部署本地Apache+PHP+MySQL神器USBWebserver(转)
    shiro简单配置(转)
    重写ajax方法实现异步请求session过期时跳转登录页面(转)
    jquery实现ajax提交form表单的方法总结(转)
    使用ajax提交form表单,包括ajax文件上传
    Spring Boot Freemarker特别篇之contextPath【从零开始学Spring Boot】(转)
    Uncaught SyntaxError: Unexpected token <
    Qt5.5.0在Windows下静态编译(VS2013修改参数以后才能支持XP)good
  • 原文地址:https://www.cnblogs.com/linyuhong/p/10515530.html
Copyright © 2011-2022 走看看