多态
什么是多态?
同一个对象在不同时刻表现出来的不同形态(多种形态)
例:Cat extends Animal
第一种形态:Cat c1 = new Cat(); //c1是只猫
第二种形态:Animal c2 = new Cat(); //c2是个动物
(多种形态)举例:数字:2
十进制:2
二进制:00000010
多态的前提 ?
1 有继承/实现关系
2 有方法的重写
3 父类的引用指向子类的对象
多态的使用?
//多态的代码体现格式
父类型 对象 = new 子类();//大类型包含小类型 int a = 10; long b = a;
多态代码的书写:
1. 创建对象
//父类型 父引用 = new 子类()
Father f = new Son();
2. 作为参数
public void method( Father f )
{
f.方法()
}
3. 作为返回值
public Animal getInstance()
{
//返回:子类对象
return new Cat();
}
多态在程序中解决什么问题?
1.提高代码的复用性
2.提高代码的扩展性
java
public interface Player{
public abstract void play();
public abstract 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 = mp3
p.play();
p.stop();
}
}
//集合:ArrayList类 implements List接口
List list = new ArrayList();
需要改的时候(体现扩展性)List list = new LinkedList();
多态在使用时的注意细节?
1. 多态中:父类和子类拥有一模一样的成员变量时:
编译时:以父类型中的成员变量为主
运行时:使用父类中的成员变量
2. 多态中:父类和子类拥有一模一样的成员方法时:
编译时:以父类中的成员方法为主(检查父类中有没有这个成员方法,没有:报错)
运行时:以子类中的成员方法为主(调用子类对象中重写后的成员方法)
java
public class Father {
int num = 100;
public void show() {
System.out.println("父类的show方法");
}
}
public class Son extends Father {
//成员变量
int num = 10;
//成员方法
public void show() {
System.out.println("子类的show方法");
}
public void show2(){
System.out.println("子类特有的方法");
}
}
public class Test {
public static void main(String[] args) {
// 父类的引用指向子类的对象
Father f = new Son();
// 多态对象调用成员变量:调用的是父类的成员变量
System.out.println(f.num);
// 多态对新对象调用成员方法
f.show();
// 多态对象不能调用子类特有的方法
// f.show2();
//向下转型
Son s = (Son)f;//子类 对象 = (子类) 父引用;
s.show2();
}
}
java
运行结果:
100
子类的show方法
子类特有的方法
多态的优缺点
多态的好处:提高了程序的扩展性,灵活性
多态形式体现(使用方向):
- 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象
2 .定义方法的时候, 使用父类作为方法的返回值类型 , 该方法可以返回此父类任意子类对象
- 定义变量时 , 用父类类型变量接收子类类型对象
多态的弊端:不能使用子类的特有功能
多态转型
向上转型(自动类型提升)
例:int a =10; long num = a;
//多态: 父类型 父引用 = new 子类(); //子类型变为:父类型 (弊端:父引用不能使用子类特有成员)
向下转型(强制类型转换) //解决的问题: 父引用不能使用子类中特有成员
例:long a =100L; int b = (int) a;
//多态的向下转型: 子类 对象 = (子类) 父引用;
注意细节:
向下转型时容易发生:
java.lang.ClassCastException(类型转换异常)
解决方案:instanceof
java
if( 父引用对象 instanceof 子类型 ){
子类型 对象 = (子类型)父引用对象;
对象.特有成员
}
java
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();
}
-------------------------------------------------------------
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("抓老鼠...");
}
}
------------------------------------------------------------
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("狗看门...");
}
}
----------------------------------------------------------------
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("一直再睡...");
}
}
---------------------------------------------------------------
public class Test {
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 animal){
animal.eat();
if(animal instanceof Cat){
Cat cat = (Cat) animal;
cat.catchMouse();
}else if(animal instanceof Dog){
Dog dog = (Dog)animal;
dog.lookDoor();
} else if (animal instanceof Pig) {
Pig pig = (Pig) animal;
pig.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 p) {// Pig p = new Pig();
// p.eat();
// p.sleep();
// }
}
运行结果:
猫吃鱼...
抓老鼠...
---------
狗吃骨头!
狗看门...
---------
猪拱白菜...
一直再睡...
多态的应用之处有哪些 ?
第一 : 以多态形式创建一个类的对象
第二 : 方法的参数是一个类或者是一个接口 , 那么我们可以传入子类对象
第三 : 方法的返回值类型是一个类或者接口 , 那么我们可以返回子类对象
内部类
什么是内部类?
在一个类中,定义了另外一个类(内部类[成员内部类])
内部类的使用方法?
public class HelloWorld{
//成员变量
//成员方法
//在一个类中,定义了另外一个类(内部类[成员内部类])
class Hello{
}
}
问题:如何访问某个类中的成员变量or成员方法?
答案:创建类的对象,通过"对象名.成员"的方式访问
成员内部类
java
public class Person {
// 心脏
class Heart {
// 变量-频率
private int rate;//60~75
// 跳动方法
public void beats() {
System.out.println("咚咚咚~~");
}
}
}
------------------------------------------------------------
public class Test {
public static void main(String[] args) {
//创建Person对象
Person p = new Person();
//创建成员内部类对象
Person.Heart heart = p.new Heart();
//外部类名.内部类名 变量 = 外部类对象.new 内部类构造方法(参数);
heart.beats();
}
}
运行结果:咚咚咚~~
java
局部变量:直接访问,
内部类成员变量:this 访问
外部类成员变量:外部类名.this 访问
java
public class Person {
private String name = "张三";
int num = 30;//外部类成员变量
class Heart {
private int rate;//60~75
int num = 20;//内部类成员变量
public void beats() {
int num = 10;//内部类方法中的局部变量
System.out.println(num);//10
System.out.println(this.num);//20
System.out.println(Person.this.num);//30
}
}
}
--------------------------------------------------------------
public class Test {
public static void main(String[] args) {
Person.Heart heart = new Person().new Heart();
heart.beats();
}
}
--------------------------------------------------------------
匿名内部类:
解决程序中什么问题?
简化程序中代码的书写
怎么使用?
//语法格式: new 类名/接口(){ //重写方法 }
java
//接口
public interface Flyable {
void fly();
}
---------------------------------------------------------------
public class Test2 {
public static void main(String[] args) {
//调1次
new Flyable(){
@Override
public void fly() {
System.out.println("我在学习");
}
}.fly();
//想要调用fly方法:2次
Flyable f = new Flyable() {
@Override
public void fly() {
System.out.println("我在玩代码");
}
};
f.fly();
f.fly();
}
}
------------------------------------------------------
运行结果:
我在学习
我在玩代码
我在玩代码
工具类:为解决某些特定问题,特意编写的公共类(都可以使用)
1.JDK(java开发工具包) = JRE + 核心类库
核心类库: jdk提供一些现成的功能,这些功能封装在不同的类中
2.JDK就提供了一些工具类:Math、Arrays
2.1,Arrays工具类:针对数组,提供了一系列现成的功能(例:排序)
java
import java.util.Arrays; //导入工具类所在包
import java.util.Comparator;
public class ArraysTest {
public static void main(String[] args) {
//数组
Integer[] array = {3, 1, 5, 2, 8, 4};//Integer就是int类型
System.out.println("排序前:" + Arrays.toString(array));
//对数组进行排序
//使用JDK提供的现成工具类:Arrays,实现排序
Arrays.sort(array);//默认排序规则: 升序(从小到大)
System.out.println("排序后:" + Arrays.toString(array));
//程序需求:数组元素必须是从大到小(降序)
Arrays.sort(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println("排序后:" + Arrays.toString(array));
}
}
运行结果:
排序前:[3, 1, 5, 2, 8, 4]
排序后:[1, 2, 3, 4, 5, 8]
排序后:[8, 5, 4, 3, 2, 1]
常用API(1)
在Java继承体系中,有一个顶层父类:Object(鼻祖类)
在java语言中,程序员自定义的类或者jdk中存在的类,直接或间接都要继承Object
继承了Object类后,就可以使用Object提供的相关方法:
1.boolean equals(Object obj)
-boolean: 方法的返回值类型
-Object: 方法传递参数的类型
-作用:比较两个对象是否相同(比较两个对象的地址值是否相同)
java
import java.util.Objects;
public class Phone {
private String brand;
private int price;
public Phone() {
}
@Override
public boolean equals(Object o) {
//两个对象地址值相同说明是同一个对象
if (this == o) return true;
//当要比较的对象是null时,就不需要比较,直接返回:false
//当比较两个对象类型不一样,不需要比较,直接返回:false
if (o == null || getClass() != o.getClass()) return false;
//向下转型
Phone phone = (Phone) o;
//基本数据类型比较 使用Objects工具类中的equals方法,比较两个字符串是否相同
// return price == phone.price && Objects.equals(brand, phone.brand);
return price == phone.price && this.brand.equals(phone.brand);
}
@Override
public int hashCode() {
return Objects.hash(brand, price);
}
public Phone(String brand, int price) {
this.brand = brand;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
--------------------------------------------------------------------
public class Test {
//演示:equals方法
public static void main(String[] args) {
Phone p1 = new Phone("小米",1999);
Phone p2 = new Phone("小米",1999);
System.out.println(p1);
System.out.println(p2);
System.out.println("-----------------------------------------");
System.out.println(p1==p2);//==比较的是变量中的数据值,比较的是对象中存储的地址值;p1,p2是对象
System.out.println(p1.equals(p2));//Ojbect类中的equals方法,比较的是对象中存储的地址值
//当希望比较Phone中存储的数据值时,在Phone中重写equals方法,不重写,比较的是地址值
}
}
--------------------------------------------------
运行结果:
com.Demo.object.equals.Phone@168b1cc
com.Demo.object.equals.Phone@168b1cc
-----------------------------------------
false
false
2.String toString()
- 作用: 把对象转换为字符串
java
public class Student {
private String name;
private int age;
public Student() {
}
@Override
public String toString() {
return "Student{name=" + name + ", age=" + age + '}';
}
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 Test {
//演示:toString方法
public static void main(String[] args) {
//创建学生对象
Student stu = new Student("熊大",23);
//把对象转换为字符串
String str = stu.toString();
System.out.println(str);
System.out.println(stu);
}
}
--------------------------------------------------------------
运行结果:
Student{name=熊大, age=23}
比较两个字符串是否相同 :
1: String类中的equals方法
boolean result = 字符串1.equals(字符串2);
2:Objects工具类中的equals方法
boolean result = Objects.equals(字符串1 , 字符串2);
区别:Objects工具类中的equals方法 可以避免NullPointerException异常的发生
java
import java.util.Objects;
public class ObjectsTest {
public static void main(String[] args) {
String str1 = null;
String str2 = "itext";
//使用Objects工具类中的API方法:比较两个字符串是否相同
boolean result2 = Objects.equals(str1,str2);
System.out.println(result2);//Objects工具类中的equals方法 可以避免NullPointerException异常的发生
//使用String类中的API方法:比较两个字符串是否相同
boolean result1 = str1.equals(str2);
System.out.println(result1);
}
}
--------------------------------------------
运行结果:
报错
false
日期类型的数据:
java
public class Emp{
//姓名 private String name;//String表示字符串
//年龄 private int age;//int表示整数
//生日 private Date birthday;
//Date表示日期
}
Date类:
归属包:java.util
作用:表示日期时间(精确到毫秒)
使用: 构造方法(创建对象)
public Date()
public Date(long time)
java
import java.util.Date;
public class DateTest {
//演示:Date对象的使用
public static void main(String[] args) {
method1();
}
public static void method1(){
//创建Date对象,输出实时时间
Date date1 = new Date();
System.out.println(date1);
Date date2 = new Date(0);//传参时输出:Date对象 = 1970/1/1 0:0:0 + time毫秒值
System.out.println(date2);
//成员方法:获取毫秒值
long time = date1.getTime();//返回毫秒值 = 当前Date代表的时间 - 1970/1/1 0:0:0
System.out.println(time);
}
}
---------------------------------------------------------------------
运行结果:
Wed Jul 16 23:02:33 CST 2025
Thu Jan 01 08:00:00 CST 1970
1752678153025
常用方法DateFormat类
DateFormat类是什么?
DateFormat类是java语言提供的日期格式化类
DateFormat类解决什么问题?
对日期进行格式化操作:Date类型 -> String类型 => String format(Date)
对日期进行解析操作:String类型 -> Date类型 => Date parse(String )
java
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormatTest {
//演示:日期格式化、日期解析
public static void main(String[] args) throws ParseException {
method1();
String str="2025-07-16 14:07:33";
method2(str);//Alt+回车,选第一个解决问题
}
//把日期转换为字符串
public static void method1(){
//日期对象
Date date = new Date();
System.out.println(date);
//创建日期格式化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//日期转换为字符串(按照日期模板,把日期对象变成相应格式的字符串
String strDate = sdf.format(date);
System.out.println(strDate);
}
//把字符串解析为日期
public static void method2(String s) throws ParseException {
////创建日期格式化对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//String类型->Data类型
Date date = sdf.parse(s);//Alt+回车
System.out.println(date);
}
}
-------------------------------------------------------------
运行结果:
Wed Jul 16 23:04:57 CST 2025
2025-07-16 23:04:57
Wed Jul 16 14:07:33 CST 2025
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类:日历类(存储的有日期、时间、日历信息)
代替java.util.Date类中的过期方法
Calendar类的使用: 构造方法、 常用方法
Calendar类是一个抽象类,无法创建对象。
子类:GregorianCalendar
在Calendar类中,提供了一个静态方法,该静态方法可以实现:Calendar对象的实例化(底层还是使用GregorianCalendar子类)
获取Calendar类对象Calendar c = Calendar.getInstance();
Calendar对象中存储的内容:
获取Calendar对象中存储的数据:
//API方法: public int get(int 字段名) //字段名:YEAR MONTH DAY_OF_MONTH在Calendar类中有一些静态常量: YEAR MONTH DAY_OF_MONTHCalenar.YEAR Calendar.MONTH
//获取日历对象中的年
Calendar c = Calendar.getInstance();
int year = c.get( Calenar.YEAR )
java
import java.util.Calendar;
public class CalendarTest {
//演示:Calendar日历类的使用
public static void main(String[] args) {
//创建Calendar类对象
Calendar c = Calendar.getInstance();
System.out.println(c);
//获取日历对象中的:年,月,日
int year = c.get( Calendar.YEAR );
int month = c.get( Calendar.MONTH );//月分范围0~11
int day = c.get( Calendar.DATE );
System.out.println(year+"年"+(month+1)+"月"+day+"日");
}
}
给日历对象设置具体的:年月日时分秒...
//获取日历对象中的年Calendar c = Calendar.getInstance(); //日历对象是基于当前系统日期时间获取的//修改日历对象中的信息
public void set(int 字段 , int 数值)
c.set( Calendar.YEAR , 2000 );
//修改日历对象中的年月日
c.set( 2000, 9, 31 );
java
import java.util.Calendar;
public class CalendarTest2 {
public static void main(String[] args) {
//给日历对象设置具体的:年月日时分秒
//获取日历对象中的年
Calendar c = Calendar.getInstance(); //日历对象是基于当前系统日期时间获取的
//修改日历对象中的年月日
c.set( 2000, 9, 31 );
int year = c.get( Calendar.YEAR );
int month = c.get( Calendar.MONTH );//月分范围0~11
int day = c.get( Calendar.DATE );
System.out.println(year+"年"+month+"月"+day+"日");
}
}
给日历对象中的信息,增加或减少
public void add(int 字段 , int 数值) //数值是负数是减少 , 数据是正数表示增加
java
import java.util.Calendar;
public class DataFormate3 {
public static void main(String[] args) {
//创建Calendar类对象
Calendar c = Calendar.getInstance();
System.out.println(c);
//增加一年
c.add(Calendar.YEAR,1);
System.out.println(c);
//减少一年
c.add(Calendar.YEAR,-1);
System.out.println(c);
}
}