Java基础加强重温_03:多态(使用前提、格式、流程、利弊、类型转换)、instanceof关键字(判断引用类型)、内部类()、包和权限修饰符()、代码块()、Object类和Objects类()

本文主要是介绍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. 人里面有一颗心脏。
  2. 汽车内部有一个发动机。
  3. 为了实现更好的封装性

内部类分类

按定义的位置来分

  • 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. 这个类实现了父类,或者父类接口
  3. 匿名内部类会创建这个没有名字的类的对象
匿名内部类做了什么事情:

1、创建了实现类/子类对象,对象是实现类/子类
2、重写了接口/父类的方法

4、匿名内部类案例1(简化继承/实现)

我們使用接口时,得做如下几步操作:

  1. 定义子类
  2. 重写接口中的方法
  3. 创建子类对象
  4. 调用重写后的方法
//定义接口
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类()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/382006

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听