Day03-面向对象和Java基础类库
一、抽象类
1:概念
在Java中, 一个没有方法体的方法应该定义为抽象方法, 而类中如果有抽象方法, 该类必须定义为抽象类.
2:案例
需求
1.创建抽象类Animal.
2.在该类中定义抽象方法eat()
//抽象的动物类.
public abstract class Animal {
//抽象方法, 吃.
public abstract void eat();
}
3:特点
-
抽象类和抽象方法必须用abstract关键字修饰.
//抽象类 public abstract class 类名{ } //抽象方法 public abstract void eat();
2.抽象类中不一定有抽象方法, 有抽象方法的类一定是抽象类
3.抽象类不能实例化.
4.抽象类的子类:
1) 如果是普通类, 则必须重写父抽象类中所有的抽象方法.
2) 如果是抽象类, 则可以不用重写父抽象类中的抽象方法.
4:案例
1.定义抽象类Animal , 类中有一个抽象方法eat(), 还有一个非抽象方法sleep().
2.尝试在测试类中, 创建Animal类的对象, 并观察结果.
3.创建普通类Cat, 继承Animal类, 观察是否需要重写Animal#eat()方法.
4.创建抽象类Dog, 继承Animal类, 观察是否需要重写Animal#eat()方法.
public abstract class Animal {
public abstract void eat();
public void sleep(){
System.out.println("动物睡觉");
}
}
public class AnimalTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();
cat.sleep();
Dog dog = new Dog();
dog.eat();
dog.sleep();
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
}
public abstract class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
二、接口
1:概念
为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现。
2:特点
1.接口用interface关键字修饰.
2.类和接口之间是实现关系, 用implements关键字表示.
3.接口不能实例化.
– 那接口如何实例化呢?
– 可以通过多态的方式, 创建其子类对象, 来完成接口的实例化. 这也叫: 接口多态.
4.接口的子类:
1.如果是普通类, 则必须重写父接口中所有的抽象方法.
2.如果是抽象类, 则可以不用重写父接口中的抽象方法.
3:案例
1.定义Flying 接口, 接口中有一个抽象方法fly().
2.定义Cat类, 实现Flying 接口, 重写fly()方法.
3.在测试类的main方法中, 创建Flying 接口对象, 并调用其fly()方法
public interface Flying {
public void fly();
}
public class Cat implements Flying {
@Override
public void fly() {
System.out.println("cat fly");
}
}
public class CatTest {
public static void main(String[] args) {
Flying f= new Cat();
f.fly();
}
}
4:接口与类之前的关系
• 类与类之间: 继承关系, 只能单继承, 不能多继承, 但是可以多层继承.
• 类与接口之间: 实现关系, 可以单实现, 也可以多实现. 还可以在继承一个类的同时实现多个接口.
• 接口与接口之间: 继承关系, 可以单继承, 也可以多继承.
5:案例
1.已知有乒乓球运动员(PingPangPlayer)和篮球运动员(BasketballPlayer), 乒乓球教练(PingPangCoach)和篮球教练(BasketballCoach).
2.他们都有姓名和年龄, 都要吃饭, 但是吃的东西不同.
3.乒乓球教练教如何发球, 篮球教练教如何运球和投篮.
4.乒乓球运动员学习如何发球, 篮球运动员学习如何运球和投篮.
5.为了出国交流, 跟乒乓球相关的人员都需要学习英语.
//Person类 代码略
//教练类
public abstract class Coach extends Person {
public abstract void teach();
}
//运动员类
public abstract class Player extends Person{
public abstract void study();
}
public interface Speak {
public void speakEnglish();//学英语:乒乓球人员额外功能
}
//乒乓球教练
public class PingPangCoach extends Coach implements Speak {
@Override
public void teach() {
System.out.println("乒乓球教练教如何发球");
}
@Override
public void eat() {
System.out.println("乒乓球教练吃鸡腿");
}
@Override
public void speakEnglish() {
System.out.println("乒乓球教练学英语");
}
}
//篮球教练
public class BasketballCoach extends Coach{
@Override
public void teach() {
System.out.println("篮球教练教如何运球和投篮");
}
@Override
public void eat() {
System.out.println("篮球教练吃白米饭");
}
}
//乒乓球运动员
public class PingPangPlayer extends Player implements Speak{
@Override
public void study() {
System.out.println("乒乓球运动员学习如何发球");
}
@Override
public void eat() {
System.out.println("乒乓球运动员吃大餐");
}
@Override
public void speakEnglish() {
System.out.println("乒乓球运动员学英语");
}
}
//篮球运动员
public class BasketballPlayer extends Player {
@Override
public void study() {
System.out.println("篮球运动员学习如何运球和投篮");
}
@Override
public void eat() {
System.out.println("篮球运动员吃大白菜");
}
}
//测试类
略
三、API
1:概念
API全称是(Application Programming Interface)应用程序编程接口, 本意指的是JDK提供的各种功能的Java类和接口, 但是我们常说的”打开API”并不是指打开这些Java类和接口, 而是打开API帮助文档.
API 帮助文档就相当于说明书
是用来介绍JDK提供的各个类和接口的功能的, 从而帮助我们快速上手使用.
2:案例
需求
按照帮助文档的使用步骤学习Scanner类的使用, 并实现键盘录入一个字符串, 然后把结果输出在控制台上.
public class Test {
public static void main(String[] args) {
//1.导包
//2.创建对象
Scanner sc = new Scanner(System.in);
//3.接收数据
System.out.println("请您输入一行内容:");
String str = sc.nextLine();
System.out.println("您输入的是:"+str);
// System.out.println("请输入一个字符串:");
// String s = sc.next();
// System.out.println("您输入的是:"+s);
}
}
3:常用API
3-1:Object类
概述:Object类是所有类的父类, 所有的类都直接或者间接继承自Object类.
构造方法: public Object() //Object类中只有一个空参构造.
成员方法:
public String toString(); 返回对象的字符串表示形式(即: 地址值), 无意义, 建议子类重写该方法.
public boolean equals(Object obj); 比较两个对象是否相等, 默认比较的是地址值, 无意义, 子类一般都会重写该方法.
注意: 实际开发中, 我们认为如果同一个类的两个对象, 各个属性值都相同,那么它们就是同一个对象.
//虽然s1和s2对象的地址值不同, 但是它们的属性值都相同, 所以实际开发中我们认为它们是同一个对象.
Student s1 = new Student("张三", 18);
Student s2 = new Student("张三", 18);
3-2:案例
案例一:toString方法演示
需求
定义学生类Student, 属性为姓名和年龄, 生成对应的空参, 全参, getXxx()和setXxx()方法.
在StudentTest测试类中, 创建学生类对象并直接打印, 观察程序的运行结果.
public class Student {
private String name;
private int age;
public Student(){}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class StudentTest {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.toString());//直接调用无意义,建议子类重写toString
}
}
案例二:equals()方法演示
需求
•定义学生类Student, 属性为姓名和年龄, 生成对应的空参, 全参, getXxx()和setXxx()方法.
•在StudentTest测试类中, 创建两个学生类对象, 属性值都是: 刘亦菲, 33
•并直接打印, 观察程序的运行结果.
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student("张三",18);
Student s2 = new Student("张三",18);
//打印第一个学生的对象
System.out.println(s1);
//打印第二个学生的对象
System.out.println(s2);
//查看两个对象是否相等
System.out.println(stu1==stu2);
}
}
3-3:String类
概述:String代表字符串类, 即: 由多个字符组成的一串数据. 字符串的本质就是一个字符数组.
3-4:案例
案例一:字符串比较
1.public boolean equals(Object obj)
解释: 比较两个字符串的内容是否相同, 区分大小写. 即: “a” 和 "A"不是同一个字符串.
2.public boolean equalsIgnoreCase(String s)
解释: 比较两个字符串的内容是否相同, 不区分大小写. 即: “a” 和 "A"是同一个字符串.
需求
定义字符数组chs, 初始化值为: 'a', 'b', 'c', 这三个字符 .
将其分别封装成s1, s2这两个字符串对象.
直接通过""的方式创建两个字符串对象s3和s4.
通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
通过equalsIgnoreCase()判断字符串abc和ABC是否相同.
public class StringCompare {
public static void main(String[] args) {
char[] chs = {'a','b','c'};
//封装字符串对象
String s1 = new String(chs);
String s2 = new String(chs);
//直接通过""的方式创建两个字符串对象s3和s4.
String s3 = "abc";
String s4 = "abc";
//通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s3==s4);
//通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s3.equals(s4));
//通过equalsIgnoreCase()判断字符串abc和ABC是否相同.
System.out.println("abc".equalsIgnoreCase("ABC"));
}
}
案例二:模拟用户登录
需求
模拟用户登录, 只给3次机会, 登录成功则提示"欢迎您, ***".
登录失败则判断是否还有登录机会, 有则提示剩余登录次数2-i, 没有则提示"您的账号已被锁定".
假设初始化账号和密码分别为: "传智播客", "黑马程序员".
public class StimulateLogin {
public static void main(String[] args) {
//1.初始化用户和密码
String user = "传智播客";
String password = "黑马程序员";
//2.输入用户名和密码
Scanner scanner = new Scanner(System.in);
//定义一个计数器
int count = 0;
//3.循环判断3次是否登录正确,如果登录成功直接返回
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String userName = scanner.next();
System.out.println("请输入密码:");
String pwd = scanner.next();
if (user.equals(userName) && password.equals(pwd)) {
System.out.println("登录成功请返回!");
break;
} else {
if (count < 2) {
//3.1.如果登录失败,提示剩余登录次数
System.out.println("登录失败,剩余登录次数为:" + (2 - i));
count++;
} else {
//3.2.如果登录超过3次失败,退出登录,提示 您的账号已被锁定
System.out.println("您的账号已被锁定");
break;
}
}
}
}
}
3-4: StringBuilder类
分析如下代码, 执行效率是高还是低呢?
String s = “hello”;
s += “world”;
System.out.println(s);
解释:
如果字符串String进行拼接操作, 每次拼接, 都会构建一个新的String对象, 即耗时, 又浪费内存空间. 而这种操作还不可避免,.那有没有一种比较好的方式来解决这个问题呢?
答案是肯定的, 我们可以通过Java提供的StringBuilder类来解决这个问题.
3-5-1:概念
StringBuilder类在java.lang包下, 无需导包, 可以直接使用.
StringBuilder是一个可变的字符序列, 也叫字符串缓冲区类.
我们可以把它看做一个容器, 这里的可变指的是StringBuilder对象中的内容是可变的
3-5-2:String和StringBuilder之间的区别
String: 内容是不可变的.
StringBuilder: 内容是可变的.
3-5-3:构造方法
public StringBuilder()
解释: 创建一个空白 StringBuilder对象, 它不含有任何内容.
public StringBuilder(String str)
解释: 根据字符串的内容, 来创建 StringBuilder对象.、
3-6:案例
案例一: StringBuilder
需求
通过上述的两种方式, 创建StringBuilder对象.
在控制台直接打印上述创建好的两个对象, 并观察结果.
public class Test1 {
public static void main(String[] args) {
//空参
StringBuilder sb1 = new StringBuilder();
System.out.println(sb1);
//带参
StringBuilder sb2 = new StringBuilder("abc");
System.out.println(sb2);
}
}
案例二:StringBuilder和String之间的相互转换
String转成StringBuilder
解释: 通过StringBuilder类的构造方法实现, `public StringBuilder(String s)
StringBuilder转化成String
解释: 可以通过StringBuilder#**toString()**方法直接实现.
需求
定义空参不可变StringBuilder对象, 往里边添加完"hello"字符串后, 再将其转成String类型的对象.
将String字符串转成StringBuilder对象, 然后打印.
public class Test2 {
public static void main(String[] args) {
//String转成StringBuilder
StringBuilder sb = new StringBuilder("hello");
//StringBuilder转String
String s = sb.toString();
System.out.println(s);
}
}
案例三:拼接字符串
提示: 可以通过StringBuilder的**append()**方法实现.
需求
定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
在main方法中, 调用上述的方法.
例如: 数组为int[] arr = {1, 2, 3}, 则拼接后, 结果为: [1, 2, 3]
public class Test3 {
public static void main(String[] args) {
int[] arr={1,2,3};
//调用方法,传入arr数组
String s = arrayToString(arr);
System.out.println(s);
}
//定义方法
private static String arrayToString(int[] arr) {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
if (i==arr.length-1){
sb.append(arr[i]).append("]");
}else{
sb.append(arr[i]).append(",");
}
}
//返回字符串
return sb.toString();
}
}
3-5:包装类
概述:
假如让我们判断一个数据是否在int范围内, 首先我们的得知道int的范围, 在前边我们讲解数据类型的时候说过, 这个范围是: -2147483648 ~ 2147483647. 但是这个数据程序员不一定能记得住. 于是我们就想着, 如果有个变量或者常量能记录这个值该多好呢?
其实这个需求, 我们就可以通过Integer类的MAX_VALUE和MIN_VALUE两个常量来实现.
1.public static final int MIN_VALUE
解释: 获取int类型所能表示的最小值
2.public static final int MAX_VALUE
解释: 获取int类型所能表示的最大值
为了对基本类型进行更多更方便的操作, Java就针对每一种基本类型提供了一个对应的引用类型, 这就是包装类.’
对应关系如下:
基本类型 | 对应的包装类型 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
最常见用法
包装类最常见的用法就是用于该类型对应的基本类型和字符串之间进行相互转换.
例如:
Byte用于byte和String之间的相互转换.
Integer用于int和String之间的相互转换.
Double用于double和String之间的相互转换.
3-6:Integer类
3-6-1:概念
Integer 类是基本类型int所对应的包装类, 该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法.
3-6-2:构造方法
public Integer(int value)
解释: 把int类型的数据封装成其对应的Integer对象.
public Integer(String s)
解释: 把字符串类型的整数封装成其对应的Integer对象.
注意: 这里传入的必须是纯数字类型的字符串.
3-6-3:创建Integer对象
需求
通过上述的两个构造方法, 分别创建Integer类型的对象.
在main方法中, 打印创建好的Integer对象.
public class Test08 {
public static void main(String[] args) {
//封装整数10
Integer a = new Integer(10);
System.out.println(a);
//封装字符串"20"
Integer b = new Integer("20");
System.out.println(b);
}
}
3-6-4:int类型和String类型的相互转换
int类型 -> String类型
方式一(常用): 直接在后边拼接""即可
String s1 = 10 + "";
方式二(了解): 通过String#valueOf()方法.
String s1 = String.valueOf(10);
String类型 -> int类型
方式一(常用): 通过Integer#parseInt()方法来实现.
String s1 = 100;
int num = Integer.parseInt(s1);
方式二(了解): 通过String -> Integer -> int思路来实现.
//1. 先把String类型的对象转成Integer类型的对象.
String s1 = "10";
Integer i1 = new Integer(s1);
//2. 把Integer类型的对象转成int类型.
int num = i1.intValue();
3-7:Data类
3-7-1:概述
Date类表示特定的瞬间,精确到毫秒. 它是java.util包下的类, 用之前需要先导包.
3-7-2:构造方法
public Date();
解释: 根据当前系统时间, 获取其对应的Date对象.
public Date(long date);
解释: 根据给定的整数, 获取其对应的Date对象.
3-7-3:成员方法
public long getTime()
解释: 获取毫秒值.
public void setTime(long time)
解释: 设置时间, 单位是毫秒值.
3-7-4:案例
需求
通过上述的两种方式创建Date对象.
在main方法中, 打印上述创建好的Date对象, 并观察结果.
编写代码, 测试上述的两个方法.
public class Test10 {
public static void main(String[] args) {
Date d = new Date();
//打印日期对象
System.out.println(d);
//打印时间原点到现在的毫秒值
System.out.println(d.getTime());
}
}
3-8:SimpleDateFormat类
3-8-1:概念
SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类。
它允许进行格式化和解析。
SimpleDateFormat类, 叫日期格式化类, 专门用来格式化和解析日期的.
-
格式化(日期 -> 文本), 即: Date -> String
-
解析(文本 -> 日期), 即: String -> Date
3-8-2:构造方法
public SimpleDateFormat()
解释: 根据空参构造, 创建SimpleDateFormat类的对象.
public SimpleDateFormat(String pattern)
解释: 根据给定的模板, 创建其对应的SimpleDateFormat类的对象.
3-8-3:成员方法
1.public final String format(Date date)
解释: 用来格式化日期的.
2.public Date parse(String source)
解释: 用来解析字符串形式的日期的.
public class Test10 {
public static void main(String[] args) throws ParseException {
Date d = new Date();
//打印日期对象
System.out.println(d);
//创建日期格式类对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//格式化:把日期转成咱们习惯看的字符串格式
String str = sdf.format(d);
System.out.println(str);
//解析: 把字符串转成日期对象
String str2="2022-03-06 18:18:18";
Date d2 =sdf.parse(str2);
System.out.println(d2);
}
}
3-8-4:工具类的定义
需求
定义工具类DateUtils, 该类有两个方法: date2String(), string2Date(), 分别用来格式化, 解析日期.
在测试类中, 测试上述的两个方法.
注意: 解析日期字符串时, SImpleDateFormat对象的模板要和被解析的字符串格式保持一致.
public class DateUtils {
public static String date2String(Date d){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = sdf.format(d);
return s;
}
public static Date string2Date(String s) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
return d;
}
}
public class Test11 {
public static void main(String[] args) throws ParseException {
//Date->字符串
Date d = new Date();
String s = DateUtils.date2String(d);
System.out.println(s);
//字符串->Date
String str="2022-3-6 18:18:18";
Date date = DateUtils.string2Date(str);
System.out.println(date);
}
}
3-9:Calendar类
3-9-1:概述
Calendar类叫: 日历类, 是方便我们操作日期的. 它里边的功能大多数是用来替代java.util.Date类的功能的.
3-9-2:构造方法
Calendar类可以理解为是工具类, 因为它是一个抽象类, 所以外界无法通过new的方式创建本类对象.
问题: 如何创建Calendar类的对象呢?
答案: 通过Calendar的getInstance()方法实现.
3-9-3:Calendar案例
需求
通过上述的方式, 创建Calendar对象.
public static void main(String[] args) {
Calendar instance = Calendar.getInstance();
}
3-9-4:成员变量
public static final int YEAR
解释: 表示年份.
public static final int MONTH
解释: 表示月份.
public static final int DATE
解释: 表示年中的某一天.
public static final int DAY OF MONTH
解释: 表示月中的某一天.
public static final int DAY OF WEEK
解释: 表示星期中的某一天.
3-9-5:成员方法
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 count)
解释: 修改指定的时间为指定的偏移量, 例如: 往前推2天, 推3个月, 往后推2年.
3-9-6:获取指定的年月日
需求
通过上述的方法, 获取当前的年, 月, 日信息.
public class Test12 {
public static void main(String[] args) {
//获取子类对象
Calendar c = Calendar.getInstance();
//获取时间字段
System.out.println(c.get(Calendar.YEAR));//年
System.out.println(c.get(Calendar.MONTH));//月 范围:0-11
System.out.println(c.get(Calendar.DATE));//日
System.out.println(c.get(Calendar.DAY_OF_YEAR));//年中的第多少天
System.out.println(c.get(Calendar.DAY_OF_MONTH));//月中第多少天
System.out.println(c.get(Calendar.DAY_OF_WEEK));//星期中第多少天 周日是第1天
}
}