黑马程序员技术交流社区
标题:
学习笔记
[打印本页]
作者:
雪落
时间:
2018-4-14 17:18
标题:
学习笔记
day3 面向对象(接口, 多态)## 接口和类的关系类与类的关系: 继承关系: 子类继承父类 单继承, 多层继承类与接口的关系: 实现关系: 类实现接口 多实现. (不能多层实现, 因为接口不能实现接口, 只能继承接口)接口与接口的关系: 继承关系: 子接口继承父接口 多继承, 多层继承## 接口和抽象类的异同* 相同点 * 接口和抽象类都是抽取出共性的内容* 不同点 * 与类的关系不同 * 类和接口是实现关系: 多实现 * 类和抽象类是继承关系: 单继承, 多层继承 * 成员变量定义不同 * 接口只能有静态常量, public static final * 抽象类可以有成员变量, 也可以有常量 * 成员方法定义不同 * 接口只能有抽象方法, public abstract * 抽象类可以有抽象方法, 也可以没有抽象方法(避免创建对象), 也可以有非抽象方法 * 构造方法定义不同 * 接口不能有构造方法, 也不能创建对象 * 抽象类可以有构造方法, 用于初始化成员, 但不能创建对象* 什么时候用抽象类, 什么时候用接口? * 当需要定义的类可以作为子类的父类, 且里面有抽象的方法时, 则定义为抽象类 * 如动物和猫. 猫属于动物, 动物中包含猫 * 当需要定义的类不足以作为子类的父类, 而只是用于扩展功能时, 则定义为接口 * 如爬树和猫. 猫不属于爬树, 猫只是具有爬树的功能## 多态中的向上转型和向下转型* 转型: * 即转换类型* 向上转型: * 子类型转换为父类型(自动转换)* 向下转型: * 父类型转换为子类型(强制转换)* 举例 * 向上转型: 这只狗是动物吗? 肯定是, 让它去睡觉肯定会 * 向下转型: 这只动物是狗吗? 不一定, 强制把一个动物转成狗, 如果真是狗则看家没问题; 如果不是狗而实际是老鼠, 则不能看家, 会出现问题* 类型转换 * 基本数据类型 * 自动转换: 从小到大. `byte, short, char -> int -> long -> float -> double` * 强制转换: 从大到小. `double d = 1000.0; int i = (int)d;` * 引用数据类型 * 自动转换: 向上转型. `Father fa = new Son(); * 强制转换: 向下转型. `Son son = (Son)fa;`day4 面向对象(包, 权限修饰符, 内部类)## 所有修饰符总结|修饰符 | 类 |成员变量|成员方法|构造方法||---------|--------|-------|-------|-------||public | √ | √ | √ | √ ||默认 | √ | √ | √ | √ ||protected| × | √ | √ | √ ||private | × | √ | √ | √ ||abstract | √ | × | √ | × ||static | × | √ | √ | × ||final | √ | √ | √ | × |* 修饰符使用规范: * 使用public修饰类, 一个Java文件中只能有一个public修饰的类 * 如果一个Java文件中有多个类, 必须是和文件名一样的类名使用public修饰, 其他不能public * 所有成员变量使用private修饰 * 所有供外界使用的成员方法使用public修饰 * 所有构造方法使用public修饰(不想创建对象的除外)* 内部类 * 概念: 定义在类中的类 * 分类: * 成员内部类 * 非静态成员内部类 * 创建内部类的格式: `外部类名.内部类名 对象名 = new 外部类名().new 内部类名();` * 导入内部类: `import 包名.外部类名.内部类名;` * 静态成员内部类 * 创建内部类的格式: `外部类名.内部类名 对象名 = new 外部类名.内部类名();` * 局部内部类 * 定义位置: 定义在方法中 * 如何使用: 调用方法, 才会出现类的定义, 然后创建对象, 调用方法 * 注意: 类随着方法的调用而定义, 随着方法的调用完毕而消失 * 用的非常非常少 * 匿名内部类 * 定义位置: 方法中或方法形参上 * 格式: (见下方) * 注意: * new出来的本质上是父类或父接口的实现类, 该实现类没有名字 * 如果创建的是继承普通类的匿名内部类对象, 则可以选择重写父类方法 * 如果创建的是继承抽象类或实现接口的匿名内部类对象, 则必须重写方法 * 应用场景: * 作为方法的参数传递 * 作为只使用一次的对象, 避免定义一个类day5 API(Object, System, 日期, 包装类, 正则)* Object * 是所有类的根类, 所有类默认都直接或间接的继承自它 * 成员方法: * `String toString()`: 返回对象的字符串表示方式 * 重写toString()的作用: 改变对象的字符串显示方式 * `boolean equals(Object o)`: 比较两个对象是否"相等" * Object类中实现方式: `==`, 比较对象的地址值是否相同 * 重写equals()方法: 改变比较的规则. 可以直接生成 * 获取字节码的3种方式 * `Class 对象.getClass()` * `类名.class` * `Class Class.forName("类的全名")` * 类的字节码对象注意点: * 同一个类的字节码对象只有一个, 地址值也是相同的 * 区分Class和class, 前者是类, 后者是关键字* System类 * java.lang包下, 不用导包 * 常用静态方法 * `static void arrayCopy(Object src, int srcPos, Object dest, int destPos, int length)`: 复制数组 * `static long currentTimeMillis()`: 返回当前系统时间的毫秒值, 从1970-01-01 00:00:00 * `static void exit(int status)`: 终止虚拟机的运行. 传入0是正常退出, 非0是异常退出* Date类 * 注意导包: java.util.Date * 表示特定的瞬间 * 构造方法 * `Date Date()`: 创建Date对象, 并表示当前系统时间 * `Date Date(long timestamp)`: 创建Date对象, 使用指定的时间 * 成员方法 * `String toLocalString()`: (已过时)转换为本地时间格式的字符串 * `void setTime(long time)`: 设置Date对象的时间 * `long getTime()`: 获取Date对象中保存的时间毫秒值.* SimpleDateFormat类 * 作用: * String转Date * Date转String * 构造方法 * `SimpleDateFormat(String pattern)`: 创建SimpleDateFormat对象, 并设置指定的格式 * 常用2个成员方法 * `String format(Date date)`: 格式化Date对象返回字符串 * `Date parse(String source)`: 将字符串解析为Date对象 * 字符串必须符合模式, 否则抛出异常day6 集合(Collection, 迭代器, 增强for, 泛型, List子集)* 集合 * 包含了不同的实现类, 向上抽取出了很多共性的接口, 形成了一个体系结构* 数据结构 * 数据的组织和存储方式* 迭代器 * 作用: 遍历集合 * 并发修改异常: * 原因: 迭代集合时改变了集合的长度 * 解决: * 不使用迭代器 * 使用迭代器对象中的修改方法* 泛型 * 作用: * 约束集合中元素的数据类型 * 将运行时发生的类型转换异常提前到了编译时期* 遍历集合的3种方式 * 普通for循环 * 迭代器 * 增强for循环 * 优点: 快速简便的遍历集合元素 * 缺点: 不能在遍历过程中修改集合, 也没有索引可以使用* 常见的数据结构 * 数组 * 特点: * 长度一旦确定则不可改变 * 有整数索引 * 只能存储同一个数据类型的元素 * 既能存储基本数据类型, 又能存储引用数据类型 * 增删慢, 查询快 * 链表 * 特点: * 增删快, 查询慢 * 栈 * 特点: 先进后出, FILO * 队列 * 特点: 先进先出, FIFO```java// 增强for循环格式for (元素的数据类型 变量名 : 数组或集合对象) { // 遍历出来的变量可以直接使用}Collection接口(单列集合体系的顶层) | * boolean add(E e): 添加元素, 添加成功返回true, 否则false | * void clear(): 清空集合中的元素 | * boolean contains(Object o): 判断集合中是否包含指定的对象 | * boolean isEmpty(): 判断集合中是否没有元素. 与null区分 | * boolean remove(Object o): 从集合中删除一个元素, 删除成功返回true, 否则false | * int size(): 获取集合的长度(元素的数量) | * Object[] toArray(): 将集合转换为Object[]数组 | * Iterator<E> iterator(): 获取集合的迭代器对象 |- List接口(有序, 可重复, 有索引) | * void add(int index, E e): 添加元素到指定索引上 | * E remove(int index): 删除索引上的元素, 并返回 | * E set(int index, E e): 修改指定索引上的元素, 并返回被替换的元素 | * E get(int index): 获取指定索引上的元素 | * ListIterator listIterator(): 获取List特有的迭代器对象 |- ArrayList类(底层是数组, 查询快, 增删慢) |- LinkedList类(底层是链表, 查询慢, 增删快) * void addFirst(E e): 添加元素到集合的开头 * void addLast(E e): 添加元素到集合的末尾 * E getFirst(): 获取集合开头的元素 * E getLast(): 获取集合末尾的元素 * E removeFirst(): 删除开头的元素, 并返回 * E removeLast(): 删除末尾的元素, 并返回Iterator接口 | * boolean hasNext(): 判断是否有下一个元素 | * E next(): 获取下一个元素 | * void remove(): 删除迭代器返回的最后一个元素 |- ListIterator接口 * void add(E e): 使用迭代器添加元素到集合 * void remove(): 使用迭代器删除元素day7 集合(HashSet, HashMap, Map集合嵌套)Collection接口(单列集合体系的顶层) | * boolean add(E e): 添加元素, 添加成功返回true, 否则false | * void clear(): 清空集合中的元素 | * boolean contains(Object o): 判断集合中是否包含指定的对象 | * boolean isEmpty(): 判断集合中是否没有元素. 与null区分 | * boolean remove(Object o): 从集合中删除一个元素, 删除成功返回true, 否则false | * int size(): 获取集合的长度(元素的数量) | * Object[] toArray(): 将集合转换为Object[]数组 | * Iterator<E> iterator(): 获取集合的迭代器对象 |- List接口(元素存取有序, 元素可重复, 有索引) | | * void add(int index, E e): 添加元素到指定索引上 | | * E remove(int index): 删除索引上的元素, 并返回 | | * E set(int index, E e): 修改指定索引上的元素, 并返回被替换的元素 | | * E get(int index): 获取指定索引上的元素 | | * ListIterator listIterator(): 获取List特有的迭代器对象 | |- ArrayList类(底层是数组, 查询快, 增删慢) | |- LinkedList类(底层是链表, 查询慢, 增删快) | * void addFirst(E e): 添加元素到集合的开头 | * void addLast(E e): 添加元素到集合的末尾 | * E getFirst(): 获取集合开头的元素 | * E getLast(): 获取集合末尾的元素 | * E removeFirst(): 删除开头的元素, 并返回 | * E removeLast(): 删除末尾的元素, 并返回 |- Set接口(元素存取无序, 元素不可重复, 无索引) | * `boolean add(E e)`: 添加成功返回true; 添加失败(重复了)返回false |- HashSet类(底层哈希表)Map接口(双列集合体系的顶层, 以键值对方式存储, 键不可重复, 值可以重复) | * `V put(K key, V value)`: 添加键值对 | * `V get(Object key)`: 通过指定键获取值 | * `int size()`: 获取集合长度 | * `containsKey(Object key)`: 是否包含指定的键 | * `containsValue(Object value)`: 是否包含指定的值 | * `boolean isEmpty()`: 是否为空 | * `void clear()`: 清空集合 | * `V remove(Object key)`: 删除指定键的值(key和value都会删除) | * `Set<Map.Entry<K, V>> entrySet()`: 获取键值对的Set集合 | * `Set<K> keySet()`: 获取所有键的Set集合 | * `Collection<V> values()`: 获取所有值得Collection集合 |- Map.Entry(Map内部接口, 表示键值对对象) | * `K getKey()`: 获取键 | * `V getValue()`: 获取值 |- HashMap类Iterator接口(迭代器) | * boolean hasNext(): 判断是否有下一个元素 | * E next(): 获取下一个元素 | * void remove(): 删除迭代器返回的最后一个元素 |- ListIterator接口(List体系专用迭代器) * void add(E e): 使用迭代器添加元素到集合 * void remove(): 删除迭代器返回的最后一个元素Collections工具类 * `static int binarySearch(List list, T key)`: 使用二分查找来查找元素在指定列表的索引位置 * `static void copy(List dest, List src)`: 将源列表中的数据覆盖到目标列表 * `static void fill(List list, Object obj)`: 使用指定对象填充指定列表的所有元素 * `static void reverse(List list)`: 反转集合中的元素 * `static void shuffle(List list)`: 随机打乱集合中元素的顺序 * `static void sort(List list)`: 将集合中的元素按照元素的自然顺序排序 * `static void swap(List list, int i, int j)`: 将指定列表中的两个索引进行位置互换day8 异常, 递归异常的集成体系: java.lang.Throwable(最顶层) *Error: 不应该试图捕获的异常 *Exception: 可以处理的异常(编译时异常, 除了运行时异常) *RuntimeException: 运行时异常异常的分类 *编译时异常: 编译时就发生的异常. 必须在编译时期处理 *运行时异常: 编译时正常, 运行时发生的异常. 自己选择是否处理自定义异常 *自定义编译时异常: 继承Exception类, 重写构造方法 *自定义运行时异常: 继承RuntimeException, 重写构造方法异常的处理方式 *JVM默认的异常处理方式 * 把异常信息打印到控制台, 终止程序的运行, 发生异常之后的代码都不会执行 手动处理异常的方式(2种) * 捕获异常: try catch * try catch格式(见下方) 多异常的处理 *catch代码块的顺序 *如果多个异常没有继承关系, 顺序无所谓 *如果多个异常有继承关系, 子类异常在上, 父类异常在下捕获异常的执行逻辑 *如果try代码块中发生异常, 则会从发生异常的代码直接跳转到catch语句中finally *是一个关键字, 与final区分 *作用: 与try catch配合, 无论是否发生异常, 无论是否捕获异常, 都会执行finally代码块 应用: * IO流释放资源时, 将close()方法放在finally代码块中抛出异常: throws: *定义在方法声明上 *是处理异常的一种方式, 方法内部不处理, 由方法的调用者处理 *格式: 方法声明 throws 异常类型1, 异常类型2 {}throw *用在方法中 *制造异常, 抛出一个异常对象 *格式: throw new 异常类型构造方法();Throwable常用方法 *String getMessage(): 获取异常的原因, 没有原因则返回null *String toString(): 返回异常的类型和原因 *void printStackTrace(): 使用标准错误输出流打印异常详情递归 *原理: 将大的问题拆分为小问题, 再将小问题拆分为更小的问题, 解决了最小的问题后, 更大的问题也可以解决, 最终整个问题得到解决 *在代码中指的是方法自己调用自己 注意事项 *递归必须有出口, 否则内存溢出 StackOverFlowError *递归次数不能太多, 否则也会内存溢出 补充: 递归和循环的相互转换 *递归都可以转换为循环实现 *循环不一定能转换为递归
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2