包
什么是包?
-
包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护。
-
包装语法格式: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修饰,叫抽象类。
public abstract class Animal{ public abstract void run(); }
抽象使用总结和注意事项
-
抽象类可以理解为被子类继承的不完整设计图。
-
,否则,这一类也必须定义为抽象类。
总结
1.抽象的作用是什么? 它可以被子类继承,作为模板,也可以改进代码重用。 2.抽象方法是什么? 只有方法签名,没有方法体,使用abstract修饰。 3.继承抽象有哪些注意事项? 如果一个类继承了抽象类,那么这个类必须重写抽象类的所有抽象方法。 否则,这一类也必须定义为抽象类。
抽象案例
系统需求 某加油站推出了两种支付卡,一种是预存1万张金卡,后续加油享受80%的折扣,另一种是预存5万张银卡 ,后续加油享受8.5折优惠。 进入出纳系统后,请分别实现两张卡的逻辑,卡需要包含主人的名称、余额、支付功能。
分析实现 创建卡片父类:定义属性包括主人名称、余额、支付功能(具体实现子类) 创建一张白金卡类:重写支付功能,按照原价的8折计算输出。 创建银卡类:重写支付功能,按原价8.五折计算输出。
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
-
变量名 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 } }
静态内部类的访问拓展:
内部类之二:成员内部类[了解]
什么是成员内部类?
-
无static修饰,
public class Outer { // 成员内部类 public class Inner { } } -
JDK16之前,成员内部类中不能定义静态成员,JDK 16开始也可以定义静态成员了。
-
成员内部类创建对象的格式:
格式:
外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
范例:
Outer.Inner in = new Outer().new Inner();
成员内部类的访问扩展
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();
(可以理解为既是一个类也是一个对象)
特点总结:
-
匿名内部类是一个没有名字的内部类。
-
匿名内部类的对象类型。
匿名内部类常见使用形式
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) | 比较两个对象的,底层会,从而可以避免空指针异常。 |
| public static boolean isNull(Object obj) | 判断变量是否为null ,为null返回true ,反之 |
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 |
-
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 (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 ( ) | * ** |
| 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 () | 返回当前系统的时间毫秒值形式 |
| 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 | 将日期格式化成日期/时间字符串 |
| public final String | 将时间毫秒值式化成日期/时间字符串 |
正在上传…重新上传取消
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代表