本文主要是介绍Java基础加强重温_03:多态(使用前提、格式、流程、利弊、类型转换)、instanceof关键字(判断引用类型)、内部类()、包和权限修饰符()、代码块()、Object类和Objects类(),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、多态
多态: 是指同一行为,具有多个不同表现形式,即是同一类事物多种形态。是面向对象三大特性之一(封装、继承、多态),出现在继承或者实现关系中。
1、使用多态
前提
- 1、(必)要有继承、实现
- 2、(选)方法重写
- 3、(必) 父类/接口变量引用子类/实现类对象。
父类 变量 = new 子类();
接口 变量 = new 实现类();
定义格式
//继承定义格式
父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();//实现定义格式
接口 变量 = new 实现类();
多态运行流程
当使用多态方式调用方法时,
首先检查父类中是否有该方法,如果没有,则编译错误;
如果有,执行的是子类重写后方法。如果子类没有重写该方法,就会调用父类的该方法。
总结起来就是:编译看左边(看左边父类有没有这个方法),运行看右边(实际运行执行右边子类重写的方法)。
多态案例
定义父类:
public class Animal { public void eat(){System.out.println("动物吃东西!")}
}
定义子类:
class Cat extends Animal { public void eat() { System.out.println("吃鱼"); }
} class Dog extends Animal { public void eat() { System.out.println("吃骨头"); }
}
定义测试类:
public class Test {public static void main(String[] args) {// 多态形式,创建对象Animal a1 = new Cat();// 调用的是 Cat 的 eata1.eat();// 多态形式,创建对象Animal a2 = new Dog();// 调用的是 Dog 的 eata2.eat();}
}
2、多态利弊
多态的好处:
父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。
即:提高代码的通用性、拓展性
代码实例
定义父类:
public abstract class Animal { public abstract void eat();
}
定义子类:
class Cat extends Animal { public void eat() { System.out.println("吃鱼"); }
} class Dog extends Animal { public void eat() { System.out.println("吃骨头"); }
}
定义测试类:
public class Test {public static void main(String[] args) {// 多态形式,创建对象Cat c = new Cat(); Dog d = new Dog();// 调用showCatEatshowCatEat(c);// 调用showDogEatshowDogEat(d);/*以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代 而执行效果一致*/showAnimalEat(c);showAnimalEat(d);}public static void showCatEat (Cat c){c.eat();}public static void showDogEat (Dog d){d.eat();}public static void showAnimalEat (Animal a){a.eat();}
}
由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当然可以把Cat对象和Dog对象,传递给方法。
当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致,所以showAnimalEat完全可以替代以上两方法。
不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用
showAnimalEat都可以完成。从而实现了实现类的自动切换。
所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。
多态的弊端:
只能使用父类的方法、变量,运行方法的时候实际是子类的方法。如果子类有些独有的功能,此时多态的写法就无法访问子类独有功能了。
class Animal{public void eat(){System.out.println("动物吃东西!")}
}class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); }
} class Dog extends Animal { public void eat() { System.out.println("吃骨头"); }
}class Test{public static void main(String[] args){Animal a = new Cat();a.eat();a.catchMouse();//编译报错,编译看左边,Animal没有这个方法}
}
3、引用类型转换(解决多态弊端)
多态的写法只能用父类有的变量、方法,无法访问子类独有功能。想要调用子类特有的方法,必须做向下转型。多态的转型分为向上转型(自动转换)与向下转型(强制转换)两种。
向上转型(自动转换)
多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。父类变量接收子类对象,其实就是多态
父类类型 变量名 = new 子类类型();如:
Animal a = new Cat();
子类范围小可以直接自动转型给父类类型的变量。
向下转型(强制转换)
父类类型向子类类型向下转换的过程,这个过程是强制的。 一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
子类类型 变量名 = (子类类型) 父类变量名;如:
Aniaml a = new Cat();
Cat c =(Cat) a;
对比 基本数据类型转换
自动转换: 范围小的赋值给范围大的,自动完成:double d = 5;
强制转换: 范围大的赋值给范围小的,强制转换:int i = (int)3.14
引用类型转换 案例演示
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。转型演示,代码如下:
定义类:
abstract class Animal { abstract void eat();
}
class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); }
}
class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void watchHouse() { System.out.println("看家"); }
}
定义测试类:
public class Test {public static void main(String[] args) {// 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat// 向下转型 Cat c = (Cat)a; c.catchMouse(); // 调用的是 Cat 的 catchMouse}
}
转型的异常
public class Test {public static void main(String[] args) {// 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat// 向下转型 Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】}
}
这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了
Cat类型对象,运行时,当然不能转换成Dog对象的。
4、instanceof关键字
为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验。即判断对象是否某种引用类型,往往与多态一起使用,实现类型的向下转换
boolean flag = 对象 instanceof 类/接口
代码示例:
public class Test {public static void main(String[] args) {// 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat// 向下转型 if (a instanceof Cat){Cat c = (Cat)a; c.catchMouse(); // 调用的是 Cat 的 catchMouse} else if (a instanceof Dog){Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse}}
}
二、内部类
类中定义类,就是内部类。类A定义在类B里面,里面的那个类A就称为内部类,B则称为外部类。内部类是Java类的五大成份之一
应用场景
一个事物内部还有一个独立的事物,内部的事物脱离外部的事物无法独立使用
- 人里面有一颗心脏。
- 汽车内部有一个发动机。
- 为了实现更好的封装性
内部类分类
按定义的位置来分
- 1、成员内部类
静态的(有static修饰)
非静态的(无static修饰) - 2、局部内部类
类定义在方法内 - 3、 匿名内部类。
一般定义在方法中,或者可执行代码中
1、成员内部类
静态内部类(static修饰)
有static修饰的内部类,属于外部类本身的。静态内部类与其他类的用法完全一样。只是访问的时候需要加上外部类.内部类。
静态内部类可以直接访问外部类的静态成员。
定义格式:
//创建静态内部类对象
外部类.内部类 变量 = new 外部类.内部类构造器;//使用内部类
外部类.内部类。
示例代码:
// 外部类:Outer01
class Outer01{private static String sc_name = "黑马程序";// 内部类: Inner01public static class Inner01{// 这里面的东西与类是完全一样的。private String name;public Inner01(String name) { this.name = name;}public void showName(){System.out.println(this.name);// 拓展:静态内部类可以直接访问外部类的静态成员。System.out.println(sc_name);}}
}public class InnerClassDemo01 {public static void main(String[] args) {// 创建静态内部类对象。// 外部类.内部类 变量 = new 外部类.内部类构造器;Outer01.Inner01 in = new Outer01.Inner01("张三");in.showName();}
}
静态内部类与成员内部类的区别:
静态内部类只能使用外部类的静态变量与方法
实例内部类(非static修饰)
无static修饰的内部类,属于外部类对象的。(每个外部类对像都有一份)
拓展1:实例内部类不能定义静态成员。(因为静态成员比实例先创建)
拓展2:实例内部类可以直接访问外部类的私有和静态成员。
定义格式
//创建非静态内部类对象
外部类.内部类 变量 = new 外部类构造器.new 内部类构造器;//使用实例内部类。访问内部类的类型都是用 外部类.内部类
外部类.内部类。
代码示例
public class InnerClassDemo02 {public static void main(String[] args) {// 宿主:外部类对象。// Outer02 out = new Outer02();// 创建内部类对象。Outer02.Inner02 in = new Outer02().new Inner02("张三");in.showName();}
}class Outer02{// 实例内部类,属于外部类对象的。// 拓展:实例内部类不能定义静态成员。public class Inner02{// 这里面的东西与类是完全一样的。private String name;public Inner02(String name) {this.name = name;}public void showName(){System.out.println(this.name);}}
}
实例内部类面试题
成员内部类与外部类出现同名变量
请在?地方向上相应代码,以达到输出的内容
注意:内部类访问外部类对象的格式是:外部类名.this(=外部类对象)
public class Demo05 {public static void main(String[] args) {Body.Heart heart = new Body().new Heart();heart.jump();}
}class Body { // 身体private int weight = 30;// 在成员位置定义一个类class Heart {private int weight = 20;public void jump() {int weight = 10;//内部类访问实例内部类的局部变量 weightSystem.out.println("心脏在跳动 " + ?); // 10//内部类访问实例内部类的成员变量 this.weightSystem.out.println("心脏在跳动 " + ?); // 20//内部类访问外部类的成员变量 Body.this.weigtSystem.out.println("心脏在跳动 " + ?); // 30//内部类访问外部类的局部变量?局部变量只在方法中有效}}
}
执行流程
1、编译时,内部类,外部类各编译出一个Class文件
Body$Heart.Class
Body.Class
2、通过反编译Body$Heart.Class知道,内部类对象持有指向外部类对象的引用。即声明一个Body类型的final变量(外部类数据类型)。这个成员变量是编译器自动加上的。
final Body this$0;
3、编译器会自动为内部类添加一个有参构造方法,专门给这个常量赋值,指向外部类对象。参数的类型就是外部类的类型。
深入理解Java中为什么内部类可以访问外部类的成员
https://blog.csdn.net/weixin_39214481/article/details/80372676
2、局部内部类
定义在类中方法中的类。
class 外部类名 {数据类型 变量名;修饰符 返回值类型 方法名(参数列表) {// …class 内部类 {// 成员变量// 成员方法}}
}
局部内部类编译后仍然是一个独立的类,编译后有$还有一个数字。Chinese$1Chopsticks.class
局部内部类的好处:
能使用外部类的静态变量和方法。
访问方式:
静态变量:直接使用静态变量名
方法:外部类名.静态方法,外部类对象.方法
public class Demo08 {static String place = "白马程序员";public static void main(String[] args) {Demo08.show();}//成员方法public static void show(){//一个人的名字应该分为姓+名+字+昵称//局部内部类只能在方法中使用class Name{String xing;String ming;String zi;String niname;public Name(String xing, String ming, String zi, String niname) {this.xing = xing;this.ming = ming;this.zi = zi;this.niname = niname;}}//类需要创建对象才能使用Name name = new Name("菜","虚鲲","习生","篮球小王子");//直接使用外部类的静态变量placeSystem.out.println(place+"我姓"+name.xing+"名"+name.ming+"字"+name.zi+",人称"+name.niname);}
}
3、匿名内部类【重点】
是内部类的简化写法。本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象。 开发中,最常用到的内部类就是匿名内部类了。
应用场景
1、如果我们希望定义一个只要使用一次的类,就可考虑使用匿名内部类。匿名内部类的本质作用是为了简化代码。
2、方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。
优点和缺点:
优点:写法简单,一段代码做2件事情
缺点:找不到一个类来接收匿名内部类的对象,只能使用多态接收,接收后无法使用实现类本身独有的方法(多态缺点)。解决:可以在创建匿名内部类时,在{}后调用
//定义一个接口
public interface BeautyFish {//鼻子像头蒜public void noseIsSuan();//眼睛像绿豆public void eysIsBean();
}
public class Demo09 {public static void main(String[] args) {//中括号里面等于是一个实现BeautyFish接口的类,匿名内部类BeautyFish shanshan2 = new BeautyFish() {@Overridepublic void noseIsSuan() {System.out.println("鼻子像头蒜");}@Overridepublic void eysIsBean() {System.out.println("眼睛像绿豆");}//实现类独有方法,public void teethIsJian(){System.out.println("牙齿尖尖的");}}; //shanshan2.teethIsJian() //多态不能调用//在创建匿名内部类时可调用独有方法new BeautyFish() {@Overridepublic void noseIsSuan() {System.out.println("鼻子像头蒜");}@Overridepublic void eysIsBean() {System.out.println("眼睛像绿豆");}//实现类独有方法,public void teethIsJian(){System.out.println("牙齿尖尖的");}}.teethIsJian(); }
}
使用匿名内部类的前提和格式
使用前提:
匿名内部类必须继承一个父类或者实现一个父接口。即new的是父类/父接口
定义格式
//匿名内部类对象,格式1
父类名或者接口名 变量名 = new 父类名或者接口名(){// 方法重写@Overridepublic void method() {// 执行语句}
};//匿名内部类对象,格式2
new 父类名或者接口名(){// 方法重写@Overridepublic void method() {// 执行语句}
};//匿名内部类调用重写后的方法。如果有多个重写的方法,也只能调用一个方法
new 父类名或者接口名(){// 方法重写@Overridepublic void method() {// 执行语句}@Override...
}.method();
理解:即在创建父类/接口的对象,在后面加中括号{},在中括号里重写父类/接口方法。相当于这个中括号的代码就是一个子类/实现类
匿名内部类的特点
- 定义一个没有名字的内部类
- 这个类实现了父类,或者父类接口
- 匿名内部类会创建这个没有名字的类的对象
匿名内部类做了什么事情:
1、创建了实现类/子类对象,对象是实现类/子类
2、重写了接口/父类的方法
4、匿名内部类案例1(简化继承/实现)
我們使用接口时,得做如下几步操作:
- 定义子类
- 重写接口中的方法
- 创建子类对象
- 调用重写后的方法
//定义接口
interface Swim {public abstract void swimming();
}// 1. 定义接口的实现类
class Student implements Swim {// 2. 重写抽象方法@Overridepublic void swimming() {System.out.println("狗刨式...");}
}public class Demo07 {public static void main(String[] args) {// 3. 创建实现类对象Student s = new Student();// 4. 调用方法 s.swimming();}
}
我们的目的,最终只是为了调用方法,简化一下,把以上四步合成一步,匿名内部类就是做这样的快捷方式。
简化后代码
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 使用匿名内部类new Swim() {@Overridepublic void swimming() {System.out.println("自由泳...");}}.swimming();// 接口 变量 = new 实现类(); // 使用多态,走子类的重写方法Swim s2 = new Swim() {@Overridepublic void swimming() {System.out.println("蛙泳...");}};s2.swimming();}
}
总结:
即使用匿名内部类简化了 定义子类去继承/实现、创建子类对象 的代码部分
5、匿名内部类案例2(匿名内部类对象作为参数传入)
在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 方法一:普通方式传入对象// 创建实现类对象Student s = new Student();goSwimming(s);// 方法二:使用匿名内部类作为方法参数传入Swim s3 = new Swim() {@Overridepublic void swimming() {System.out.println("蝶泳...");}};// 传入匿名内部类goSwimming(s3);// 完美方案: 一步到位goSwimming(new Swim() {@Overridepublic void swimming() {System.out.println("大学生, 蛙泳...");}});goSwimming(new Swim() {@Overridepublic void swimming() {System.out.println("小学生, 自由泳...");}});}// 定义一个方法,模拟请一些人去游泳public static void goSwimming(Swim s) {s.swimming();}
}
6、匿名内部类案例3(匿名内部类写法实现成员内部类、局部内部类)
即这时候定义的成员内部类、局部内部类都继承类/实现接口。普通内部类就是定义一个类
三、包和权限修饰符
1、包
包就是我们每天建的项目目录,我们每次都会建立一个包,这个包在磁盘下其实就是一个目录。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护。
命名规范:
路径名.路径名.xxx.xxx
// 例如:com.itheima.oa
- 包名一般是公司域名的倒写。例如:黑马是www.itheima.com,包名就可以定义成com.itheima.技术名称。
- 包名必须用”.“连接。
- 包名的每个路径名必须是一个合法的标识符,而且不能是Java的关键字
- 包名英文全部小写
2、权限修饰符
Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限
- public:公共的,所有地方都可以访问。
- protected:当前类 ,当前包,当前类的子类可以访问。
- 缺省(没有修饰符):当前类 ,当前包可以访问。
- private:私有的,当前类可以访问。
public > protected > 缺省 > private
不同权限的访问能力
权限修饰符的选择使用
编写代码时,如果没有特殊的考虑,建议这样使用权限:
- 成员变量使用 private ,隐藏细节。
- 构造方法使用 public ,方便创建对象。
- 成员方法使用 public ,方便调用方法。
小贴士:不加权限修饰符,就是default权限
四、代码块
使用{}括起来的代码被称为代码块,代码块是类的五大成分之一。按照有无static可以分为静态代码块和实例代码块。
类有且仅有五大成分:1.成员变量,2.构造器,3.成员方法,4.代码块,5.内部类
1、静态代码块
有static修饰,必须放在类下。与类一起加载执行。
static{// 执行代码
}
特点:
1、每次执行类,加载类的时候都会先执行静态代码块一次。静态代码块会快于对象创建
2、静态代码块是自动触发执行的,只要程序启动静态代码块就会先执行一次。
3、在类加载的init阶段,类的类构造器中会收集所有的static块和字段并执行,static块只执行一次,由JVM保证其只执行一次。
作用:在启动程序之前可以做资源的初始化,一般用于初始化静态资源。
public class DaimaKuaiDemo01 {public static String sc_name ; // 1.静态代码块static {// 初始化静态资源sc_name = "黑马程序员!";System.out.println("静态代码块执行!");}public static void main(String[] args) {System.out.println("main方法执行");System.out.println(sc_name);}
}
2、实例代码块(又叫 构造代码块 / 非静态代码块)
直接在类中定义且没有加static关键字的代码块称为{}构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。
{// 执行代码
}
特点
1、无static修饰。属于对象,与对象的创建一起执行的。每次调用构造方法【前】运行
- 每次在执行构造方法之前,如果当前类中有构造代码块,优先执行构造代码块,然后在执行构造方法
2、每次调用构造器初始化对象,实例-代码块都要自动触发执行一次。
3、实例代码块实际上是提取到每一个构造器中去执行的。
作用:实例代码块用于初始化对象的资源。
public class DaimaKuaiDemo02 {private String name ;// 实例代码块。 无static修饰。{System.out.println("实例代码块执行");name = "dl";}// 构造器public DaimaKuaiDemo02(){//System.out.println("实例代码块执行");}// 有参数构造器public DaimaKuaiDemo02(String name){//System.out.println("实例代码块执行");} public static void main(String[] args) {// 匿名对象,创建出来没有给变量。new DaimaKuaiDemo02();new DaimaKuaiDemo02();new DaimaKuaiDemo02("xulei");}
}// 输出三次:实例代码块执行
面试题:
静态代码块,构造代码块,构造方法的执行顺序?
静态代码块 > 构造代码块 > 构造方法
- 静态代码块:只执行一次
- 构造代码块:每次调用构造方法都执行
- 主方法类中的静态代码块:优先于主方法执行
3、局部代码块
位置:方法中
作用:限定变量的生命周期(即变量仅在局部代码块的{}中有效)
public class 局部代码块 {public static void main(String[] args) {int i = 10;//局部代码块内的内容在主方法里是一定会被执行的(除非有限制条件),只是中间变量的生存期不同了。{System.out.println(i);//这里的i是主方法里的局部变量i = 20;//这里的j是局部代码块中的局部变量int j = 100;System.out.println(j);//上面的j执行完在这个代码块中已经没有使用了,将会随着代码块执行的结束而消亡别回收System.out.println("我是局部代码块");}System.out.println(i);//这里的i的值已经在局部代码块中被改变了,局部代码块只是会限制局部代码块里声明的变量,会保留对外部的变量进行的修改//System.out.println(j);报错,不能访问到局部代码块中的变量}
https://blog.csdn.net/qq_39565202/article/details/102858940
深入了解代码块
任何大括号封装的,得到的都是一个区块,可以称为代码块。
如果在代码块的前面加上if(), 那么这就叫做if代码块;如果加的是public static void main(String[] args),那么这就叫做主函数代码块。这些都相当于代码块的名称。
如果什么都不加,根据位置,在类中方法外称为构造代码块、静态代码块。在方法中称为局部代码块
class Demo
{//类代码块public static void main(String[] args){//主函数代码块if(false){//if代码块System.out.println("A");}System.out.println("Helllo World!");}}
有名字的都叫xxx代码块,如类代码块,主函数代码块,if代码块,如果代码块前面没有语句,根据位置,在类中方法外称为构造代码块、静态代码块。在方法中称为局部代码块
https://www.cnblogs.com/wsw-bk/p/7488549.html
五、Object类
java.lang.Object 类是Java语言中的根类,即所有类的父类/基类。Object的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:
public class MyClass /*extends Object*/ {// ...
}
Object 是一个特殊的类,是所有类的父类;它提供了11个方法。今天我们主要学习其中的2个:
public String toString() :返回该对象的字符串表示。
public boolean equals(Object obj) :指示其他某个对象是否与此对象“相等”。
1、toString()
在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法。
toString方法返回该对象的字符串表示,该字符串内容就是对象的类型+@+内存地址值。
在开发中,经常需要按照对象的属性得到相应的字符串表现形式(即属性值的字符串),因此也需要重写toString方法。
即toString()未重写前,输出的是对象的内存地址,重写后输出的是对象属性的值
- 默认情况下:包名.类名@(16进制)内存地址
- 有时候需要看类中的属性:就需要重写equals
覆盖重写
在IntelliJ IDEA中,可以点击 Code 菜单中的 Generate… ,也可以使用快捷键 alt+insert ,点击 toString() 选项。选择需要包含的成员变量并确定。
public class Person { private String name;private int age;@Overridepublic String toString() {return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';}// 省略构造器与Getter Setter
}
2、equals方法
euqlas是Object的方法,默认情况下其实 与 == 一样。
boolean equals(Object obj){return (this == obj);
}
回顾 ==:
1、基本类型:判断的是值
2、引用类型:判断的是引用地址
覆盖重写
覆盖重写,使equals方法可以按照自定义规则比较2个对象是否一致。
import java.util.Objects;
public class Person {private String name;private int age;@Overridepublic boolean equals(Object o) {// 如果对象地址一样,则认为相同if (this == o)return true;// 如果参数为空,或者类型信息不一样,则认为不同if (o == null || getClass() != o.getClass())return false;// 转换为当前类型Person person = (Person) o;// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果return age == person.age && Objects.equals(name, person.name);}
}
自动覆盖重写equals:
在IntelliJ IDEA中,可以使用 Code 菜单中的 Generate… 选项,也可以使用快捷键 alt+insert ,并选择equals() and hashCode() 进行自动代码生成。
使用
boolean flag = 对象.equals(对象); //将调用该方法的对象与传入的对象比较
Object类当中的hashCode等其他方法,今后学习。
六、Objects类
Objects类是对象工具类,它里面的的方法都是用来操作对象的。
所有工具类的方法使用
工具类名.方法名
1、equals方法(Objects类)
比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问
题。
public static boolean equals(Object a, Object b) :判断两个对象是否相等。//工具类equals方法使用
boolean flag = Objects.equals(对象,对象); //传入两个要比较的的对象
Objects(工具类)的equals方法源码
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b));
}
本质是进行了空判断的Obejct(基类)的equals方法
2、isNull方法
static boolean isNull(Object obj) //判断对象是否为null,如果为null返回true。//使用方法
boolean flag = Objects.isNull(对象); //传入要判断的的对象
这篇关于Java基础加强重温_03:多态(使用前提、格式、流程、利弊、类型转换)、instanceof关键字(判断引用类型)、内部类()、包和权限修饰符()、代码块()、Object类和Objects类()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!