【Java基础二】

Java基础2


学习黑马java系列课程所作笔记

文章目录


四、面向对象高级

1.面向对象高级一

1.1static

1.1.1static修饰成员变量
  • 叫静态,可以修饰成员变量、成员方法

成员变量按照有无static修饰,分为两种:

  • 类变量:有static修饰,属于类,在计算机中只有一份发,会被类的全部变量共享
  • 实例变量(变量的对象):无static修饰,属于每个对象自己。
    在这里插入图片描述
    Student
package com.itheima.d1_staticDemo;

public class Student {
    //类变量
    static String name;
    //实例变量(对象的变量)
    int age;
}

Test

package com.itheima.d1_staticDemo;

public class Test {
    public static void main(String[] args) {
        //目标:掌握有无Static修饰成员变量的用法,特点。
        //1.类变量的用法
        //类名.类变量(推荐)
        Student.name="袁华";

        //对象.类变量(不推荐)
        Student s1=new Student();
        s1.name="马冬梅";

        Student s2=new Student();
        s2.name="秋雅";
        System.out.println(s1.name);
        System.out.println(Student.name);

        //2.实例变量的用法
        s1.age=23;
        s2.age=18;
        System.out.println(s1.age);
        //System.out.println(Student.age);报错
    }


}

在这里插入图片描述
成员变量的执行原理
在这里插入图片描述
在这里插入图片描述

1.1.2static修饰成员变量的应用场景

类变量的应用场景

  • 在开发中,如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成类变量来记住。

案例导学

  • 系统启动后,要求用户类可以记住自己创建了多少个用户对 象了。
    在这里插入图片描述
    Test2
package com.itheima.d1_staticDemo;

public class Test2 {
    public static void main(String[] args) {
        //目标:通过案例理解类变量的应用场景
        User u1=new User();
        User u2=new User();
        User u3=new User();
        User u4=new User();


        System.out.println(User.number);
    }
}

User

package com.itheima.d1_staticDemo;

public class User {
    //类变量一般用public修饰,对外暴露,方便被外界访问
    public static int number;
    public User(){
        //User.number++;
        //在同一个类中,访问自己类的类变量,才可以省略类名不写
        number++;
    }
}

在这里插入图片描述

1.1.3static修饰成员方法
  • 类方法:有static修饰的成员方法,属于类。
    在这里插入图片描述

  • 实例方法:无static修饰的成员方法,属于对象。
    在这里插入图片描述
    Student

package com.itheima.d2_static_method;

public class Student {
    double score;

    //类方法
    public static void printHelloWorld(){
        System.out.println("Hello World");
    }
    public void printPass() {
        System.out.println("成绩:" +
                (score >= 60 ? "及格" : "不及格"));
    }
}

Test

package com.itheima.d2_static_method;

public class Test {
    public static void main(String[] args) {
    //目标:掌握有无static修饰方法的用法。
    //1、类方法的用法
    //类名。类方法(推荐)
        Student.printHelloWorld();

        //对象.类方法(不推荐)
        Student s = new Student();
        s.printHelloWorld();

        //2实例方法的用法
        //对象.实例方法
        s.printPass();
        //Student.printPass();报错
    }
}

成员方法执行原理
在这里插入图片描述
在这里插入图片描述


补充知识:搞懂main方法
在这里插入图片描述

  • 虚拟机会用Test类来执行main()方法
  • 括号里表示可以传一些参数进去,实际开发中没啥用
    在这里插入图片描述
1.1.4static修饰成员方法的应用场景

类方法的常见应用场景

  • 类方法最常见的应用场景是做工具类。

工具类是什么?

  • 工具类中的方法都是一些类方法,每个方法都是用来完成一个功能的,工具类是给开发人员共同使用的。

使用类方法来设计工具类有啥好处?

  • 提高了代码复用:调用方便,提高了开发效率。
    在这里插入图片描述
    案例
    在这里插入图片描述
    在这里插入图片描述
    LoginDemo
package com.itheima.d3_util;

/**
登录界面
 */
public class LoginDemo {
    public static void main(String[] args) {
        //定义两个变量,一个记住最终产生的随机验证码,一个是记住可能
        System.out.println(MyUtil.createCode(4));
    }

}

RegisterDemo

package com.itheima.d3_util;

public class RegisterDemo {
    public static void main(String[] args) {
        System.out.println(MyUtil.createCode(6));
    }
}

MyUtil

package com.itheima.d3_util;

import java.util.Random;

public class MyUtil {
    private  MyUtil(){

    }
    public static String createCode(int n){
            String code ="";
            String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            Random r=new Random();
            //2、开始定义一个循环产生每位随机字符
            for (int i=0;i < n;i++){
            //3、随机一个字符范围内的索引。
                int index = r.nextInt(data.length());
            //4、根据索引去全部字符中提取该字符
                code+=data.charAt(index);//code=code+字符
            }
            return code;
    }
}

为什么工具类中的方法要用类方法,而不用实例方法?

  • 实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,这样会浪费内存。
  • 类方法,直接用类名调用即可,调用方便,也能节省内存。

多学一招:
工具类没有创建对象的需求,建议将工具类的构造器进行私有。

1.1.5staticd的注意事项
  • 类方法中可以直接访问类的成员,不可以直接访问实例成员。
  • 实例方法中既可以直接访问类成员,也可以直接访问实例成员。
  • 实例方法中可以出现ths关键字,类方法中不可以出现ths关键字的。

示例:
在这里插入图片描述
Student

package com.itheima.d4_static_attention;

public class Student {
    static String schoolName;//类变量
    double score;//实例变量
    //1、类方法中可以直接访问类的成员,不可以直接访问实例成员。
    public static void printHelloWorld() {
    //注意:同一个类中,访问类成员,可以省略类名不写
        //Student.schoolName="黑马";
        //Student.printHelloWorld2();
        schoolName="黑马";
        printHelloWorld2();
        //System.out.println(score);报错
        //printPass();报错

        //System.out.println(this);报错
    }


//2、实例方法中既可以直接访问类成员,也可以直接访问实例成员。
//实例方法
//3、实例方法中可以出现this关键字,类方法中不可以出现this关键字的

        public static void printHelloWorld2(){
}
        public void printPass(){
        schoolName="黑马";
        printHelloWorld2();

        System.out.println(score);
        printPass2();//相当于this.printPass2();

        System.out.println(this);//会输出地址
        }
    public void printPass2(){

    }
}


Test

package com.itheima.d4_static_attention;

public class Test {
    public static void main(String[] args) {
        Student s1=new Student();
        s1.printPass();

    }
}

1.1.6staticd的应用知识:代码块

代码块概述

  • 代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)。
    代码块分为两种

  • 静态代码块:
    ->格式:static{}
    ->特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
    ->作用:完成类的初始化,例如:对类变量的初始化赋值。

  • 实例代码块:
    ->格式:{}
    ->特点:每次创建对象时,执行实例代码块,并在构造器前执行。
    ->作用:和构造器一样,都是用来完成对象的初始化的心例如:对实例变量进行初始化赋值。
    示例
    在这里插入图片描述
    Student

package com.itheima.d5_block;

public class Student {
    static int number=80;
    static String schoolName;
    //静态代码块
    static{
        System.out.println("静态代码块执行了~~");
        schoolName="黑马";
    }
    //实例代码块
    {
        System.out.println("实例代码块执行了~~");
        System.out.println("有人创建了对象:"+this);
        //可以把构造器中重复代码拿到实例代码块中
    }
    public Student(){
        System.out.println("无参数构造器执行了~~");
    }
    public Student(String name){
        System.out.println("有参数构造器执行了~~");
    }
}

Test

package com.itheima.d5_block;

public class Test {
    public static void main(String[] args) {
        //目标:认识两种代码块,了解他们的特点和基本作用
        System.out.println(Student.number);
        System.out.println(Student.number);
        System.out.println(Student.number);
        System.out.println(Student.schoolName);//黑马
        System.out.println("-----------------------------------------");
        Student s1=new Student();
        System.out.println("-----------------------------------------");
        Student s2 = new Student("张三");
    }

}

1.1.7staticd的应用知识:单例设计模式

什么是设计模式(Design pattern)?

  • 一个问题通常有种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
  • 设计模式有20多种,对应20多种软件开发中会遇到的问题。
    关于设计模式的学习,主要学什么?
  1. 解决什么问题?
  2. 怎么写?

单例设计模式

  • 确保一个类只有一个对象。

写法(饿汉式)

  • 把类的构造器私有。
  • 定义一个类变量记住类的一个对象。
  • 定义一个类方法,返回对象。

示例
在这里插入图片描述
A

package com.itheima.d6_singleInstance;

public class A {
    //2.定义一个类变量记住类顶点的一个对象
    private static A a=new A();

    //1.必须私有类的构造器
    private A(){

    }
    //定义一个类方法返回类的对象
    public static A getObject() {
        return  a;
    }
}

Test1

package com.itheima.d6_singleInstance;

public class Test1 {
    public static void main(String[] args) {
        //目标:掌握单例设计模式的写法
        System.out.println(A.getObject());
        A a1=A.getObject();
        A a2=A.getObject();
        System.out.println(a1);
        System.out.println(a2);


    }
}

懒汉式单例设计模式

  • 拿对象时,才开始创建对象。

写法

  • 把类的构造器私有。
  • 定义一个类变量用于存储对象。
  • 提供一个类方法,保证返回的是同一个对象。

B

package com.itheima.d6_singleInstance;

public class B {
    //2.定义一个类变量,用于存储这个类的一个对象。
    private static B b;
    //1.把类的构造器私有
    private B(){

    }

    //定义一个类方法,保证第一次调用时才创建一个对象,后面调用时都会用同一个对象返回
    public static B getInstance(){
        if(b==null){
            b=new B();
        }
        return b;
    }
}

Test2

package com.itheima.d6_singleInstance;
//目标:掌握懒汉式单例的写法
public class Test2 {
    public static void main(String[] args) {
        B b1=B.getInstance();//第一次拿对象
        B b2=B.getInstance();
        System.out.println(b1 == b2);
    }
}

1.2面向对象三大特征之二:继承

1.2.1认识继承、特点

什么是继承?

  • Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。
    在这里插入图片描述
    继承的特点
  • 子类能继承父类的非私有成员(成员变量、成员方法)。
    继承后对象的创建
  • 子类的对象是由子类、父类共同完成的。

示例:
在这里插入图片描述
A

package com.itheima.d7_extends;

//父类
public class A {

    //公开成员
    public int i;
    public void print1(){
        System.out.println("===print1===");
    }
    //私有成员
    private int j;
    private void print2(){
        System.out.println("===print2===");
    }
}

B

package com.itheima.d7_extends;

//子类
public class B extends A{
    private int k;
    //子类可以继承父类的非私有成员
    public void print3(){
        System.out.println(i);
        print1();

        //System.out.println(j);
        //print2();private,不能继承,报错
    }
}

Test

package com.itheima.d7_extends;

public class Test {
    public static void main(String[] args) {
        //认识继承,掌握继承的特点
        B b=new B();
        System.out.println(b.i);
       //System.out.println(b.j);//
        //System.out.println(b.k);

        b.print1();
        //b.print2();
        b.print3();
    }

}

继承的执行原理
在这里插入图片描述
在这里插入图片描述

1.2.2继承的好排除、应用场景

使用继承有什么好处?

  • 减少重复代码的编写。
    在这里插入图片描述
    在这里插入图片描述
    示例:
    在这里插入图片描述
    People
package com.itheima.d8_extends_application;

public class People {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Teacher

package com.itheima.d8_extends_application;

public class Teacher extends People{
    private  String skill;

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
    public void printInfo(){
        System.out.println(getName()+"具备的技能:"+skill);
    }
}

Test

package com.itheima.d8_extends_application;

public class Test {
    public static void main(String[] args) {
        //目标:弄清楚继承的好处
        Teacher t=new Teacher();
        t.setName("波仔");
        t.setSkill("Java");
        System.out.println(t.getName());
        System.out.println(t.getSkill());
        t.printInfo();
    }
}

1.2.3继承的相关注意事项
1.2.3.1权限修饰符

什么是权限修饰符?

  • 就是是用来限制类中的成员(成员变量、成员方法、构造器、代码块)能够被访问的范围。

权限修饰符有几种?各自的作用是什么?
在这里插入图片描述
示例:
在这里插入图片描述
Demo

package com.itheima.d9_modifer;

public class Demo {
    public static void main(String[] args) {
        //目标:掌握不同修饰类的作用
        Fu f=new Fu();
        //f.privateMethod();报错
        f.method();
        f.protectedMethod();
        f.publicMethod();
    }
}

Fu

package com.itheima.d9_modifer;

public class Fu {
    //1、私有:只能在本类中访问
    private void privateMethod(){
        System.out.println("==private==");
    }

    //2、缺省:本类,同一个包下的类
    void method(){
        System.out.println("==缺省=");
    }
    //3、protected:本类,同一个包下的类,任意包下的子类
    protected void protectedMethod(){
        System.out.println("==protected==");
    }
    //4、pUbL1c:本类,同一个包下的类,任意包下的子类,任意包下的任意类
    public void publicMethod(){
        System.out.println("==public==");
    }
    public void test(){
        privateMethod();
        method();
        protectedMethod();
        publicMethod();
    }
}

Demo2

package com.itheima.d10_modifer;

import com.itheima.d9_modifer.Fu;

public class Demo2 {
    public static void main(String[] args) {
        Fu f=new Fu();
        //f.protectedMethod();报错
        //f.method();报错
        //f.protectedMethod();报错
        f.publicMethod();

        //注意,protected可以在子类里访问,不能在子类的对象里访问
       // f.protectedMethod();
    }
}

Zi

package com.itheima.d10_modifer;

import com.itheima.d9_modifer.Fu;

public class Zi extends Fu {
    public void test() {
        //privateMethod();报错
        //method;报错
        protectedMethod();
        publicMethod();
    }
}

1.2.3.2单继承与Object类

Java是单继承的,Java中的类不支持多继承,但是支持多层继承
在这里插入图片描述
Java为何不支持多继承?
在这里插入图片描述
Object类

  • object类是java所有类的祖宗类。我们写的任何一个类 ,其实都object的子类或子孙类
    在这里插入图片描述
    示例:
    在这里插入图片描述
package com.itheima.d11_extends_feature;

public class Test {
    public static void main(String[] args) {
        //目标:掌握继承的两个注意事项事项。
        //1、Java是单继承的:一个类只能继承一个直接父类:Java中的类不支持多继承,但是支持多层继承。
        //2、Object类是Java中所有类的祖宗。
        A a=new A();
        B b=new B();
        b.hashCode();
    }

}
class A{}//extends Object{}
class B extends A{}
//class C extends A,B{}报错
class C extends B{}//支持多层继承
1.2.3.3方法重写

什么是方法重写

  • 当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
  • 注意:重写后,方法的访问,Java会遵循就近原则
    示例:
    在这里插入图片描述
    A
package com.itheima.d12_extends_override;

public class A {
    public void print1(){
        System.out.println("111");
    }
    public void print2(int a,int b){
        System.out.println("111111");
    }
}

B

package com.itheima.d12_extends_override;

public class B extends A{
    //方法重写
    public void print1(){
        System.out.println(666);

    }
    public void print2(int a,int b){
        System.out.println("66666");
    }
}

C

package com.itheima.d12_extends_override;

public class C extends B{
}

Test

package com.itheima.d12_extends_override;

public class Test {
    public static void main(String[] args) {
        //目标:认识方法重写,掌握方法重写的常见应用场景。
        B b=new B();
        b.print1();
        b.print2(2,3);
        C c=new C();
        c.print1();
    }
}

在这里插入图片描述
方法重写的其它注意事项

  • 重写小技巧:使用Override:注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好
  • 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public>protected>缺省)。
  • 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
  • 私有方法、静态方法不能被重写,如果重写会报错的。

方法重写在开发中的常见应用场景

  • 子类重写Object类的toString(方法,以便返回对象的内容。

示例:
在这里插入图片描述
Student

package com.itheima.d12_extends_override;

public class Student {
    private String name;
    private int age;
    public String toString(){
        return "Student{name="+name+",age="+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;
    }
}

Test

package com.itheima.d12_extends_override;

public class Test {
    public static void main(String[] args) {
        //目标:认识方法重写,掌握方法重写的常见应用场景。
        B b=new B();
        b.print1();
        b.print2(2,3);
        C c=new C();
        c.print1();
        System.out.println("----------------------------------------------------");
        Student s =new Student("波妞",19);
        System.out.println(s);//实际上是s.toString();
    }
}

直接右键生成点toString()即可

1.2.3.4子类中访问其他成员的特点
  1. 在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的。
  • 先子类局部范围找。
  • 然后子类成员范围找。
  • 然后父类成员范围找,如果父类范围还没有找到则报错。
  1. 如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?
  • 可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法

示例:
在这里插入图片描述
F

package com.itheima.d13_extends_visit;

public class F {
    String name="父类名字";
    public void  print1(){
        System.out.println("父类的print1方法执行" +
                "" +
                "");
    }
}

Z

package com.itheima.d13_extends_visit;

public class Z extends F{
    String name="子类名称";
    public void showName(){
        String name="局部名称";
        System.out.println(name);//局部名称
        System.out.println(this.name);//子类成员
        System.out.println(super.name);

    }
    @Override
    public void print1(){
        System.out.println("==子类的print1方法执行了==");
    }
    public void showMethod(){
            print1();//父类的
            super.print1();
    }
}

Test

package com.itheima.d13_extends_visit;

public class Test {
    public static void main(String[]args){
        //目标:掌握子类中访问其他成员的特点:就近原则。
        Z z=new Z();
        z.showName();
        z.showMethod();
    }
}

在这里插入图片描述

1.2.3.5子类构造器的特点

子类构造器的特点:

  • 子类的全部构造器,都会先调用父类的构造器,再执行自己。

子类构造器是如何实现调用父类构造器的:

  • 默认情况下,子类全部构造器的第一行代码都是Supr0(写不写都有),它会调用父类的无参数构造器。
  • 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(),指定去调用父类的有参数构造器。

示例:
Test

package com.itheima.d14_extends_constructor;

class F{
 //  public F(){
   //    System.out.println("==父类F的无参数构造器执行了==");
   //}
    public F(String name){
        System.out.println("==父类F的有参数构造器执行了==");
    }
}
class Z extends F{
    public Z(){
        //super();//默认存在的
        super("波妞");
        System.out.println("==子类Z的无参数构造器执行了==");
    }
    public Z(String name){
        super("波妞");
        System.out.println("==子类Z的有参数构造器执行了==");
    }
}

public class Test {
    public static void main(String[] args) {
        //目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景
    Z z=new Z();
    Z z2=new Z("波妞");

    }
}

在这里插入图片描述
如果父类和子类都有各自的无参和有参构造器,子类无论调用自己的有参还是无参构造器,都会调用父类的无参构造器

1.2.3.6子类构造器应用场景

示例:

package com.itheima.d14_extends_constructor;

public class Test2 {
    public static void main(String[] args) {
        //目标:搞清楚子类构造器为什么要调用父类构造器,有啥应用场景。
        Teacher t=new Teacher("李四",36,"java");
        System.out.println(t.getName());
        System.out.println(t.getAge());
        System.out.println(t.getSkill());
    }
}
class Teacher extends People{
    private String skill;

    public Teacher(String name, int age, String skill) {
        super(name, age);
        this.skill = skill;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
}
class People{
    private String name;
    private int age;

    public People() {
    }

    public People(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;
    }
}

在这里插入图片描述

  • 子类构造器调用父类构造器的常见应用场景
    在这里插入图片描述
    在这里插入图片描述
  • 子类构造器可以通过调用父类构造器,把对象中包含父类这部分的数据先初始化赋值,再回来把对象里包含子类这部分的数据也进行初始化层值。

补充知识:ths(…)调用兄弟构造器

  • 任意类的构造器中,是可以通过this(.…)去调用该类的其他构造器的。
    示例:
    Test3
package com.itheima.d14_extends_constructor;

public class Test3 {
    public static void main(String[] args) {
    //目标:掌握在类的构造器中,通过this(...)调用兄弟构造器的作用。
        Student s1=new Student("李四",26,"家里蹲大学");
    //需求:如果学生没有填写学校,那么学校默认就是黑马程序员
        Student s2=new Student("张三",28);
        System.out.println(s2.getName());
        System.out.println(s2.getAge());
        System.out.println(s2.getSchoolName());
    }
}
class Student{
    private String name;
    private int age;
    private String schoolName;

    public Student() {
    }
    public Student(String name, int age) {
        //this.name = name;
        //this.age = age;
        //this.schoolName = "黑马程序员";
        this(name,age,"黑马程序员");
    }
    public Student(String name, int age, String schoolName) {
        this.name = name;
        this.age = age;
        this.schoolName = schoolName;

    }

    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 String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
}

在这里插入图片描述
注意不能在一个构造器里同时写this和super构造器,因为this借用兄弟构造器时已经调用了一次父类构造器,不能调用两次super构造器,并且,this和super构造器都得放在构造器的第一行

2.面向对象高级二

2.1面向对象的三大特征之三:多态

2.1.1认识多态
  • 多态是在继承/实现情况下的一种现象,表现为:对象多态、行为多态。

多态的具体代码体现
在这里插入图片描述

多态的前提

  • 继承/实现关系;存在父类引用子类对象;存在方法重写。

多态的一个注意事项

  • 多态是对象、行为的多态,Jva中的属性(成员变量)不谈多态。

示例:
在这里插入图片描述
People

package com.itheima.d1_polymorphism;
//父类
public class People {
    public String name="父类People的名称";
    public void run(){

        System.out.println("人可以跑");
    }
}

Student

package com.itheima.d1_polymorphism;

public class Student extends People{
    public String name="子类Student的名称";
    @Override
    public void run(){
        System.out.println("学生跑的很快!");
    }

}

Teacher

package com.itheima.d1_polymorphism;

public class Teacher extends People{
    public String name="子类Teacher的名称";
    public void run(){

        System.out.println("老师跑不动");
    }
}

Test

package com.itheima.d1_polymorphism;

public class Test {
    public static void main(String[] args) {
        //目标:认识多态:对象多态、行为多态。
        //1.对象多态
        People p1=new Teacher();
        p1.run();//识别技巧:编译看左边,运行看右边
        System.out.println(p1.name);
        People p2=new Student();
        p2.run();
        System.out.println(p2.name);
    }

}

在这里插入图片描述

2.1.2使用多态的好处
  • 在多态形式下,右边对象解耦合的,更便于扩展和维护。
  • 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。

多态下会产生的一个问题,怎么解决?

  • 多态下不能使用子类的独有功能。

示例:
在这里插入图片描述

People

package com.itheima.d2_polymorphism.d1_polymorphism;
//父类
public class People {
    public String name="父类People的名称";
    public void run(){

        System.out.println("人可以跑");
    }
}


Student

package com.itheima.d2_polymorphism.d1_polymorphism;

public class Student extends People {
    public String name="子类Student的名称";
    @Override
    public void run(){
        System.out.println("学生跑的很快!");
    }
    public void test(){
        System.out.println("学生需要考试");
    }

}

Teacher

package com.itheima.d2_polymorphism.d1_polymorphism;

public class Teacher extends People {
    public String name="子类Teacher的名称";
    public void run(){

        System.out.println("老师跑不动");
    }
    public void teach(){
        System.out.println("老师需要教知识");
    }
}

Test

package com.itheima.d2_polymorphism.d1_polymorphism;

public class Test {
    public static void main(String[] args) {
        //目标:理解多态的好处
        //好处1:可以实现解耦合,右边对象可以随时切换,后续业务随即改变
        People p1=new Student();
        p1.run();
        //p1.test;多态下存在的问题:无法直接调用子类的独有功能
        Student s=new Student();
        go(s);

        Teacher t=new Teacher();
        go(t);

    }
    //好处2:可以使用父类类型的变量作为形参,可以实现一切子类对象
    public static void go(People p){

    }
}

2.1.3多态下的类型转换问题
  • 自动类型转换:父类 变量名=new 子类();

  • 强制类型转换:子类 变量名=(子类)父类变量

强制类型转换的一个注意事项

  • 存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错。
  • 运行时,如果发现对象的真实类型与强转后的类型不同,就会报==类型转换异常(ClassCastException)==的错误出来。
    在这里插入图片描述
    强转前,Java建议:
  • 使用instanceof关键字,判断当前对象的真实类型,再进行强转。
    在这里插入图片描述
    是Student的子类也行

示例:
Test

package com.itheima.d2_polymorphism.d1_polymorphism;

public class Test {
    public static void main(String[] args) {
        //目标:理解多态的好处
        //好处1:可以实现解耦合,右边对象可以随时切换,后续业务随即改变
        People p1=new Student();
        p1.run();
        //p1.test;多态下存在的问题:无法直接调用子类的独有功能

        //强制类型转换
        Student s1=(Student) p1;
        s1.test();

        //强制类型转换存在的问题:编译阶段有继承或者实现关系就可以强制类型转换,
        // 但是运行时就可能出现类型转换异常

        //Teacher t1=(Teacher) p1;//运行时出现异常:ClassCastException
        System.out.println("---------------------------------");
        //好处2:可以使用父类类型的变量作为形参,可以实现一切子类对象
        People s=new Student();
        go(s);

        People t=new Teacher();
        go(t);


    }

//好处2:可以使用父类类型的变量作为形参,可以实现一切子类对象
    public static void go(People p){
        System.out.println(p.name);
        p.run();
        if (p instanceof Student){
            Student s=(Student) p;
            s.test();
        }
        else{
            Teacher t=(Teacher) p;
            t.teach();
        }
    }
}

在这里插入图片描述

2.2final

2.2.1认识final
  • final关键字是最终的意思,可以修饰(类、方法、变量)
  • 修饰类:该类被称为最终类,特点是不能被继承了。
  • 修饰方法。该方法被称为最终方法,特点是不能被重写了。
  • 修饰变量:该变量只能被赋值一次。

final修饰变量的注意

  • final修饰基本类型的变量,变量存储的数据不能被改变。
  • fial修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向对象的内容是可以被改变的。

示例:
在这里插入图片描述

package com.itheima.da_final;

public class Test {

    //常量: static final修饰的成员变量,建议名称全部大写,多个单词下划线连接

    //private final String name="猪八戒";这种用法无意义,final一般不用来修饰实例变量

   // public static final String schoolname;报错,必须赋一次值
    public static final String schoolname="黑马大学";
    //schoolname="白马大学";二次赋值,报错
    public static void main(String[] args) {
        //目标:认识final的作用
        //3.final可以修饰变量总规则:有且仅能赋值一次
        //变量:一.局部变量 二.成员变量:1.静态成员变量2.实例成员变量
        final int a;
        a=1;
        //a=2;不能二次赋值,会出错

        final int[] arr={11,22,33};
        arr[2]=333;
    }
    public static void buy(final double z){
        //z=0.1;只能接一次值,内部不能变
    }
}


//1.final修饰类,类不能被继承
final class A{
}
//class B extends A{}

//2.final修饰方法,方法不能被重写
class C{
    public final void test(){

    }
}
class D extends C{
    //@Override
    // public final void test(){}
}

2.2.2补充知识:常量详解

常量

  • 使用了static final修饰的成员变量就被称为常量;
  • 作用:通常用于记录系统的配置信息
    在这里插入图片描述

注意!常量名的命名规范:建议使用大写英文单词,多个单词使用下划线连接起来。

使用常量记录系统配置信息的优势、执行原理

  • 代码可读性更好,可维护性也更好。
  • 程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量, 这样可以保证使用常量和直接用字面量的性能是一样的。

示例
Test2

package com.itheima.da_final;

public class Test2 {
    public static final String SCHOOL_NAME="黑马大学";

    public static void main(String[] args) {
        System.out.println(SCHOOL_NAME);
        System.out.println(SCHOOL_NAME);
        System.out.println(SCHOOL_NAME);
        System.out.println(SCHOOL_NAME);
    }
}

在这里插入图片描述

2.3抽象类

2.3.1认识抽象类

什么是抽象类?

  • 在Java中有一个关键字叫:abstract,它就是抽象的意思,可以用它修饰类、成员方法。
  • abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。
    在这里插入图片描述
    抽象类的注意事项、特点
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
  • 类该有的成员(成员变量、方法、构造器)抽象类都可以有。
  • 抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
  • 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。

示例

在这里插入图片描述
A

package com.itheima.d4_abstract;
//抽象类
public abstract class A {
    private String name;
    public static String schoolName;

    public A(){
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //抽象方法:必须用abstract修饰,只有方法签名,一定不能有方法体
    public abstract void run();
}

B

package com.itheima.d4_abstract;

public class B extends A{
    //一个类继承了抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
    @Override
    public void run(){}
}

Test

package com.itheima.d4_abstract;

public class Test {
    public static void main(String[] args) {
        //目标:认识抽象类和其特点。
        //注意:抽象类不能创建对象
        //A a=new A();错误
        //a.run();
    }
}

2.3.2使用抽象类的好处

-父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态。
在这里插入图片描述
示例
在这里插入图片描述
Animal

package com.itheima.d5_abstract2;

public abstract class Animal {
    private String name;
    public abstract void cry();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Cat

package com.itheima.d5_abstract2;

public class Cat extends Animal{
    @Override
    public void cry(){
        System.out.println(getName()+"喵喵喵地叫");
    }
}

Dog

package com.itheima.d5_abstract2;

public class Dog extends Animal{
    @Override
    public void cry(){
        System.out.println(getName()+"汪汪汪地叫");
    }
}

Test

package com.itheima.d5_abstract2;

public class Test {
    public static void main(String[] args) {
        //目标:认识抽象类的好处
       Animal a=new Cat();
       a.setName("叮当猫");
       a.cry();
    }
}

在这里插入图片描述

2.3.3抽象类的常见应用场景:模板方法设计模式

模板方法设计模式解决了什么问题?

  • 解决方法中存在重复代码的问题。
    在这里插入图片描述
    模板方法设计模式的写法
  • 1、定义一个抽象类。
  • 2、在里面定义2个方法

一个是模板方法:把相同代码放里面去。
一个是抽象方法:具体实现交给子类完成。

示例
在这里插入图片描述
多学一招:使用final关键字修饰模板方法

  • 模板方法是给对象直接使用的,不能被子类重写。
  • 一旦子类重写了模板方法,模板方法就失效了。

People

package com.itheima.d6_abstract_template;

public abstract class People {
    //设计模板方法
    //1.定义模板方法
    public final void write(){
        System.out.println("\t\t\t\t\t《我的爸爸》");
        //2.模板方法不知道正文到底怎么写,但知道子类肯定要写
        System.out.println(writeMain());
        System.out.println("我的爸爸太好了");

    }
    //3.定义一个抽象方法写正文,具体的实现交给子类来完成
    public abstract String writeMain();
}

Student

package com.itheima.d6_abstract_template;

public class Student extends People{

    @Override
    public  String writeMain(){
        return "我的爸爸很爱我";
    }
}

Teacher

package com.itheima.d6_abstract_template;

public class Teacher extends People{

        @Override
        public  String writeMain(){
            return "我的爸爸很辛苦";
        }
    }


Test

package com.itheima.d6_abstract_template;

public class Test {
    public static void main(String[] args) {
        //目标:搞清楚抽象类的应用场景之一:经常用来设计模板方法设计模式,
        //场景:写作文,老师和学生各自写一篇,开头结尾一样,正文自由发挥;
        Teacher t=new Teacher();
        t.write();
    }
}

在这里插入图片描述

2.4接口

2.4.1接口概述

认识接口

  • Java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊的结构:接口。
    在这里插入图片描述
  • 注意:接口不能创建对象;接口是用来被类实现(implements)的,实现接口的类称为实现类
    在这里插入图片描述
  • 一个类可以实现多个接口(接口可以理解成干爹),实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义为抽象类

示例:
在这里插入图片描述
A

package com.itheima.d7_interface;

public interface A {
    //成员变量(常量)
    String SCHOOL_NAME="黑马程序员";//加不加public static final无所谓

    //成员方法(抽象方法),加不加public abstract无所谓
    void test();//不能有方法体{}
}

B

package com.itheima.d7_interface;

public interface B {
    void testb1();
    void testb2();

}

C

package com.itheima.d7_interface;

public interface C {
    void testc1();
    void testc2();

}

D

package com.itheima.d7_interface;
//
public class D implements B,C{
    @Override
    public void testb1() {

    }

    @Override
    public void testb2() {

    }

    @Override
    public void testc1() {

    }

    @Override
    public void testc2() {

    }
}

Test

package com.itheima.d7_interface;

public class Test {
    public static void main(String[] args) {
        //目标:认识接口
        System.out.println(A.SCHOOL_NAME);

       // A a=new A();接口无法创建对象
        D d=new D();
    }
}

2.4.2接口的好处(重点)
  • 弥补了类单继承的不足,一个类同时可以实现多个接口。
  • 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。
    示例
    Test
package com.itheima.d8_interface2;

import com.itheima.d5_abstract2.Animal;
import com.itheima.d5_abstract2.Dog;

public class Test {
    public static void main(String[] args) {
        //目标:弄清楚使用接口的好处。
        Driver s=new A();
        s.drive();
        Driver d=new B();
        d.drive();
        
    }
}
class B implements Driver{
    @Override
    public void drive(){

    }
}
class A extends Student implements Driver, Singer{
    @Override
    public void drive() {

    }

    @Override
    public void sing() {

    }
}
class Student{

}

    interface Driver{
    void drive();

}
    interface Singer {
    void sing();
}
2.4.3接口的综合案例(重点)

在这里插入图片描述
示例:
在这里插入图片描述

ClassManager

package com.itheima.d9_interface_demo;

import java.util.ArrayList;

public class ClassManager {
    private ArrayList<Student> students = new ArrayList<>();
    private StudentOperator studentOperator=new StudentOperatorImpl2();
    public ClassManager() {
        students.add(new Student("迪丽热巴", '女', 99));
        students.add(new Student("古力娜扎", '女', 100));
        students.add(new Student("波波维奇", '男', 60));
        students.add(new Student("科比曼巴", '男', 23));
    }

    //打印全部学生的信息
    public void printInfo(){
        studentOperator.printAllInfo(students);

    }
    //打印全部学生的平均分
    public void printScore(){
        studentOperator.printAverageScore(students);

    }
}

Student

package com.itheima.d9_interface_demo;

public class Student {
    private String name;
    private char sex;
    private double score;

    public Student() {
    }

    public Student(String name, char sex, double score) {
        this.name = name;
        this.sex = sex;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

StudentOperator

package com.itheima.d9_interface_demo;

import java.util.ArrayList;

public interface StudentOperator {
    void printAllInfo(ArrayList<Student> students);
    void printAverageScore(ArrayList<Student> students);
}

StudentOperatorImpl1

package com.itheima.d9_interface_demo;

import java.util.ArrayList;

public class StudentOperatorImpl1 implements StudentOperator{
    @Override
    public void printAllInfo(ArrayList<Student> students) {
        System.out.println("------------全班全部学生信息如下-------------");
        for (int i = 0; i < students.size(); i++) {
            System.out.println("第"+i+"号学生:");
            Student s=students.get(i);
            System.out.println("姓名:"+s.getName()+",性别:"+s.getSex()+",成绩:"+s.getScore());
        }
        System.out.println("------------------------------");
    }

    @Override
    public void printAverageScore(ArrayList<Student> students) {
        double allScore=0.0;
        for (int i = 0; i < students.size(); i++) {
            Student s=students.get(i);
            allScore+=s.getScore();
        }
        System.out.println("平均分"+(allScore)/students.size());
    }
}

StudentOperatorImpl2

package com.itheima.d9_interface_demo;

import java.util.ArrayList;

public class StudentOperatorImpl2 implements StudentOperator{
    @Override
    public void printAllInfo(ArrayList<Student> students) {
        int count1=0,count2=0;
        System.out.println("------------全班全部学生信息如下-------------");
        for (int i = 0; i < students.size(); i++) {
            System.out.println("第"+i+"号学生:");
            Student s=students.get(i);
            System.out.println("姓名:"+s.getName()+",性别:"+s.getSex()+",成绩:"+s.getScore());

            if(s.getSex()=='男'){
                count1++;
            }else {
                count2++;
            }
        }
        System.out.println("男生人数是:"+count1+",女生人数是"+count2);
        System.out.println("班级总人数是:"+students.size());
        System.out.println("------------------------------");
    }

    @Override
    public void printAverageScore(ArrayList<Student> students) {
        double allScore=0.0;
        double max=students.get(0).getScore();
        double min=students.get(0).getScore();
        for (int i = 0; i < students.size(); i++) {
            Student s=students.get(i);
            if(s.getScore()>max){
                max=s.getScore();
            }
            if (s.getScore()<min){
                min=s.getScore();
            }
            allScore+=s.getScore();
    }
        System.out.println("学生的最高分是:"+max);
        System.out.println("学生的最低分是:"+min);
        System.out.println("平均分"+(allScore-min-max)/(students.size()-2));
    }
}

Test

package com.itheima.d9_interface_demo;

public class Test {
    public static void main(String[] args) {
        //目标:完成学生信息管理的案例
        ClassManager c=new ClassManager();
        c.printInfo();
        c.printScore();
    }

}

2.4.4接口的其他细节:JDK8开始,接口中新增的三种方法

JDK8开始,接口新增了三种形式的方法:
在这里插入图片描述

JDK8开始,接口中为啥要新增这些方法?

  • 增强了接口的能力,更便于项目的扩展和维护。

示例:
在这里插入图片描述
A

package com.itheima.d10_interface_jdk8;

public interface A {
    //1.默认方法:必须使用default修饰,默认会被public修饰
    //实例方法:对象的方法,必须使用实现类的对象来访问
    default void test1(){
        System.out.println("==默认方法==");
        test2();//在一般方法中访问私有方法
    }

    //2.私有方法:必须使用private修饰(Jdk9开始支持)
    private void test2(){
        System.out.println("==私有方法==");
    }

    //3.静态方法:必须使用static修饰,默认会被public修饰
    static void test3(){
        System.out.println("==静态方法==");
    }
}

B

package com.itheima.d10_interface_jdk8;

public class B implements A{

}

Test

package com.itheima.d10_interface_jdk8;

public class Test {
    public static void main(String[] args) {
        B b=new B();
        b.test1();
        A.test3();
    }

}

2.4.5接口的其他细节:接口的多继承、使用接口的注意事项【了解】

接口多继承的作用

  • 便于实现类去实现。

示例
在这里插入图片描述
Test

package com.itheima.d11_interface_attention;

public class Test {
    public static void main(String[] args) {
        //目标:理解接口的多继承

    }
}
interface A{
    void testA();
}
interface B{
    void testB();
}
interface C{
    void testC();
}

//接口是多继承的
interface D extends C,B,A{
}
class E implements D{
    @Override
    public void testA() {

    }

    @Override
    public void testB() {

    }

    @Override
    public void testC() {

    }
}

接口其他注意事项(了解)

  1. 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承。
  2. 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
  3. 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
  4. 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。

3.面向对象高级三

3.1内部类

  • 是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。
  • 场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
    在这里插入图片描述
    内部类有四种形式
    1.成员内部类
    2.静态内部类
    3.局部内部类
    4.匿名内部类
3.1.1成员内部类(了解)
  • 就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法。
    在这里插入图片描述
    注意: JDK16之前,成员内部类中不能定义静态成员,JDK16开始也可以定义静态成员了
    创建对象的格式:
    在这里插入图片描述
    成员内部类中访问其他成员的特点:
    1、和前面学过的实例方法一样,成员内部类的实例方法中,同样可以直接访问外部类的实例成员、静态成员。
    2、可以在成员内部类的实例方法中,拿到当前外部类对象,格式是:外部类名.this。
    示例:
    在这里插入图片描述
    Test
package com.itheima.d1_inner_class1;

public class Test {
    public static void main(String[] args) {
        //了解成员内部类和其特点
        Outer.Inner in = new Outer().new Inner();
        in.test();

    }
}

Outer

package com.itheima.d1_inner_class1;

public class Outer {
    private int age=99;
    public static String a="Hello";
    //成员内部类
    public class Inner{
        private String name;
        private int age=88;
        public static String schoolName;//jdk16开始支持定义静态成员
        public void test(){
            //可以访问外部类的私有、公有成员变量
            System.out.println(age);
            System.out.println(a);

            int age=66;
            System.out.println(age);//66
            System.out.println(this.age);//88
            System.out.println(Outer.this.age);//99
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public static String getSchoolName() {
            return schoolName;
        }

        public static void setSchoolName(String schoolName) {
            Inner.schoolName = schoolName;
        }

    }
}

在这里插入图片描述

3.1.2静态内部类(了解)
  • 有static修饰的内部类,属于外部类自己持有
    在这里插入图片描述
    创建对象的格式:
    在这里插入图片描述
    静态内部类中访问外部类成员的特点
  • 可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。

示例:
在这里插入图片描述
Outer

package com.itheima.d2_inner_class2;

public class Outer {
    private int age;
    public static String schoolname;
    //静态内部类
    public static class Inner{
        private String name;
        public static int a;

        public void test(){

        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public static int getA() {
            return a;
        }

        public static void setA(int a) {
            Inner.a = a;
        }
        public static void test2(){
            System.out.println(schoolname);
            //System.out.println(age);不能直接访问外部类实例成员
        }
    }
}

Test

package com.itheima.d2_inner_class2;

public class Test {
    public static void main(String[] args) {
        //目标:了解静态内部类
        Outer.Inner in=new Outer.Inner();
    }
}

3.1.3局部内部类(了解)

-局部内部类是定义在在方法中、代码块中、构造器等执行体中。
在这里插入图片描述

3.1.4匿名内部类(重点)
3.1.4.1认识匿名内部类

匿名内部类

  • 就是一种特殊的局部内部类;所谓匿名,指的是程序员不需要为这个类声明名字
    在这里插入图片描述
  • 特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
  • 作用:用于更方便的创建一个子类对象。

示例:
在这里插入图片描述
Test

package com.itheima.d3_inner_class3;

public class Test {
    public static void main(String[] args) {
        //目标:人士匿名的内部类,并掌握其作用
        // Animal a= new Cat();
        //   a.cry();

        //1.把这个匿名内部类编译成一个子类,然后立即创建一个子类对象出来
        Animal a= new Animal(){
            @Override
            public void cry(){
                System.out.println("猫咪喵喵地叫");

            }
        };
    a.cry();
    }

}

abstract class Animal{
    public abstract void cry();
}
/*
class Cat extends Animal{
    @Override
    public void cry(){
        System.out.println("猫咪喵喵地叫");
    }
}*/

3.1.4.2匿名内部类使用场景
  • 通常作为一个参数传输给方法

需求:猫、狗参加游泳比赛
在这里插入图片描述
示例:
在这里插入图片描述

Test2

package com.itheima.d3_inner_class3;

public class Test2 {
    public static void main(String[] args) {
        //目标:掌握匿名的常见使用场景。
  /*      Swimming s1=new Swimming() {
            @Override
            public void swim() {
                System.out.println("狗游得飞快~~~");
            }
        };
        go(s1);
    }*/
        go(new Swimming() {
            @Override
            public void swim() {
                System.out.println("狗游得飞快~~~");
            }
        });
    }

        //设计一个方法,可以接收swimming接口的一切实现类对象进来参加游泳比赛。

    public static void go(Swimming s){
        System.out.println("开始-------------------------------");
        s.swim();
    }
}

//猫和狗都要参加游泳比赛
interface Swimming{
    void swim();
}

在这里插入图片描述
真是使用场景

示例:
在这里插入图片描述

Test

package com.itheima.d5_inneer_class5;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLOutput;

public class Test {
    public static void main(String[] args) {
        //拓展:搞清楚匿名内部类在开发中的真是使用场景
        //GUI编程
        //1.创建窗口
        JFrame win=new JFrame("登录界面");
        JPanel panel=new JPanel();
        win.add(panel);

        JButton btn=new JButton("登录");
        panel.add(btn);

        //给按钮绑定单机事件监听器
       /* btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(win,"登录一下");
            }
        });*/
        //最终的核心目的:简化代码
        btn.addActionListener(e->JOptionPane.showMessageDialog(win,"登录一下"));
        
        win.setSize(400,400);
        win.setLocationRelativeTo(null);//居中
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        win.setVisible(true);//设置可见

    }
}

在这里插入图片描述

3.2枚举

3.2.1认识枚举

枚举

  • 枚举是一种特殊类
    在这里插入图片描述
    注意:
  • 枚举类中的第一行,只能写一些合法的标识符(名称),多个名称用逗号隔开。
  • 这些名称,本质是常量,每个常量都会记住枚举类的一个对象。

枚举类的特点:
在这里插入图片描述
在这里插入图片描述

  • == 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。==
  • 枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象。
  • 枚举都是最终类,不可以被继承。
  • 枚举类中,从第二行开始,可以定义类的其他各种成员。
  • 编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法。

示例:
在这里插入图片描述
A

package com.itheima.d6_enum;

public enum A {
    //注意,枚举的第一行必须罗列的是枚举对象的名字
    X,Y,Z;
    private  String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

B

package com.itheima.d6_enum;
//拓展:抽象枚举
public enum B {
    X(){
        @Override
        public void go() {

        }
    },Y("张三"){
        @Override
        public void go() {
            System.out.println(getName()+"在跑~~");
        }
    };
    private String name;

    //枚举构造器只能是私有的
    B() {
    }

    B(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void go();
}

Test

package com.itheima.d6_enum;

public class Test {
    public static void main(String[] args) {
        //目标:认识枚举
        A a1=A.X;

        //1、枚举类的构造器都是私有的,不能对外创建对象
        // A a=new A();

        //2、枚举类的第一行都是常量,记住的是枚举类的对象
        A a2=A.Y;

        //3、枚举类提供了一些额外的API
        A[] as =A.values();//拿到全部对象
        A a3=A.valueOf("Z");//根据常量名得到枚举对象
        System.out.println(a3.name());//Z
        System.out.println(a3.ordinal());//索引
        System.out.println("-------------------");
        B y=B.Y;
        y.go();

    }
}

3.2.1枚举的常见应用场景

枚举的常见应用场景:

  • 用来表示一组信息,然后作为参数进行传输。
    选择定义一个一个的常量来表示一组信息,并作为参数传输
  • 参数值不受约束。
    选择定义枚举表示一组信息,并作为参数传输
  • 代码可读性好,参数值得到了约束,对使用者更友好,建议使用

示例:
在这里插入图片描述
Constant

package com.itheima.d7_enum2;

public class Constant {
    public static final int BOY=0;
    public static final int GIRL=1;
}

Constant2

package com.itheima.d7_enum2;

public enum Constant2 {
    BOY,GIRL
}

Test

package com.itheima.d7_enum2;

public class Test {


    public static void main(String[] args) {

        //目标:掌握枚举的应用场景,做信息标志和分类
        check(Constant2.BOY);
    }
    public static void check(Constant2 sex){
        //switch天生知道枚举可以做信息标和分类,不需要前缀
        switch (sex){
            case BOY:
                System.out.println("展示一些美女图,游戏信息~");
                break;
            case GIRL:
                System.out.println("展示一些帅哥图,一些土豪信息");
        }
    }
/*    public static void check(int sex){
        switch (sex){
            case Constant.BOY:
                System.out.println("展示一些美女图,游戏信息~");
                break;
            case Constant.GIRL:
                System.out.println("展示一些帅哥图,一些土豪信息");
        }
    }*/
}

3.3泛型

3.3.1认识泛型
  • 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:),称为泛型类、泛型接口,泛型方法、它们统称为泛型。
  • 作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。
  • == 泛型的本质:把具体的数据类型作为参数传给类型变量。==

示例:
在这里插入图片描述
Test1

package com.itheima.d5_generics;

import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) {
        //目标:认识泛型
        ArrayList list=new ArrayList();
        list.add("java1");
        list.add("java2");
        list.add("java3");
        //list.add(new Cat());
        for (int i = 0; i < list.size(); i++) {
        String e = (String) list.get(i);//必须强转,但是对Cat的实例强转会出错,即使没有其他类型,实际上都是字符串,也得强转
            System.out.println(e);
        }
        System.out.println("------------------------------");
       // ArrayList<String> list1=new ArrayList<String>();
        ArrayList<String> list1=new ArrayList<>();//从jdk1.7开始,后面的数据类型可以不声明

        list1.add("python1");
        list1.add("python2");
        list1.add("python3");

        for (int i = 0; i < list1.size(); i++) {
            String e=list1.get(i);
            System.out.println(e);
        }

    }
}
class Cat{

}

在这里插入图片描述

3.3.2泛型类

泛型类
在这里插入图片描述

  • 注意:类型变量建议用大写的英文字母,常用的有:E、T、K、V

示例:
在这里插入图片描述
Animal

package com.itheima.d8_generics_class;

public class Animal {
}

Cat

package com.itheima.d8_generics_class;

public class Cat extends Animal{
}

Dog

package com.itheima.d8_generics_class;

public class Dog extends Cat{
}

MyArrayList

package com.itheima.d8_generics_class;
//泛型类
public class MyArrayList<E> {
    Object[] arr=new Object[10];
    private int size;

    public boolean add(E e){
        arr[size++]=e;
        return true;
    }
    public E get(int index){
        return (E)arr[index];
       // return arr[index];不能直接返回Object类
    }
}

MyClass2

package com.itheima.d8_generics_class;

public class MyClass2<E,T> {
    public void put(E e,T t){

    }
}

MyClass3

package com.itheima.d8_generics_class;

public class MyClass3 <E extends Animal>{
}

Test

package com.itheima.d8_generics_class;

public class Test {
    public static void main(String[] args) {
        //目标:掌握泛型类的定义和使用
        MyArrayList<String> list =new MyArrayList();
        list.add("Java1");
        list.add("Java2");
        list.add("Java3");
        String ele =list.get(1);
        System.out.println(ele);

        MyClass2<Cat,String> c2=new MyClass2<>();

        MyClass3<Animal> c3=new MyClass3<>();
          MyClass3<Cat> c4=new MyClass3<>();
        MyClass3<Dog> c5=new MyClass3<>();//限定送进来的必须是Animal或其子类(孙类也行)


    }
}

3.3.3泛型接口

泛型接口
在这里插入图片描述

  • 注意:类型变量建议用大写的英文字母,常用的有:E、T、K、V

示例:
在这里插入图片描述
Data

package com.itheima.d9_generics_interface;

import java.util.ArrayList;

//泛型接口同样可以继承某一类型
public interface Data <T extends Object>{
    void add(T t);
    ArrayList<T> getByName(String name);

}

Student

package com.itheima.d9_generics_interface;

public class Student {
}

StudentData

package com.itheima.d9_generics_interface;

import java.util.ArrayList;

public class StudentData implements Data<Student>{
    @Override
    public void add(Student student) {

    }

    @Override
    public ArrayList<Student> getByName(String name) {
        return null;
    }
}

Teacher

package com.itheima.d9_generics_interface;

public class Teacher {
}

TeacherData

package com.itheima.d9_generics_interface;

import java.util.ArrayList;

public class TeacherData implements Data<Teacher>{
    @Override
    public void add(Teacher teacher) {

    }

    @Override
    public ArrayList<Teacher> getByName(String name) {
        return null;
    }
}

Test

package com.itheima.d9_generics_interface;

public class Test  {
    public static void main(String[] args) {
        //目标:掌握泛型接口的定义和使用。
        //场景:系统需要处理学生和老师的数据,需要提供2个功能:保存对象数据。根据名称查询数据。
    }
}

3.3.4泛型方法、通配符、上下限

泛型方法
在这里插入图片描述
通配符

  • 就是“?”,可以在“使用泛型”的时候代表一切类型;E T K V是在定义泛型的时候使用。

泛型的上下限:

  • 泛型上限:?extends Car:?能接收的必须是Car或者其子类。
  • 泛型下限:?super Car:?能接收的必须是Car或者其父类。

示例:
在这里插入图片描述
BENZ

package com.itheima.d10_generics_method;

public class BENZ extends Car{
}

BMW

package com.itheima.d10_generics_method;

public class BMW extends Car{
}

Car

package com.itheima.d10_generics_method;

public class Car {
}

Dog

package com.itheima.d10_generics_method;

public class Dog {
}

Test

package com.itheima.d10_generics_method;

import com.itheima.d6_enum.A;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        //目标:掌握泛型方法的定义和使用
       String s= test("java");//T可以是任何类型,即所谓的泛型
        System.out.println(s);


        Dog d=test(new Dog());
        System.out.println(d);

        //需求:所有的汽车可以一起参加比赛。
        ArrayList<Car> cars=new ArrayList<>();
        cars.add(new BMW());
        cars.add(new BENZ());
        go(cars);

        ArrayList<BMW> bmws=new ArrayList<>();
        bmws.add(new BMW());
        bmws.add(new BMW());
        go(bmws);

        ArrayList<BENZ> benzs=new ArrayList<>();
        benzs.add(new BENZ());
        benzs.add(new BENZ());
        go(benzs);
        //重点:ArrayList<BENZ>和ArrayList<Car>没有继承关系,不相干,想用go必须用泛型
    /*    ArrayList<Dog> dogs=new ArrayList<>();
        dogs.add(new Dog());
        dogs.add(new Dog());
        go(dogs);报错,因为Dog不是Car的子类*/
    }
    //?通配符,在使用泛型的时候可以代表一切类型 ?extends Car(上限)  ?super Car(下限)
    public static void go(ArrayList<?extends Car> cars){

    }
 /*   public static <T extends Car> void go(ArrayList<T> cars){

    }*/
    //泛型方法
    public static <T> T test(T t){
        return t;
    }
}

在这里插入图片描述

3.3.5 泛型的注意事项:擦除问题、基本数据类型问题
  • 泛型是工作在编译阶段的,一旦程序编译成class:文件,class文件中就不存在泛型了,这就是泛型擦除。
  • 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

示例:
在这里插入图片描述
Test

package com.itheima.d11_generics_attention;

import com.itheima.d6_enum.A;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        //目标:理解泛型的注意事项。
        //1、泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除。
        ArrayList<String> list=new ArrayList<>();
        list.add("java1");
        list.add("java2");
        list.add("java3");
        String rs =list.get(2);//反编译后发现其实还是帮你强转了
        System.out.println(rs);

        //2.泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。
        //ArrayList<int> list1 =new ArrayList<>();不支持
        //ArrayList<double> list2 =new ArrayList<>();不支持
        ArrayList<Integer> list1=new ArrayList<>();
        list1.add(12);
        ArrayList<Double> list2=new ArrayList<>();
        list2.add(12.3);
    }
}

3.4常用API(一)

3.4.1API概述

什么是API?

  • API(Application Programming interface):应用程序编程接口
  • 就是java帮我们已经写好一些程序,如:类、方法等,我们直接拿过来用就可以解决一些问题。

常用API
在这里插入图片描述

3.4.2Object

Object:类的作用:

  • Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法。

Object类的常见方法
在这里插入图片描述

  • toString存在的意义:toString()方法存在的意义就是为了被子类重写,以便返回对象具体的内容。
  • equals存在的意义:直接比较两个对象的地址是否相同完全可以用"==”替代equals,equals存在的意义
    就是为了被子类重写,以便子类自己来定制比较规则(比如比较对象内容)。

示例:
在这里插入图片描述
Student

package com.itheima.d12_api_object;

import java.util.Objects;

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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //重写equals方法,比较两个对象的内容,一样就返回true
    //比较者:s2 == this (调用者)
    //被比较者:s1 == o
    @Override
    public boolean equals(Object o) {
        //1.判断两者地址是否一样,是就返回true
        if (this == o) return true;
        //2.判断o是null直接返回false或者双方类型不一样,直接false
        //               Student.class(比较者的类型)!=o.class(被比较者的类型)
        if (o == null || getClass() != o.getClass()) return false;
        //3.o不是null,且o一定是学生类型的对象,开始比较内容了!
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

Test

package com.itheima.d12_api_object;

public class Test {
    public static void main(String[] args) {
        //目标:掌握Object类提供的常见方法
        Student s1=new Student("赵云",30);
       // System.out.println(s1.toString());可以直接输出s1,结果一样
        System.out.println(s1);

        Student s2=new Student("赵云",30);
        System.out.println(s2.equals(s1));//equal本身也是比较地址,但是更多是让我们重写比较
        System.out.println(s2==s1);//直接比较地址
    }

}

在这里插入图片描述

Object类提供的对象克隆方法
在这里插入图片描述

  • 当某个对象调用这个方法时,这个方法会复制一个一模一样的新对象返回。

浅克隆

  • 拷贝出的新对象,与原对象中的数据一模一样(引用类型拷贝的只是地址)
    在这里插入图片描述

深克隆

  • 对象中基本类型的数据直接拷贝
  • 对象中的字符串数据拷贝的还是地址
  • 对象中还包含的其他对象,不会拷贝地址,会创建新对象。
    在这里插入图片描述
    示例:
    在这里插入图片描述
    Test2
package com.itheima.d12_api_object;

public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        //目标:掌握Object类提供的对象克隆的方法。
        //1、protected Object clone():对象克隆。
        User u1 =new User(1,"张三","1234",new double[]{99.0,31.4});
        User u2=(User) u1.clone();// clone本身会返回一个Object,但我们知道克隆出来的肯定是User,强转一下
        System.out.println(u1.getId());
        System.out.println(u1.getUsername());
        System.out.println(u1.getPassword());
        System.out.println(u1.getScores());

        System.out.println(u2.getId());
        System.out.println(u2.getUsername());
        System.out.println(u2.getPassword());
        System.out.println(u2.getScores());

        System.out.println(u2.equals(u1));
    }
}

User

package com.itheima.d12_api_object;
//Cloneable是一个标记接口
//这是一种规则

public class User implements Cloneable{
    private int id;
    private String username;
    private String password;
    private double[] scores;

    public User() {
    }

    public User(int id, String username, String password, double[] scores) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.scores = scores;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //super去调用父类Object中的clone方法;
        User u2=(User) super.clone();
        u2.scores=u2.scores.clone();//新建数组,实现深克隆
        
        //浅克隆只需要 return super.clone();这一行就行
        return u2;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public double[] getScores() {
        return scores;
    }

    public void setScores(double[] scores) {
        this.scores = scores;
    }
}

在这里插入图片描述

3.4.3Objects
  • Objects是一个工具类,提供了很多操作对象的静态方法给我们使用。
    在这里插入图片描述
    在这里插入图片描述
    示例
    在这里插入图片描述
    Test
package com.itheima.d13_api_objects;

import java.util.Objects;

public class Test {
    public static void main(String[] args) {
        //目标:掌握Objects类提供的常见方法。
        String s1 =null;
        String s2 ="itheima";

        //System.out.println(s1.equals(s2));有null会报错,空指针异常

        System.out.println(Objects.equals(s1, s2));//更安全

        System.out.println(Objects.isNull(s1));//true
        System.out.println(s1==null);
        System.out.println(Objects.isNull(s2));//false
        System.out.println(s2==null);//其实代码都一样,调用比较更有逼格

        System.out.println(Objects.nonNull(s1));//false
        System.out.println(Objects.nonNull(s2));//true

    }
}

3.4.4包装类
  • 包装类就是把基本类型的数据包装成对象。
    在这里插入图片描述
    自动装箱:基本数据类型可以自动转换为包装类型。 自动拆箱:包装类型可以自动转换为基本数据类型

包装类的其他常见操作

  • 可以把基本类型的数据转换成字符串类型。
    在这里插入图片描述

  • 可以把字符串类型的数值转换成数值本身对应的数据类型。
    在这里插入图片描述
    示例
    在这里插入图片描述
    Test

package com.itheima.d14_integer;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        //目标:掌握包装类的使用
        //Integer a1=new Integer(12);过时
        Integer a2=Integer.valueOf(12);
        System.out.println(a2);

        //自动装箱:可以自动把基本类型的数据转换成对象
        Integer a3=12;
        // 自动拆箱:可以自动把包装类型的对象转换成对应的基本数据类型。
        int a4=a3;
        //泛型和集合不支持基本数据类型,只能支持引用数据类型。
        //ArrayList<int>list =new ArrayList<>();
        ArrayList<Integer> list =new ArrayList<>();
        list.add(12);//自动装箱
        int rs=list.get(0);//自动拆箱
        System.out.println("----------------------------------------------");

        //1.把基本类型的数据转换为字符串、
        Integer a=23;
        String rs1=Integer.toString(a);//"23"
        System.out.println(rs1 + 1);//"231"

        String rs2=a.toString();//Object类的toString "23"
        System.out.println(rs2 + 1);//"231"

        String rs3= a+"";
        System.out.println(rs3 + 1);//"231"

        //2.把字符串的数值转换成对应的基本类型

        String ageStr ="29";//一定要是对应的数值类型,29a,29.2都不行
        //int ageI=Integer.parseInt(ageStr);//29,不建议这么用
        int ageI=Integer.valueOf(ageStr);//29
        System.out.println(ageI+1);//30

        String scoreStr="99.5";
        //double score=Double.parseDouble(scoreStr);
        double score=Double.valueOf(scoreStr);
        System.out.println(score+0.5);

    }
}

3.4.5 StringBuild与StringBuffer
  • StringBuilder代表可变字符串对象,相当于是一个容器,它里面装的字符串是可以改变的,就是用来操作字符串的。
  • 好处:StringBuilder比String更适合做字符串的修改操作,效率会更高,代码也会更简洁。
    在这里插入图片描述
    在这里插入图片描述
    为什么操作字符串建议使用StringBuilder,而不用原来学过的String?
    在这里插入图片描述
  • 对于字符串相关的操作,如频繁的拼接、修改等,建议用StringBuidler,效率更高!
  • 注意:如果操作字符串较少,或者不需要操作,以及定义字符串变量,还是建议用String。

StringBufferStringBuilder
注意:

  • StringBuffer的用法与StringBuilder是一模一样的
  • 但StringBuilder是线程不安全的StringBuffer是线程安全的

在这里插入图片描述
示例
在这里插入图片描述

Test1

package com.itheima.d15_stringbuild;

public class Test1 {
    public static void main(String[] args) {
        //目标:搞清楚StringBuilder的用法和作用。
        //StringBuilder s = new StringBuilder();//s "
        StringBuilder s = new StringBuilder("itheima");//s "itheima"
        //1、拼接内容
        s.append(12);
        s.append("黑马");
        s.append(true);
        System.out.println(s);//itheima12黑马true

        //支持链式编程
        s.append(666).append("黑马2");
        System.out.println(s);//itheima12黑马true666黑马2

        //2.反转操作
        s.reverse();
        System.out.println(s);//2马黑666eurt马黑21amiehti

        //3.返回字符串长度
        System.out.println(s.length());//21

        //4.把StringBuilder对象转换成String类型
        String rs=s.toString();
        System.out.println(rs);//2马黑666eurt马黑21amiehti

    }
}

Test2

package com.itheima.d15_stringbuild;

public class Test2 {
    public static void main(String[] args) {
        //目标:掌握StringBuilder的好处。
        //需求:要拼接100万次abc
        //先用String测试看看性能

/*
            String rs ="";
            for(int i=1;i<=1000000;i++){
                rs +="abc";
            }
            System.out.println(rs);
            太慢了,半天出不来
*/

            //使用StringBuilder演示
            StringBuilder sb=new StringBuilder();
            for (int i = 0; i < 1000000; i++) {
            sb.append("abc");
            }
        System.out.println(sb);
    }
}

Test3

package com.itheima.d15_stringbuild;

public class Test3 {
    public static void main(String[] args) {
        //目标:完成遍历数组内容,并拼接成指定格式的案例。
        System.out.println(getArrayData(new int[]{11, 22, 33}));
    }
    public static String getArrayData(int[] arr){
        //1、判断arr是否为null
        if (arr==null){
            return null;
        }
        //2.arr数组对象存在,arr[11,22,33]
        StringBuilder sb= new StringBuilder();
        sb.append("[");
        for (int i = 0; i < arr.length; i++) {
            if(i==arr.length-1){
                sb.append(arr[i]);
            }else {
                sb.append(arr[i]).append(",");
            }

        }
        sb.append("]");
        return sb.toString();
    }
}

3.4.6 StringJoiner
  • JDK8开始才有的,跟StringBuilder一样,也是用来操作字符串的,也可以看成是一个容器,创建之后里面的内容是可变的。
  • 好处:不仅能提高字符串的操作效率,并且在有些场景下使用它操作字符串,代码会更简洁
    在这里插入图片描述
    示例
    在这里插入图片描述
package com.itheima.d16_stringjoiner;

import java.util.StringJoiner;

public class Test {
    public static void main(String[] args) {
        //目标:掌握StringJoiner的使用
       // StringJoiner s=new StringJoiner(",");//间隔符
        StringJoiner s=new StringJoiner(",","[","]");
        s.add("java1");
        s.add("java2");
        s.add("java3");
        s.add("java4");
        System.out.println(s);//[java1,java2,java3,java4]
    }
}

3.5常用API(二)

3.5.1 Math、System、Runtime

Math

  • 代表数学,是一个工具类,里面提供的都是对数据进行操作的一些静态方法。
    在这里插入图片描述
    System
  • System代表程序所在的系统,也是一个工具类。
    System类提供的常见方法
    在这里插入图片描述
    时间毫秒值
  • 指的是从1970年1月1日 00:00:00走到此刻的总的毫秒数,应该是很大的。1s=1000ms

为啥选择“1970年1月1日00:00:00”作为时间的起点?
1969年8月,贝尔实验室的程序员肯汤普逊利用妻儿离开一个月的机会,开始着手创造一个全新的革命性的操作
系统,他使用B编译语言在老旧的PDP-7机器上开发出了Uix的一个版本。随后,汤普逊和同事丹尼斯里奇改进了B
语言,开发出了C语言,重写了UNX.
1970年1月1日算C语言的生日

Runtime

  • 代表程序所在的运行环境
  • Runtime是一个单例类
    Runtime类提供的常见方法
    在这里插入图片描述
    示例
    在这里插入图片描述
    MathTest
package com.itheima.math;

public class MathTest {
    public static void main(String[] args) {
        //目标:了解下Math类提供的常见方法。
        //1、public static int abs(inta):取绝对值(拿到的结果一定是正数)
        //public static double abs(double a)
        System.out.println(Math.abs(-13));//13
        System.out.println(Math.abs(123));//123
        System.out.println(Math.abs(-3.14));//-3.14

        //2、public static double ceil(double a):向上取整
        System.out.println(Math.ceil(4.0000001));//5.0
        System.out.println(Math.ceil(4.0));//4.0

        //3、public static double floor(double a):向下取整
        System.out.println(Math.floor(4.999999999999));//4.o
        System.out.println(Math.floor(4.0));//4.0

        //4、public static long round(double a):四舍五入
        System.out.println(Math.round(3.4999999999));//3
        System.out.println(Math.round(3.5000000001));//4

        //5、public static int max(inta,intb):取较大值
        //public static int min(inta,intb):取较小值
        System.out.println(Math.max(10, 20));//20
        System.out.println(Math.min(10, 20));//10

        //6、public static double pow(double a,double b):取次方
        System.out.println(Math.pow(2, 3));//2的3次方  8
        System.out.println(Math.pow(3, 2));//3的2次方 9


        //7、public static double random():取随机数[0.0,1.0)(包前不包后)
        System.out.println(Math.random());
    }
}

RuntimeTest

package com.itheima.math;

import java.io.IOException;

public class RuntimeTest {
    public static void main(String[] args) throws IOException, InterruptedException {
        //目标:了解Runtime的几个常见方法
        //1、public static Runtime getRuntime()返回与当前Java应用程序关联的运行时对象。
        Runtime r=Runtime.getRuntime();

        //2、public void exit(int status)终止当前运行的虚拟机,该参数用作状态代码;按照惯例,非零状态代码表示异常终止。
        //r.exit(0);  System的exit也是调用runtime的exit

        //3.public int availableProcessors() 获取虚拟机能够使用的处理器数
        System.out.println(r.availableProcessors());

        //4、public long totalMemory()返回Java虚拟机中的内存总量。
        System.out.println(r.totalMemory()/1024.0/1024.0+"MB");//1024=1k  1024*1024=1M

        //5、public long freeMemory()返回Java虚拟机中的可用内存量
        System.out.println(r.freeMemory()/1024.0/1024.0+"MB");

        //6、public Process exec(String command)启动某个程序,并返回代表该程序的对象。
       // r.exec("D:\\download\\CloudMusic\\cloudmusic.exe");
        Process p= r.exec("QQ");//前提是路径添加到Path中
       Thread.sleep(5000);//程序在这里停5秒
        p.destroy();//关闭程序
    }
}

SystemTest

package com.itheima.math;

public class SystemTest {
    public static void main(String[] args) {
        //目标:了解下System类的常见方法。
        //1. public static void exit(int status);
        //终止当前运行的Java虚拟机。
        //该参数用作状态代码;按照惯例,非零状态代码表示异常终止。
        //System.exit(0);//人为中止虚拟机(不要使用)

        //2.public static long currentTimeMillis();
        //获取当前系统的时间
        //返回的是long类型的时间毫秒值:指的是从1970-1-1 0:0:0开始走到此刻的总的毫秒值,1s=1000ms
        long time =System.currentTimeMillis();
        System.out.println(time);

        for (int i = 0; i < 1000000; i++) {
            System.out.println("输出了:"+i);
        }
        long time2=System.currentTimeMillis();
        System.out.println("花了"+(time2-time)/1000.0+"s");
    }

}

3.5.2BigDecimal
  • 用于解决浮点型运算时,出现结果失真的问题。
    在这里插入图片描述
    BigDecimall的常见构造器、常用方法
    在这里插入图片描述
    示例
    在这里插入图片描述

BigDecimalDemo

package com.itheima.bigDecimal;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalDemo1 {
    public static void main(String[] args) {
        //目标:掌握BigDecimal的使用,用于解决浮点型运算时出现结果失真的问题,
        double a=0.1;
        double b=0.2;
        double c=a+b;
        System.out.println(c);//0.30000000000000004
        System.out.println("--------------------------------------");

        //1.把他们变成字符串封装成BigDecimal对象来运算

      /*  BigDecimal a1=new BigDecimal(Double.toString(a));
        BigDecimal b1=new BigDecimal(Double.toString(b));
        可以优化写法
        */

        BigDecimal a1=BigDecimal.valueOf(a);//封装好了上面注释的写法
        BigDecimal b1=BigDecimal.valueOf(b);

        BigDecimal c1=a1.add(b1);//加
       /* BigDecimal c1=a1.subtract(b1);减
        BigDecimal c1=a1.multiply(b1);乘
        BigDecimal c1=a1.divide(b1)除;
        */
        System.out.println(c1);//0.3

        BigDecimal i=BigDecimal.valueOf(0.1);
        BigDecimal j=BigDecimal.valueOf(0.3);

        BigDecimal k=i.divide(j,2, RoundingMode.HALF_UP);//除法,两位小数,四舍五入
        double rs=k.doubleValue();
        System.out.println(rs);//0.33dd
    }
}

3.5.3JDK8之前传统的日期、时间
3.5.3.1Date
  • 代表时间和日期
    在这里插入图片描述
3.5.3.2SimpleDateFormat
  • 代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式。
    在这里插入图片描述
    在这里插入图片描述

时间格式的常见符号
在这里插入图片描述
SimpleDateFormat解析字符串时间成为日期对象
在这里插入图片描述
示例
在这里插入图片描述
TestDate

package com.itheima.time;

import com.itheima.d9_generics_interface.Data;

import java.util.Date;

public class TestDate {
    public static void main(String[] args) {
        //目标:掌握Date日期类的使用
        //1.创建一个Date的对象,代表系统当前时间信息
        Date d=new Date();
        System.out.println(d);

        //2.拿到时间毫秒值。
        long time =d.getTime();
        System.out.println(time);

        //3.把时间毫秒值转换成日期对象,2s之后的时间是多少
        time+=2000;
        Date d2 = new Date(time);
        System.out.println(d2);


        //直接把日期对象的时间通过setTime方法进行修改
        Date d3 = new Date();
        d3.setTime(time);
        System.out.println(d3);
    }
}

TestSimpleDateFormat

package com.itheima.time;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestSimpleDateFormat {
    public static void main(String[] args) throws ParseException {
        //目标:掌握SimpleDateFormat的使用。
        //1、准备一些时间
        Date d =new Date();
        System.out.println(d);//Fri Mar 29 18:13:14 AWST 2024
        Long time = d.getTime();
        System.out.println(time);//1711707194177

        //2、格式化日期对象,和时间毫秒值
       SimpleDateFormat f= new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
        String rs=f.format(d);
        System.out.println(rs);//2024年03月29日 18:13:14 周五 下午
        String rs2=f.format(time);
        System.out.println(rs2);//2024年03月29日 18:13:14 周五 下午
        System.out.println("-----------------------------------------");

        //目标:掌握SimpleDateFormat解析字符串时间成为日期对象。
        String datestr="2022-12-12 12:12:11";
        //1.创建简单日期格式化对象,指定的时间格式必须与被解析的时间格式一模一样,否则程序会出bug
        SimpleDateFormat f2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d2 =f2.parse(datestr);
        System.out.println(d2);//Mon Dec 12 12:12:11 AWST 2022
    }
}

3.5.3.3练习:秒杀活动

在这里插入图片描述
示例:
在这里插入图片描述
Demo

package com.itheima.time;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws ParseException {
        //目标:完成秒杀案例。
        //1、把开始时间、结束时间、小贾下单时间、小皮下单时间拿到程序中来。
        String start="2023年11月11日 0:0:0";
        String end="2023年11月11日 0:10:0";
        String xj="2023年11月11日 0:01:18";
        String xp="2023年11月11日 0:10:57";
        //2.把字符串时间解析成日期对象
        SimpleDateFormat s = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date startDt=s.parse(start);
        Date endDt=s.parse(end);
        Date xjDt=s.parse(xj);
        Date xpDt=s.parse(xp);

        //3.开始判断小皮和小贾是否秒杀成功了。
        //把日期对象转换成时间毫秒值来判断
        long startTime = startDt.getTime();
        long endTime = endDt.getTime();
        long xjTime = xjDt.getTime();
        long xpTime = xpDt.getTime();

        if(xjTime>=startTime&&xjTime<=endTime){
            System.out.println("小贾您秒杀成功了~~");
        }else {
            System.out.println("小贾您秒杀失败了~~");
        }
        if(xpTime>=startTime&&xpTime<=endTime){
            System.out.println("小皮您秒杀成功了~~");
        }else {
            System.out.println("小皮您秒杀失败了~~");
        }
    }
}

3.5.3.4Calendar

Calendar

  • 代表的是系统此刻时间对应的日历。
  • 通过它可以单独获取、修改时间中的年、月、日、时、分、秒等。

Calendar日历类的常见方法
在这里插入图片描述
示例
在这里插入图片描述
TestCalendar

package com.itheima.time;

import java.util.Calendar;
import java.util.Date;

public class TestCalendar {
    public static void main(String[] args) {
        //目标:学握Calendar的使用和特点。
        //1、得到系统此刻时阿对应的日历对象。
        Calendar now = Calendar.getInstance();
        System.out.println(now);
       /* java.util.GregorianCalendar[time=1711717009607,areFieldsSet=true,
         areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Australia/Perth",
         offset=28800000,dstSavings=0,useDaylight=false,transitions=20,lastRule=null],firstDayOfWeek=1,
         minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=2,WEEK_OF_YEAR=13,WEEK_OF_MONTH=5,DAY_OF_MONTH=29,
         DAY_OF_YEAR=89,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=56,
         SECOND=49,MILLISECOND=607,ZONE_OFFSET=28800000,DST_OFFSET=0]*/

        //2.获取日历中的某个值
       int year=now.get(Calendar.YEAR);
        System.out.println(year);
        System.out.println(now.get(Calendar.MONTH));

        //3.拿到日历中记录的日期对象
        Date d=now.getTime();
        System.out.println(d);

        //4.拿到时间毫秒值
        long time =now.getTimeInMillis();
        System.out.println(time);

        //5.修改日历中的某个信息
        now.set(Calendar.MONTH,9);//修改月份为10月(从0开始)
        now.set(Calendar.DAY_OF_YEAR,125); //修改成一年中的第125天
        System.out.println(now);

        //6.为某个信息增加或者减少多少
        now.add(Calendar.DAY_OF_YEAR,100);
        now.add(Calendar.DAY_OF_YEAR,-10);
        now.add(Calendar.DAY_OF_MONTH,6);
        now.add(Calendar.HOUR,12);
        System.out.println(now);
    }
}

3.5.4JDK8之前传统的日期、时间
3.5.4.1为什么要学JDK8新增的时间?

在这里插入图片描述
JDK8新增的时间
LocalDate:年、月、日
LocalTime:时、分、秒
LocalDateTime:年、月、日时、分、秒
ZoneId:时区
ZonedDateTime:带时区的时间
Instant:时间戳/时间线
DateTimeFormatter:用于时间的格式化和解析
Duration:时间间隔(时、分、秒,纳秒)
Period:时间间隔(年,月,日)

在这里插入图片描述
示例
在这里插入图片描述

Test

package com.itheima.jdk8_time;

import java.util.Calendar;
import java.util.Date;

/*
目标:搞清楚为什么要用JDK8开始新增的时间类。
        */
public class Test {

    public static void main(String[] args) {
        //传统的时间类(Date、SimpleDateFormat、Calendar)存在如下问题:
        //1、设计不合理,使用不方便,很多都被淘汰了。
        Date d = new Date();
        System.out.println(d.getYear() + 1900);//getYear拿到的是当前年份减去1900

        Calendar c= Calendar.getInstance();
        int year =c.get(Calendar.YEAR);//麻烦,还要自己记字段
        System.out.println(year);



        //2、都是可变对象,修改后会丢失最开始的时间信息。

        //3、线程不安全。

        //4、不能精确到纳秒,只能精确到毫秒。

    }
}
3.5.4.2LocalDate、LocalTime、LocalDateTime

LocalDate:代表本地日期(年、月、日、星期)
LocalTime:代表本地时间(时、分、秒、纳秒)
LocalDateTime:代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)

它们获取对象的方案
在这里插入图片描述

LocalDate的常用API (都是处理年、月、日、星期相关的)
在这里插入图片描述
什么是时区

  • 由于世界各个国家与地区的经度不同,各地区的时间也有所不同,因此会划分为不同的时区。

在这里插入图片描述
Zoneld时区的常见方法
在这里插入图片描述

ZonedDateTime带时区时间的常见方法
在这里插入图片描述
示例:
在这里插入图片描述
Test1_LocalDate

package com.itheima.jdk8_time;

import java.time.LocalDate;

public class Test1_LocalDate {
    public static void main(String[] args) {
        //0、获取本地日期对象
        LocalDate ld=LocalDate.now();//年月日
        System.out.println(ld);

        //1、获取日期对象中的信息
            int year=  ld.getYear();//
        int month = ld.getMonthValue();//(1-12)
        int day = ld.getDayOfMonth();//
        int dayOfYear=ld.getDayOfYear();//一年中的第几天
        int dayOfWeek=ld.getDayOfWeek().getValue();//星期几

        System.out.println(year);
        System.out.println(day);
        System.out.println(dayOfWeek);
        //2、直接修改某个信息:withYear、withMonth、withDayOfMonth、withDayIOfYear
        LocalDate ld2=ld.withYear(2099);
        LocalDate ld3=ld.withMonth(9);
        System.out.println(ld);//2024-03-30,说明是不可变对象
        System.out.println(ld2);//2099-03-30
        System.out.println(ld3);//2024-09-30

        //3、把某个信息加多少:plusYears、plusMonths、plusDays、plusWeeks
        LocalDate ld4=ld.plusYears(2);
        LocalDate ld5=ld.plusMonths(2);

        //4、把某个信,息减多少:minusYears、minusMonths、minusDays、minusWeeks
        LocalDate ld6=ld.minusYears(2);
        LocalDate ld7=ld.minusMonths(2);

        //5、获取指定日期的LocalDate对象:public static LocalDate of(int year,int month,int day)
        LocalDate ld8=LocalDate.of(2077,7,7);
        LocalDate ld9=LocalDate.of(2077,7,7);

        //6、判断2个日期对象,是否相等,在前还是在后:equals isBefore isAfter

        System.out.println(ld8.equals(ld9));//true
        System.out.println(ld8.isAfter(ld));//true
        System.out.println(ld8.isBefore(ld));//false
    }
}

Test2_LocalTime

package com.itheima.jdk8_time;

import java.time.LocalTime;

public class Test2_LocalTime {
    public static void main(String[] args) {
        //0、获取本地时间对象
        LocalTime lt=LocalTime.now();//时分秒纳秒不可变的
        System.out.println(lt);
        //1、获取时间中的信息
        int hour = lt.getHour();//时
        int minute = lt.getMinute();//分
        int second = lt.getSecond();//秒
        int nano=lt.getNano();//纳秒

        //2、修改时间:withHour、withMinute、withSecond、withNano
        LocalTime lt3 = lt.withHour(10);
        LocalTime lt4 = lt.withMinute(10);
        LocalTime lt5 = lt.withSecond(10);
        LocalTime lt6 = lt.withNano(10);

        //3、加多少:plUsHours、plusMinutes、plusSeconds、plusNanos
        LocalTime lt7 = lt.plusHours(10);
        LocalTime lt8 = lt.plusMinutes(10);
        LocalTime lt9 = lt.plusSeconds(10);
        LocalTime lt10 = lt.plusNanos(10);

        //4、减多少:minusHours、minusMinutes、minusSeconds、minusNanos
        LocalTime lt11 = lt.minusHours(10);
        LocalTime lt12 = lt.minusMinutes(10);
        LocalTime lt13 = lt.minusSeconds(10);
        LocalTime lt14 = lt.minusNanos(10);

        //5、获取指定时间的localTome对象:
        //public static LocalTime of(int hour,int minute,int second)
        LocalTime lt15 =LocalTime.of(12,12, 12);
        LocalTime lt16 = LocalTime.of(12,12,12);
        //6、判断2个时间对象,是否相等,在前还是在后:equals isBefore isAfter
        System.out.println(lt15.equals(lt16));
        System.out.println(lt15.isAfter(lt));
        System.out.println(lt15.isBefore(lt));
    }
}

Test3_LocalDateTime

package com.itheima.jdk8_time;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class Test3_LocalDateTime {
    public static void main(String[] args) {
        //0、获取本地日期和时间对象。
        LocalDateTime ldt= LocalDateTime.now();//年 月 日 时 分 秒 纳秒
        System.out.println(ldt);

        //1可以获取日期和时间的全部信息
        int year = ldt.getYear();//年
        int month = ldt.getMonthValue();//
        int day = ldt.getDayOfMonth();//
        int dayOfYear=ldt.getDayOfYear();//一年中的第几天
        int dayofWeek=ldt.getDayOfWeek().getValue();//获取是周几
        int hour = ldt.getHour();//
        int minute = ldt.getMinute();//
        int second = ldt.getSecond();//
        int nano = ldt.getNano();//纳秒
        //2、修改时间信息:
        //withYear withMonth withDayofMonth withDayofYear withHour withMinute withSecond withNano
        LocalDateTime ldt2=ldt.withYear(2029);
        LocalDateTime ldt3 = ldt.withMinute(59);
        //3、加多少:
        //plusYears plusMonths plusDays plusWeeks plusHours plusMinutes plusSeconds plusNanos
        LocalDateTime ldt4 = ldt.plusYears(2);
        LocalDateTime ldt5 = ldt.plusMinutes(3);

        //4、减多少:
        //minusDays minusYears minusMonths minusWeeks minusHours minusMinutes minusSeconds minusNanos
        LocalDateTime ldt6 =ldt.minusYears(2);
        LocalDateTime ldt7 =ldt.minusMinutes(3);

        //5、获取指定日期和时间的LocalDateTime对象:
        //public static LocalDateTime of(int year,Monthmonth,int dayofMonth,int hour,
        //                                  int minute,int second,int nanoOfSecond)
        LocalDateTime ldt8 = LocalDateTime.of(2028,12,5,9,30,10,1200);
        LocalDateTime ldt9 = LocalDateTime.of(2029,12,5,9,30,10,1200);

        //6、判断2个日期、时间对象,是否相等,在前还是在后:equals、isBefore、isAfter
        System.out.println(ldt9.equals(ldt8));
        System.out.println(ldt9.isAfter(ldt));
        System.out.println(ldt9.isBefore(ldt));

        //7、可以把LocalDateTime转换成LocalDate和ocalTime
        //public LocalDate toLocalDate()
        //public LocalTime toLocalTime()
        //public static LocalDateTime of(LocalDatddde date,LocalTime time)

        LocalDate ld=ldt.toLocalDate();
        LocalTime lt=ldt.toLocalTime();
        LocalDateTime ldt10=LocalDateTime.of(ld,lt);

    }
}

Test4_ZoneId_ZonedDateTime

package com.itheima.jdk8_time;

import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.zip.ZipEntry;

public class Test4_ZoneId_ZonedDateTime {
    public static void main(String[] args) {
        //目标:了解时区和带时区的时间。
        //1、ZoneId的常见方法:
        //public static ZoneId systemDefault():获取系统默认的时区

        ZoneId zoneId =ZoneId.systemDefault();
        System.out.println(zoneId.getId());
        System.out.println(zoneId);//实际上是调用toString方法


        //public static Set<String>getAvailableZoneIds():获取Java支持的全部时区Id
        System.out.println(ZoneId.getAvailableZoneIds());


        //public static ZoneId of(String zoneId):把某个时区id封装成ZoneId对象。
        ZoneId Id1=ZoneId.of("America/Cuiaba");

        //2、ZonedDateTime:带时区的时间。
        //public static ZonedDateTime now(ZoneId zone):获取某个时区的ZonedDateTime对象。
        ZonedDateTime now = ZonedDateTime.now(Id1);
        System.out.println(now);

        //世界标准时间
        ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());
        System.out.println(now1);

        //public static ZonedDateTime now():获取系统默认时区的ZonedDateTime对象
        ZonedDateTime now2 = ZonedDateTime.now();
        System.out.println(now2);

        //Calender instance= Calendar.getInstance(TimeZone.getTimeZone(Id1));过时了
    }
}

3.5.4.3 Instant

Instant时间线上的某个时刻/时间戳

  • 通过获取1 nstant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-0100:00:00开始走到此刻的总秒数+不够1秒的纳秒数
    在这里插入图片描述
  • 作用:可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点。
  • 传统的Date类,只能精确到毫秒,并且是可变对象。
  • 新增的Instant类,可以精确到纳秒,并且是不可变对象,推荐用Instant代替Date。

示例
在这里插入图片描述
Test5_Instant

package com.itheima.jdk8_time;

import java.time.Instant;/*
 *目标:掌握Instont的使用。
 */
public class Test5_Instant{

    public static void main(String[] args){
        //1、创建Instant的对象,获取此刻时间信息
        Instant now = Instant.now();//不可变对象

        //获取总秒数
        long second = now.getEpochSecond();
        System.out.println(second);

        //3、不够一秒的纳秒数
        int nano =now.getNano();
        System.out.println(nano);

        System.out.println(now);

        Instant instant = now.plusNanos(111);

        //Instant对象的作用:代码性能分析,或记录用户的操作时间点
        Instant now1 = Instant.now();
        //代码执行...
        Instant now2 = Instant.now();
    }
}
3.5.4.4DateTimeFormatter

在这里插入图片描述

LocalDateTime提供的格式化、解析时间的方法
在这里插入图片描述
示例
在这里插入图片描述
Test6_DateTimerFormatter

package com.itheima.jdk8_time;

//目标:掌握JDK8新增的DateTimeFormatter格式化器的用法。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Test6_DateTimerFormatter {
    public static void main(String[] args) {
        //1.创建一个日期时间格式化器对象出来
        DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");

        //2.对时间进行格式化
        LocalDateTime now=LocalDateTime.now();
        System.out.println(now);

        String rs=formatter.format(now);//正向格式化
        System.out.println(rs);

        //格式化时间,其实还有一种方法
        String rs2=now.format(formatter);//反向格式化
        System.out.println(rs2);

        //4.解析时间,解析时间一般使用LocalDateTime提供的解析方法来解析。
        String dateStr ="2029年12月12日 10:10:8";
        LocalDateTime ldt =LocalDateTime.parse(dateStr,formatter);
        System.out.println(ldt);
    }
}

3.5.4.5Period与Duration

Period(一段时期)

  • 可以用于计算两个LocalDate对象相差的年数、月数、天数。
    在这里插入图片描述
    Duration(持续时间)
  • 可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间

在这里插入图片描述
示例:
在这里插入图片描述
Test7_Period

package com.itheima.jdk8_time;

import java.time.LocalDate;
import java.time.Period;


//目标:掌握Period的作用:计算机两个日期相差的年数,月数、天数。
public class Test7_Period {
    public static void main(String[] args) {
        LocalDate start =LocalDate.of(2029,8,10);
        LocalDate end =LocalDate.of(2035,10,15);

        //1.创建Period对象,封装两个日期对象
        Period period= Period.between(start,end);
        //2.通过period对象获取两个对象相差的信息
        System.out.println(period.getYears());//间隔6年
        System.out.println(period.getMonths());//间隔2个月
        System.out.println(period.getDays());//间隔5天
    }
}

Test8_Duration

package com.itheima.jdk8_time;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;

//目标:掌握Period的作用:计算机两个日期相差的年数,月数、天数。
public class Test8Duration {
    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2025, 11, 11, 10, 10);
        LocalDateTime end = LocalDateTime.of(2025, 11, 11, 11, 11);
        //1、得到Duration对象
        Duration duration = Duration.between(start,end);

        //2.获取两个时间对象间隔的时间
        System.out.println(duration.toDays());//间隔多少天
        System.out.println(duration.toHours());//间隔多少小时
        System.out.println(duration.toMinutes());//间隔多少分
        System.out.println(duration.toSeconds());//间隔多少秒
        System.out.println(duration.toMillis());//间隔多少毫秒
        System.out.println(duration.toNanos());//间隔多少纳秒,秒都是累积起来的
    }
}

3.5.5Arrays

Arrays

  • 用来操作数组的一个工具类。

Arrays.类提供的的常见方法Arrays

在这里插入图片描述
如果数组中存储的是对象,如何排序?
在这里插入图片描述

  • 方式一: 让该对象的类实现Comparable(比较规则)接口,然后重写compareTo方法,自己来制定比较规则。
  • 方式二:使用下面这个sort方法,创建Comparator比较器接口的匿名内部类对象,然后自己制定比较规则。

在这里插入图片描述
自定义排序规则时,需要遵循的官方约定如下:
在这里插入图片描述
示例:
在这里插入图片描述
Student

package com.itheima.arrays;

public class Student implements Comparable<Student>{

    private String name;
    private double height;
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", height=" + height +
                ", age=" + age +
                '}';
    }

    //指定比较规则
    //this o
    @Override
    public int compareTo(Student o){
        //约定1:左边对象大于右边对象,返回正整数
        //约定2:左边对象小于右边对象,返回负整数
        //约定3:左边对象等于于右边对象,返回0
        //按照年龄升序。


      /*  if(this.age>o.age){
            return 1;
        }else if(this.age<o.age){
            return -1;
        }
       return 0;
       */

        //一行代码实现
        //return this.age-o.age;//升序
        return -(this.age-o.age);//降序

    }
    public Student() {
    }

    public Student(String name, double height, int age) {
        this.name = name;
        this.height = height;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Test1

package com.itheima.arrays;

import com.itheima.d6_enum.A;

import java.util.Arrays;
import java.util.function.IntToDoubleFunction;

public class Test1 {
    public static void main(String[] args) {
        //1、public static String toString(类型[] arr):返回数组的内容
        int[] arr={10,20,40,60};//[10, 20, 40, 60]
        System.out.println(Arrays.toString(arr));

        //2、public static int[] copyOfRange(类型[] arr,起始索引,结束索引):拷贝数组(指定范围,包前不包后)
       int arr2[]= Arrays.copyOfRange(arr,1,3);//[20, 40]
        System.out.println(Arrays.toString(arr2));
        //3、public static copyof(类型[] arr,int newLength.):拷贝数组,可以指定新数组的长度。
        int arr3[] = Arrays.copyOf(arr,10);
        System.out.println(Arrays.toString(arr3));//[10, 20, 40, 60, 0, 0, 0, 0, 0, 0]
        int arr4[] = Arrays.copyOf(arr,3);
        System.out.println(Arrays.toString(arr4));//[10, 20, 40]

        //4、public static setAll(double[] array,IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
        double[] prices={99.8,128,100};
        //所有价格打八折,然后存进去
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {//会一个一个拿索引
                return 0.8*prices[value];
            }
        });
        System.out.println(Arrays.toString(prices));//此错没有失真,若失真,就要用BigDecimal处理

        //5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
        Arrays.sort(prices);
        System.out.println(Arrays.toString(prices));
    }
}

Test2

package com.itheima.arrays;

import com.itheima.d6_enum.A;

import java.util.Arrays;
import java.util.Comparator;

public class Test2 {
    public static void main(String[] args) {
        //目标:掌握如何对数组中的对象进行排序
        Student[] students =new Student[4];
        students[0]=new Student("蜘蛛精",169.5,23);
        students[1]=new Student("紫霞",165.8,25);
        students[2]=new Student("至尊宝",178.5,29);
        students[3]=new Student("牛魔王",185.4,28);

        //1.public static void sort(类型[] arr);对数组进行排序



        //2.public static <T> void sort(T[] arr, Comparator<? super T> c)
        //参数一:需要排序的数组
        //参数二:Comparator比较器对象(用来指定对象的比较规则)
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //指定比较规则
                //约定1:左边对象大于右边对象,返回正整数
                //约定2:左边对象小于右边对象,返回负整数
                //约定3:左边对象等于于右边对象,返回0

                /*按照身高升序,注意身高是double,不能直接做差,老老实实if语句
                if(o1.getHeight()> o1.getHeight()){
                    return 1;
                }else if(o1.getHeight()<o2.getHeight()){
                    return -1;
                }
                return 0;*/

                //一行代码搞定
                return Double.compare(o1.getHeight(),o2.getHeight());//升序
                // return -Double.compare(o1.getHeight(),o2.getHeight());//降序
            }
        });
        System.out.println(Arrays.toString(students));
    }
}
3.5.6JDK8新特性:Lambda表达式
3.5.6.1认识Lambda表达式

Lambda表达式

  • Lambda表达式是JDK8开始新增的一种语法形式;作用:用于简化匿名内部类的代码写法。

格式
在这里插入图片描述
什么是函数式接口?

  • 有且仅有一个抽象方法的接口。
  • 注意:将来我们见到的大部分函数式接口,上面都可能会有一个@Functionalinterface的注解,有该注解
    的接口就必定是函数式接口。
3.5.6.2Lambda表达式的省略规则

Lambda表达式的省略写法(进一步简化Lambda表达式的写法)

  • 参数类型可以省略不写。
  • 如果只有一个参数,参数类型可以省略,同时()也可以省略。
  • 如果Lambda表达式中的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!此时,如
    果这行代码
    是return语句,也必须去掉return不写。

示例:
在这里插入图片描述
Student

package com.itheima.arrays;

public class Student implements Comparable<Student>{

    private String name;
    private double height;
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", height=" + height +
                ", age=" + age +
                '}';
    }

    //指定比较规则
    //this o
    @Override
    public int compareTo(Student o){
        //约定1:左边对象大于右边对象,返回正整数
        //约定2:左边对象小于右边对象,返回负整数
        //约定3:左边对象等于于右边对象,返回0
        //按照年龄升序。


      /*  if(this.age>o.age){
            return 1;
        }else if(this.age<o.age){
            return -1;
        }
       return 0;
       */

        //一行代码实现
        //return this.age-o.age;//升序
        return -(this.age-o.age);//降序

    }
    public Student() {
    }

    public Student(String name, double height, int age) {
        this.name = name;
        this.height = height;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Test1

package com.itheima.arrays;

import com.itheima.d6_enum.A;

import java.util.Arrays;
import java.util.function.IntToDoubleFunction;

public class Test1 {
    public static void main(String[] args) {
        //1、public static String toString(类型[] arr):返回数组的内容
        int[] arr={10,20,40,60};//[10, 20, 40, 60]
        System.out.println(Arrays.toString(arr));

        //2、public static int[] copyOfRange(类型[] arr,起始索引,结束索引):拷贝数组(指定范围,包前不包后)
       int arr2[]= Arrays.copyOfRange(arr,1,3);//[20, 40]
        System.out.println(Arrays.toString(arr2));
        //3、public static copyof(类型[] arr,int newLength.):拷贝数组,可以指定新数组的长度。
        int arr3[] = Arrays.copyOf(arr,10);
        System.out.println(Arrays.toString(arr3));//[10, 20, 40, 60, 0, 0, 0, 0, 0, 0]
        int arr4[] = Arrays.copyOf(arr,3);
        System.out.println(Arrays.toString(arr4));//[10, 20, 40]

        //4、public static setAll(double[] array,IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
        double[] prices={99.8,128,100};
        //所有价格打八折,然后存进去
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {//会一个一个拿索引
                return 0.8*prices[value];
            }
        });
        System.out.println(Arrays.toString(prices));//此错没有失真,若失真,就要用BigDecimal处理

        //5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
        Arrays.sort(prices);
        System.out.println(Arrays.toString(prices));
    }
}

Test2

package com.itheima.arrays;

import com.itheima.d6_enum.A;

import java.util.Arrays;
import java.util.Comparator;

public class Test2 {
    public static void main(String[] args) {
        //目标:掌握如何对数组中的对象进行排序
        Student[] students =new Student[4];
        students[0]=new Student("蜘蛛精",169.5,23);
        students[1]=new Student("紫霞",165.8,25);
        students[2]=new Student("至尊宝",178.5,29);
        students[3]=new Student("牛魔王",185.4,28);

        //1.public static void sort(类型[] arr);对数组进行排序



        //2.public static <T> void sort(T[] arr, Comparator<? super T> c)
        //参数一:需要排序的数组
        //参数二:Comparator比较器对象(用来指定对象的比较规则)
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //指定比较规则
                //约定1:左边对象大于右边对象,返回正整数
                //约定2:左边对象小于右边对象,返回负整数
                //约定3:左边对象等于于右边对象,返回0

                /*按照身高升序,注意身高是double,不能直接做差,老老实实if语句
                if(o1.getHeight()> o1.getHeight()){
                    return 1;
                }else if(o1.getHeight()<o2.getHeight()){
                    return -1;
                }
                return 0;*/

                //一行代码搞定
                return Double.compare(o1.getHeight(),o2.getHeight());//升序
                // return -Double.compare(o1.getHeight(),o2.getHeight());//降序
            }
        });
        System.out.println(Arrays.toString(students));
    }
}
3.5.7JDK8新特性:方法引用

静态方法的引用

  • 类名::静态方法

使用场景

  • 如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用.

实例方法的引用

  • 对象名::实例方法.

使用场景

  • 如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用.

特定类型的方法引用

  • 类型::方法.

使用场景

  • 如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用.

构造器引用

  • 类名::new

使用场景
●如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用.

示例:
在这里插入图片描述
Car

package com.itheima.method_references;

public class Car {
    private String name;
    private double price;

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    public Car() {
    }

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

CompareByData

package com.itheima.method_references;

import com.itheima.arrays.Student;

public class CompareByData {
    public static int compareByAge(Student o1, Student o2){

        return o1.getAge()- o2.getAge();//升序排序的规则;
    }

    public int compareByAgeDesc(Student o1,Student o2){
        return o2.getAge()-o1.getAge();//降序排序的规则;
    }
}

Test1

package com.itheima.method_references;

import com.itheima.arrays.Student;
import com.itheima.d6_enum.A;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;

public class Test1 {
    public static void main(String[] args) {
        Student[] students =new Student[4];
        students[0]=new Student("蜘蛛精",169.5,23);
        students[1]=new Student("紫霞",165.8,25);
        students[2]=new Student("至尊宝",178.5,29);
        students[3]=new Student("牛魔王",185.4,28);

        //原始写法:对数组中的学生对象,按照年龄升序排序
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge()- o2.getAge();//按照年龄升序排序
            }
            });

        //使用Lambda表达式进行简化
        //Arrays.sort(students,((o1, o2) -> o1.getAge()- o2.getAge()));

        //Arrays.sort(students,((o1, o2) -> CompareByData.compareByAge(o1,o2)));

        //静态方法引用
       // Arrays.sort(students, CompareByData::compareByAge);



        Arrays.sort(students,((o1, o2) -> o2.getAge()- o1.getAge()));
        CompareByData compare=new CompareByData();

        Arrays.sort(students,((o1, o2) -> compare.compareByAgeDesc(o1,o2)));

        //实例方法引用
        Arrays.sort(students, compare::compareByAgeDesc);

        System.out.println(Arrays.toString(students));
    }
}

Test2

package com.itheima.method_references;

import java.util.Arrays;
import java.util.Comparator;

public class Test2 {
    public static void main(String[] args) {
        String[]names = {"boby","angela","Andy","dlei","caocao","Babo","jack","cici"};

        //进行排序(默认字典序)
        Arrays.sort(names);

        //忽略带小写比较
       /* Arrays.sort(names, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //制定比较规则。 o1="Andy" o2="angela"
                return o1.compareToIgnoreCase(o2);
            }
        });
        */
        //简化
        //Arrays.sort(names,( o1,o2) -> o1.compareToIgnoreCase(o2));

        //再次简化
        Arrays.sort(names,String::compareToIgnoreCase);

        System.out.println(Arrays.toString(names));
    }
}

Test3

package com.itheima.method_references;

import com.itheima.d6_enum.A;

//目标:构造器引用(理解语法)
public class Test3 {
    public static void main(String[] args) {
        //1.创建这个接口的匿名内部类对象。
       /* CreateCar cc=new CreateCar(){
            @Override
            public Car create(String name,double price){
                return new Car(name,price);
            }
        };*/
       // CreateCar cc=( ( name, price)->new Car(name,price));

        //构造器引用
        CreateCar cc=Car::new;
        Car c = cc.create("奔驰", 49.9);
        System.out.println(c);
    }
}

interface CreateCar{
    Car create(String name,double price);
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值