day10

作者: bd3e3d34c7d2 | 来源:发表于2017-03-13 00:02 被阅读6次

Object类

  • 性质
    • Java中的根类
  • 特点
    • 所有的引用类型均继承自Object类
    • Object类要么是一个类的直接父类, 要么是一个类的间接父类
  • 说明
    • 如果一个类没有指明其父类, 则其继承自Object
    • 如: class Test{}, 相当于 class Test extends Object{}
  • 常见方法
    • protected void finalize()
      • 无需手动调用
      • 当GC确定一个对象无变量引用时, 就会调用该方法回收该对象的内存空间
    • public final Class getClass()
      • 获得调用对象的类型
    • public int hashCode()
      • 获得调用对象的哈希值(不同对象的哈希值是不同的)
    • public boolean equals(Object obj)
      • 建议自定义类中覆盖该方法
      • 默认情况下, 比较两个对象的内存地址值
    • public String toString()
      • 建议自定义类中覆盖该方法
      • 默认情况下, 返回的是对象的 类名 + "@" + hashCode
      • 控制台打印对象时, 底层调用的正是 对象.toString() 方法

多态

  • 定义: 对象的多种状态
  • 核心: 父类变量可以引用子类
    • 理解核心: 子类继承自父类, 但子类仍然是父类的一种
    • 例: Student继承自Person, Student仍然是Person
  • 对象的两种类型
    • 编译类型: 编译器看到的类型, 当使用父类变量引用子类对象时, 编译器会将其看做是一个父类对象
    • 运行类型: 程序运行后, 对象的真实类型
    • 编译类型要么和运行类型相同, 要么是运行类型的父类
  • 存在多态时, 编译器看到的是一个父类对象, 实际运行时是一个子类对象
  • 多态存在的前提
    • 编译类型和运行类型可以是继承关系, 也可以是实现关系(接口和实现类), 在开发中一般指实现关系
  • 多态的作用
    • 1 编译时屏蔽子类之间的差异
    • 2 运行时体现子类之间的差异
    • 3 代码通用, 功能各异

多态时的方法调用问题

  • 背景

    • 存在多态时, 编译器将对象作为父类类型, 运行时其为子类类型
    • 如果父类类型和子类类型存在着 所调用的方法 不一致的情况, 就会有很多可能性
  • 可能性分析

    • 考虑因素: 父类是否存在方法A, 子类是否存在方法A, 子类能否继承父类方法A

      情况1 父类存在方法A, 子类存在方法A 且 父类方法A可以被子类继承

      情况2 父类存在方法A, 子类不存在方法A 且 父类方法A可以被子类继承

      情况3 父类存在方法A, 子类存在方法A 且 父类方法A不可以被子类继承

      情况4 父类存在方法A, 子类不存在方法A 且 父类方法A不可以被子类继承

      情况5 父类不存在方法A, 则编译时就会报找不到方法错误, 无需考虑子类是否有方法A

    • 非静态方法

      情况1 编译通过, 调用子类方法A

      情况2 编译通过, 调用父类方法A, 此时this变量 == 子类对象

      情况3 编译通过, 调用子类方法A

      情况4 编译通过, 运行报错 ???结论是否正确???

      核心思想: 父类有方法A, 编译通过; 子类有或者可继承方法A, 运行通过

    • 静态方法

      情况1 编译通过, 调用父类方法A

      情况2 编译通过, 调用父类方法A

      情况3 编译通过, 调用父类方法A

      情况4 编译通过, 调用父类方法A

      核心思想: 父类有方法A, 编译通过, 运行也通过

引用类型的转换

  • 基本类型转换
    • 自动: 小转大
    • 强制: 大转小
  • 引用类型转换
    • 考虑: 父类 和 子类
    • 可以理解为: 父类 == 大类型, 子类 == 小类型
    • 自动: 子类转父类, 即: 父类变量 = 子类对象
    • 强制: 父类转子类, 即: 父类变量 = 子类对象; 子类变量 = (子类类型)父类变量 (不觉得是强转)
      • 子类变量 = (子类类型)父类变量; 错误: 编译通过, 运行异常
  • instanceof
    • 性质: 运算符
    • 作用: 判断某个类是否是某个对象的本类或父类
    • 格式: 对象 instanceof 类
      • 结果为 boolean类型数据
    • 只判断某个类是否是某个对象的本类: 对象.getClass() == 类.class

多态时的字段访问

  • 结论: 只有非静态方法有多态特征, 静态方法和字段均没有多态特征
    • 静态方法: 通过编译类型去寻找静态方法
    • 字段: 编译时期就决定调用哪一块存储空间. 所以表现不出运行时的特征
  • 注意: 当父类和子类存在着名称相同的字段时, 在各自的内存空间中都存储着对应的同名字段
    • 参考: day09 - 继承关系中子类对象创建的内存分析

代码块

  • 定义: 使用{}括号括起来的一段代码

  • 代码块内变量: 局部变量, 只在代码块中有效

  • 语法格式

    [修饰符]
    {
      // 代码块内容
    }
    
  • 分类

    • 局部代码块

      • 定义在方法中的代码块
      • 一般不用直接局部代码块, 而是和if,while,for等关键字结合使用
    • 初始化代码块

      • 定义在类中方法外的代码块
      • 又称: 构造代码块
      • 执行时机: 使用new创建所在对象时, 首先执行初始化代码块, 而后执行构造器
      • 反编译: 反编译后可以看到, 初始化代码块被放到了构造器中, 作为构造器的最初几条语句
      • 实际使用: 一般不使用, 如果需要进行初始化操作, 直接在构造器中添加初始化方法即可
    • 静态代码块:

      • static 修饰的初始化代码块

      • 执行时机: 字节码加载进JVM时, 先执行静态代码块, 而后才会执行main方法

        • 如果一个类中没有main方法, 那么在字节码加载进JVM时只执行静态代码块

          class ClassA
          {
            static
            {
              System.out.println("静态代码块");
            }
          }
          
          class ClassB
          {
            public static void main(String[] args)
            {
              System.out.println("主方法");
              new ClassA();
              ClassA a = new ClassA();
            }
          }
          
          /*
          打印结果:
              主方法
              静态代码块
              
          ClassA.class 加载进JVM的时机: 程序中第一次使用到ClassA类时. 并且只加载一次
          */  
          
      • 实际使用: 初始化操作, 加载资源和配置文件等

    • 初始化代码块和静态代码块定义的位置没有意义

final修饰符

  • 表示: 最终的

  • 作用

    • final修饰的类: 该类无法创建子类, 为最终类
    • final修饰的方法: 子类不能再覆盖该方法, 只能调用
    • final修饰的变量: 该变量只能赋值一次, 无法再修改变量的值
  • 注意:

    • 多个修饰符是没有先后顺序的, 如修饰方法: final public static test(){};
    • 构造方法不能使用final修饰
      • 因为构造方法不能被子类继承, 已经是最终方法
  • 使用场景

    • 何时使用final修饰一个类

      • 1 不是为继承设计的
      • 2 类中的实现方法只许使用, 不许覆盖
      • 3 该类不会再被拓展
      • Java中常见的final修饰类: String, 八大基本类型包装类
    • 何时使用final修饰一个方法

      • 1 构造器中调用的方法
      • 2 父类中统一的算法骨架
    • 何时使用final修饰一个变量

      • 1 统一使用的数据, 将其定义为一个final变量. 如: final double pi = 3.1415;

      • 2 常量类中的数据, 均使用final修饰

        public class Consts
        {
          public static final double PI = 3.1415;
          ......
        }
        
  • final修饰的变量的特点

    • 该变量只能初始化一次, 其后不能修改
    • 如果变量是基本数据类型, 则其中的值不能修改
    • 如果变量是引用类型, 则其中的地址值不能修改
    • final是局部变量唯一能使用的修饰符
    • final修饰符不会改变变量的作用域
  • final变量的命名规范

    • 变量名全部大写, 中间以 _线隔开 如: MAX_INT
  • 全局静态常量

    • public static final double PI = 3.1415;
    • 使用 类名.变量名 调用

单例设计模式

  • 设计模式: 一种之前开发者总结的代码设计经验.
  • 单例: 一个项目中只有一份该类的对象
  • 单例设计步骤
    • 1 添加一个私有的, final修饰的, 该类型类成员, 并设置一个初始值
    • 2 私有化本类构造器
    • 3 提供一个公共静态方法, 用于返回创建的私有类成员

工具类的设计

  • 根据访问方式的不同, 分为
    • 单例工具
      • 工具中的成员使用 public 修饰, 不使用 static 修饰
      • 设计为一个单例
    • 类工具
      • 工具中的成员使用 public static 修饰
      • 将构造器私有化
    • 首选使用类工具
  • 工具类的包名: xxx.util, xxx.utils, xxx.tool, xxx.tools
    • 如: com._520it.util
  • 工具类名: XxxUtil, XxxUtils, XxxTool, XxxTools
    • 如: com._520it.util.ArrayUtil, com._520it.util.StringUtil

相关文章

网友评论

      本文标题:day10

      本文链接:https://www.haomeiwen.com/subject/siaxnttx.html