【Java温故知新(二)】面向对象|API|工具类
抽象类
抽象类的由来:
回顾昨天写的动物类代码, 我们在其中写了1个eat()方法, 方法中有一句”废话”: 动物会吃.不同的动物吃的内容是不一样的, 所以这句话写了也没有意义, 我们就思考, 能不能删掉呢?这样的方法就叫: 抽象方法, 有抽象方法的类, 就叫抽象类, Java中, 抽象用abstract表示.
抽象类的特点:
- Java中, 抽象用 abstract关键字表示.
- 有抽象方法的类一定是抽象类(或者接口), 但是抽象类中不一定有抽象方法.
- 抽象类不能直接实例化.
问: 那抽象类怎么实例化呢?
答: 通过 抽象类多态 实现, 即: 创建该抽象类的子类对象即可.- 抽象类的子类.
如果是普通类: 则必须重写该抽象类中所有的抽象方法.
如果是抽象类: 则可以不用重写父类中的抽象方法.
抽象类的成员特点: (即, 抽象类中能写啥, 不能写啥.)
专业版: 变量, 常量, 构造方法, 非静态方法, 静态方法, 抽象方法.
简单记忆: 抽象类比普通类多一种抽象方法, 而且还可以不写.
问: 抽象类中的 抽象方法 和 非抽象方法有什么意义?
抽象方法: 强制要求子类必须完成某些操作.
非抽象方法: 让子类继承, 提高代码的复用性.
快捷键:
alt + enter(回车)
面向对象接口
接口的由来
我们知道, 抽象类中不仅可以写抽象方法, 还可以写变量, 常量, 构造方法, 静态方法, 非抽象方法等, 所以抽象类相对 “不纯粹”,
而且, 子类可以通过继承的方式从父类继承 除父构造方法外, 所有的公共内容(public修饰的), 这种方式, 耦合性比较强, 于是,
就出现了接口, 就是用来:降低耦合性的.
举例
问: 假设Animal(动物类), 有子类Cat(猫类), Dog(狗类), 部分的猫, 经过了训练, 学会了跳高, 请问: 跳高的功能应该写到哪里?
答:
写到Animal类? 这就意味着 所有的 动物 都会跳高, 不合适.
写到Cat类? 这就意味着 所有的 猫 都会跳高, 不合适.
写到JumpCat类中? 可以, 但是不推荐, 万一其它的动物经过训练, 也学会了跳高呢? 不方便集中管理.
推荐: 定义1个接口, 里边有跳高的功能, 谁会跳高, 谁实现这个接口即可.
接口的特点
- Java中, 接口用 interface关键字表示, 类与接口之间是实现关系,用
implements修饰
.- 有抽象方法的类一定是抽象类(或者接口), 但是抽象类(接口)中不一定有抽象方法.
- 接口不能直接实例化.
问: 那接口怎么实例化呢?
答: 通过 接口多态 实现, 即: 创建该接口的子类对象即可.- 接口的子类.
如果是普通类: 则必须重写该接口中所有的抽象方法.
如果是抽象类: 则可以不用重写父接口中的抽象方法.
接口的成员特点
JDK1.5及其以前: 接口中有且只能有 常量, 抽象方法.
因为你写的变量, 默认会有:public static final 修饰.
因为你写的方法, 默认会有:public abstract 修饰.
JDK1.8及其以后: 接口中可以写 静态方法 和 默认方法了.
静态方法: 要用static修饰.
默认方法: 要用default修饰, 其实就是我们写的非静态方法.
接口 和 (抽象)类的区别
- 成员特点区别.
接口: 有且只能有常量, 抽象方法, JDK1.8开始, 可以有静态方法 和 默认方法.
类: 变量, 常量, 构造方法, 抽象方法, 静态方法, 非静态方法.- 关系特点区别.
类与类: 继承关系, 只能单继承, 不能多继承, 但是可以多层继承.
类与接口: 实现关系, 既可以单实现, 也可以多实现, 还可以在继承1个类的同时, 实现多个接口.
接口与接口: 继承关系, 可以单继承, 也可以多继承.
- 设计理念的区别.
抽象类: 一般充当父类, 定义的是整个继承体系的 共性内容.
接口: 一般充当父接口, 定义的是整个继承体系的 扩展内容.
Jumping(接口类)
1 | //接口, 表示具有跳高功能. |
JumpCat(继承自接口)
1 | //表示会跳高的猫, 继承自: Cat类(亲爹), 实现 Jumpping接口(干爹) |
Animal类(父类)
1 | //动物类 |
Cat类(继承自Animal类)
1 | //猫类, 继承自: 动物类. |
Demo(测试类)
1 | public class Demo01 { |
内部类
内部类介绍:
内部类的本质: 匿名内部类是1个 继承了该类, 或者实现了该接口的 匿名的
子类对象
.
概述:
内部类指的是类里边还有1个类, 里边的类叫: 内部类, 外边的类叫: 外部类.
分类:
根据内部类的定义位置不同, 内部类可以分为:
成员内部类: 一般是底层源码的时候会用, 表示对该类的功能做 加强, 扩展延伸. 例如: ArrayList
局部内部类: 一般用于快速的初始化某个抽象类(接口), 即: 创建它的子类对象.匿名内部类:
概述:
没有名字的 局部内部类.
格式:
new 类名或者接口名() {
//重写类或者接口的所有抽象方法
};本质: 重点.
匿名内部类是1个 继承了该类, 或者实现了该接口的 匿名的 子类对象.
应用场景:
1. 匿名内部类可以作为 方法的实参 进行传递. 2. 当对成员方法仅调用一次的时候.
Demo(测试类)
1 | public class Demo01 { |
API简介
API全称是Application Programming Interface(应用程序编程接口), 本意指的是JDK提供的各种功能的Java类和接口, 但是我们常说的”打开API”并不是指打开这些Java类和接口, 而是打开API帮助文档.
API 帮助文档就相当于说明书,是用来介绍JDK提供的各个类和接口的功能的, 从而帮助我们快速上手使用.
API帮助文档的使用步骤:
1. 找到你要用的类.
2. 看类的结构.
即: 父类是谁, 有哪些子类, 在哪个包下等…
如果 java.lang 包下的类, 可以直接使用, 其它包下的类, 用之前需要导包.
3. 大概的看下类的说明, 知道该类是干啥的.
4. 看构造方法.
有构造: 说明方法基本上都是 非静态的, 需要通过 对象名. 的方式调用.
无构造: 说明方法基本上都是 静态的, 可以通过 类名. 的方式调用.
5. 具体的调用方法的过程.
注意方法名大小写, 别写错了, 传参, 接收返回值等…
常用API
Scanner类的踩坑经验
问题描述
1
2
3 public int nextInt(); 接收用户录入的 整数
public String next(); 接收用户录入的 字符串, 只接收空格前的内容.
public String nextLine(); 接收用户录入的 字符串, 接收所有.
遇到的问题:
先用nextInt()接收整数, 再用nextLine()接收字符串, 会导致 字符串无法录入的情况.产生原因:
1. nextInt() 和 nextLine()的结束标记都是: \r\n 2. nextInt() 只接收用户录入的数字, 不接收最后的 回车换行符(\r\n) 3. nextInt()"遗留"下来的 \r\n, 被nextLine()直接识别了, 导致nextLine()直接结束.
解决方案:
思路1: 用next()方法 替换 nextLine()
思路2: 重新调用1次nextLine()
思路3: 重新new 1个Scanner对象.
思路4: 实际开发解决方案, 都用字符串接收, 然后把字符串形式的数字 转成 int类型的数字.
包装类写法: int num = Integer.parseInt(“123”); “123” => 123
Demo(测试)
1 | public class Demo01 { |
Object类
概述:
它是java.lang包下的类, 可以直接使用, 无需导包.
它是所有类的父类, 任何的类都直接或者间接继承自Object, Object类是所有类的父类, 基类, 超类.构造方法:
public Object() 它里边只有1个默认的 公共的 空参构造, 回顾: 我之前说过, 类你不写构造方法, 系统默认给1个 公共的无参构造.成员方法:
public String toString(); 默认打印的是对象的地址值, 无意义, 一般会重写它, 改为打印该对象的各个属性值.
public boolean equals(Object obj); 默认比较的是地址值, 无意义, 子类一般都会重写该方法, 改为比较: 对象的各个属性值.细节:
1. 输出语句直接打印对象, 默认调用了该对象的 toString()方法. 2. 实际开发中, 我们认为, 同一个类的对象, 只要各个属性值相同, 它们就是同1个对象, 例如: Student s1 = new Student("张三", 23); Student s2 = new Student("李四", 24); 因为s1 和 s2都是学生对象, 且各个属性值都相同, 实际开发中, 我们会认为: s1 和 s2是同1个对象.
记忆:
以后写JavaBean类的时候, 记得重写下 Object#toString(), equals() 功能.
Demo(测试类)
1 | public class Demo02_Object { |
String类
概述:
它表示字符串类, 每1个字符串值, 例如: “a”, “abc”都是它(String)的示例.
常用成员方法:
1 | public boolean equals(Object obj) 比较两个字符串的内容是否相同, 区分大小写. |
Demo(测试类)
1 | public class Demo03_String { |
StringBuilder
概述:
它叫字符串缓冲区类, 主要涉及到 大量字符串拼接操作等的, 不会开辟新空间, 而是在 该对象空间中, 直接拼接.
它是java.lang包下的类, 可以直接使用, 无需导包.
构造方法:
1 | public StringBuilder() 空参构造, 创建StringBuilder对象. |
成员方法:
1 | public StringBuilder append(任意类型); 往字符串缓冲区对象中 添加元素, 返回自身. |
细节:
String 和 StringBuilder之间的区别?
String: 内容固定.
StringBuilder: 内容可变.
blic class Demo04_StringBuilder {
Demo(测试类)
1 | public class Demo04_StringBuilder { |
Arrays工具类
概述:
它属于java.util包下的类, 用之前需要导包.
它表示数组工具类, 里边定义的大多数都是操作数据的方法, 例如: 排序, 查找, 打印等…成员方法:
public static void sort(int[] arr); 对数组元素排序, 默认: 升序.
public static String toString(int[] arr); 把数组元素拼接成字符串, 格式为: “[值1, 值2, 值3…]”细节:
1. 问: 什么是工具类呢?
答:
特点1: 构造方法私有化. 目的: 不让外界创建该类的对象.
特点2: 成员都是静态的. 可以通过 类名. 的方式调用.
Demo(测试类)
1 | public class Demo05_Arrays { |
包装类
包装类的由来:
我们知道Java的数据类型分为 基本类型 和 引用类型, 引用类型是可以创建对象的, 通过对象名. 或者 类名. 的方式就可以调用该类的很多方法.
但是基本类型是不能直接创建的对象, 例如: int a = 10; 这个是无法直接new的, 就有点不符合Java的 面向”对象”的思维, 于是就有了 包装类,
所谓的包装类, 其实就是: 基本类型 对应的 引用类型. 这样就完美了, Java中所有的类型都可以有 对象形式了.
基本类型 和 对应的包装类型之间的关系:
1 | 基本类型 对应的包装类型(引用类型) |
问: 为啥要用包装类呢?
就是为了学习包装类中的 parseXxx()方法, 用来把 字符串值 转成对应的 基本类型.
例如:
1 | Integer#parseInt(), 可以把字符串数字(例如: "123") 转成 int类型的 123 |
细节:
1 | 1. parseXxx()方法, 除了Character类之外, 都有. 因为Character表示字符, 它和字符串之间有特殊的转换方式. |
Demo(测试类)
1 | public class Demo06_包装类 { |
Date类
概述:
它表示时间(日期), 可以精确到 毫秒.
它属于java.util包下的类, 用之前需要先导包.构造方法:
public Date(); 默认用系统当前的时间.
public Date(long seeds); 根据传入的时间种子, 获取指定时间, 如果种子一致, 则获取的时间也是一样的.成员方法:
public void setTime(long Time); 设置时间的.
public long getTime(); 获取时间的(单位: 毫秒)目的:
讲Date类的目的不是真正让你学会它, 而是让你懂怎么操作日期, 如果你去API中查看对Date类的解释, 你会发现,
该类(java.util.Date类)中 大多数的方法都已经过时了. 已经被 Calendar类(日历类) 替代了.遇到的两个问题:
1. Date类的格式看起来不舒服(例如: Thu Jan 01 08:00:02 CST 1970), 如何改成: 1970/01/01 08:00:02 形式?
通过 SimpleDateFormat类实现.
2. 观察API帮助帮助文档, 发现Date类绝大多数方法已经被Calendar替代了, Calendar类怎么用?
Demo(测试类)
1 | public class Demo07_Date类 { |
SimpleDateFormat类
概述:
它叫日期格式化类, 主要是用来在 字符串 和 日期对象之间做转换的.
构造方法:
1
2 public SimpleDateFormat(); 创建SimpleDateFormat对象, 采用默认模块.
public SimpleDateFormat(String pattern); 创建SimpleDateFormat对象, 采用指定模块.
成员方法:
1
2 public String format(Date d); 把 Date 日期对象 => String字符串.
public Date parse(String dateStr); 把 String字符串日期 => Date日期对象.
Demo(测试类)
1 | public class Demo08_SimpleDateFormat { |
Calendar类
概述:
它表示日历类, 里边绝大多数的方法, 都是用来替代Date类的.
它是java.util包下的类, 用之前需要先导包.
它(Calendar)是1个抽象类, 不能直接实例化, 可以通过创建它的子类对象来完成实例化, 抽象类多态.成员常量:
1
2
3
4
5 public static final int YEAR; 年
public static final int MONTH; 月, 范围: 0 ~ 11
public static final int DATE; 日
public static final int DAY_OF_MONTH; 月中的第几天, 同上
public static final int DAY_OF_YEAR; 年中的第几天.成员方法:
1
2
3
4 public static Calendar getInstance(); 底层会通过抽象类多态的方式, 创建 Calendar类的对象.
public int get(int field); 根据传入的日期字段, 获取其对应的 值.
public void set(int year, int month, int day); 设置时间为, 年, 月, 日.
public void add(int field, int amount) 把指定的日期偏移指定的值, 例如: 往前推几天, 往后推几月.
Demo(测试类)
1 | public class Demo09_Calendar { |