多态,内部类(匿名内部类),常用API(1)

多态

什么是多态?

同一个对象在不同时刻表现出来的不同形态(多种形态)

例: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方法
子类特有的方法

多态的优缺点

多态的好处:提高了程序的扩展性,灵活性

多态形式体现(使用方向):

  1. 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象

2 .定义方法的时候, 使用父类作为方法的返回值类型 , 该方法可以返回此父类任意子类对象

  1. 定义变量时 , 用父类类型变量接收子类类型对象

多态的弊端:不能使用子类的特有功能

多态转型

向上转型(自动类型提升)

例: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);
    }
}