黑马程序员Java零基础视频教程_上部(P129-P176)
- 1. 面向对象进阶
- 1.1 认识多态
- 1.2 多态的优势与劣势
- 1.3 多态的综合练习
- 1.4 包、final、权限修饰符、代码块
- 1.5 抽象类与抽象方法
- 1.6 接口
- 1.6.1 接口与抽象类的综合练习
- 1.6.2 接口多学三招
- 1.7 内部类
- 1.8 拼图小游戏
- 2. 常用API
- 2.1 Math
- 2.2 System
- 2.3 Runtime
- 2.4 Object和Objects
- 2.4.1 toString()
- 2.4.2 equals
- 2.4.3 Clone
- 2.5 BigInteger和BigDecimal
- 2.5.1 BigInteger 介绍
- 2.5.2 BigInteger 构造方法
- 2.5.3 BigInteger 成员方法
- 2.5.4 BigInteger 底层存储方式
- 2.5.5 BigDecimal 介绍
- 2.5.6 BigDecimal 介绍
- 2.5.7 BigDecimal 底层存储方式
- 2.6 正则表达式
- 2.6.1 正则表达式——字符类
- 2.6.2 正则表达式——预定义
- 2.6.3 正则表达式练习
- 2.6.4 爬虫
- 2.7 JDK7时间
- 2.7.1 Date时间
- 2.7.3 Calendar日历
- 2.8 JDK8时间
- 2.9 包装类
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{
@Override
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 多态的优势与劣势
优势:
- 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
- 定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。
弊端:
- 不能调用子类的特有功能
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 外部类名.内部类名();
调用非静态方法的格式:先创建对象,用对象调用
调用静态方法的格式: 外部类名.内部类名.方法名();
局部内部类
- 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
- 外界是无法直接使用,需要在方法内部创建对象并使用。
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
匿名内部类
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图形化界面,但是为了前面的知识点相结合,我们做一个小游戏。
大家可以看着 这个大牛的博客:
2. 常用API
2.1 Math
- Math:帮助我们进行数学计算的工具类
- 里面的方法都是静态的。
判断质数
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]+" ");
}
}
}
- 如果数据源数组和月的地数组都是基本数据类型,那么两者的类型必须保持一致, 否则会报错
- 在拷贝的时候需要考虑数组的长度,如果超出范围也会报错
- 如果数据源数组和目的地数组都是引用数据类型,那么子类类型可以赋值给父类类型
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 zhangsan@itcast.cnn 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("3232323@qq.com" . matches (regex3));
System . out. println("zhangsan@itcast.cnn" . matches (regex3));
System. out . println("d1ei0009@163.com" . matches(regex3));
System. out . println("d1ei0009@pci.com.cn" . 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);
}
}