包
什么是包?
-
包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护。
-
建包的语法格式:package 公司域名倒写.技术名称。报名建议全部英文小写,且具备意义。
package com.itheima.javabean; public class Student { }
-
建包语句必须在第一行,一般IDEA工具会帮助创建
导包
-
相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!导包格式:import 包名.类名;
-
假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
权限修饰符
什么是权限修饰符?
-
权限修饰符:是用来控制一个成员能够被访问的范围的。
-
可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能够被访问的范围将受到限制。
权限修饰符的分类和具体作用范围:
-
权限修饰符:有四种作用范围由小到大(private -> 缺省 -> protected - > public )
正在上传…重新上传取消
学完权限修饰符需要具备如下能力
-
能够识别别人定义的成员的访问权限。
-
自己定义成员(方法,成员变量,构造器等)一般满足如下要求:
-
成员变量一般私有。
b. 方法一般公开。
c. 如果该成员只希望本类访问,使用private修饰。
d. 如果该成员只希望本类,同一个包下的其他类和子类访问,使用protected修饰。
-
final
final的作用
final 关键字是最终的意思,可以修饰(方法,变量,类)
修饰方法:表明该方法是最终方法,不能被重写。
修饰变量:表示该变量第一次赋值后,不能再次被赋值(有且仅能被赋值一次)。
修饰类:表明该类是最终类,不能被继承。
final修饰变量的注意
-
final修饰的变量是基本类型:那么变量存储的**数据值**不能发生改变。
-
final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
常量
常量概述和基本作用
常量
-
常量是使用了public static final修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变。
-
常量的作用和好处:可以用于做系统的配置信息,方便程序的维护,同时也能提高可读性。
常量命名规范:英文单词全部大写,多个单词下划线连接起来。
public class Constant { public static final String SCHOOL_NAME = “传智教育"; public static final String LOGIN_NAME = “admin"; public static final String PASS_WORD = “123456"; }
常量的执行原理
-
在编译阶段会进行“宏替换”,把使用常量的地方全部替换成真实的字面量。
-
这样做的好处是让使用常量的程序的执行性能与直接使用字面量是一样的。
常量做信息标志和分类
现在开发的超级玛丽游戏需要接收用户输入的四个方向的信号(上下左右),以便控制玛丽移动的方向。
选择常量做信息标志和分类: 代码可读性好,实现了软编码形式。
枚举
枚举的概述
枚举的概述
-
枚举是Java中的一种特殊类型
-
枚举的作用:"是为了做信息的标志和信息的分类"。
定义枚举类的格式:
修饰符 enum 枚举名称{ 第一行都是罗列枚举类实例的名称。 }
enum Season{ SPRING , SUMMER , AUTUMN , WINTER; }
枚举的特征
-
枚举类都是继承了枚举类型:java.lang.Enum
-
枚举都是最终类,不可以被继承。
-
构造器都是私有的,枚举对外不能创建对象。
-
枚举类的第一行默认都是罗列枚举对象的名称的。
-
枚举类相当于是多例模式。
-
枚举的使用场景演示
案例说明: 现在开发的超级玛丽游戏需要接收用户输入的四个方向的信号(上下左右),以便控制玛丽移动的方向。
选择常量做信息标志和分类: 虽然可以实现可读性,但是入参值不受约束,代码相对不够严谨。
枚举做信息标志和分类: 代码可读性好,入参约束严谨,代码优雅,是最好的信息分类技术!建议使用!
抽象类
抽象类概述
-在Java中abstract是抽象的意思,如果一个类中的某个方法的具体实现不能确定,就可以申明成abstract修饰的抽象方法(不能写方法体了),这个类必须用abstract修饰,被称为抽象类。
修饰符 abstract 返回值类型 方法名称(形参列表);
修饰符 abstract class 类名{ }
public abstract class Animal{ public abstract void run(); }
抽象的使用总结与注意事项
-
抽象类可以理解成类的不完整设计图,是用来被子类继承的。
-
一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
总结
1、抽象类的作用是什么样的? 可以被子类继承、充当模板的、同时也可以提高代码复用。 2、抽象方法是什么样的? 只有方法签名,没有方法体,使用了abstract修饰。 3、继承抽象类有哪些要注意? 一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法。 否则这个类也必须定义成抽象类。
抽象类的案例
系统需求 某加油站推出了2种支付卡,一种是预存10000的金卡,后续加油享受8折优惠,另一种是预存5000的银卡 ,后续加油享受8.5折优惠。 请分别实现2种卡片进入收银系统后的逻辑,卡片需要包含主人名称,余额,支付功能。
分析实现 创建一张卡片父类:定义属性包括主人名称、余额、支付功能(具体实现交给子类) 创建一张白金卡类:重写支付功能,按照原价的8折计算输出。 创建一张银卡类:重写支付功能,按照原价的8.5折计算输出。
package com.itheima.d7_abstract_test; public abstract class Card { private String userName; private double money; //定义一个支付方法,表示卡片可以支付。 //抽象方法 public abstract void pay(double money); public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public double getMoney() { return money; } public void setMoney(double money) { this.money = money; } }
package com.itheima.d7_abstract_test; public class GoldCard extends Card { @Override public void pay(double money2) { System.out.println("您当前消费:"+money2); System.out.println("您当前余额:"+getMoney()); //优惠价 double rs=money2*0.8; System.out.println("您实际支付:"+rs); //更新账户余额 setMoney(getMoney()-rs); } }
package com.itheima.d7_abstract_test; public class Test { public static void main(String[] args) { //学习抽象类的基本使用,做父类,被继承,重写抽象方法 GoldCard c=new GoldCard(); c.setMoney(10000); c.setUserName("贾明超"); c.pay(300); System.out.println("剩余:"+c.getMoney()); } }
抽象类的特征、注意事项
特征和注意事项
-
有得有失: 得到了抽象方法,失去了创建对象的能力。
-
抽象类为什么不能创建对象?
-
类有的成员(成员变量、方法、构造器)抽象类都具备
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必
须定义成抽象类。
-
不能用abstract修饰变量、代码块、构造器。
final和abstract是什么关系?
-
互斥关系
-
abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
-
抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
-
抽象类的应用知识:模板方法模式
-
使用场景说明:当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候。
使用步骤
-
把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码。
-
模板方法中不能决定的功能定义成抽象方法让具体子类去实现。
package com.itheima.d9_abstract_template; public abstract class Student { //正式声明了模板方法模式 public final void write(){//防止子类重写以防改模板 System.out.println("\t\t\t\t我的爸爸"); System.out.println("你的爸爸是啥样"); //正文(每个子类都要写的,每个子类写的情况不一样) //因此,模板方法把正文部分定义成抽象方法,交给具体的子类来完成 System.out.println(writeMain());//就近选择子类重写的方法 System.out.println("我的爸爸简直太好了"); } public abstract String writeMain(); }
package com.itheima.d9_abstract_template; public class StudentChild extends Student { @Override public String writeMain() { return"我的爸爸太牛了"; } }
package com.itheima.d9_abstract_template; public class StudentMiddle extends Student{ @Override public String writeMain() { return "我的爸爸也很牛"; } }
package com.itheima.d9_abstract_template; public class Test { public static void main(String[] args) { //模板方法模式思想和使用步骤。 //写作文,中学生和小学生都写《我的爸爸》,开头结尾固定,正文自由发挥。 StudentMiddle s=new StudentMiddle(); s.write(); StudentChild s2=new StudentChild(); s2.write(); } }
模板方法我们是建议使用final修饰的,这样会更专业**
总结
-
模板方法模式解决了什么问题?
-
极大的提高了代码的复用性
-
模板方法已经定义了通用结构,模板不能确定的定义成抽象方法。
-
使用者只需要关心自己需要实现的功能即可。
-
-
-
接口
接口概述、特点
接口的定义与特点
-
接口的格式如下:
接口用关键字interface来定义 public interface 接口名 { // 常量 // 抽象方法 }
-
JDK8之前接口中只能是抽象方法和常量,没有其他成分了。
-
接口不能实例化。
-
接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化。
package com.itheima.d10_interface; //声明的接口:体现了一种规范,规范一定是公开的。 public interface InterfaceDome { //接口中的成分特点:JDK8之前接口中只有抽象方法和常量 //1.常量 // public static final String SCHOOL_NAME="黑马程序员"; String SCHOOL_NAME="黑马程序员"; //2.抽象方法 //注意:由于接口体现规范思想,规范默认都是公开的,所以代码层面,public abstract可以省略不写。 // public abstract void run(); void run(); }
接口的基本使用:被实现
接口的用法:
-
接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类。
修饰符 class 实现类 implements 接口1, 接口2, 接口3 , ... { } 实现的关键字:implements
从上面可以看出,接口可以被类单实现,也可以被类多实现。
接口实现的注意事项:
-
一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
package com.itheima.d11_implements; public interface Law { void rule(); }
package com.itheima.d11_implements; public interface SportMan { void run(); void competition(); }
package com.itheima.d11_implements; public class PingpongMan implements SportMan,Law{ private String name; public PingpongMan(String name) { this.name = name; } @Override public void run() { System.out.println(name+"必须训练"); } @Override public void competition() { System.out.println(name+"必须参加比赛"); } @Override public void rule() { } }
package com.itheima.d11_implements; public class Test { public static void main(String[] args) { //理解接口的基本使用,被类实现。 PingpongMan p=new PingpongMan("张继科"); p.run(); p.competition(); p.rule(); } }
接口与接口的关系:多继承
基本小结
-
类和类的关系:单继承。
-
类和接口的关系:多实现。
-
接口和接口的关系:多继承,一个接口可以同时继承多个接口。
接口多继承的作用
规范合并,整合多个接口为同一个接口,便于子类实现。
JDK8开始接口新增方法
允许接口中直接定义带有方法体的方法
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
总结
-
JDK8开始后新增了那些方法?
-
默认方法:default修饰,实现类对象调用。
-
静态方法:static修饰,必须用当前接口名调用
-
私有方法:private修饰,jdk9开始才有的,只能在接口内部被调用。 他们都会默认被public修饰。
使用接口的注意事项
1、接口不能创建对象 2、一个类实现多个接口,多个接口中有同样的静态方法不冲突。 3、一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。 4、一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可。 5、一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。
面向对象三大特征之三:多态
多态的概述,多态的形式
什么是多态?
-
同类型的对象,执行同一个行为,会表现出不同的行为特征。
多态的常见形式
父类类型 对象名称 = new 子类构造器; 接口 对象名称 = new 实现类构造器;
多态中成员访问特点
-
方法调用:编译看左边,运行看右边。
-
变量调用:编译看左边,运行也看左边。(多态侧重行为多态)
多态的前提
有继承/实现关系;有父类引用指向子类对象;有方法重写。
package com.itheima.d1_polymorphic; public abstract class Animal { public String name="父类动物"; public abstract void run(); }
package com.itheima.d1_polymorphic; public class Dog extends Animal{ public String name="子类狗"; @Override public void run() { System.out.println("狗跑的贼快"); } }
package com.itheima.d1_polymorphic; public class Tortoise extends Animal{ public String name="子类乌龟"; @Override public void run() { System.out.println("乌龟根本不会跑"); } }
package com.itheima.d1_polymorphic; public class Test { public static void main(String[] args) { //1.多态的形式: Animal a=new Dog(); a.run();//方法调用:编译看左边,运行看右边 System.out.println(a.name);//变量调用:编译运行都看左 Animal a2=new Tortoise(); a2.run(); System.out.println(a2.name);//父类动物 } }
多态的好处
优势
在多态形式下,右边对象可以实现解耦合,便于扩展和维护。 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
Animal a = new Dog(); a.run(); // 后续业务行为随对象而变,后续代码无需修改
多态下会产生的一个问题:
多态下不能使用子类的独有功能
多态下引用数据类型的类型转换
自动类型转换(从子到父):
-
子类对象赋值给父类类型的变量指向。
强制类型转换吗(从父到子)
-
此时必须进行强制类型转换:子类 对象变量 = (子类)父类类型的变量 作用:可以解决多态下的劣势,可以实现调用子类独有的功能。
-
注意: 如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException
-
Java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换
变量名 instanceof 真实类型 判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之。
package com.itheima.d3_polymorphic_convert.d1_polymorphic; public abstract class Animal { public String name="父类动物"; public abstract void run(); }
package com.itheima.d3_polymorphic_convert.d1_polymorphic; public class Dog extends Animal { public String name="子类狗"; @Override public void run() {System.out.println("狗跑的贼快");} //独有功能 public void lookDoor(){ System.out.println("狗在看门"); } }
package com.itheima.d3_polymorphic_convert.d1_polymorphic; public class Tortoise extends Animal { public String name="子类乌龟"; @Override public void run() { System.out.println("乌龟根本不会跑"); } public void leyEggs(){ System.out.println("乌龟会下蛋"); } }
package com.itheima.d3_polymorphic_convert.d1_polymorphic; public class Test { public static void main(String[] args) { //自动类型转换 Animal a=new Dog(); a.run(); //强制类型转换 Animal a2=new Tortoise(); a2.run(); // Dog d= (Dog) a2;//强制类型转换,编译阶段不报错。(注意:有继承或者实现关系编译阶段可以强转。运行时可能出错) if(a2 instanceof Tortoise){ Tortoise t= (Tortoise) a2; t.leyEggs(); }else if(a2 instanceof Dog){ Dog d=new Dog(); d.lookDoor(); } System.out.println("............................"); go(new Dog()); go(new Tortoise()); } public static void go(Animal a){ a.run(); //不知道a是狗还是乌龟 if(a instanceof Tortoise){ Tortoise t= (Tortoise) a; t.leyEggs(); }else if(a instanceof Dog){ Dog d= (Dog) a; d.lookDoor(); } } }
总结
-
引用数据类型的类型转换,有几种方式? 自动类型转换、强制类型转换。
-
强制类型转换能解决什么问题?强制类型转换需要注意什么。
a. 可以转换成真正的子类类型,从而调用子类独有功能。
b.有继承关系/实现的2个类型就可以进行强制转换,编译无问题。 c.运行时,如果发现强制转换后的类型不是对象真实类型则报错。 类型转换异常:ClassCastException
多态的综合案例
需求: 使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备 鼠标:被安装时可以完成接入、调用点击功能、拔出功能。 键盘:被安装时可以完成接入、调用打字功能、拔出功能。 分析 定义一个USB的接口(申明USB设备的规范必须是:可以接入和拔出)。 提供2个USB实现类代表鼠标和键盘,让其实现USB接口,并分别定义独有功能。 创建电脑对象,创建2个USB实现类对象,分别安装到电脑中并触发功能的执行。
package com.itheima.d4_polymorphic_test; public class Computer { private String name; public Computer(String name) { this.name = name; } public void start(){ System.out.println(name+"开机了"); } // 提供安装USB设备的入口 public void installUSB(USB usb){ //多态。父类接口作为入参。usb可能是鼠标还可能是键盘 usb.connect(); //独有功能:判断 强转 if (usb instanceof KeyBoard){ KeyBoard k= (KeyBoard) usb; k.keyDown(); }else if(usb instanceof Mouse){ Mouse m= (Mouse) usb; m.dbClick(); } usb.unconnect(); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package com.itheima.d4_polymorphic_test; //USB接口==规范 public interface USB { //接入 拔出 void connect(); void unconnect(); }
package com.itheima.d4_polymorphic_test; public class KeyBoard implements USB{ private String name; //独有功能 public void keyDown(){ System.out.println(name+"敲击了"); } public KeyBoard(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void connect() { System.out.println("成功连接了电脑"); } @Override public void unconnect() { System.out.println("成功断开了电脑"); } }
package com.itheima.d4_polymorphic_test; public class Mouse implements USB{ private String name; //独有功能 public void dbClick(){ System.out.println(name+"双击点亮小红心"); } public Mouse(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void connect() { System.out.println("成功连接了电脑"); } @Override public void unconnect() { System.out.println("成功断开了电脑"); } }
package com.itheima.d4_polymorphic_test; //定义一个USB的接口(申明USB设备的规范必须是:可以接入和拔出)。 // 提供2个USB实现类代表鼠标和键盘,让其实现USB接口,并分别定义独有功能。 // 创建电脑对象,创建2个USB实现类对象,分别安装到电脑中并触发功能的执行。 public class Test { public static void main(String[] args) { //1.创建电脑对象 Computer c=new Computer("外星人"); c.start(); //2.创建鼠标对象,键盘对象 USB u=new KeyBoard("双飞燕"); c.installUSB(u); USB u1=new Mouse("罗技鼠标"); c.installUSB(u1); } }
内部类
内部类概述
内部类
-
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。
-
public class People{ // 内部类 public class Heart{ } }
内部类的使用场景、作用
-
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。
-
内部类通常可以方便访问外部类的成员,包括私有的成员。
-
内部类提供了更好的封装性,内部类本身就可以用private protectecd等修饰,封装性可以做更多控制。
内部类的分类
-
静态内部类[了解]
-
成员内部类(非静态内部类) [了解]
-
局部内部类[了解]
-
匿名内部类(重点)
内部类之一:静态内部类[了解]
什么是静态内部类?
-
有static修饰,属于外部类本身。
-
它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。
public class Outer{ // 静态成员内部类 public static class Inner{ } }
-
静态内部类创建对象的格式:
外部类名.内部类名 对象名 = new 外部类名.内部类构造器; 范例:Outer.Inner in = new Outer.Inner();
package com.itheima.d5_innerclass_static; //外部类 public class Outer { public static int a=100; private String hobby; public static class Inner{ private String name; private int age; public static String schoolName; public Inner() { } public Inner(String name, int age) { this.name = name; this.age = age; } public void show(){ System.out.println("名称:"+name); System.out.println(a); // System.out.println(hobby); // Outer o=new Outer(); // System.out.println(o.hobby);可以直接访问外部类的静态成员,不能直接访问外部类的实例成员。 } 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 static String getSchoolName() { return schoolName; } public static void setSchoolName(String schoolName) { Inner.schoolName = schoolName; } } }
package com.itheima.d5_innerclass_static; public class Test { public static void main(String[] args) { Outer.Inner in=new Outer.Inner(); in.setName("张三");//张三 in.show();//100 } }
静态内部类的访问拓展:
1、静态内部类中是否可以直接访问外部类的静态成员? 可以,外部类的静态成员只有一份可以被共享访问。 2、静态内部类中是否可以直接访问外部类的实例成员? 不可以的,外部类的实例成员必须用外部类对象访问。
内部类之二:成员内部类[了解]
什么是成员内部类?
-
无static修饰,属于外部类的对象。
public class Outer { // 成员内部类 public class Inner { } }
-
JDK16之前,成员内部类中不能定义静态成员,JDK 16开始也可以定义静态成员了。
-
成员内部类创建对象的格式:
格式: 外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器(); 范例: Outer.Inner in = new Outer().new Inner();
成员内部类的访问扩展
1、成员内部类中是否可以直接访问外部类的静态成员? 可以,外部类的静态成员只有一份可以被共享访问。 2、成员内部类的实例方法中是否可以直接访问外部类的实例成员? 可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员
package com.itheima.d6_innerclass; //外部类 public class Outer { //成员内部类:不能加static修饰 public static int num=11; private String hobby; public Outer() { } public Outer(String hobby) { this.hobby = hobby; } public class Inner { private String name; private int age; public static int a=100;//JDK 16开始也可以定义静态成员了 public static void test(){ System.out.println(a); } public void show() { System.out.println("名称:"+name); System.out.println("数量:"+num); System.out.println("爱好:"+hobby); } 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 static int getA() { return a; } public static void setA(int a) { Inner.a = a; } } }
package com.itheima.d6_innerclass; public class Test { public static void main(String[] args) { Outer.Inner in=new Outer().new Inner(); in.setName("内部"); in.show(); Outer.Inner.test(); System.out.println("......................"); Outer.Inner in1=new Outer("爱学习").new Inner(); in1.show(); } } //名称:内部 数量:11 爱好:null 100 ...................... 名称:null 数量:11 爱好:爱学习
内部类之三:局部内部类[了解]
局部内部类 (鸡肋语法,了解即可) 局部内部类放在方法、代码块、构造器等执行体中。 局部内部类的类文件名为: 外部类$N内部类.class。
内部类之四:匿名内部类概述[重点]
匿名内部类:
本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。 作用:方便创建子类对象,最终目的为了简化代码编写。
格式:
new 类|抽象类名|或者接口名() { 重写方法; };
Animal a = new Animal() { public void run() { } }; a. run();
(可以理解为既是一个类也是一个对象)
特点总结:
-
匿名内部类是一个没有名字的内部类。
-
匿名内部类写出来就会产生一个匿名内部类的对象。
-
匿名内部类的对象类型相当于是当前new的那个的类型的子类类型。
匿名内部类常见使用形式
Test1
package com.itheima.d8_innerclass_anoymous; public class Test { public static void main(String[] args) { Animal a=new Animal() { @Override public void run() { System.out.println("老虎跑得快"); } }; a.run(); } } //class Tiger extends Animal{ // @Override // public void run() { // System.out.println("老虎跑得快"); // } //} abstract class Animal{ public abstract void run(); } 老虎跑得快
Test2
package com.itheima.d8_innerclass_anoymous; //掌握匿名内部类的使用形式(语法) public class Test2{ public static void main(String[] args) { // Swimming s=new Student(); Swimming s=new Swimming() { @Override public void swim() { System.out.println("学生自由泳"); } }; go(s); System.out.println(".................."); Swimming s1=new Swimming() { @Override public void swim() { System.out.println("老师游得贼快"); } }; go(s1); System.out.println("................."); go(new Swimming() { @Override public void swim() { System.out.println("运动员游得贼快"); } }); } //学生老师运动员可以一起参加比赛 //接口充当一种父类,所有子类都可以送进来 public static void go(Swimming s){ System.out.println("开始"); s.swim(); System.out.println("结束"); } } //class Student implements Swimming{ // @Override // public void swim() { // System.out.println("学生快乐的游泳"); // } //} //会游泳 interface Swimming{ void swim(); } 开始 学生自由泳 结束 .................. 开始 老师游得贼快 结束 ................. 开始 运动员游得贼快 结束
匿名内部类真实使用场景演示
正在上传…重新上传取消
常用API
Object
Object类的方法
-
Object类的方法是一切子类对象都可以直接使用的,所以我们要学习Object类的方法。
-
一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类。
PUBLIC STRING TOSTRING() 默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址 public boolean equals(Object o) 默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false
toString方法
问题引出
开发中直接输出对象,默认输出对象的地址其实是毫无意义的。 开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息。
toString存在的意义
父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
equals方法
问题提出
直接比较两个对象的地址是否相同完全可以用“==”替代equals。
equals存在的意义
父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则。
总结
Object的equals方法的作用是什么?
-
默认是与另一个对象比较地址是否一样
-
让子类重写,以便比较2个子类对象的内容是否相同。
package com.itheima.d9_api_object; import java.util.Objects; public class Student {//extends Object private String name; private char sex; private int age; public Student() { } public Student(String name, char sex, int age) { this.name = name; this.sex = sex; this.age = age; } 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } //重写equals,自己定制相等规则。两个对象内容一样就认为是相等的。比较者:s1==this(谁调这个方法,this就代表谁) // 被比较者:s2==>o // @Override // public boolean equals(Object o) { // //1.判断o是不是学生类型 // if (o instanceof Student) { // Student s2 = (Student) o;//强转成学生类型,才能调用学生类中的独有属性 // //2.判断两个对象内容是否一样 if (this.name.equals(s2.name) && this.age == s2.age && this.sex == s2.sex) { return true; }else{ return false; } // return this.name.equals(s2.name) && this.age == s2.age && this.sex == s2.sex; // } else { // //学生只能和学生比,否则结果一定是false // return false; // } // } @Override public boolean equals(Object o) { //1.判断是否为同一个对象比较,如果是返回true if (this == o) return true; //2.如果o==null 返回false,如果o不是学生类型返回false if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return sex == student.sex && age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, sex, age); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex=" + sex + ", age=" + age + '}'; } }
package com.itheima.d9_api_object; public class Test1 { public static void main(String[] args) { //掌握object类中toString方法的使用 Student s=new Student("贾明超",'男',19); String rs=s.toString(); System.out.println(rs); //直接输出对象变量,默认可以省略toString调用不写的 System.out.println(s); } }
package com.itheima.d9_api_object; //掌握Object类中equals方法的使用 public class Test2 { public static void main(String[] args) { Student s1=new Student("贾明超",'男',19); Student s2=new Student("贾明超",'男',19); //equals默认是比较两个不同的对象对象地址是否相同 System.out.println(s1.equals(s2));//true 重写后 System.out.println(s1 == s2);//false } }
Objects
Objects是一个工具类,提供了一些方法去完成一些功能。
官方在进行字符串比较时,没有用字符串对象的的equals方法,而是选择了Objects的equals方法来比较。
@Override public boolean equals(Object o) { // 1、判断是否是同一个对象比较,如果是返回true。 if (this == o) return true; // 2、如果o是null返回false 如果o不是学生类型返回false ...Student != ..Pig if (o == null || this.getClass() != o.getClass()) return false; // 3、说明o一定是学生类型而且不为null Student student = (Student) o; return sex == student.sex && age == student.age && Objects.equals(name, student.name); }
方法名 | 说明 |
---|---|
public static boolean equals(Object a, Object b) | 比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常。再进行equals比较 |
public static boolean isNull(Object obj) | 判断变量是否为null ,为null返回true ,反之 |
使用Objects的equals方法在进行对象的比较会更安全。
package com.itheima.d10_api_objects; import java.util.Objects; //掌握objects类的常用方法:equals public class Test { public static void main(String[] args) { String s1=null; String s2=new String("itheima"); // System.out.println(s1.equals(s2));//留下了隐患,可能出现了空指针异常。 System.out.println(Objects.equals(s1,s2));//false 更安全,结果也是对的 System.out.println(Objects.isNull(s1));//true System.out.println(s1==null);//true System.out.println(Objects.isNull(s2));//false System.out.println(s2==null);//false } }
StringBuilder
方法名称 | 说明 |
---|---|
public StringBuilder append(任意类型) | 添加(连接)数据并返回StringBuilder对象本身 |
public StringBuilder reverse() | 将对象的内容反转 |
public int length() | 返回对象内容长度 |
public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
为什么拼接、反转字符串建议使用StringBuilder?
-
String :内容是不可变的、拼接字符串性能差。
-
StringBuilder:内容是可变的、拼接字符串性能好、代码优雅。
-
定义字符串使用String
-
拼接、修改等操作字符串使用StringBuilder
package com.itheima.d11_api_StringBuilder; public class StringBuilderDome1 { public static void main(String[] args) { StringBuilder sb=new StringBuilder(); sb.append("a"); sb.append("abc"); sb.append(1); System.out.println(sb); StringBuilder sb1=new StringBuilder(); //支持链式编程 sb1.append("a").append("b").append("我爱你中国"); System.out.println(sb1);//ab我爱你中国 //反转 sb1.reverse().append("110"); System.out.println(sb1);//国中你爱我ba110 //长度 System.out.println(sb1.length()); //注意:目的StringBuilder只是拼接字符串的手段,效率好。 //最终的还是要恢复String类型。 StringBuilder sb2=new StringBuilder(); sb2.append("123").append("456"); //恢复 String String rs=sb2.toString(); check(rs); } public static void check (String data){ System.out.println(data); } }
package com.itheima.d11_api_StringBuilder; public class StringBuilderTest2 { public static void main(String[] args) { int []arr1=null; System.out.println(toString(arr1)); int []arr2={10,20,30}; System.out.println(toString(arr2)); } //1.定义方法接受任意整型数组,返回数组内容格式 public static String toString(int[] arr) { if (arr != null) { //2.开始拼接内容 StringBuilder sb = new StringBuilder("[");//可以用有参构造器 for (int i = 0; i < arr.length; i++) { sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", "); } sb.append("]"); return sb.toString(); } else { return null; } } }
Math
Math类
包含执行基本数字运算的方法,Math类没有提供公开的构造器,相当于一个工具类,不能创建对象。 如何使用类中的成员呢?看类的成员是否都是静态的,如果是,通过类名就可以直接调用.
Math类常用方法
方法名 | 说明 |
---|---|
public static int abs(int a) | 获取参数绝对值 |
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static int round(float a) | 四舍五入 |
public static int max(int a,int b) | 获取两个int值中的较大值 |
public static double pow(double a,double b) | 返回**a的b次幂的值 ** |
public static double random() | 返回值为double的随机值,范围**[0.0,1.0)** |
package com.itheima.d12_math; /** 目标:Math类的使用。 Math用于做数学运算。 Math类中的方法全部是静态方法,直接用类名调用即可。 方法: 方法名 说明 public static int abs(int a) 获取参数a的绝对值: public static double ceil(double a) 向上取整 public static double floor(double a) 向下取整 public static double pow(double a, double b) 获取a的b次幂 public static long round(double a) 四舍五入取整 小结: 记住。 */ public class MathDome { public static void main(String[] args) { // 1.取绝对值:返回正数 System.out.println(Math.abs(10)); // 10 System.out.println(Math.abs(-10.3)); // 10.3 // 2.向上取整: 5 System.out.println(Math.ceil(4.00000001)); // 5.0 System.out.println(Math.ceil(4.0)); // 4.0 // 3.向下取整:4 System.out.println(Math.floor(4.99999999)); // 4.0 System.out.println(Math.floor(4.0)); // 4.0 // 4.求指数次方 System.out.println(Math.pow(2 , 3)); // 2^3 = 8.0 // 5.四舍五入 10 System.out.println(Math.round(4.49999)); // 4 System.out.println(Math.round(4.500001)); // 5 System.out.println(Math.random()); // 0.0 - 1.0 (包前不包后) // 拓展: 3 - 9 之间的随机数 (0 - 6) + 3 // [0 - 6] + 3 int data = (int)(Math.random() * 7) + 3; System.out.println(data); } }
System
System 类概述
System也是一个工具类,代表了当前系统,提供了一些与系统相关的方法。
System类常用方法
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的 Java 虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前系统的时间毫秒值形式 |
public static void arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数) | 数组拷贝 |
package com.itheima.d13_system; import java.lang.reflect.Array; import java.util.Arrays; public class SystemDemo { public static void main(String[] args) { System.out.println("程序开始"); // System.exit(0);//JVM终止!静态方法属于类,用类调用。 0表示正常终止。 System.out.println("程序结束"); // 2.计算机认为时间是有起点的,起始时间: 1970年1月1日 00:00:00 // 时间毫秒值:指的是从1970年1月1日 00:00:00走到此刻的总的毫秒数,应该是很大的。 1s = 1000ms。 long time=System.currentTimeMillis(); System.out.println(time); long startTime=System.currentTimeMillis(); //进行时间的计算:性能分析 for (int i = 0; i < 100000; i++) { System.out.println("输出:"+i); } long endTime=System.currentTimeMillis(); System.out.println((endTime-startTime)/1000.0+"s"); //3.数组拷贝 // 参数一:被拷贝的数组 // 参数二:从那个索引位置开始拷贝 // 参数三:复制的目标数组 // 参数四:粘贴位置 // 参数五:拷贝元素的个数 int[] arr1={10,20,30,40}; int[] arr2=new int[4];//[0,0,0,0]==>[0,0,30,40] System.arraycopy(arr1,2,arr2,2,2); System.out.println(Arrays.toString(arr2)); } }
BigDecimal
BigDecimal作用
用于解决浮点型运算精度失真的问题
使用步骤
创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
public static BigDecimal valueOf(double val):包装浮点数成为BigDecimal对象。
package com.itheima.d14_bigdecimal; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.NumberFormat; /** 目标:BigDecimal大数据类。 引入: 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。 BigDecimal可以解决浮点型运算数据失真的问题。 BigDicimal类: 包:java.math. 创建对象的方式(最好的方式:) public static BigDecimal valueOf(double val) :包装浮点数成为大数据对象。 方法声明 public BigDecimal add(BigDecimal value) 加法运算 public BigDecimal subtract(BigDecimal value) 减法运算 public BigDecimal multiply(BigDecimal value) 乘法运算 public BigDecimal divide(BigDecimal value) 除法运算 public double doubleValue(): 把BigDecimal转换成double类型。 */ public class BigDecimalDemo { public static void main(String[] args) { // 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。 System.out.println(0.09 + 0.01); System.out.println(1.0 - 0.32); System.out.println(1.015 * 100); System.out.println(1.301 / 100); System.out.println("-------------------------"); double a = 0.1; double b = 0.2; double c = a + b; System.out.println(c); System.out.println("--------------------------"); // 包装浮点型数据成为大数据对象 BigDeciaml 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); // 目的:double double rs = c1.doubleValue(); System.out.println(rs); // 注意事项:BigDecimal是一定要精度运算的 BigDecimal a11 = BigDecimal.valueOf(10.0); BigDecimal b11 = BigDecimal.valueOf(3.0); /** 参数一:除数 参数二:保留小数位数 参数三:舍入模式 */ BigDecimal c11 = a11.divide(b11, 2, RoundingMode.HALF_UP); // 3.3333333333 System.out.println(c11); System.out.println("-------------------"); } } 0.09999999999999999 0.6799999999999999 101.49999999999999 0.013009999999999999 ------------------------- 0.30000000000000004 -------------------------- 0.3 0.3 3.33 -------------------
BigDecima常用API
方法名 | 说明 |
---|---|
public BigDecimal add(BigDecimal b) | 加法 |
public BigDecimal subtract(BigDecimal b) | 减法 |
public BigDecimal multiply(BigDecimal b) | 乘法 |
public BigDecimal divide(BigDecimal b) | 除法 |
public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) | 除法 |
日期与时间
Date 类
Date类概述
Date类代表当前所在系统的日期时间信息。
Date的构造器
名称 | 说明 |
---|---|
public Date() | 创建一个Date对象,代表的是系统当前此刻日期时间。 |
Date的方法
名称 | 说明 |
---|---|
public long getTime() | 返回从1970年1月1日 00:00:00走到此刻的总的毫秒数 |
案例
请计算出当前时间往后走1小时121秒之后的时间是多少。
时间毫秒值 -> 日期对象
构造器 | 说明 |
---|---|
public Date(long time) | 把时间毫秒值转换成Date日期对象。 |
DATE方法 | 说明 |
---|---|
public void setTime(long time) | 设置日期对象的时间为当前时间毫秒值对应的时间 |
package com.itheima.d1_date; import java.util.Date; //目标:学会使用 data类处理时间,获取时间信息。 public class DataDemo1 { public static void main(String[] args) { //1.创建一个Data类对象,代表系统此刻的日期时间对象 Date d=new Date(); System.out.println(d); //2.获取时间毫秒值 long time=d.getTime(); System.out.println(time); long time1=System.currentTimeMillis(); System.out.println(time1); System.out.println("...................."); //1.得到当前时间的毫秒值 Date d1=new Date(); System.out.println(d1); //2.当前时间往后走1小时121秒 long time2=System.currentTimeMillis(); time2+=(60*60+121)*1000; //3.把时间毫秒值转换成对应的日期对象 // Date d2=new Date(time2); // System.out.println(d2); Date d3=new Date(); d3.setTime(time2); System.out.println(d3); } } Mon Apr 11 14:25:23 CST 2022 1649658323951 1649658323981 .................... Mon Apr 11 14:25:23 CST 2022 Mon Apr 11 15:27:24 CST 2022
总结
-
日期对象如何创建,如何获取时间毫秒值?
-
public Date();
-
public long getTime();
-
-
时间毫秒值怎么恢复成日期对象
-
public Date(long time);
-
public void setTime(long time);
SimpleDateFormat
正在上传…重新上传取消
正在上传…重新上传取消
正在上传…重新上传取消
SimpleDateFormat 类作用
可以去完成日期时间的格式化操作
正在上传…重新上传取消
构造器
构造器 | 说明 |
---|---|
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat,使用指定的格式 |
格式化方法
格式化方法 | 说明 |
---|---|
public final String format(Date date) | 将日期格式化成日期/时间字符串 |
public final String format(Object time) | 将时间毫秒值式化成日期/时间字符串 |
正在上传…重新上传取消
SimpleDateFormat解析字符串时间成为日期对象
解析字符串时间成为日期对象: 2011-11-11 11:11:22 -> Date日期对象
package com.itheima.d2_simpledateformat; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatDemo1 { // SimpleDateFormatDemo1简单日期格式化类的使用 //格式化时间 解析时间 public static void main(String[] args) { //1.日期对象 Date d=new Date(); System.out.println(d); //2.格式化这个日期对象(指定格式化形式) SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a"); //3.开始格式化日期对象成为喜欢的字符串形式 String rs= sdf.format(d); System.out.println(rs); //4.格式化时间毫秒值.121秒后的时间 long time1=System.currentTimeMillis()+121*1000; String rs2= sdf.format(time1); System.out.println(rs2); System.out.println(sdf.format(time1)); } } Mon Apr 11 14:46:36 CST 2022 2022年04月11日 14:46:36 周一 下午 2022年04月11日 14:48:37 周一 下午 2022年04月11日 14:48:37 周一 下午
案例
请计算出 2021年08月06日11点11分11秒,往后走2天14小时49分06秒后的时间是多少。
解析方法 | 说明 |
---|---|
public Date **parse(String source)** | 从给定字符串的开始解析文本以生成日期 |
package com.itheima.d2_simpledateformat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatDemo2 { public static void main(String[] args) throws ParseException { //目标:学会使用SimpleDateFormat解析字符串成为日期对象 //请计算出 2021年08月06日11点11分11秒,往后走2天14小时49分06秒后的时间是多少。 //1.把字符串拿到程序中来 String datestr="2021年08月06日11:11:11"; //2.把字符串时间解析成日期对象(重点):形式必须与被解析时间的形式完全一样,否则运行时解析报错。 SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss"); Date d=sdf.parse(datestr); //3.往后走 long time=d.getTime()+(2L*24*60*60+14*60*60+49*60+6)*1000; //4.格式化这个时间毫秒值 System.out.println(sdf.format(time)); } }
总结
1.SimleDateFormat可以格式化哪些时间形式,? Date日期对象,时间毫秒值。 2、SimpleDateFormat如何进行字符串时间的解析的? 通过一个方法: public Date parse(String source)
Test秒杀活动
需求 某购物网站举办秒杀活动,开始时间和结束时间如左图所示,当前活动结束后,系统记录到2位用户的付款时间分别如下: 小贾下单并付款的时间为:2020年11月11日 0:03:47 小皮下单并付款的时间为:2020年11月11日 0:10:11 规则:顾客的付款时间必须在秒杀时间之内,请判断出两位顾客是否秒杀成功。 分析 把4个字符串形式的时间解析成日期对象。 判断小贾和小皮的时间是否在秒杀时间范围之内,并给出相应的提示。
package com.itheima.d2_simpledateformat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatTest3 { public static void main(String[] args) throws ParseException { //1.开始时间和结束时间 String startTime="2021-11-11 00:00:00"; String endTime="2021-11-11 00:10:00"; //2.小贾 小皮 String xiaoJia="2021-11-11 0:03:47"; String xiaoPi="2021-11-11 0:10:11"; //3.解析他们的时间(否则计算机无法识别) SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date d1=sdf.parse(startTime); Date d2=sdf.parse(endTime); Date d3=sdf.parse(xiaoJia); Date d4=sdf.parse(xiaoPi); if(d3.after(d1)&&d3.before(d2)){ System.out.println("小贾秒杀成功"); }else { System.out.println("小贾秒杀失败"); } if(d4.after(d1)&&d4.before(d2)){ System.out.println("小皮秒杀成功"); }else{ System.out.println("小皮秒杀失败"); } } }
Calendar
Calendar概述
-
Calendar代表了系统此刻日期对应的日历对象。
-
Calendar是一个抽象类,不能直接创建对象。
Calendar日历类创建日历对象的方法:
方法名 | 说明 |
---|---|
public static Calendar getInstance() | 获取当前日历对象 |
Calendar方法
方法名 | 说明 |
---|---|
public int get(int field) | 取日期中的某个字段信息。 |
public void set(int field,int value) | 修改日历的某个字段信息。 |
public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
public final Date getTime() | 拿到此刻日期对象。 |
public long getTimeInMillis() | 拿到此刻时间毫秒值 |
package com.itheima.d3_calendar; import java.util.Calendar; import java.util.Date; public class CalendarDemo1 { public static void main(String[] args) { //1.拿到日历对象 Calendar cal = Calendar.getInstance();//多态写法 // 2.public int get(int field) 取日期中的某个字段信息。 System.out.println(cal); int year = cal.get(Calendar.YEAR); System.out.println(year); int mm = cal.get(Calendar.MONTH) + 1; System.out.println(mm); int days = cal.get(Calendar.DAY_OF_YEAR);//一年中的第几天 System.out.println(days); // 3.public void set(int field,int value) 修改日历的某个字段信息。(不建议修改) // cal.set(Calendar.HOUR,12); // System.out.println(cal); // 4.public void add(int field,int amount) 为某个字段增加/减少指定的值 //64天后是什么时间 cal.add(Calendar.DAY_OF_YEAR, 64); cal.add(Calendar.MINUTE, 50); // 5.public final Date getTime() 拿到此刻日期对象。 Date d = cal.getTime(); System.out.println(d); // 6.public long getTimeInMillis() 拿到此刻时间毫秒值 long time = cal.getTimeInMillis(); System.out.println(time); } }
注意:calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化。
JDK8新增日期类
概述、LocalTime /LocalDate / LocalDateTime
正在上传…重新上传取消
LocalDate、LocalTime、LocalDateTime
-
他们 分别表示日期,时间,日期时间对象,他们的类的实例是不可变的对象。
-
他们三者构建对象和API都是通用的.
构建对象的方法
正在上传…重新上传取消
LocalDate、LocalTime、LocalDateTime获取信息的API.
方法名 | 说明 |
---|---|
public int geYear() | 获取年 |
public int getMonthValue() | 获取月份(1-12) |
Public int getDayOfMonth() | 获取月中第几天乘法 |
Public int getDayOfYear() | 获取年中第几天 |
Public DayOfWeek getDayOfWeek() | 获取星期 |
正在上传…重新上传取消
修改相关的API
-
LocalDateTime 综合了 LocalDate 和 LocalTime 里面的方法,所以下面只用 LocalDate 和 LocalTime 来举例。
-
这些方法返回的是一个新的实例引用,因为LocalDateTime 、LocalDate 、LocalTime 都是不可变的。
-
方法名 说明 plusDays, plusWeeks, plusMonths, plusYears 向当前 LocalDate 对象添加几天、 几周、几个月、几年 minusDays, minusWeeks, minusMonths, minusYears 从当前 LocalDate 对象减去几天、 几周、几个月、几年 withDayOfMonth, withDayOfYear, withMonth, withYear 将月份天数、年份天数、月份、年 份 修 改 为 指 定 的 值 并 返 回 新 的 LocalDate 对象 isBefore, isAfter 比较两个 LocalDate
package com.itheima.d4_jdk8_time; import java.time.LocalDate; import java.time.Month; public class Demo01LocalDate { public static void main(String[] args) { // 1、获取本地日期对象。 LocalDate nowDate = LocalDate.now(); System.out.println("今天的日期:" + nowDate);//今天的日期: int year = nowDate.getYear(); System.out.println("year:" + year); int month = nowDate.getMonthValue(); System.out.println("month:" + month); int day = nowDate.getDayOfMonth(); System.out.println("day:" + day); //当年的第几天 int dayOfYear = nowDate.getDayOfYear(); System.out.println("dayOfYear:" + dayOfYear); //星期 System.out.println(nowDate.getDayOfWeek()); System.out.println(nowDate.getDayOfWeek().getValue()); //月份 System.out.println(nowDate.getMonth());//AUGUST System.out.println(nowDate.getMonth().getValue());//8 System.out.println("------------------------"); LocalDate bt = LocalDate.of(1991, 11, 11); System.out.println(bt);//直接传入对应的年月日 System.out.println(LocalDate.of(1991, Month.NOVEMBER, 11));//相对上面只是把月换成了枚举 } } 今天的日期:2022-04-11 year:2022 month:4 day:11 dayOfYear:101 MONDAY 1 APRIL 4 ------------------------ 1991-11-11 1991-11-11
package com.itheima.d4_jdk8_time; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; public class Demo02LocalTime { public static void main(String[] args) { // 1、获取本地时间对象。 LocalTime nowTime = LocalTime.now(); System.out.println("今天的时间:" + nowTime);//今天的时间: int hour = nowTime.getHour();//时 System.out.println("hour:" + hour);//hour: int minute = nowTime.getMinute();//分 System.out.println("minute:" + minute);//minute: int second = nowTime.getSecond();//秒 System.out.println("second:" + second);//second: int nano = nowTime.getNano();//纳秒 System.out.println("nano:" + nano);//nano: System.out.println("-----"); System.out.println(LocalTime.of(8, 20));//时分 System.out.println(LocalTime.of(8, 20, 30));//时分秒 System.out.println(LocalTime.of(8, 20, 30, 150));//时分秒纳秒 LocalTime mTime = LocalTime.of(8, 20, 30, 150); System.out.println("---------------"); System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20)); System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20)); System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20, 30)); System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20, 30)); System.out.println(LocalDateTime.of(1991, 11, 11, 8, 20, 30, 150)); System.out.println(LocalDateTime.of(1991, Month.NOVEMBER, 11, 8, 20, 30, 150)); } } 今天的时间:15:45:27.857054200 hour:15 minute:45 second:27 nano:857054200 ----- 08:20 08:20:30 08:20:30.000000150 --------------- 1991-11-11T08:20 1991-11-11T08:20 1991-11-11T08:20:30 1991-11-11T08:20:30 1991-11-11T08:20:30.000000150 1991-11-11T08:20:30.000000150
package com.itheima.d4_jdk8_time; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; public class Demo03LocalDateTime { public static void main(String[] args) { // 日期 时间 LocalDateTime nowDateTime = LocalDateTime.now(); System.out.println("今天是:" + nowDateTime);//今天是: System.out.println(nowDateTime.getYear());//年 System.out.println(nowDateTime.getMonthValue());//月 System.out.println(nowDateTime.getDayOfMonth());//日 System.out.println(nowDateTime.getHour());//时 System.out.println(nowDateTime.getMinute());//分 System.out.println(nowDateTime.getSecond());//秒 System.out.println(nowDateTime.getNano());//纳秒 //日:当年的第几天 System.out.println("dayOfYear:" + nowDateTime.getDayOfYear());//dayOfYear:249 //星期 System.out.println(nowDateTime.getDayOfWeek());//THURSDAY System.out.println(nowDateTime.getDayOfWeek().getValue());//4 //月份 System.out.println(nowDateTime.getMonth());//SEPTEMBER System.out.println(nowDateTime.getMonth().getValue());//9 LocalDate ld = nowDateTime.toLocalDate(); System.out.println(ld); LocalTime lt = nowDateTime.toLocalTime(); System.out.println(lt.getHour()); System.out.println(lt.getMinute()); System.out.println(lt.getSecond()); } } 今天是:2022-04-11T15:45:54.754507800 2022 4 11 15 45 54 754507800 dayOfYear:101 MONDAY 1 APRIL 4 2022-04-11 15 45 54
package com.itheima.d4_jdk8_time; import java.time.LocalDate; import java.time.LocalTime; import java.time.MonthDay; public class Demo04UpdateTime { public static void main(String[] args) { LocalTime nowTime = LocalTime.now(); System.out.println(nowTime);//当前时间 System.out.println(nowTime.minusHours(1));//一小时前 System.out.println(nowTime.minusMinutes(1));//一分钟前 System.out.println(nowTime.minusSeconds(1));//一秒前 System.out.println(nowTime.minusNanos(1));//一纳秒前 System.out.println("----------------"); System.out.println(nowTime.plusHours(1));//一小时后 System.out.println(nowTime.plusMinutes(1));//一分钟后 System.out.println(nowTime.plusSeconds(1));//一秒后 System.out.println(nowTime.plusNanos(1));//一纳秒后 System.out.println("------------------"); // 不可变对象,每次修改产生新对象! System.out.println(nowTime); System.out.println("---------------"); LocalDate myDate = LocalDate.of(2018, 9, 5); LocalDate nowDate = LocalDate.now(); System.out.println("今天是2018-09-06吗? " + nowDate.equals(myDate));//今天是2018-09-06吗? false System.out.println(myDate + "是否在" + nowDate + "之前? " + myDate.isBefore(nowDate));//2018-09-05是否在2018-09-06之前? true System.out.println(myDate + "是否在" + nowDate + "之后? " + myDate.isAfter(nowDate));//2018-09-05是否在2018-09-06之后? false System.out.println("---------------------------"); // 判断今天是否是你的生日 LocalDate birDate = LocalDate.of(1996, 8, 5); LocalDate nowDate1 = LocalDate.now(); MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth()); MonthDay nowMd = MonthDay.from(nowDate1); System.out.println("今天是你的生日吗? " + birMd.equals(nowMd));//今天是你的生日吗? false } } 18:23:47.281594500 17:23:47.281594500 18:22:47.281594500 18:23:46.281594500 18:23:47.281594499 ---------------- 19:23:47.281594500 18:24:47.281594500 18:23:48.281594500 18:23:47.281594501 ------------------ 18:23:47.281594500 --------------- 今天是2018-09-06吗? false 2018-09-05是否在2022-04-11之前? true 2018-09-05是否在2022-04-11之后? false --------------------------- 今天是你的生日吗? false
Instant
Instant时间戳
JDK8获取时间戳特别简单,且功能更丰富。Instant类由一个静态的工厂方法now()可以返回当前时间戳。
Instant instant = Instant.now(); System.out.println("当前时间戳是:" + instant); Date date = Date.from(instant); System.out.println("当前时间戳是:" + date); instant = date.toInstant(); System.out.println(instant);
-
时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是类似JDK8 以前的Date。
-
Instant和Date这两个类可以进行转换。
package com.itheima.d4_jdk8_time; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; import java.util.Date; public class Demo05Instant { public static void main(String[] args) { // 1、得到一个Instant时间戳对象 Instant instant = Instant.now(); System.out.println(instant); // 2、系统此刻的时间戳怎么办? Instant instant1 = Instant.now(); System.out.println(instant1.atZone(ZoneId.systemDefault()));//系统默认时区(中国) // 3、如何去返回Date对象 Date date = Date.from(instant);//date和时间戳可以互转 System.out.println(date); Instant i2 = date.toInstant(); System.out.println(i2); } } 2022-04-11T07:47:29.528925400Z 2022-04-11T15:47:29.533923600+08:00[Asia/Shanghai] Mon Apr 11 15:47:29 CST 2022 2022-04-11T07:47:29.528Z
DateTimeFormatter
在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。
正反都能调用format方法。
LocalDateTime ldt = LocalDateTime.now(); System.out.println(ldt);//2021-03-01T15:09:17.444190900 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String ldtStr = ldt.format(dtf); System.out.println(ldtStr);//2021-03-01 15:09:17 String ldtStr1 = dtf.format(ldt); System.out.println(ldtStr1);//2021-03-01 15:09:17
package com.itheima.d4_jdk8_time; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Demo06DateTimeFormat { public static void main(String[] args) { // 本地此刻 日期时间 对象 LocalDateTime ldt = LocalDateTime.now(); System.out.println(ldt); // 解析/格式化器 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a"); // 正向格式化 System.out.println(dtf.format(ldt)); // 逆向格式化 System.out.println(ldt.format(dtf)); // 解析字符串时间 DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 解析当前字符串时间成为本地日期时间对象 LocalDateTime ldt1 = LocalDateTime.parse("2019-11-11 11:11:11" , dtf1); System.out.println(ldt1); System.out.println(ldt1.getDayOfYear()); } } 2022-04-11T15:48:33.942783500 2022-04-11 15:48:33 周一 下午 2022-04-11 15:48:33 周一 下午 2019-11-11T11:11:11 315
Duration/Period
Period
-
在Java8中,我们可以使用以下类来计算日期间隔差异:java.time.Period
-
主要是 Period 类方法 getYears(),getMonths() 和 getDays() 来计算,只能精确到年月日。
-
用于 LocalDate 之间的比较。
LocalDate today = LocalDate.now(); System.out.println(today); // 2021-03-01 LocalDate birthDate = LocalDate.of(1995, 1, 11); System.out.println(birthDate); // 1995-01-11 Period period = Period.between(birthDate, today); System.out.printf("年龄 : %d 年 %d 月 %d 日", period.getYears(), period.getMonths(), period.getDays());
package com.itheima.d4_jdk8_time; import java.time.LocalDate; import java.time.Period; public class Demo07Period { public static void main(String[] args) { // 当前本地 年月日 LocalDate today = LocalDate.now(); System.out.println(today);// // 生日的 年月日 LocalDate birthDate = LocalDate.of(1998, 10, 13); System.out.println(birthDate); Period period = Period.between(birthDate, today);//第二个参数减第一个参数 System.out.println(period.getYears()); System.out.println(period.getMonths()); System.out.println(period.getDays()); } }
Duration
-
在Java8中,我们可以使用以下类来计算时间间隔差异:java.time.Duration
-
提供了使用基于时间的值测量时间量的方法。
-
用于 LocalDateTime 之间的比较。也可用于 Instant 之间的比较。
-
LocalDateTime today = LocalDateTime.now(); System.out.println(today);LocalDateTime birthDate = LocalDateTime.of(1990,10,1,10,50,30);System.out.println(birthDate); Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数 System.out.println(duration.toDays());//两个时间差的天数 System.out.println(duration.toHours());//两个时间差的小时数 System.out.println(duration.toMinutes());//两个时间差的分钟数 System.out.println(duration.toMillis());//两个时间差的毫秒数 System.out.println(duration.toNanos());//两个时间差的纳秒数
package com.itheima.d4_jdk8_time; import java.time.Duration; import java.time.LocalDateTime; public class Demo08Duration { public static void main(String[] args) { // 本地日期时间对象。 LocalDateTime today = LocalDateTime.now(); System.out.println(today); // 出生的日期时间对象 LocalDateTime birthDate = LocalDateTime.of(2021,8 ,06,01,00,00); System.out.println(birthDate); Duration duration = Duration.between( birthDate, today );//第二个参数减第一个参数 System.out.println(duration.toDays());//两个时间差的天数 System.out.println(duration.toHours());//两个时间差的小时数 System.out.println(duration.toMinutes());//两个时间差的分钟数 System.out.println(duration.toMillis());//两个时间差的毫秒数 System.out.println(duration.toNanos());//两个时间差的纳秒数 } } 2022-04-11T15:49:36.827432900 2021-08-06T01:00 248 5966 358009 21480576827 21480576827432900
1、 Duration: 用于计算两个“时间”间隔。 2、 Period: 用于计算两个“日期”间隔。
ChronoUnit
java.time.temporal.ChronoUnit
-
ChronoUnit类可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位
package com.itheima.d4_jdk8_time; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; public class Demo09ChronoUnit { public static void main(String[] args) { // 本地日期时间对象:此刻的 LocalDateTime today = LocalDateTime.now(); System.out.println(today); // 生日时间 LocalDateTime birthDate = LocalDateTime.of(1990,10,1, 10,50,59); System.out.println(birthDate); System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today)); System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today)); System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today)); System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today)); System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today)); System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today)); System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today)); System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today)); System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today)); System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today)); System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today)); System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today)); System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today)); System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today)); System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today)); } } 2022-04-11T15:50:25.040298400 1990-10-01T10:50:59 相差的年数:31 相差的月数:378 相差的周数:1645 相差的天数:11515 相差的时数:276364 相差的分数:16581899 相差的秒数:994913966 相差的毫秒数:994913966040 相差的微秒数:994913966040298 相差的纳秒数:994913966040298400 相差的半天数:23030 相差的十年数:3 相差的世纪(百年)数:0 相差的千年数:0 相差的纪元数:0
包装类
包装类
其实就是8种基本数据类型对应的引用类型。
基本数据类型 | 引用数据类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
为什么提供包装类?
-
Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。
-
后面的集合和泛型其实也只能支持包装类型,不支持基本数据类型。
自动装箱:
基本类型的数据和变量可以直接赋值给包装类型的变量。
自动拆箱:
包装类型的变量可以直接赋值给基本数据类型的变量。
包装类的特有功能
-
包装类的变量的默认值可以是null,容错率更高。
-
可以把基本类型的数据转换成字符串类型(用处不大)
调用toString()方法得到字符串结果。 调用Integer.toString(基本类型的数据)。
-
可以把字符串类型的数值转换成真实的数据类型(真的很有用)
Integer.parseInt(“字符串类型的整数”) Double.parseDouble(“字符串类型的小数”)。
package com.itheima.d5_integer; import java.time.Instant; public class Test { public static void main(String[] args) { int a=10; Integer a1=11; Integer a2=a;//自动装箱 System.out.println(a); System.out.println(a1); Integer it=100; int it1=it;//自动拆箱 System.out.println(it1); // int age=null; Integer age=null; //1.包装类可以把基本类型的数据转换成字符串类型(用处不大) Integer i3=23; String rs=i3.toString(); System.out.println(rs+1); String rs1=Integer.toString(i3); System.out.println(rs1+1); //可以直接加字符串 String rs2=i3+""; System.out.println(rs2+1); //2.包装类可以把字符串类型的数值转换成真实的数据类型(真的很有用) System.out.println(".........................."); String number="23"; //转换为整数 // int ag=Integer.parseInt(number); int ag=Integer.valueOf(i3); System.out.println(ag+1); //转换为小数 String number1="99.99"; // double score=Double.parseDouble(number1); double score=Double.valueOf(number1); System.out.println(score+0.01); } } 10 11 100 231 231 231 .......................... 24 100.0
正则表达式
正则表达式概述、初体验
正在上传…重新上传取消
正则表达式的匹配规则
字符串对象提供了匹配正则表达式的方法
public boolean matches(String regex): 判断是否匹配正则表达式,匹配返回true,不匹配返回false。
字符类(默认匹配一个字符)
[abc] 只能是a, b, 或c abc 除了a, b, c之外的任何字符 [a-zA-Z] a到z A到Z,包括(范围) [a-d[m-p]] a到d,或m通过p:([a-dm-p]联合) [a-z&&[def]] d, e, 或f(交集) [a-z&&bc] a到z,除了b和c:([ad-z]减法) [a-z&&m-p] a到z,除了m到p:([a-lq-z]减法)
预定义的字符类(默认匹配一个字符)
. 任何字符 \d 一个数字: [0-9] \D 非数字: 0-9 \s 一个空白字符: [ \t\n\x0B\f\r] \S 非空白字符: \s \w [a-zA-Z_0-9] 英文、数字、下划线 \W \w 一个非单词字符
贪婪的量词(配合匹配多个字符)
X? X , 一次或根本不 X* X,零次或多次 X+ X , 一次或多次 X {n} X,正好n次 X {n, } X,至少n次 X {n,m} X,至少n但不超过m次
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]+")); //true
package com.itheima.d6_regex; //正则表达式 public class RegexDemo1 { public static void main(String[] args) { //需求:校验qq号码,必须数字6-20位 System.out.println(checkQQ("276732827881")); System.out.println(checkQQ("27673282788a")); System.out.println(checkQQ(null)); System.out.println(checkQQ("2348")); System.out.println("........................................"); //正则表达式初体验 System.out.println(checkQQ2("276732827881")); System.out.println(checkQQ2("27673282788a")); System.out.println(checkQQ2(null)); System.out.println(checkQQ2("2348")); } public static boolean checkQQ2(String qq){ return qq!=null&&qq.matches("\\d{6,20}"); } public static boolean checkQQ(String qq){ //1.判断qq号码长度是否满足需求 if(qq==null||qq.length()<6||qq.length()>20){ return false; } //2.判断qq中是否全部为数字 for (int i = 0; i < qq.length(); i++) { //获取每位字符 char ch=qq.charAt(i); //判断字符是否不是数字 if(ch<'0'||ch>'9'){ return false; } } return true; } }
package com.itheima.d6_regex; /** 目标:全面、深入学习正则表达式的规则 */ public class RegexDemo02 { public static void main(String[] args) { //public boolean matches(String regex):判断是否与正则表达式匹配,匹配返回true // 只能是 a b c System.out.println("a".matches("[abc]")); // true System.out.println("z".matches("[abc]")); // false // 不能出现a b c System.out.println("a".matches("[^abc]")); // false System.out.println("z".matches("[^abc]")); // true //只能是一个数字 System.out.println("a".matches("\\d")); // false System.out.println("3".matches("\\d")); // true System.out.println("333".matches("\\d")); // false //一个英文、数字、下划线 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 //[^\w] System.out.println("你".matches("\\W")); // true System.out.println("---------------------------------"); // 以上正则匹配只能校验单个字符。 // 校验密码 //匹配多个字符 (贪婪的量词) // 必须是数字 字母 下划线 至少 6位 System.out.println("2442fsfsf".matches("\\w{6,}")); System.out.println("244f".matches("\\w{6,}")); // 验证码 必须是数字和字符 必须是4位 System.out.println("23dF".matches("[a-zA-Z0-9]{4}")); System.out.println("23_F".matches("[a-zA-Z0-9]{4}")); System.out.println("23dF".matches("[\\w&&[^_]]{4}")); System.out.println("23_F".matches("[\\w&&[^_]]{4}")); } }
正则表达式的常见案例
需求 请编写程序模拟用户输入手机号码、验证格式正确,并给出提示,直到格式输入正确为止。 请编写程序模拟用户输入邮箱号码、验证格式正确,并给出提示,直到格式输入正确为止。 请编写程序模拟用户输入电话号码、验证格式正确,并给出提示,直到格式输入正确为止。
分析 定义方法,接收用户输入的数据,使用正则表达式完成检验,并给出提示。
package com.itheima.d6_regex; import java.util.Scanner; public class RegexTest3 { public static void main(String[] args) { //目标:校验手机号 邮箱 电话号码 checkPhone(); checkEmail(); checkTel(); } public static void checkTel() { while (true) { Scanner sc = new Scanner(System.in); System.out.println("请输入您的电话号码"); String tel = sc.next(); //判断号码格式:区号027-7267896 0277267896 if (tel.matches("0\\d{2,6}-?\\d{5,20}")) { System.out.println("格式正确,注册完成!"); break; } else { System.out.println("格式有误"); } } } public static void checkEmail() { while (true) { Scanner sc = new Scanner(System.in); System.out.println("请输入您注册的邮箱号码"); String emile = sc.next(); //判断邮箱格式:3567828689@qq.com //判断邮箱格式:35678286shug89@163.com //判断邮箱格式:3567828689@pci.com.cn if (emile.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")) { System.out.println("邮箱格式正确,注册完成!"); break; } else { System.out.println("格式有误"); } } } public static void checkPhone() { while (true) { Scanner sc = new Scanner(System.in); System.out.println("请输入您注册的手机号码"); String phone = sc.next(); //判断手机号码格式 if (phone.matches("1[3-9]\\d{9}")) { System.out.println("手机号码格式正确,注册完成!"); break; } else { System.out.println("格式有误"); } } } }
正则表达式在方法中的应用
方法名 | 说明 |
---|---|
public String replaceAll(String regex,String newStr) | 按照正则表达式匹配的内容进行替换 |
public String[] split(String regex): | 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。 |
package com.itheima.d6_regex; public class RegexDemo4 { public static void main(String[] args) { // public String replaceAll(String regex,String newStr) 按照正则表达式匹配的内容进行替换 // public String[] split(String regex): 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。 String names="小路dsjkiah蓉儿hjaibjhd过儿hjahbdk"; String []arrs=names.split("\\w+");//匹配多个 for (int i = 0; i < arrs.length; i++) { System.out.println(arrs[i]); } String names2=names.replaceAll("\\w+"," "); System.out.println(names2); } }
正则表达式爬取信息
package com.itheima.d6_regex; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexDemo5 { public static void main(String[] args) { String rs = "来黑马程序学习Java,电话020-43422424,或者联系邮箱" + "itcast@itcast.cn,电话18762832633,0203232323"+"邮箱bozai@itcast.cn,400-100-3233 ,4001003232"; // 需求:从上面的内容中爬取出 电话号码和邮箱。 //1.定义爬取规则 String regex="(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(1[3-9]\\d{9})" + "|(0\\d{2,6}-?\\d{5,20})|(400-?\\d{3,9}-?\\d{3,9})"; //2.爬取规则编译成匹配对象 Pattern pattern=Pattern.compile(regex); //3.得到一个内容匹配器对象 Matcher matcher=pattern.matcher(rs); //4.开始找 while(matcher.find()){ String rs1=matcher.group(); System.out.println(rs1); } } } 020-43422424 itcast@itcast.cn 18762832633 0203232323 bozai@itcast.cn 400-100-3233 4001003232
Arrays类
Arrays类概述,常用功能演示
Arrays类概述
数组操作工具类,专门用于操作数组元素的。
Arrays类的常用API
方法名 | 说明 |
---|---|
public static String toString(类型[] a) | 返回数组的内容(字符串形式) |
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static <T> void sort(类型[] a, Comparator<? super T> c) | 使用比较器对象自定义排序 |
public static int binarySearch(int[] a, int key) | 二分搜索数组中的数据,存在返回索引,不存在返回-1 |
package com.itheima.d7_arrays; import java.lang.reflect.Array; import java.util.Arrays; public class ArraysDemo1 { public static void main(String[] args) { //目标:学会使用Arrays类的常用API,并理解其原理 int[]arr={10,2,55,23,24,100}; System.out.println(arr); //1.返回数组内容 // String rs= Arrays.toString(arr); // System.out.println(rs); System.out.println(Arrays.toString(arr)); //2.排序的API(默认对数组元素进行升序排序) Arrays.sort(arr); System.out.println(Arrays.toString(arr)); //3.二分搜索技术(前提是数组必须排好序,否则出bug) int index=Arrays.binarySearch(arr,55); System.out.println(index); //返回不存在元素的规律:-(应该插入的位置索引+1) int index2=Arrays.binarySearch(arr,555); System.out.println(index2); //注意:数组如果没有排好序,可能会找不到存在的元素,从未出现bug int[]arr2={12,36,34,25,13,24,234,100}; Arrays.binarySearch(arr2,36);//-7 } } [I@119d7047 [10, 2, 55, 23, 24, 100] [2, 10, 23, 24, 55, 100] 4 -7
Arrays类对于Comparator比较器的支持
Arrays类的排序方法
方法名 | 说明 |
---|---|
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static <T> void sort(类型[] a, Comparator<? super T> c) | 使用比较器对象自定义排序 |
自定义排序规则
设置Comparator接口对应的比较器对象,来定制比较规则。
如果认为左边数据 大于 右边数据 返回正整数 如果认为左边数据 小于 右边数据 返回负整数 如果认为左边数据 等于 右边数据 返回0
package com.itheima.d7_arrays; import java.util.Arrays; import java.util.Comparator; public class ArraysDemo2 { public static void main(String[] args) { //自定义数组的排序规则:comparator //1.Arrays的sort方法对于默认值特性的数组是升序排序的。 int []ages={34,12,42,23}; Arrays.sort(ages); System.out.println(Arrays.toString(ages)); //需求:降序排序!(自定义比较器对象,只能支持引用类型排序) Integer[]ages1={34,12,42,23}; /** 参数一:被排序的数组 必须是引用类型的元素 参数二:匿名内部类对象,代表了一个比较器对象。 */ Arrays.sort(ages1, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // return o1-o2;//默认升序 //return -(o1-o2); return o2-o1;//默认降序 } }); System.out.println(Arrays.toString(ages1)); System.out.println("............................."); Student[]students=new Student[3]; students[0]=new Student("吴磊",23,185.5); students[1]=new Student("谢鑫",18,175); students[2]=new Student("王亮",20,195.5); System.out.println(Arrays.toString(students)); Arrays.sort(students);//直接运行崩溃 Arrays.sort(students, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { //自己指定比较规则 //return o1.getAge()- o2.getAge();//升序 //return o2.getAge()- o1.getAge();//降序 // return Double.compare(o1.getHeight(),o2.getHeight());比较浮点型可以这样写 升序 return Double.compare(o2.getHeight(),o1.getHeight());//降序 } }); } }
package com.itheima.d7_arrays; public class Student { private String name; private int age; private double height; public Student() { } public Student(String name, int age, double height) { this.name = name; this.age = age; this.height = height; } 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 double getHeight() { return height; } public void setHeight(double height) { this.height = height; } }
常见算法
冒泡排序
正在上传…重新上传取消
选择排序
正在上传…重新上传取消
package com.itheima.d8_sort_binarysearch; import java.util.Arrays; public class Test1 { public static void main(String[] args) { //1.定义数组 int[]arr={5,1,3,2}; // 0 1 2 3 //2.定义一个循环控制选择几轮:arr。length-1 for (int i = 0; i < arr.length-1; i++) { //i=0 j=1 2 3 //i=1 j=2 3 //i=2 j=3 //3.定义内部循环。控制选择几次 for (int j = i+1; j < arr.length; j++) { //当前位:arr[i] //如果有比当前位数据更小的则交换 if(arr[i]>arr[j]){ int temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; } } } System.out.println(Arrays.toString(arr)); } }
二分查找
数组的二分查找的实现步骤是什么样的?
-
定义变量记录左边和右边位置。
-
使用while循环控制查询(条件是左边位置<=右边位置)
-
循环内部获取中间元素索引
-
判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
-
判断当前要找的元素如果小于中间元素,右边位置=中间索引-1
-
判断当前要找的元素如果等于中间元素,返回当前中间元素索引。
package com.itheima.d8_sort_binarysearch; public class Test2 { public static void main(String[] args) { //1.定义数组 int[]arr={10,14,16,25,28,30,35,88,100}; System.out.println(binarySearch(arr, 35)); } /** * * @param arr 排序的数组 * @param data 要找的数据 * @return 索引:如果元素不存在,直接返回-1 */ public static int binarySearch(int[]arr,int data){ //1.定义左边位置 和 右边位置 int left=0; int right= arr.length-1; //2.开始循环,折半查询 while(left<=right){ //取中间索引 int middleIndex=(left+right)/2; //3.判断当前中间位置的元素和要找的元素的大小情况 if(data>arr[middleIndex]){ //往右边找,左位置更新为=左位置+1 left=middleIndex+1; }else if(data<arr[middleIndex]){ right=middleIndex-1; }else{ return middleIndex; } } return -1; } }
Lambda表达式
Lambda概述
Lambda概述
-
Lambda表达式是JDK 8开始后的一种新语法形式。
-
作用:简化匿名内部类的代码写法。
Lambda表达式的简化格式
(匿名内部类被重写方法的形参列表) -> { 被重写方法的方法体代码} 注:-> 是语法形式,无实际含义
注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式
函数式接口
首先必须是接口、其次接口中有且仅有一个抽象方法的形式
package com.itheima.d9_lambda; public class lambadaDemo1 { public void main(String[] args) { //目标:学会使用lambda的标准格式简化匿名内部类的代码形式 Animal a= new Animal() { @Override public void run() { System.out.println("乌龟跑得很慢"); } }; a.run(); } abstract class Animal{ public abstract void run(); } }
Lambda实战-简化常见函数式接口
package com.itheima.d9_lambda; public class LambdaDemo2 { public static void main(String[] args) { //目标:学会使用lambda的标准格式简化匿名内部类的代码形式 //lambda只能简化接口中只有一个抽象方法的匿名内部类形式 // Swimming s1=new Swimming() { // @Override // public void swim() { // System.out.println("老师游泳贼6"); // } // }; Swimming s1=() ->System.out.println("老师游泳贼6"); go(s1); System.out.println("......................................."); // go(new Swimming() { // @Override // public void swim() { // System.out.println("学生游泳很开心"); // } // }); go(()->System.out.println("学生游泳很开心")); } public static void go(Swimming s){ System.out.println("开始"); s.swim(); System.out.println("结束"); } } @FunctionalInterface //一旦加上这个注解,必须是函数式接口,里面只能有一个抽象方法 interface Swimming{ void swim(); }
正在上传…重新上传取消正在上传…重新上传取消
package com.itheima.d9_lambda; import javax.swing.*; import java.awt.event.ActionEvent; import java.util.Arrays; import java.util.Comparator; public class LambdaDemo3 { public static void main(String[] args) { Integer[]ages1={34,12,42,23}; /** 参数一:被排序的数组 必须是引用类型的元素 参数二:匿名内部类对象,代表了一个比较器对象。 */ Arrays.sort(ages1, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2-o1;//默认降序 } }); //简化代码 Arrays.sort(ages1, (o1,o2)-> o2-o1); System.out.println(Arrays.toString(ages1)); System.out.println("........................."); JFrame win=new JFrame("登陆界面"); JButton btn=new JButton("我是一个很大的按钮"); // btn.addActionListener(new AbstractAction() { // @Override // public void actionPerformed(ActionEvent e) { // System.out.println("有人点我"); // } // }); btn.addActionListener((ActionEvent e)-> { System.out.println("有人点我"); }); btn.addActionListener(( e)-> { System.out.println("有人点我"); }); btn.addActionListener( e-> { System.out.println("有人点我"); }); btn.addActionListener(e-> System.out.println("有人点我") ); win.add(btn); win.setSize(400,300); win.setVisible(true); } }
Lambda表达式的省略规则
Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化)
-
参数类型可以省略不写。
-
如果只有一个参数,参数类型可以省略,同时()也可以省略。
-
如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
-
如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
[abc]