黑马程序员Java零基础视频教程_上部(P129-P176)_黑马java视频-程序员宅基地

技术标签: jvm  Java  java  开发语言  

1. 面向对象进阶

1.1 认识多态

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
什么是多态?
同类型的对象,表现出的不同形态。

多态的表现形式:父类类型 对象名称 = 子类对象;

多态的前提:

  • 有继承关系
  • 有父类引用指向子类对象
  • 有方法重写

Animal.java

package Demo1;

public class Animal {
    
    public void eat(){
    
        System.out.println("动物吃东西");
    }
}

Cat.java

package Demo1;

public class Cat extends Animal{
    
    
    public void eat() {
    
        System.out.println("猫吃鱼");
    }
}

AnimalDemo.java

package Demo1;
/*
    多态:
        同一个对象,在不同时刻表现出来的不同形态

    举例:猫
        我们可以说猫是猫:     猫 cat = new 猫();
        我们也可以说猫是动物:  动物 animal = new 猫();

    多态的前提和体现
        有继承/实现关系
        有方法重写
        有父类引用指向子类对象
 */

public class AnimalDemo {
    
    public static void main(String[] args) {
    
        //有父类引用指向子类对象
        Animal a = new Cat();
        a.eat();
    }
}

多态调用成员的特点

  • 变量调用:编译看左边,运行也看左边。
  • 方法调用:编译看左边,运行看右边。
Fu f = new Zi();

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

在这里插入图片描述

1.2 多态的优势与劣势

优势:

  1. 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。

在这里插入图片描述

  1. 定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。

弊端:

  1. 不能调用子类的特有功能
    在这里插入图片描述

在这里插入图片描述
instanceof

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

1.3 多态的综合练习

在这里插入图片描述
Animal.java

package Duotai;

public class Animal {
    
    private int age;
    private String color;

    public Animal() {
    
    }

    public Animal(int age, String color) {
    
        this.age = age;
        this.color = color;
    }

    public int getAge() {
    
        return age;
    }

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

    public String getColor() {
    
        return color;
    }

    public void setColor(String color) {
    
        this.color = color;
    }
    public void eat(String food)
    {
    
        System.out.println("在吃东西");
    }
}

Cat.java

package Duotai;

public class Cat extends Animal {
    
    public Cat() {
    
    }

    public Cat(int age, String color) {
    
        super(age, color);
    }
    public void catchMouse(){
    
        System.out.println("抓老鼠");
    }
}

Dog.java

package Duotai;

public class Dog extends Animal{
    
    public Dog() {
    
    }

    public Dog(int age, String color) {
    
        super(age, color);
    }

    public void lookHome(){
    
        System.out.println("在看家");
    }
}

Person.java

package Duotai;

public class Person {
    
    private int age;
    private String name;

    public Person() {
    
    }

    public Person(int age, String name) {
    
        this.age = age;
        this.name = name;
    }

    public int getAge() {
    
        return age;
    }

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

    public String getName() {
    
        return name;
    }

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

    public void keepPet(Animal a, String food)
    {
    
        if( a instanceof  Dog d )
        {
    
            System.out.println(d.getAge()+" 岁 "+d.getColor()+" 的狗两条腿死死的抱住 "+food+" 猛吃");
        } else if (a instanceof  Cat c) {
    
            System.out.println(c.getAge()+" 岁 "+c.getColor()+" 的猫眯着眼睛侧着头吃 "+food);
        }
        else
        {
    
            System.out.println("这是什么动物 这是废物 宝贝");
        }
    }
}

Test.java

package Duotai;

public class Test {
    
    public static void main(String[] args) {
    
        Animal a1 = new Dog(2,"黑色");
        Animal a2 = new Cat(3,"灰色");
        Person p1 = new Person(30,"老王");
        Person p2 = new Person(25,"老李");
        System.out.println("年龄 "+p1.getAge()+" 的 "+p1.getName()+"养了一只 "+a1.getAge()+" 岁的狗");
        p1.keepPet(a1,"肉");
        System.out.println("年龄 "+p2.getAge()+" 的 "+p2.getName()+"养了一只 "+a2.getAge()+" 岁的猫");
        p2.keepPet(a2,"小鱼干");
    }
}

1.4 包、final、权限修饰符、代码块

什么是包?
包就是文件夹。用来管理各种不同功能的Java类,方便后期代码维护。
在这里插入图片描述

在这里插入图片描述
使用其他类的规则

  • 使用同一个包中的类时,不需要导包。
  • 使用java.lang包中 的类时,不需要导包。
  • 其他情况都需要导包
  • 如果同时使用两个包中的同名类,需要用全类名。

在这里插入图片描述

final
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
权限修饰符

权限修饰符:是用来控制一个成员能够被访问的范围的。
可以修饰成员变量、 方法、构造方法、内部类。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
代码块

  • 局部代码块
    在这里插入图片描述
    用完立马回收

在这里插入图片描述

  • 构造代码块

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

  • 静态代码块

在这里插入图片描述

1.5 抽象类与抽象方法

在这里插入图片描述
抽象方法所在的类就是抽象类

抽象方法

●抽象方法:将共性的行为(方法)抽取到父类之后。
由于每一个子类执行的内容是不一样,所以,在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。

●抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类。
在这里插入图片描述

public abstract class Pers {
    
    public abstract void work();
}

抽象类和抽象方法的注意事项

  • 抽象类不能实例化
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 可以有构造方法
  • 抽象类的子类
    要么重写抽象类中的所有抽象方法
    要么是抽象类

Dog.java

package com.itheima;

public abstract class Dog {
    
    public void eat()
    {
    
        System.out.println("吃gongliang");
    }
    public abstract void drink();


}

Hashiqi.java

package com.itheima;

public class Hashiqi  extends Dog{
    
    @Override
    public void eat() {
    
        System.out.println("吃rou");
    }
    @Override
    public void drink(){
    
        System.out.println("喝水");
    }
    public void caijia()
    {
    
        System.out.println("我在拆家");
    }
}

Test.java

package com.itheima;

public class Test {
    
    public static void main(String[] args) {
    
        Dog  hh = new Hashiqi();
        hh.drink();

    }
}

1.6 接口

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

在这里插入图片描述

在这里插入图片描述

接口的定义和使用

  • 接口用关键字interface来定义public interface接口名{}
  • 接口不能实例化
  • 接口和类之间是实现关系, 通过implements关键字表示public class类名implements接口名{}
  • 接口的子类(实现类)

要么重写接口中的所有抽象方法
要么是抽象类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接口和类之间的关系

●类和类的关系

继承关系,只能单继承,不能多继承,但是可以多层继承

●类和接口的关系

实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
在这里插入图片描述

●接口和接口的关系

继承关系,可以单继承,也可以多继承

1.6.1 接口与抽象类的综合练习

在这里插入图片描述
在这里插入图片描述
person.java

package Interface;

public class Person {
    
    private String name;
    private int Age;

    public Person(String name, int age) {
    
        this.name = name;
        Age = age;
    }

    public Person() {
    
    }

    public String getName() {
    
        return name;
    }

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

    public int getAge() {
    
        return Age;
    }

    public void setAge(int age) {
    
        Age = age;
    }
}

Ydy.java

package Interface;

public abstract class Ydy extends Person{
    
    public Ydy(String name, int age) {
    
        super(name, age);
    }

    public Ydy() {
    
    }
    public abstract void work();
}

Jl.java

package Interface;

public abstract class Jl extends Person{
    
    public Jl(String name, int age) {
    
        super(name, age);
    }

    public Jl() {
    
    }
    public abstract void teach();
}

English.java

package Interface;

public interface English {
    
    public static void English()
    {
    
        System.out.println("学英语");
    }
}

Pp_Ydy.java

package Interface;

public class Pp_Ydy extends Ydy implements English{
    
    public Pp_Ydy(String name, int age) {
    
        super(name, age);
    }

    public Pp_Ydy() {
    
    }
    @Override
    public void work(){
    
        System.out.println("学乒乓球");
    }
}

Baskertball_Ydy.java

package Interface;

public class Basketball_Ydy extends Ydy{
    
    public Basketball_Ydy(String name, int age) {
    
        super(name, age);
    }

    public Basketball_Ydy() {
    
    }
    @Override
    public void work(){
    
        System.out.println("学篮球");
    }
}

Pp_Jl.java

package Interface;

public class Pp_Jl extends Jl implements English{
    
    public Pp_Jl(String name, int age) {
    
        super(name, age);
    }

    public Pp_Jl() {
    
    }
    @Override
    public  void teach(){
    
        System.out.println("教乒乓球");
    }
}

Baskertball_Jl.java

package Interface;

public class Basketball_Jl extends Jl{
    
    public Basketball_Jl(String name, int age) {
    
        super(name, age);
    }

    public Basketball_Jl() {
    
    }
    @Override
    public void teach(){
    
        System.out.println("教篮球");
    }
}

Test.java

package Interface;


public class Test implements English{
    
    public static void main(String[] args) {
    
        Person p1 = new Pp_Ydy("11",23);
        Person p2 = new Pp_Jl("22",45);
        Person p3 = new Basketball_Ydy("33",45);
        Person p4 = new Basketball_Jl("44",56);

        System.out.println(p1.getName()+p1.getAge());
        if(p1 instanceof Pp_Ydy){
    
            ((Pp_Ydy) p1).work();
        }
        System.out.println(p2.getName()+p2.getAge());
        if(p2 instanceof Pp_Jl){
    
            ((Pp_Jl) p2).teach();
        }
        System.out.println(p3.getName()+p3.getAge());
        if(p3 instanceof Basketball_Ydy){
    
            ((Basketball_Ydy) p3).work();
        }
        System.out.println(p4.getName()+p4.getAge());
        if(p4 instanceof Basketball_Jl){
    
            ((Basketball_Jl) p4).teach();
        }

    }

}

1.6.2 接口多学三招

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

1.接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。
2.当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。

适配器设计模式

  • 设计模式(Design pattern): 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
    使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
    简单理解:设计模式就是各种套路。

  • 适配器设计模式:解决接口与接口实现类之间的矛盾问题

简单理解:设计模式就是各种套路。

适配器设计模式:解决接口与接口实现类之间的矛盾问题

1.当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以适配器设计模式
2.书写步骤:
编写中间类XXXAdapter,实现对应的接口对接口中的抽象方法进行空实现让真正的实现类继承中间类,并重写需要用的方法为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰

1.7 内部类

什么是内部类?
类的五大成员:属性、方法、构造方法、代码块、内部类

在一个类的里面,再定义一个类。
举例:在A类的内部定义B类,B类就被称为内部类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package Neibulei;

import Interface.Person;

public class Car {
    
    private String Carname;
    private int Carage;
    private String Carcolor;
    class engine{
    
        private String name;
        private int age;

        public engine(String name, int age) {
    
            this.name = name;
            this.age = age;
        }

        public engine() {
    
        }

        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 Car() {
    
    }

    public Car(String carname, int carage, String carcolor) {
    
        Carname = carname;
        Carage = carage;
        Carcolor = carcolor;
    }

    public String getCarname() {
    
        return Carname;
    }

    public void setCarname(String carname) {
    
        Carname = carname;
    }

    public int getCarage() {
    
        return Carage;
    }

    public void setCarage(int carage) {
    
        Carage = carage;
    }

    public String getCarcolor() {
    
        return Carcolor;
    }

    public void setCarcolor(String carcolor) {
    
        Carcolor = carcolor;
    }
    public void  show (){
    
        System.out.println(this.Carname);
        engine e = new engine();
        System.out.println(e.name);
    }
}

package Neibulei;

public class Main {
    
    public static void main(String[] args) {
    
        Car c = new Car();
    }
}

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

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

在这里插入图片描述
在这里插入图片描述
创建静态内部类对象的格式:外部类名.内部类名 对象名= new 外部类名.内部类名();
调用非静态方法的格式:先创建对象,用对象调用
调用静态方法的格式: 外部类名.内部类名.方法名();

在这里插入图片描述
局部内部类

  1. 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
  2. 外界是无法直接使用,需要在方法内部创建对象并使用。
  3. 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

匿名内部类
在这里插入图片描述

package Niming;

public interface Swim {
    
    public abstract void swim();
}

package Niming;

public class Test {
    
    public static void main(String[] args) {
    
        new Swim(){
    

            @Override
            public void swim() {
    
                System.out.println("重写了游泳的方法");
            }
        };
    }
}

在这里插入图片描述

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

1.8 拼图小游戏

在这里插入图片描述
Java语言主要是做后台服务器开发的,与用户交流很少 所以很少用GUI图形化界面,但是为了前面的知识点相结合,我们做一个小游戏。

大家可以看着 这个大牛的博客:

Java实现魔板拼图小游戏(完整版)

2. 常用API

2.1 Math

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

  1. Math:帮助我们进行数学计算的工具类
  2. 里面的方法都是静态的。

判断质数

import java.util.Scanner;

public class main {
    
    public static void main(String[] args) {
    
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个正整数,我将判断它是否为质数");
        int num = sc.nextInt();
        System.out.println(isPrime(num));
    }
    public static boolean isPrime(int num)
    {
    
        for(int i =2;i<=Math.sqrt(num);i++)
        {
    
            if(num%i ==0)return false;
        }
        return true;
    }

}

自幂数,一个n位自然数等于自身各个数位上数字的n次幂之和
在这里插入图片描述

2.2 System

System也是一个工具类,提供了一些与系统相关的方法。

在这里插入图片描述
在这里插入图片描述
1970年1月1日算C语言的生日
由于时差:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


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


public class main {
    
    public static void main(String[] args) {
    
        int [] arr1 = {
    1,2,3,4,5,6,7,8,9,10};
        int [] arr2 = new int[10];
        //把arr1数组中的数据拷贝到arr2中
        //参数一:数据源,要拷贝的数据从哪个数组而来
        //参数二:从数据源数组中的第几个索引开始拷贝
        //参数三:目的地,我要把数据拷贝到哪个数组中
        //参数四:目的地数组的索引。
        //参数五:拷贝的个数

        System.arraycopy(arr1,0,arr2,0,10);
        for (int i = 0; i < arr2.length; i++) {
    
            System.out.print(arr2[i]+" ");
        }

    }



}

  1. 如果数据源数组和月的地数组都是基本数据类型,那么两者的类型必须保持一致, 否则会报错
  2. 在拷贝的时候需要考虑数组的长度,如果超出范围也会报错
  3. 如果数据源数组和目的地数组都是引用数据类型,那么子类类型可以赋值给父类类型

在这里插入图片描述

2.3 Runtime

Runtime表示当前虚拟机的运行环境
在这里插入图片描述

import java.io.IOException;

public class main {
    
    public static void main(String[] args) throws IOException {
    
        1.获得RunTime的对象
        //Runtime r1 = Runtime.getRuntime();
        2.exit        停止虚拟机
        //Runtime.getRuntime().exit(0);
        //System.out.println("看看我执行了吗? ");
        //3.获得CPU的线程数
        System.out.println(Runtime.getRuntime().availableProcessors());
        //4.总内存大小,单位是byte
        System.out.println(Runtime.getRuntime().maxMemory()/1024/1024);
        //5.虚拟机已经获得总内存 大小
        System.out.println(Runtime.getRuntime().totalMemory()/1024/1024);
        //6.剩余内存大小
        System.out.println(Runtime.getRuntime().freeMemory()/1024/1024);
        //7.CMD
        Runtime.getRuntime().exec("TIM");//前提是设置好了环境


    }
}

在这里插入图片描述

2.4 Object和Objects

Object是Java中的顶级父类。所有的类都直接或间接的继承于Object类。
Object类中的方法可以被所有子类访问,所以我们要学习0bject类和其中的方法。
Object没有成员变量,所以只有空参构造。

在这里插入图片描述
Object的成员方法,一共11个,这里我们先学三个。

在这里插入图片描述

2.4.1 toString()

import java.io.IOException;

public class main {
    
    public static void main(String[] args) {
    
        Object obj = new Object();
        String str = obj.toString();
        System.out.println(str);//java.lang.Object@7ef20235
    }
}

Ctrl+b,然后Ctrl+F12 搜索 toString

在这里插入图片描述

在这里插入图片描述
System 是一个类名 选中 Ctrl+B
out 是 System 里的一个静态变量
所以是类名直接调用静态变量
//System. out:获取打印的对象
//printan():方法

2.4.2 equals

在这里插入图片描述
比较了地址值。但是地址值对我们来讲不重要,我只想比较内容

那么就要在子类里面重写(Object是父类),Ctrl+insert 点击equals() and hashCode(),一直点击next,到结束。可以输出下面的内容。

在这里插入图片描述

重写之后的equals方法比较的就是对象内部的属性值了。

import java.io.IOException;
import java.util.StringJoiner;

public class main {
    
    public static void main(String[] args) {
    
        String s = "abc";
        StringBuilder sb = new StringBuilder("abc");
        System.out.println(s.equals(sb));//f
        //因为equals方法是被s调用的,而s是字符串
        //所以equals要看String类中的
        //字符串中的equals方法, 先判断参数是否为字符串
        //如果是字符串,再比较内部的属性
        //但是如果参数不是字符串,直接返回false
        System.out.println(sb.equals(s));//f
        //因为equals方法是被sb调用的,而sb是StringBuilder
        //所以这里的equals方法要看StringBuilder中的equals方法
        //那么在StringBuilder当中,没有重写equals方法
        //使用的是Object中的
        //在Object当中默认是使用==号比较两个对象的地址:值
        //而这里的s和sb记录的地址值是不一样的,所以结果返回false
    }
}

2.4.3 Clone

把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制
在这里插入图片描述
不同的区就是不同服务器。

在这里插入图片描述

//2.克隆对象
//细节:
//方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去。
//书写细节:
//1.重写Object中的clone方法
//2.让javabean类实现Cloneable接口
//3.创建原对象并调用clone就可以了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
直接拷贝:(浅拷贝)
在这里插入图片描述

深克隆:
在这里插入图片描述
在这里插入图片描述
依旧在串池中寻找。
在这里插入图片描述
深克隆的重写:
在这里插入图片描述
利用第三方工具来实现深克隆。
在这里插入图片描述
在这里插入图片描述

//细节:
//1.方法的底层会判断s1是否为null,如果为null,直接返回false
//2.如果s1不为null,那么就利用s1再次调用equals方法
//3.此时s1是Student类型,所以最终还是会调用Student中的equals方法。
// 如果没有重写,比较地址值,如果重写了,就比较属性值。

2.5 BigInteger和BigDecimal

2.5.1 BigInteger 介绍

在Java中,整数有四种类型: byte, short, int, long。
在底层占用字节个数:byte1个字节、short2个字节、int4个字节、long8个字节。
在这里插入图片描述

2.5.2 BigInteger 构造方法

在这里插入图片描述

import java.math.BigInteger;
import java.util.Random;

public class main {
    
    public static void main(String[] args) {
    
        Random r =  new Random();
        BigInteger bg1 = new BigInteger(4,r);
        System.out.println(bg1);
    }
}

import java.math.BigInteger;

public class main {
    
    public static void main(String[] args) {
    
        //获取一个指定的大整数
        BigInteger bg1 = new BigInteger("99999999999999999999999999999999999");
        System.out.println(bg1);
    }
}

import java.math.BigInteger;

public class main {
    
    public static void main(String[] args) {
    
        //获取一个指定的大整数
        BigInteger bg1 = new BigInteger("99999999999999999999999999999999999",11);
        System.out.println(bg1);//2529219316325782306555092513018064365
    }
}

在这里插入图片描述

import java.math.BigInteger;

public class main {
    
    public static void main(String[] args) {
    
        BigInteger bg1 = BigInteger.valueOf(1000);
        System.out.println(bg1);
        //能取的范围比较小,是在long的取值范围内
        System.out.println(Long.MAX_VALUE);
        System.out.println(Long.MIN_VALUE);
//        1000
//        9223372036854775807
//        -9223372036854775808
    }
}

在这里插入图片描述
BigInteger构造方法小结

  • ①如果BigInteger表示的数字没有超出long的范围,可以用静态方法获取。
  • ②如果BigInteger表示的超出long的范围,可以用构造方法获取。
  • ③对象一旦创建,BigInteger内部记录的值不能发生改变。
  • ④只要进行计算都会产生一个新的BigInteger对象

2.5.3 BigInteger 成员方法

在这里插入图片描述

import java.math.BigInteger;

public class main {
    
    public static void main(String[] args) {
    
        BigInteger bg1 = BigInteger.valueOf(1000);
        BigInteger bg2 = BigInteger.valueOf(20);
        System.out.println(bg1.add(bg2));//1020
        System.out.println(bg1.subtract(bg2));//980
        System.out.println(bg1.multiply(bg2));//20000
        System.out.println(bg1.divide(bg2));//50

        BigInteger bg3 = BigInteger.valueOf(21);
        BigInteger[] arr = bg1.divideAndRemainder(bg3);
        System.out.println(arr[0]);//47
        System.out.println(arr[1]);//13

        System.out.println(bg2.pow(2));//400

        //max
        BigInteger bg4 = bg1.max(bg2);
        System.out.println(bg4);//1000
        System.out.println(bg4 == bg1);//true
        System.out.println(bg4 == bg2);//false

        int a = bg1.intValue();

        System.out.println(a);//1000
        System.out.println(bg1.longValue());//1000
        System.out.println(bg1.doubleValue());//1000.0

    }
}

2.5.4 BigInteger 底层存储方式

在这里插入图片描述
数据太大,把数据分段,然后分段存到数组中即可
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是电脑的内存是扛不住这么大的内存的,所以是理论值。
数组中最多能存储元素个数: 21亿多
数组中每一位能表示的数字: 42亿多

BigInteger能表示的最大数字为: 42亿的21亿次方

2.5.5 BigDecimal 介绍

public class main {
    
    public static void main(String[] args) {
    
        System.out.println(0.09+0.01);
        System.out.println(0.216-0.1);
        System.out.println(0.22*0.1);
        System.out.println(0.09/0.1);
//        0.09999999999999999
//        0.11599999999999999
//        0.022000000000000002
//        0.8999999999999999
    }
}

发现一个问题,不是我们现实的计算结果 计算机结果不精确。
由于存储都是二进制存储,
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
BigDecima的作用

  • 用于小数的精确计算
  • 用来表示很大的小数

在这里插入图片描述

2.5.6 BigDecimal 介绍

import java.math.BigDecimal;

public class main {
    
    public static void main(String[] args) {
    
        //1.通过传递double类型的小数来创建对象
        BigDecimal bd1 = new BigDecimal(0.01);
        BigDecimal bd2 = new BigDecimal(0.09);

        System.out.println(bd1);//0.01000000000000000020816681711721685132943093776702880859375
        System.out.println(bd2);//0.0899999999999999966693309261245303787291049957275390625

        //这种方式不精确

        //2.通过传递字符串表示的小数来创建对象
        BigDecimal bd3 = new BigDecimal("0.01");
        BigDecimal bd4 = new BigDecimal("0.09");

        System.out.println(bd3);//0.01
        System.out.println(bd4);//0.09

        //3.通过静态方法获取对象
        BigDecimal bd6 = BigDecimal.valueOf(10);
        System.out.println(bd6);//10

        //1.如果要表示的数字不大,没有超过double的取值范围
        //2.如果要表示的数字比较大,超出了double的取值范围,建议使用构造方法
        //3.如果我们传递的是0~10之间的整数,包含0,包含10,那么方法会返回已经创建好的对象,不会重新new
        

    }
}

在这里插入图片描述

import java.math.BigDecimal;

public class main {
    
    public static void main(String[] args) {
    
        //1.加法
        BigDecimal bd1 = BigDecimal.valueOf(10.0);
        BigDecimal bd2 = BigDecimal.valueOf(3.0);
        BigDecimal bd3 = bd1.add(bd2);
        System.out.println(bd3);//13.0
        //2.减法
        BigDecimal bd4 = bd1.subtract(bd2);
        System.out.println(bd4);//7.0
        //3.乘法
        BigDecimal bd5 = bd1.multiply(bd2);
        System. out. println(bd5);//30.00
        //4.除法
        BigDecimal bd6 = bd1.divide(bd2,2, BigDecimal.ROUND_HALF_UP);
        //点击ROUND_HALF_UP 然后Ctrl+b
        //BigDecimal bd6 = bd1.divide(bd2,2,RoundingMode.HALF_UP);
        System. out. println(bd6);//3.33

    }
}

在这里插入图片描述

2.5.7 BigDecimal 底层存储方式

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

2.6 正则表达式

先爽一下正则表达式
正则表达式可以校验字符串是否满足一定的规则,并用来校验数据格式的合法性。
需求:假如现在要求校验一一个qq号 码是否正确。
规则 :6位及20位之内,0不能在开头,必须全部是数字。
先使用目前所学知识完成校验需求
然后体验一下正则表达式检验。

import java.math.BigDecimal;

public class main {
    
    public static void main(String[] args) {
    
        String  qq = "1234868790";
        System.out.println(checkQQ(qq));
    }
    public static boolean checkQQ(String qq){
    
        int len = qq.length();
        if(len <6|| len >20) {
    return false;}
        if(qq.charAt(0) == '0'){
    return false;}
        for (int i = 0; i < len; i++) {
    
            char c= qq.charAt(i);
            if(c <'0'||c >'9') return false;
        }

        return true;
    }
}

正则表达式:

public class main {
    
    public static void main(String[] args) {
    
        String  qq = "1234868790";
        System.out.println(qq.matches("[1-9]\\d{5,19}"));
    }
}

//校验用户名是否满足规则
//校验密码是否满足规则
//校验身份证是否满足规则
//校验手机是否满足规则

正则表达式的作用
作用一:校验字符串是否满足规则
作用二:在一段文本中查找满足要求的内容

在这里插入图片描述

2.6.1 正则表达式——字符类

import java.math.BigDecimal;

public class main {
    
    public static void main(String[] args) {
    
        //只能是a b c
        System.out.println("---------1------------");
        System.out.println("a" .matches("[abc]")); // true
        System.out.println("z" .matches("[abc]")); // false
        System.out.println("ab".matches("[abc]")); // false  大括号中只能出现一个
        System.out.println("ab".matches("[abc][abc]")); //true

        //不能出现a b c
        System.out.println("-------------2-----------");
        System.out.println("a" .matches("[^abc]")); // false
        System.out.println("z" .matches("[^abc]")); // true
        System.out.println("zz".matches("[^abc]")); //false
        System.out.println("zz".matches("[^abc][^abc]")); //true


        //a到z A到Z (包括头尾的范围)
        System.out.println("-----------3-----------");
        System.out.println("a" .matches("[a-zA-z]")); // true
        System.out.println("z" .matches("[a-zA-Z]")); // true
        System.out.println("aa".matches("[a-zA-Z]")); //false
        System.out.println("zz".matches("[a-zA-Z]")); //false
        System.out.println("0" .matches("[a-zA-Z]")); //false

        // [a-d[m-p]]   a到d,或m到p
        System. out . println("----------4-------------");
        System . out .println("a".matches("[a-d[m-p]]")); //true
        System. out . println("d".matches("[a-d[m-p]]")); //true
        System. out . println("m".matches("[a-d[m-p]]")); //true
        System. out . println("p".matches("[a-d[m-p]]")); //true
        System. out . println("e".matches("[a-d[m-p]]")); //false
        System. out . println("0".matches("[a-d[m-p]]")); //false

        // [a-z&&[def]]  a-z和def的交集。为: d, e, f
        System.out.println("------------5-----------");

        System.out.println("&".matches("[a-z&[def]]")); //true
        //细节:如果要求两个范围的交集,那么需要写符号&&
        //如果写成了一个&,那么此时&表示就不是交集了,而是一个简简单单的&符号
        System.out.println("a".matches("[a-z&&[def]]")); //false
        System.out.println("d".matches("[a-z&&[def]]")); //true
        System.out.println("0".matches("[a-z&&[def]]")); //false

        // [a-z&&[^bc]]  a-z和非bc的交集。(等同于[ad-z])
        System.out.println("----------6---------");
        System.out.println("a".matches("[a-z&&[^bc]]")); //true
        System.out.println("b".matches("[a-z&&[^bc]]")); //false
        System.out.println("0".matches("[a-z&&[^bc]]")); //false

        // [a-z&&[^m-p]] a到z和除了m到p的交集。 (等同于[a-lq-z])
        System .out.println("-----------7-------------");
        System. out.println("a". matches("[a-z&&[^m-p]]")); //true
        System .out.println( "m".matches("[a-z&&[^m-p]]")); //false
        System. out.println( "0".matches("[a-z&&[^m-p]]")); //false
    }
}

2.6.2 正则表达式——预定义

在这里插入图片描述

import java.math.BigDecimal;

public class main {
    
    public static void main(String[] args) {
    
        //     \    转义字符     改变后面那个字符原本的含义
        //练习:以字符串的形式打印一个双引号


        // .表示任意一个字符
        System. out. println("-------------------------");
        System. out. println("你". matches( "..")); //false
        System. out. println("你a".matches( ".."));//true
        // \\d只能是任意的一位数字
        //简单来记:两个\表示一个\
        System. out. println("-------------------------");
        System. out. println("a".  matches("\\d")); // false
        System. out. println("3" . matches("\\d")); // true
        System. out. println("333".matches("\\d")); // false
        // \\w只能是一位单词字符[a-zA-Z_0-9]
        System. out. println("-------------------------");
        System. out. println("z" .matches( "\\w")); // true
        System. out. println("2" .matches( "\\w")); // true
        System. out. println("21".matches( "\\w")); // false
        System .out. println("你".matches( "\\w")); //false
        //非单词字符
        System. out. println("-------------------------");
        System .out.println("你" .matches("\\W")); // true
        System. out. println("-------------------------");
        // 以上正则匹配只能校验单个字符。

        //必须是数字字母下划线至少6位
        System. out. println("2442fsfsf".matches("\\w{6,}" ));//true
        System .out .println( "244f" . matches( "\\W{6,}"));//false
        // 必须是数字和字符 必须是4位
        System. out. println("-------------------------");
        System. out .println( "23dF" .matches("[a-zA-Z0-9]{4}"));//true
        System .out. println("23_ F" .matches("[a-zA-Z0-9]{4}"));//false
        System. out .println( "23dF" .matches("[\\w&&[^_]]{4}"));//true
        System .out .println("23_ F". matches("[\\w&&[^_]]{4}"));//false
    }
}

在这里插入图片描述

2.6.3 正则表达式练习

需求:
请编写正则表达式验证用户输入的手机号码是否满足要求。
请编写正则表达式验证用户输入的邮箱号是否满足要求。
请编写正则表达式验证用户输入的电话号码是否满足要求。

public class main {
    
    public static void main(String[] args) {
    
        //心得:
        //拿着一个正确的数据,从左到右依次去写。

        //分成三部分:
        //第一部分: 1表示手机号码只能以1开头
        //第二部分: [3-9] 表示手机号码第二位只能是3-9之间的
        //第三部分: \\d{9} 表示任意数字可以出现9次,也只能出现9次
        String regex1 = "1[3-9]\\d{9}";
        System. out. println("13112345678" . matches (regex1));//true
        System. out. println( "13712345667" . matches(regex1));//true
        System. out. println( "13945679027" . matches(regex1));//true
        System. out. println( "139456790271" . matches(regex1));//false

    }
}

public class main {
    
    public static void main(String[] args) {
    
        //座机电话号码
        //020-2324242 02122442 027-42424 0712-3242434
        //思路:
        //在书写座机号正则的时候需要把正确的数据分为三部分
        //-:区号0\\d{2,3}
        //   0:表示区号一定是以e开头的
        //   \\d{2,3}:表示区号从第二位开始可以是任意的数字,可以出现2到3次。
        //二: -?表示次数,e次或一次
        //三: 号码号码的第 一位也不能以e开头, 从第二位开始可以是任意的数字,号码的总长度: 5-19位
        String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
        System.out.println("020-2324242" . matches(regex2));//true
        System.out.println("02122442" . matches (regex2));//true
        System.out.println("027-42424" . matches (regex2));//true
        System.out.println("0712-3242434" .matches (regex2));//true

    }
}

public class main {
    
    public static void main(String[] args) {
    
        //邮箱号码
        //3232323@qq. com [email protected] d1ei0009@163. com d1ei0009@pci. com.cn
        //思路:
        //在书写邮箱号码正则的时候需要把正确的数据分为三部分
        //第一部分: @的左边\\W+
        //      任意的字母数字下划线,至少出现一次就可以了
        //第二部分: @只能出现一次
        //第三部分:
        //  3.1     .的左边[\\w&&[^_]]{2,6}
        //  任意的字母加数字,总共出现2-6次(此时不能出现下划线)
        // 3.2      .   \\.
        //大写字母,小写字母都可以,只能出现2-3次[a-zA-Z]{2,3}
        //我们可以把3.2和3.3看成一组,这一组可以出现1次或者两次
        String regex3 = "\\w+@[\\w&&[^_ ]]{2,6}(\\.[a-zA-z]{2,3}){1,2}";
        System . out. println("[email protected]" . matches (regex3));
        System . out. println("[email protected]" . matches (regex3));
        System. out . println("[email protected]" . matches(regex3));
        System. out . println("[email protected]" . matches(regex3));


    }
}

下载anyrule 不用自己写了
在这里插入图片描述
在这里插入图片描述

2.6.4 爬虫

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class main {
    
    public static void main(String[] args) {
    
        String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11, " +
                "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";

        //1.获取正则表达式的对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //2.获取文本匹配器的对象
        //拿着m去读取str,找符合p规则的子串
        Matcher m = p.matcher(str);
        //3.利用循环获取
        while(m. find()) {
    
            String s = m.group();
            System.out.println(s);
        }

    }
}

在这里插入图片描述

2.7 JDK7时间

2.7.1 Date时间

全世界的时间,有一个统一的计算标准——格林尼治时间/格林威治时间(Greenwich Mean Time)简称GMT
计算核心:地球自转一天是24小时,太阳直射时为正午12点

全世界的时间,有一个统一的计算标准——原子钟
利用铯原子的震动的频率计算出来的时间,作为世界标准时间(UTC)。

Date类是一个JDK写好的Javabean类,用来描述时间,精确到毫秒。

  • 利用空参构造创建的对象,默认表示系统当前时间。

  • 利用有参构造创建的对象,表示指定的时间。

public Date( ) 创建Date对象,表示当前时间
public Date(long date) 创建Date对象,表示指定时间
public void setTime(long time) 设置/修改亳秒值
public long getTime( ) 获取时间对象的毫秒值

学会掌握上述方法

import java.util.Date;

public class main {
    
    public static void main(String[] args) {
    
        Date d1 = new Date(0L);
        Long time = d1.getTime();
        time  = time+ 1000L*60*60*24*365;
        d1.setTime(time);
        System.out.println(d1);
    }
}

比较两个时间谁在前

import java.text.SimpleDateFormat;
import java.util.Date;
public class main {
    
    public static void main(String[] args) {
    
        SimpleDateFormat sdf1 = new SimpleDateFormat();
        Date d1 = new Date(0L);
        String str1 = sdf1.format(d1);
        System.out.println(str1);//1970/1/1 08:00

        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String str2 = sdf2.format(d1);
        System.out.println(str2);//1970年01月01日 08:00:00
    }
}

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class main {
    
    public static void main(String[] args) throws ParseException {
    
        String str = "2222-02-22 02:22:22";
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sdf1.parse(str);
        System.out.println(date);//Fri Feb 22 02:22:22 GMT+08:00 2222

    }
}

2.7.3 Calendar日历

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

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

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class main {
    
    public static void main(String[] args) throws ParseException {
    
        //1.获取日历对象
        //细:1: Calendar是一个抽象类,不能直接new,而是通过一个静态方法获取到子类对象
        //底层原理:
        //会根据系统的不同时区来获取不同的日历对象,默认表示当前时间。
        //把会把时间中的纪元,年,月,日,时,分,秒,星期,等等的都放到一个数组当中
        //细节2:11月份:范围0~11  如果获取出来的是0.那么实际上是1月。
        //星期:在老外的眼里,星期日是一周中的第- -天.
        //1 (星期日) 2 (星期一)3 (星期二)4 (星期三)5 (星期四)6 (星期五)7 (星期六)
        Calendar c= Calendar.getInstance();
        Date d = new Date(0L);
        c.setTime(d);
        System.out.println(c);

        int year = c.get(1);
        int month = c.get(2) + 1;
        int date = c.get(5);
        System. out. println(year + "," + month + "," + date);//1970, 1,1


    }
}

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

2.8 JDK8时间

JDK8新增时间相关类
ZoneId:时区
Instant:时间戳
ZoneDateTime:带时区的时间
DateTimeFormatter用于时间的格式化和解析
LocalDate:年、月、日
LocalTime:时、分、秒
LocalDateTime:年、月、日、时、分、秒
Duration:时间间隔(秒,纳秒)
Period:时间间隔(年, 月,日)
ChronoUnit:时间间隔( 所有单位)
在这里插入图片描述

2.9 包装类

在这里插入图片描述

包装类:用一个对象,把基本数据类型给包起来
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


public class main {
    
    public static void main(String[] args) {
    
        //二进制
        String str1 = Integer.toBinaryString(123);
        System.out.println(str1);
        //八进制
        String str2 = Integer.toOctalString(123);
        System.out.println(str2);
        //十六进制
        String str3 = Integer.toHexString(123);
        System.out.println(str3);
//        1111011
//        173
//        7b
    }
}

import java.util.Scanner;
public class main {
    
    public static void main(String[] args) {
    
        //键盘录入
        Scanner sc = new Scanner(System.in);
        System. out. println("请输入一个字符串");
        /* String str = sc.next();
        System. out. print1n(str);*/
        //弊端:
        //当我们在使用next,nextInt, nextDouble在接收数据的时候,遇到空格,回车,制表符的时候就停止了
        //键盘录入的是123123那么此时只能接收到空格前面的数据
        //我想要的是接收- -整行数据
        //约定:
        //以后我们如果想要键盘录入,不管什么类型,统一使用nextLine
        //特点遇到回车才停止
        String str = sc.nextLine();
        System.out.println(str);

    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_46225503/article/details/129801868

智能推荐

基于STM32的web+app的智慧灌溉系统物联网嵌入式软硬件开发单片机毕业源码案例设计-程序员宅基地

文章浏览阅读217次。5.配有基于SpringBoot、Vue、uniapp、Qt的Web端、移动端、PC端,远程控制,远程查看数据。6.云平台具有设备管理、数据管理等完整的功能。4.远程设置光照强度和土壤湿度的阈值。2.湿度太干时自动打开水泵进行浇水。1.实时监测光照强度、土壤湿度。基于STM32的智慧灌溉系统。3.光照太暗时自动开灯补光。5.通信基于MQTT协议。

bat批量复制文件(一键打包更新代码,避免手动一个个复制)-程序员宅基地

文章浏览阅读357次,点赞3次,收藏9次。如果文件夹不存在,也可以复制过去。复制文件夹用copy,复制目录和里面的文件用xcopy命令: xcopy/y /e /s /i /k源文件夹路径 目标文件夹路径@echo offChcp 65001echo -----copy start-----echo -----copy cssxcopy /y /e /s /i /k D:\crd\cms\workspace\cms..._bat批量复制文件

深度学习——BEDSR-Net_bedsr-net a deep shadow removal network from a sin-程序员宅基地

文章浏览阅读1.3k次,点赞3次,收藏9次。CVPR2020原论文:BEDSR-Net: A Deep Shadow Removal Network from a Single Document Image为了便捷记录文件内容,我们通常直接用手机或相机拍摄文件。由于环境光照的影响,拍摄的图像会产生各种阴影。就文件图像阴影的问题,文章提出了深度学习的方法去阴影。如下图:1.主要工作:首先提出了单幅文件图像去阴影的深度学习网络(Background Estimation Document Shadow Removal Network ,BEDSR_bedsr-net a deep shadow removal network from a single document image

《EROFS: A Compression-friendly Readonly File System for Resource-scarce Devices》_erofs 论文-程序员宅基地

这篇文章介绍了一种面向资源稀缺设备的压缩友好的只读文件系统EROFS,能显著减少存储空间使用,减少I/O放大和计算开销,并降低内存分配开销。

python计算机视觉编程——sift特征提取和ransac减少错配_python实现sift特征匹配及ransca误匹配剔除-程序员宅基地

文章浏览阅读5.8k次,点赞8次,收藏100次。SIFT算法运用演示一、什么是sift算法SIFT,即尺度不变特征变换(Scale-invariant feature transform,SIFT),是用于图像处理领域的一种描述。这种描述具有尺度不变性,可在图像中检测出关键点,是一种局部特征描述子。它是由David Lowe发明的。SIFT在2004年由Lowe完善并经受住了时间的考验。SIFT特征是基于物体上的一些局部外观的兴趣点而与影..._python实现sift特征匹配及ransca误匹配剔除

Visual Studio Code有哪些你常用的插件?_类似beautify插件-程序员宅基地

文章浏览阅读7.5k次。Java自学的网站(Java全栈工程师 | 以实例驱动学习 | how2j.cn)仅供参考:beautify,这款类似于vscode里格式化代码的功能,不错;Emoji,很好玩的一款插件,可以在代码中插入emoji了,也许是程序猿的娱乐方式吧;HTML Snippets,这款插件包含html标签,非常全,很实用;Can I Use,自动检测所写代码能否在相应容器正常编译执行;Java..._类似beautify插件

随便推点

大电流dcdc降压芯片20a_基于MC34063芯片DC-DC(20-5)降压型变换电路-程序员宅基地

文章浏览阅读1.4k次。目录基于MC34063芯片的DC-DC(20/5)降压型变换电路.................................................................21引言......................................................................................................_dc电源芯片 20a

About Add DataRow-程序员宅基地

文章浏览阅读128次。当从一个表中将记录Copy到另一个结构相同的表中的时候,有两种方式:DataTable.ImportRow()或: DataTable.Rows.Add()正确的使用方法: dt1.ImportRow(dt.Rows[0]);或: dt1.Rows.Add(dt.Rows[0].ItemArray);不要使用:..._add data row

linux中-f的含义,linux 下shell中if的“-e,-d,-f”的含义-程序员宅基地

文章浏览阅读1.5w次,点赞4次,收藏55次。文件表达式-e filename 如果 filename存在,则为真-d filename 如果 filename为目录,则为真-f filename 如果 filename为常规文件,则为真-L filename 如果 filename为符号链接,则为真-r filename 如果 filename可读,则为真-w filename 如果 filename可写,则为真-x filename 如果..._-f

【JS】根据日期和给定的天数,计算日期的前几天或者后几天的日期时间_js计算某个日期多少天后的日期-程序员宅基地

文章浏览阅读301次。【代码】【JS】根据日期和给定的天数,计算日期的前几天或者后几天的日期时间。_js计算某个日期多少天后的日期

WebRTC-Android 源码导读(二):预览实现分析_surfaceviewrenderer-程序员宅基地

文章浏览阅读2.4k次,点赞2次,收藏5次。在本系列第一篇中,我们分析了 WebRTC-Android 相机采集的实现,本文中我们将分析预览的实现。有过一定相机开发经验的朋友可能会疑惑,预览还有什么好分析的,不是直接 camera.setPreviewDisplay 或者 camera.setPreviewTexture 就能在 SurfaceView/TextureView上预览了吗?实际上预览还有更高级的玩法,尤其是需要加上图像处理功能..._surfaceviewrenderer

Easyx-----c语言实现斗地主_easyx制作打牌-程序员宅基地

文章浏览阅读2.7k次,点赞28次,收藏88次。tools.hpp源.cpp_easyx制作打牌