目录:
- 多态
- 面向对象三大特征?
- 什么是多态?
- 多态的前提
- 多态的成员访问特点
- 多态的优缺点
- 多态的转型
- 多态的转型注意
- 解决转型安全隐患
- 内部类
- 内部类的分类
- 什么是内部类?
- 什么时候使用内部类?
- 内部类分类?
- 成员内部类
- 成员内部类访问外部类的成员
- 匿名内部类
- 内部类的分类
- API
- Object类
- Objects类
- Date类
- 概述:java.util.Date表示特定的瞬间,精确到毫秒
- 构造方法:
- 成员方法:
- DateFormat类
- Calendar类
- 概述:
- Calendar常用方法:
- 星期对应的关系
- 月份对应的关系
- Math类
- System类
- 随堂小记
- 工具类的书写规则:
- static关键字
- final关键字
- 代码块:
- 接口:
- 枚举:
- 多态
- 什么是多态?
- 多态解决程序中的什么问题?
- 多态的使用
- 多态转型
- 注意细节:
- 多态代码的书写:
- 内部类:
- 匿名内部类:
- 工具类:
- 回顾上午内容:
- 多态
- 匿名内部类
- Object(鼻祖类)
- 日期类型的数据:
- Date类:
- DateFormat类
- Calendar类
1.多态
面向对象三大特征 ?
-
封装 , 继承 , 多态
什么是多态 ?
-
一个对象在不同时刻体现出来的不同形态
-
举例 : 一只猫对象
-
我们可以说猫就是猫 : Cat cat = new Cat();
-
我们也可以说猫是动物 : Animal cat = new Cat();
-
这里对象在不同时刻,体现出来的不同形态 , 我们就可以理解为多态
-
多态的前提
-
有继承/实现关系
-
有方法重写
-
父类的引用指向子类的对象
package com.itheima.polymorphism_demo;
/*
多态的三个前提条件
1 需要有继承/实现关系
2 需要有方法重写
3 父类的引用指向子类的对象
*/
public class AnimalTest {
public static void main(String[] args) {
// 3 父类的引用指向子类的对象
// 多态形式对象
Animal a = new Cat();
}
}
class Animal{
public void eat(){
System.out.println("吃东西");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼....");
}
}
多态的成员访问特点
-
构造方法 : 和继承一样 , 子类通过super()访问父类的构造方法
-
成员变量 : 编译看左边(父类) , 执行看左边(父类)
-
成员方法 : 编译看左边(父类) , 执行看右边(子类)
package com.itheima.polymorphism_demo;
/*
多态的成员访问特点 :
1 构造方法 : 和继承一样 , 都是通过super()访问父类的构造方法
2 成员变量 : 编译看左边(父类) , 执行看左边(父类)
3 成员方法 : 编译看左边(父类) , 执行看右边(子类) , 注意 , 如果执行时
1) 子类没有回动态去找父类中的方法
2) 子类的特有方法无法进行调用(多态的缺点)
*/
public class MemberTest {
public static void main(String[] args) {
// 父类的引用指向子类的对象
Fu f = new Zi();
// 多态对象调用成员变量
System.out.println(f.num);
// 多态对新乡调用调用成员方法
f.show();
// 多态对象不能调用子类特有的方法
// f.show2();
}
}
class Fu {
int num = 100;
public void show() {
System.out.println("父类的show方法");
}
}
class Zi extends Fu {
int num = 10;
public void show() {
System.out.println("子类的show方法");
}
public void show2(){
System.out.println("子类特有的方法");
}
}
多态的优缺点
-
优点 : 提高代码的扩展性
-
缺点 : 不能调用子类特有的功能
package com.itheima.polymorphism_test;
public abstract class Animal {
private String breed;
private String color;
public Animal() {
}
public Animal(String breed, String color) {
this.breed = breed;
this.color = color;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public abstract void eat();
}
package com.itheima.polymorphism_test;
public class Cat extends Animal {
public Cat() {
}
public Cat(String breed, String color) {
super(breed, color);
}
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
public void catchMouse() {
System.out.println("抓老鼠...");
}
}
package com.itheima.polymorphism_test;
public class Dog extends Animal {
public Dog() {
}
public Dog(String breed, String color) {
super(breed, color);
}
@Override
public void eat() {
System.out.println("狗吃骨头!");
}
public void lookDoor(){
System.out.println("狗看门...");
}
}
package com.itheima.polymorphism_test;
public class Pig extends Animal {
public Pig() {
}
public Pig(String breed, String color) {
super(breed, color);
}
@Override
public void eat() {
System.out.println("猪拱白菜...");
}
public void sleep() {
System.out.println("一直再睡...");
}
}
package com.itheima.polymorphism_test;
/*
如果方法的参数是一个类的话 , 那么调用此方法需要传入此类的对象 , 或者子类对象
多态的好处 :
提高代码的扩展性 , 灵活性
多态的缺点:
不能调用子类的特有功能
*/
public class AnimalTest {
public static void main(String[] args) {
useAnimal(new Cat());
System.out.println("---------");
useAnimal(new Dog());
System.out.println("---------");
useAnimal(new Pig());
}
public static void useAnimal(Animal a){// Animal a = new Dog()
a.eat();
// 多态不能访问子类特有的功能
// 如果解决 ?
// 向下转型
if(a instanceof Cat) {
Cat cat = (Cat) a;
cat.catchMouse();
}
if(a instanceof Dog) {
Dog dog = (Dog) a;
dog.lookDoor();
}
if(a instanceof Pig) {
((Pig) a).sleep();
}
}
// // 定义一个使用猫类的方法
// public static void useAnimal(Cat c) {// Cat c = new Cat();
// c.eat();
// c.catchMouse();
// }
//
// // 定义一个使用狗类的方法
// public static void useAnimal(Dog d) {// Dog d = new Dog();
// d.eat();
// d.lookDoor();
// }
//
// // 定义一个使用猪类的方法
// public static void useAnimal(Pig pig) {
// pig.eat();
// pig.sleep();
// }
}
多态的转型
-
向上转型 : 把子类类型数据转成父类类型数据 Animal a = new Cat();
-
向下转型 : 把父类类型数据转成子类类型数据 Cat cat = (Cat)a;
多态的转型注意
-
如果被转的对象 , 对应的实际类型和目标类型不是同一种数据类型 , 那么转换时会出现ClassCastException异常
异常代码如下
public static void main(String[] args) {
Animal a = new Cat();
useAnimal(a);
}
public static void useAnimal(Animal a) {
Dog d = (Dog) a;
d.eat();
}
解决转型安全隐患
-
使用关键字 instanceof
-
作用 : 判断一个对象是否属于一种引用数据类型
-
格式 : 对象名 instanceof 引用数据类型
-
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
-
2.内部类
内部类的分类
-
什么是内部类 ?
-
一个A类 中 定义一个B类 , 那么B类就属于A类的内部类 , A类就属于B类的外部类
-
-
什么时候使用内部类 ?
-
多个事物之间有包含关系, 可以使用内部类
-
-
内部类分类 ?
-
成员内部类
-
局部内部类
-
匿名内部类
-
成员内部类
-
定义的位置 : 类中方法外
-
创建成员内部类对象格式 : 外部类名.内部类名 对象名 = new 外部类名().new 内部类名(参数);
package com.itheima.innerclass_demo.member_innerclass;
// 外部类
public class Person {
// 成员内部类
public class Heart {
// 频率变量
private int rate;
// 跳动方法
public void beats() {
System.out.println("咚咚咚!");
}
}
}
class Test {
public static void main(String[] args) {
// 创建内部类对象
Person.Heart heart = new Person().new Heart();
// 调用内部类中的方法
heart.beats();
}
}
成员内部类访问外部类的成员
-
在内部类中有代表外部类对象的格式 : 外部类名的.this , 私有的也可以访问
-
外部类要想访问内部类成员 , 需要创建内部类对象
package com.itheima.innerclass_demo.member_innerclass;
public class Person {
private String name = "张三";
private int num = 10;
// 成员内部类
public class Heart {
int num = 100;
// 频率
private int rate;
// 跳动
public void beats() {
System.out.println("咚咚咚!");
}
// 调用外部类的成员
public void show(){
int num = 1000;
System.out.println(Person.this.name);
System.out.println(num);// 1000 就近原则
System.out.println(this.num);// 100
System.out.println(Person.this.num);// 10
}
}
}
class Test {
public static void main(String[] args) {
Person.Heart heart = new Person().new Heart();
heart.beats();
heart.show();
}
}
匿名内部类
-
匿名内部类 : 没有名字的类 , 一次性产品
-
使用场景 : 直接调用方法 , 作为方法的传参 , 返回值类型
-
好处 : 简化代码 , 快速实现接口或者抽象的抽象方法
-
格式 :
-
new 类名/接口名(){ 重写抽象方法 } 注意 : 此处创建的是子类对象!!!
-
-
使用方式 :
-
直接调用方法
-
作为方法的参数传递
-
作为方法的返回值类型
-
//接口
interface Flyable {
void fly();
}
// 直接调用方法
Flyable f1 = new Flyable() {
@Override
public void fly() {
System.out.println("不知道什么在飞.....");
}
};
f1.fly();
// 作为方法的参数传递
showFlyable(
new Flyable() {
@Override
public void fly() {
System.out.println("不知道什么在飞3333");
}
}
);
public static void showFlyable(Flyable flyable) {
flyable.fly();
}
// 作为方法的返回值类型
public static Flyable getFlyable() {
return new Flyable() {
@Override
public void fly() {
System.out.println("3333333333333");
}
};
}
package com.itheima.innerclass_demo.anonymous_innerclass;
/*
1 如果方法的参数是一个类的话 , 调用此方法需要传入此类的对象或者此类的子类对象
2 如果方法的返回值类型是一个类的话 , 需要返回此类的对象 , 或者此类的子类对象
3 如果方法的参数是一个接口的话 , 调用此方法需要传入此接口的实现类对象
4 如果方法的返回值类型是一个接口的话 , 需要返回此接口的实现类对象
匿名内部类 : 代表的就是子类对象!!!
new 类名/接口名(){
重写抽象类或者接口中的抽象方法
};
使用方向 :
1 调用方法
2 作为方法参数传递
3 作为方法的返回值
*/
public interface Swim {
public abstract void swimming();
}
class Test {
public static void main(String[] args) {
// // 子类对象!!!
// 1 调用方法
// new Swim() {
// @Override
// public void swimming() {
// System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
// }
// }.swimming();
// // 2 作为方法参数传递
// useSwim(new Swim() {
// @Override
// public void swimming() {
// System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
// }
// });
// // 3 作为方法的返回值
// Swim s = getSwim();
// s.swimming();
}
public static Swim getSwim() {
return new Swim() {
@Override
public void swimming() {
System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
}
};
}
/*
Swim swim = new Swim() {
@Override
public void swimming() {
System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
}
};
*/
public static void useSwim(Swim swim) {
swim.swimming();
}
}
3.API
Object类
-
概述 : 类Object是类层次结构的根,每个类都把Object作为超类。 所有对象(包括数组)都实现了这个类的方法
-
方法 : public String toString()
-
如果一个类没有重写toString方法 , 那么打印此类的对象 , 打印的是此对象的地址值
-
如果一个类重写了toString方法 , 那么打印此类的对象 , 打印的是此对象的属性值
-
好处 : 把对象转成字符串 , 快速查看一个对象的属性值
-
执行时机 : 打印对象时会默认调用toString方法
-
-
方法 : public boolean equals()
-
如果一个类没有重写equals方法 , 那么比较此类的对象 . 比较的是地址值
-
如果一个类重写了equals方法 . 那么比较此类的对象 , 比较的是属性值是否相等
-
好处 : 可以比较对象的内容
-
Objects类
-
Objects是JDK1.7新增的一个对象工具类,里面都是静态方法可以用来操作对象。比如对象的比较,计算对象的hash值,判断对手是否为空....比如里面的equals方法,可以避免空指针异常
public static boolean equals(Object a, Object b):判断两个对象是否相等
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
a.equals(b) :如果a是null值,肯定会空指针
Objects.equals(a,b);:如果a是null,不会导致空指针异常
Date类
-
概述 : java.util.Date 表示特定的瞬间,精确到毫秒
-
构造方法 :
-
public Date(): 创建的对象,表示的是当前计算机系统的时间
-
public Date(long time): Date对象 = 1970/1/1 0:0:0 + time毫秒值
-
-
成员方法 :
-
public long getTime(): 返回毫秒值 = 当前Date代表的时间 - 1970/1/1 0:0:0
-
public void setTime(long t): Date对象 = 1970/1/1 0:0:0 + time毫秒值
-
package com.itheima.api_demo.date_demo;
import java.util.Date;
/*
Date类 : 代表的是一个瞬间 , 精确到毫秒
构造方法 :
public Date() : 代表的是当前系统时间
public Date(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
成员方法 :
public void setTime(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
public long getTime() : 返回的是毫秒值 = Date代表的时间 - 1970/1/1 0:0:0
*/
public class DateDemo {
public static void main(String[] args) {
// public Date() : 代表的是当前系统时间
// Date d = new Date();
// System.out.println(d);
// public Date(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
// Date d2 = new Date(1000L * 60 * 60 * 24); // 1970/1/1 0:0:0 + 一天的毫秒值
// System.out.println(d2);
Date d = new Date();
// public void setTime(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
// d.setTime(1000L * 60 * 60 * 24);
System.out.println(d);
// public long getTime() : 返回的是毫秒值 = Date代表的时间 - 1970/1/1 0:0:0
// System.out.println(d.getTime());
}
}
DateFormat类
-
概述 : 主要用于操作日期格式的一个类
-
作用 :
-
格式化 : Date --> String
-
解析 : String --> Date
-
-
构造方法 :
-
SimpleDateFormat(String pattern) 给定日期模板创建日期格式化对象
-
-
成员方法 :
-
public String format ( Date d ):格式化,将日期对象格式化为字符串
-
public Date parse ( String s ):解析,将字符串解析为日期对象
-
package com.itheima.api_demo.dateformat_demo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
SimpleDateFormat类 :
"2021年04月03日 16:48:10" ---> Date
Date(Sat Apr 03 16:41:38 CST 2021) --> "2021年04月03日 16:48:10"
作用 :
格式化 : Date --> String
解析 : String --> Date
构造方法 :
public SimpleDateFormat(String pattern) : pattern : 字符串类型的日期模板
成员方法 ;
public final String format(Date date) : 接收一个Date对象返回指定模式的字符串
public Date parse(String source) : 接收一个字符串 , 返回一个Date对象
1 获取当前的日期对象,使用格式:yyyy-MM-dd HH:mm:ss 来表示,例如:2020-10-31 17:00:00【格式化】
2 将字符串的 2020年10月31日 17:00:00,转换为日期Date对象。【解析】
*/
public class SimpleDateFormatDemo {
public static void main(String[] args) throws ParseException {
// 解析 : String --> Date
String strDate = "2020年10月31日 17:00:00";
// 注意 : 解析时 , SimpleDateFormat的参数(日期模板) , 必须和要解析字符串的模式匹配
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
// public Date parse(String source) : 接收一个字符串 , 返回一个Date对象
Date date = sdf.parse(strDate);
System.out.println(date); // Sat Oct 31 17:00:00 CST 2020
}
private static void method() {
// 格式化 : Date --> String
// 获取当前系统时间
Date date = new Date();
// System.out.println(date);// Sat Apr 03 16:53:35 CST 2021
// public SimpleDateFormat(String pattern) : pattern : 字符串类型的日期模板
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// public final String format(Date date) : 接收一个Date对象返回指定模式的字符串
String strDate = sdf.format(date);
System.out.println(strDate);
}
}
Calendar类
-
概述 :
-
java.util.Calendar类表示日历,内含有各种时间信息,以及获取,计算时间的方法。
-
Calendar本身是一个抽象类,可以通过Calendar提供的静态方法getInstance日历子类对象
-
-
Calendar常用方法 :
方法名 | 说明 |
---|---|
public static Calendar getInstance() | 获取一个它的子类GregorianCalendar对象。 |
public int get(int field) | 获取指定日历字段的时间值。 |
public void set(int field,int value) | 设置指定字段的时间值 |
public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
-
get,set,add方法参数中都有一个整数类型的参数field,field用来区分当前要获取或者操作的日期时间数据的。field数据的值使用Calender中定义的整数常量来表示
-
Calendar.YEAR : 年
-
Calendar.MONTH :月
-
Calendar.DAY_OF_MONTH:月中的周
-
Calendar.HOUR:小时
-
Calendar.MINUTE:分钟,
-
Calendar.SECOND:秒
-
Calendar.DAY_OF_WEEK:星期
-
-
星期对应的关系
字段时间值 : 1 2 3 ... 7 真正的时间 : SUNDAY MONDAY TUESDAY ... SATURDAY
-
月份对应的关系
字段时间值 : 0 1 .... 11 正真的时间 : JANUARY FEBRUARY .... DECEMBER
package com.itheima.api_demo.calendar_demo;
/*
月份对应的关系
字段时间值 : 0 1 .... 11
正真的时间 : JANUARY FEBRUARY .... DECEMBER
*/
import java.util.Calendar;
/*
成员方法 :
public int get(int field) 获取指定日历字段的时间值。
public void set(int field,int value) 设置指定字段的时间值
public void add(int field,int amount) 为某个字段增加/减少指定的值
*/
public class CalendarDemo {
public static void main(String[] args) {
// 获取Calendar对象 , rightNow对象
Calendar rightNow = Calendar.getInstance();
// public void set(int field , int value) 设置指定字段的时间值
// rightNow.set(Calendar.YEAR , 2024);
// rightNow.set(Calendar.MONTH , 5);
// rightNow.set(Calendar.DAY_OF_MONTH, 10);
// public void add(int field,int amount) 为某个字段增加/减少指定的值
// rightNow.add(Calendar.DAY_OF_MONTH , -3);
// public int get(int field) : 获取指定日历字段的时间值。
int year = rightNow.get(Calendar.YEAR);
int month = rightNow.get(Calendar.MONTH);
int day = rightNow.get(Calendar.DAY_OF_MONTH);
System.out.println(year); // 2021
System.out.println(month);// 3
System.out.println(day); // 3
}
}
package com.itheima.api_demo.calendar_demo;
import java.util.Calendar;
/*
1 写代码使用get方法,将年,月,日,时,分,秒,周获取出来
特别注意获取月份,和星期有以下特点:
直接获取的月份数据是从0开始的, 0表示1月,.....11表示12月
周的获取,从周日开始计算,1就是周日,2就是周一 ......7就是周六
星期对应的关系
字段时间值 : 1 2 3 ... 7
真正的时间 : SUNDAY MONDAY TUESDAY ... SATURDAY
月份对应的关系
字段时间值 : 0 1 .... 11
正真的时间 : JANUARY FEBRUARY .... DECEMBER
*/
public class Test1 {
public static void main(String[] args) {
// 拿到当前时间
Calendar now = Calendar.getInstance();
System.out.println(now.get(Calendar.YEAR));
System.out.println(now.get(Calendar.MONTH));
System.out.println(now.get(Calendar.DAY_OF_MONTH));
System.out.println(now.get(Calendar.HOUR));
System.out.println(now.get(Calendar.MINUTE));
System.out.println(now.get(Calendar.SECOND));
int week = now.get(Calendar.DAY_OF_WEEK);// 7
System.out.println(getWeek(week));// 字段值
}
public static String getWeek(int field){
String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};
return str[field];
}
}
package com.itheima.api_demo.calendar_demo;
import java.util.Calendar;
/*
2 写代码实现,获取2022年10月1日是星期几?
参考思路:
直接获取日历对象,得到的是当前系统的日历时间信息。
获取日历对象后,要重新设置日期
再获取星期数据
*/
public class Test2 {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2022);
cal.set(Calendar.MONTH, 9);
cal.set(Calendar.DAY_OF_MONTH, 1);
int week = cal.get(Calendar.DAY_OF_WEEK);
System.out.println(getWeek(week));// 字段值
}
public static String getWeek(int field){
String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};
return str[field];
}
}
package com.itheima.api_demo.calendar_demo;
import java.util.Calendar;
/*
3 计算10000天之后的年月日
参考思路:
先获取当前日历对象
再调用add方法,指定DATE或者DAY_OF_MONTH,添加10000天
再获取日历的年,月,日
*/
public class Test3 {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, 10000);
System.out.println(cal.get(Calendar.YEAR));
System.out.println(cal.get(Calendar.MONTH));
System.out.println(cal.get(Calendar.DAY_OF_MONTH));
}
}
Math类
-
概述 : Math包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。所提供的都是静态方法,可以直接调用
-
常用方法 :
public static int abs(int a) | 获取参数a的绝对值: |
---|---|
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static double pow(double a, double b) | 获取a的b次幂 |
public static long round(double a) | 四舍五入取整 |
System类
-
System类包含几个有用的类字段和方法。 它不能被实例化
-
常用方法 :
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的 Java 虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
4. 随堂小记
工具类的书写规则:
-
工具类,修饰为final(不让继承)
-
工具类的构造方法,设置为private(不让其他类创建对象)
-
工具类中提供:静态方法(通过类名访问)
static关键字
-
解决程序中什么问题?
静态变量:共享数据
静态方法:工具类中方法的编写
- 怎么使用
public class 类{
static 类型 变量名;
public static 返回值类型 方法名(参数, ..){
}
}
类名.静态变量名=100;
类名.静态方法名();
-
细节:
- 静态内容是随着类的加载,存放在方法区的静态区域下(仅有一份)【早于对象创建】
- 静态方法中不能使用this关键字
- 静态方法只能访问静态内容(静态变量、静态方法)
final关键字
-
final修饰的类, 不能继承
-
final修饰的方法, 不能被重写
-
final修饰的变量, 初始化值后不能修改其值(变为常量)
代码块:
static{
//在对象创建之前,初始化数据
}
接口:
-
接口的作用:制定规则
-
接口的使用
-
接口定义(制定规则)
-
public interfce 接口名{
//常量
public static final String 常量名 = 值;
//抽象方法(制定规则)
public abstract 返回值类型 方法名(参数, ...);
}
- 接口实现(按照规则实现代码)
public 接口实现类 implements 接口名{
//重写接口中的抽象方法
}
问题:在继承时,子类可能把父类的构造方法继承了吗?
答案:不可以。
枚举:
-
解决什么问题?
当程序中的某个数据有固定在一定范围的取值时,为保障程序中数据的有效性,可以使用:枚举
- 使用方式:
public enum 枚举名{
固定选项值1,固定选项值2,...;
}
枚举名.选项值;
public enum Sex{
BOY,GIRL;
}
public class Student{
private Sex sex;
}
Student stu = new Student( Sex.BOY )
多态
什么是多态?
多态:多种形态
多种形态:
同一个对象,在不同时刻表现出来的不同形态
Cat extends Animal
第一种形态: Cat c1 = new Cat(); //c1是只猫
第二种形态: Animal c2 = new Cat(); //c2是个动物
举例:
数字2
10进制:2
2进制: 00000010
多态解决程序中的什么问题?
1、提高代码的复用性
2、提高代码的扩展性
public interface Player{
public void play();
public void stop();
}
public MP3 implements Player{
public void play(){
System.out.println("mp3播放")
}
public void stop(){
System.out.println("mp3停止")
}
}
public MP4 implements Player{
public void play(){
System.out.println("mp4播放")
}
public void stop(){
System.out.println("mp4停止")
}
}
public static void main(String[] args){
MP3 mp3 = new MP3();
method( mp3 )
MP4 mp4 = new MP4();
method( mp4 )
}
//多态的体现: Player p = new MP3 / MP4 ();
public static void method( Player p )// Player p = new MP4()
{
p.play();
p.stop();
}
//集合: ArrayList类 implements List接口 、 LinkedList类 implements List接口
List list = new LinkedList();
多态的使用
//多态的代码体现格式:
父类型 对象 = new 子类(); //大类型包含小类型 int a=10; long b = a;
多态在使用时的注意细节
-
多态中:父类和子类拥有一模一样的成员变量时:
-
编译时:以父类型中的成员变量为主
-
运行时:使用父类中的成员变量
-
-
多态中:父类和子类拥有一模一样的成员方法时:
-
编译时:以父类中的成员方法为主(检查父类中有没有这个成员方法,没有:报错)
-
运行时:以子类中的成员方法为主(调用子类对象中重写后的成员方法)
-
多态转型
-
向上转型(自动类型提升)
//基础班: int a =10; long num = a;
//多态:
父类型 父引用 = new 子类(); //子类型变为:父类型 (弊端:父引用不能使用子类特有成员)
- 向下转型(强制类型转换)
//解决的问题: 父引用不能使用子类中特有成员
//基础班: long a =100L; int b = (int) a;
//多态的向下转型:
子类 对象 = (子类) 父引用;
注意细节:
-
向下转型时容易发生:java.lang.ClassCastException(类型转换异常)
解决方案:instanceof
if( 父引用对象 instanceof 子类型 ){
子类型 对象 = (子类型)父引用对象;
对象.特有成员
}
多态代码的书写:
-
创建对象
//父类型 父引用 = new 子类()
Father f = new Son();
- 作为参数
public void method( Father f )
{
f.方法()
}
- 作为返回值
public Animal getInstance()
{
//返回:子类对象
return new Cat();
}
内部类:
public class HelloWorld{
//成员变量
//成员方法
//在一个类中,定义了另外一个类(内部类[成员内部类])
class Hello{
}
}
问题:如何访问某个类中的成员变量or成员方法?
答案:创建类的对象,通过"对象名.成员"的方式访问
匿名内部类:
-
解决程序中什么问题?
简化程序中代码的书写
- 怎么使用?
//语法格式:
new 类名/接口(){
//重写方法
}
//示例:
public class Father{
public String sayHello(String name){
return "早上好, "+ name;
}
}
//此时:程序的需求发生改变,要求sayHello方法的返回值为"你好,名字"
public class Son extends Father{
//重写sayHello方法
public String sayHello(String name){
return "你好, "+name;
}
}
//以下代码使用匿名内部的方式(其实本质就是一个子类对象)
new Father(){
//把父类中的方法重写
public String sayHello(String name){
return "晚上好,"+name;
}
}
工具类:
为解决某些特定问题,特意编写的公共类(程序员都可以使用)
-
JDK(java开发工具包) = JRE + 核心类库
-
核心类库: jdk提供一些现成的功能,这些功能封装在不同的类中
-
-
JDK就提供了一些工具类:Math、Arrays
-
Arrays工具类:针对数组,提供了一系列现成的功能(例:排序)
-
回顾上午内容:
多态
//多态可以解决程序中什么问题?
1、提高程序中代码的复用性
2、提高程序中代码的扩展性
//多态怎么使用?
//1、创建一个对象
父类型 父引入 = new 子类();
//2、作为参数
public void method(父类型 父引用){
父引用.成员方法()
}
//3、作为返回值
public 父类型 getInstance(){
return 子类对象;
}
//多态在使用中的细节
父子类中有相同的成员变量时:编译和运行都以父类型中的成员变量为主
父子类中有相同的成员方法时:编译时检查父类型中的成员方法是否存在
运行时以子类对象中的重写的方法为主
//多态的转型
向上转型: 父类型 父引入 = new 子类(); //弊端:父引用不能访问子类对象中特有成员
向下转型: 子类 对象 = (子类) 父引用; //向下转换后,可以访问子类对象中特有成员
在向下转型时容易发生:ClassCastException 异常
使用:instanceof 避免 ClassCastException异常发生
if(父引用 instanceof 子类类型){
子类 对象 =(子类) 父引用;
}
匿名内部类
//匿名内部类解决什么问题?
简化程序中的代码
//匿名内部类的使用
父类型 父引用 = new 父类/接口(){
//重写父类型中的方法
};
//作为参数
public void show( Flyable fly );
show( new Flyalbe(){
//重写方法
} );
//作为返回值
public Flyable getInstance(){
return new Flyable(){
//重写方法
};
}
Object(鼻祖类)
在Java继承体系中,有一个顶层父类:Object(鼻祖类)
-
在java语言中,程序员自定义的类或者jdk中存在的类,直接或间接都要继承Object
-
继承了Object类后,就可以使用Object提供的相关方法:
-
boolean equals(Object obj)
-
boolean: 方法的返回值类型
-
Object: 方法传递参数的类型
-
作用:比较两个对象是否相同(比较两个对象的地址值是否相同)
-
-
String toString()
-
作用: 把对象转换为字符串
-
-
比较两个字符串是否相同 :
//方案1: String类中的equals方法
boolean result = 字符串1.equals(字符串2);
//方案2:Objects工具类中的equals方法
boolean result = Objects.equals(字符串1 , 字符串2);
区别:Objects工具类中的equals方法 可以避免NullPointerException异常的发生
日期类型的数据:
public class Emp
{
//姓名
private String name;//String表示字符串
//年龄
private int age;//int表示整数
//生日
private Date birthday;//Date表示日期
}
Date类:
-
归属包:java.util
-
作用:表示日期时间(精确到毫秒)
-
使用:
-
构造方法(创建对象)
-
public Date()
public Date(long time)
DateFormat类
//DateFormat类是什么
DateFormat类是java语言提供的日期格式化类
//DateFormat类解决什么问题
对日期进行格式化操作:Date类型 -> String类型 => String format(Date)
对日期进行解析操作:String类型 -> Date类型 => Date parse(String )
//DateFormat类怎么使用
java.text.DateFormat
DataeFormat是一个抽象类,无法实例化。使用子类:SimpleDateFormat
DateFormat df = new SimpleDateFormat("日期模板");
//日期模板:就是使用一些特定的字符,来表示某个日期。例:yyyy表示全年 MM表示月 dd表示日
DateFormat df = new SimpleDateFormat("yyyy/MM/dd");
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format(Date date) //将Date类型的数据,按照日期模板,转换为字符串
Date parse(String s) //将日期格式的字符串数据,按照日期模板,转换为Date对象
Calendar类
Calendar类:日历类(存储的有日期、时间、日历信息)
-
代替java.util.Date类中的过期方法
//Calendar类的使用: 构造方法、 常用方法
//Calendar类是一个抽象类,无法创建对象。 子类:GregorianCalendar
//在Calendar类中,提供了一个静态方法,该静态方法可以实现:Calendar对象的实例化(底层还是使用GregorianCalendar子类)
//获取Calendar类对象
Calendar c = Calendar.getInstance();
Calendar对象中存储的内容:
java.util.GregorianCalendar[
time=1667208388632,
areFieldsSet=true,
areAllFieldsSet=true,
lenient=true,
zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null],
firstDayOfWeek=1,
minimalDaysInFirstWeek=1,ERA=1,
YEAR=2022,
MONTH=9, //月份:0~11
WEEK_OF_YEAR=45,
WEEK_OF_MONTH=6,
DAY_OF_MONTH=31,
DAY_OF_YEAR=304,
DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,
HOUR=5,
HOUR_OF_DAY=17,
MINUTE=26,
SECOND=28,
MILLISECOND=632,
ZONE_OFFSET=28800000,DST_OFFSET=0]
获取Calendar对象中存储的数据:
//API方法: public int get(int 字段名) //字段名:YEAR MONTH DAY_OF_MONTH
在Calendar类中有一些静态常量: YEAR MONTH DAY_OF_MONTH
Calenar.YEAR Calendar.MONTH
//获取日历对象中的年
Calendar c = Calendar.getInstance();
int year = c.get( Calenar.YEAR )
给日历对象设置具体的:年月日时分秒......
//获取日历对象中的年
Calendar c = Calendar.getInstance(); //日历对象是基于当前系统日期时间获取的
//修改日历对象中的信息 public void set(int 字段 , int 数值)
c.set( Calendar.YEAR , 2000 );
//修改日历对象中的年月日
c.set( 2000, 9, 31 );
给日历对象中的信息,增加或减少
public void add(int 字段 , int 数值) //数值是负数是减少 , 数据是正数表示增加