再探Java为面试赋能(二)Java基础知识(二)反射机制、Lambda表达式、多态

文章目录

    • 前言
    • 1.4 反射机制
      • 1.4.1 Class对象的获取
      • 1.4.2 Class类的方法
      • 1.4.3 通过反射机制修改只读类的属性
    • 1.5 Lambda表达式
      • 1.5.1 函数式接口
      • 1.5.2 Lambda表达式的使用
    • 1.6 多态
      • 1.6.1 多态的概念
      • 1.6.2 多态的实现条件
      • 1.6.3 重载(Overload)和重写(Override)

前言

往期精选:

再探Java为面试赋能(一)Java基础知识(一)变量初始化顺序、构造方法、clone方法

1.4 反射机制

Java语言的反射机制,是指动态获取类或对象的属性以及方法,从而完成调用功能的一种机制。它主要实现了以下功能:

  • 获取类的访问修饰符、属性、方法以及父类信息。
  • 在运行时根据类名创建对象,还可以调用对象的任意方法。
  • 生成动态代理。

1.4.1 Class对象的获取

在反射机制中,Class类是一个非常重要的类,获取Class对象主要有3种方法:

  • 1)通过className.class获取:
public class Food {static {System.out.println("Food类的静态代码块执行了...");}{System.out.println("Food类的非静态代码块执行了...");}public static void main(String[] args) {Class<Food> aClass = Food.class;System.out.println("className = " + aClass.getName());}
}

程序运行结果:

Food类的静态代码块执行了...
className = test03.Food
  • 2)通过Class.forName()获取:
public class Food {static {System.out.println("Food类的静态代码块执行了...");}{System.out.println("Food类的非静态代码块执行了...");}public static void main(String[] args) throws ClassNotFoundException {Class<?> food = Class.forName("test03.Food");System.out.println("className = " + food.getName());}
}

程序运行结果:

Food类的静态代码块执行了...
className = test03.Food
  • 3)通过Object.getClass()获取:
public class Food {static {System.out.println("Food类的静态代码块执行了...");}{System.out.println("Food类的非静态代码块执行了...");}public static void main(String[] args) {Class<? extends Food> aClass = new Food().getClass();System.out.println("className = " + aClass.getName());}
}

程序运行结果:

Food类的静态代码块执行了...
Food类的非静态代码块执行了...
className = test03.Food

如上面的例子所示,三种方式都可以获得类的Class对象,但也有一些区别:

  • 方法 1)2)执行静态代码块,但不执行非静态代码块;
  • 方法 3)由于创建了对象,因此会执行静态代码块和非静态代码块。

1.4.2 Class类的方法

Class类提供了非常多的方法,常用的有三类:

  • 1)获取类的构造方法

构造方法的封装类为Constructor。

源码:java.lang.Class// 返回类的所有的public构造方法
public Constructor<?>[] getConstructors()
// 返回类的指定参数的public构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
// 返回类的所有构造方法
public Constructor<?>[] getDeclaredConstructors()
// 返回类的指定参数的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
  • 2)获取类的成员变量的方法

成员变量的封装类为Field。

源码:java.lang.Class// 返回类的所有public成员变量
public Field[] getFields()
// 返回类的指定名称的public成员变量
public Field getField(String name)
// 返回类的所有成员变量
public Field[] getDeclaredFields()
// 返回类的指定名称的成员变量
public Field getDeclaredField(String name)
  • 3)获取类的方法

方法的封装类为Method。

源码:java.lang.Class// 返回类的所有public方法
public Method[] getMethods()
// 返回类的指定名称和参数的public方法
public Method getMethod(String name, Class<?>... parameterTypes)
// 返回类的所有方法
public Method[] getDeclaredMethods()
// 返回类的指定名称和参数的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

1.4.3 通过反射机制修改只读类的属性

有如下代码:

public class ReadOnlyClass {private Integer age = 20;public Integer getAge() {return age;}
}

在这个类中,age属性被修饰为private,且只提供了getter方法,而没有提供setter方法,因此这个类型是一个只读的类,无法通过常规方法修改age属性。

但通过Java的反射机制就可以修改age属性。例如:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {ReadOnlyClass roc = new ReadOnlyClass();System.out.println("修改前age = " + roc.getAge());Class<ReadOnlyClass> aClass = ReadOnlyClass.class;Field field = aClass.getDeclaredField("age");field.setAccessible(true);// 修改roc对象的age属性field.set(roc, 30);System.out.println("修改后age = " + roc.getAge());
}

执行结果:

修改前age = 20
修改后age = 30

1.5 Lambda表达式

简单来说,Lambda表达式就是对匿名内部类的简写。它的基本语法是:

<函数式接口> <变量名> = (参数1, 参数2, ...) -> {// 方法体
}

1.5.1 函数式接口

函数式接口就是一个有且仅有一个抽象方法的接口。

例如Runnable接口就是一个函数式接口:

源码:java.lang.Runnable@FunctionalInterface
public interface Runnable {public abstract void run();
}

可见,Runnable接口中只包含一个抽象的run()方法,并且在接口上标注了一个@FuncationInterface注解,此注解就是 Java 8 新增的注解,用来标识一个函数式接口。

想要自定义一个函数式接口也非常简单,只需要在接口中定义一个抽象方法,然后在接口上标记@FunctionalInterface注解。

当然,该注解也可以不标记,只是说标记了该注解,编辑器会自动检测自定义的函数式接口是否有问题。例如:

1.5.2 Lambda表达式的使用

下面是一个自定义的函数式接口,定义了一个有参数有返回值的sum()方法:

@FunctionalInterface
public interface MyInterface {public abstract int sum(int a, int b);
}

使用Lambda表达式调用该方法:

public static void main(String[] args) {// 使用匿名内部类方式MyInterface myInterface = new MyInterface() {@Overridepublic int sum(int a, int b) {return a+b;}};int sum = myInterface.sum(5, 10);System.out.println("匿名内部类方式 sum = " + sum);// 使用Lambda表达式MyInterface myi = (a, b) -> a+b;int sum1 = myi.sum(2, 8);System.out.println("Lambda表达式方式 sum1 = " + sum1);
}

执行结果:

匿名内部类方式 sum = 15
Lambda表达式方式 sum1 = 15

可见,使用Lambda表达式后,代码变得更加简介。

Lambda表达式还有更多编写规则如下:

  • 1)参数只需要参数名称,不需要参数类型,编译器会自动推断类型。如示例中:(a, b)
  • 2)如果参数只有一个,可以省略小括号(),没有参数或者参数多于一个,不能省略小括号。
  • 3)方法体只有一行代码时,可以省略中括号{}
  • 4)方法体只有一行代码时,且有返回值时,可以省略return关键字。如示例中:-> a+b

1.6 多态

1.6.1 多态的概念

多态是面向对象编程中的一个重要概念,它允许不同类型的对象对同一方法进行不同的实现。

具体来说,多态是指通过父类的引用变量来指向子类的对象,从而实现对不同对象的统一操作。

例如,猫和狗都是动物,都有“吃”这个共同行为,具体表现在狗身上可能是啃骨头,表现在猫身上可能是吃猫粮。这就是多态的表现,即同一件事情,发生在不同的对象身上,就会产生不同的结果。

1.6.2 多态的实现条件

在Java中,要实现多态性,就必须满足以下条件:

  • 1)继承关系
  • 2)方法重写
  • 3)父类引用指向子类对象

例如,首先定义一个父类Animal,该类有一个eat()方法:

public class Animal {public void eat() {System.out.println("动物吃东西...");}
}

再定义两个子类Dog和Cat,均继承父类Animal,并重写其eat()方法:

public class Dog extends Animal {// 1.继承关系// 2.方法重写@Overridepublic void eat() {System.out.println("狗啃骨头...");}
}
public class Cat extends Animal {// 1.继承关系// 2.方法重写@Overridepublic void eat() {System.out.println("猫吃猫粮...");}
}

最后编写测试方法:

public class Main {public static void main(String[] args) {// 3.父类引用指向子类对象Animal dog = new Dog();Animal cat = new Cat();dog.eat();cat.eat();}
}

执行结果:

狗啃骨头...
猫吃猫粮...

1.6.3 重载(Overload)和重写(Override)

Java中多态的实现条件之一是方法重写,是指子类重新定义和实现从父类继承而来的方法,以改变方法的行为,提供自己特定的实现。

方法重写必须遵循一些规则:

  • 1)子类重写方法的名称、参数列表(包括数量、类型、顺序)和返回值类型都必须与父类中被重写的方法相同。
  • 2)重写方法的访问修饰符的权限不能低于父类方法的权限。例如,父类方法被public修饰,则子类中重写方法就不能声明为protected
  • 3)重写方法不能抛出比父类方法更多或更宽泛的异常,重写方法可以抛出相同的异常或更具体的异常,或者不抛出异常。
  • 4)重写方法可以通过super()函数调用父类方法的逻辑。

重载是指在一个类中定义了多个同名的方法。 它也必须遵循一些规则:

  • 1)重载的方法必须定义在一个类中,它们的名称必须相同。
  • 2)重载的方法的参数列表必须不同,可以通过参数的个数、类型、顺序的不同来进行区分。
  • 3)重载的方法的返回值类型可以相同也可以不同。

总结一下,重载和重写的区别:

  • 1)定义位置。重载方法定义在同一个类中,而重写方法定义在父类和子类之间。
  • 2)方法签名。重载方法具有相同的名称,但方法签名(参数类型、个数或顺序)不同,而重写方法具有相同的名称和方法签名。
  • 3)调用时机。重载方法是根据方法签名的不同进行静态绑定,在编译时就确定,而重写方法是根据对象的实际类型进行动态绑定,要在运行时确定。

本节完,更多内容请查阅分类专栏:再探Java为面试赋能

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析(已完结)
  • MyBatis3源码深度解析(已完结)
  • Redis从入门到精通(持续更新中…)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/301924.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Python+OpenCV截取视频中所有含有字幕的画面

1、需求背景 有的视频文件的字幕已经压制到了视频的图像中&#xff0c;不能单独提取出字幕文件。网上的 “提取视频字幕” 网站多为提取视频中的字幕文件&#xff0c;而非识别视频图像中的字幕。少数通过OCR技术识别画面中字幕的工具需要在线运行、运行速度较慢&#xff0c;或…

力扣2- 两数相加

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

前端layui自定义图标的简单使用

iconfont-阿里巴巴矢量图标库 2. 3. 4.追加新图标 5.文件复制追加新图标

TCP/IP协议、HTTP协议和FTP协议等网络协议简介

文章目录 一、常见的网络协议二、TCP/IP协议1、TCP/IP协议模型被划分为四个层次2、TCP/IP五层模型3、TCP/IP七层模型 三、FTP网络协议四、Http网络协议1、Http网络协议简介2、Http网络协议的内容3、HTTP请求协议包组成4、HTTP响应协议包组成 一、常见的网络协议 常见的网络协议…

DIY可视化UniApp表格组件

表格组件在移动端的用处非常广泛&#xff0c;特别是在那些需要展示结构化数据、进行比较分析或提供详细信息的场景中。数据展示与整理&#xff1a;表格是展示结构化数据的理想方式&#xff0c;特别是在需要展示多列和多行数据时。通过表格&#xff0c;用户可以轻松浏览和理解数…

vue 中使 date/time/datetime 类型的 input 支持 placeholder 方法

一般在开发时&#xff0c;设置了 date/time/datetime 等类型的 input 属性 placeholder 提示文本时&#xff0c; 发现实际展示中却并不生效&#xff0c;如图&#xff1a; 处理后效果如图&#xff1a; 处理逻辑 判断表单项未设置值时&#xff0c;则设置其伪类样式&#xff0c;文…

2024-04-08 NO.6 Quest3 自定义交互事件

文章目录 1 交互事件——更改 Cube 颜色2 交互事件——创建 Cube2.1 非代码方式2.2 代码方式 ​ 在开始操作前&#xff0c;我们导入上次操作的场景&#xff0c;相关介绍在 《2024-04-08 NO.5 Quest3 手势追踪进行 UI 交互-CSDN博客》 文章中。 1 交互事件——更改 Cube 颜色 …

知识管理系统|基于Springboot和vue的知识管理系统设计与实现(源码+数据库+文档)

知识管理 目录 基于Springboot和vue的知识管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台&#xff1a; 5.2.2 文章信息 5.3.1 论坛交流 2、后台 用户管理 5.1.2 文章分类 5.2.1 资料分类 四、数据库设计 五、核心代码 六、论文参考 七、最…

OpenHarmony实战:Combo解决方案之W800芯片移植案例

本方案基于OpenHarmony LiteOS-M内核&#xff0c;使用联盛德W800芯片的润和软件海王星系列Neptune100开发板&#xff0c;进行开发移植。 移植架构采用Board与SoC分离方案&#xff0c;支持通过Kconfig图形化配置编译选项&#xff0c;增加玄铁ck804ef架构移植&#xff0c;实现了…

老子云、AMRT3D、眸瑞科技

老子云概述 老子云3D可视化快速开发平台&#xff0c;集云压缩、云烘焙、云存储云展示于一体&#xff0c;使3D模型资源自动输出至移动端PC端、Web端&#xff0c;能在多设备、全平台进行展示和交互&#xff0c;是全球领先、自主可控的自动化3D云引擎。 平台架构 平台特性 1、基…

Java | Leetcode Java题解之第18题四数之和

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> quadruplets new ArrayList<List<Integer>>();if (nums null || nums.length < 4) {return…

spring cloud gateway openfeign 联合使用产生死锁问题

spring cloud gateway openfeign 联合使用产生死锁问题&#xff0c;应用启动的时候阻塞卡住。 spring.cloud 版本如下 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><vers…

【Leetcode每日一题】 递归 - 二叉树剪枝(难度⭐⭐)(50)

1. 题目解析 题目链接&#xff1a;814. 二叉树剪枝 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 想象一下&#xff0c;你有一堆层层叠叠的积木&#xff0c;你想从底部开始&#xff0c;把那些标记为0的积木拿走。如…

在线免费图像处理

功能 尺寸修改(自定义和内置常用的照片尺寸)图像压缩(比较好的情况最高可以压缩 10 倍, 如果是无损压缩可以压缩 5 倍左右,参数范围 50~70 左右)图像方向修改图像格式修改修改后的效果支持实时反馈, 并且支持点击图像预览,同时保留历史修改图片(在预览中可以查看)支持修改撤回…

怎么防止文件被拷贝,复制别人拷贝电脑文件

怎么防止文件被拷贝&#xff0c;复制别人拷贝电,脑文件 防止文件被拷贝通常是为了保护敏感数据、知识产权或商业秘密不被未经授权的人员获取或传播。以下列出了一系列技术手段和策略&#xff0c;可以帮助您有效地防止文件被拷贝。 1. 终端管理软件&#xff1a; 如安企神、域智…

鸿蒙ArkUI声明式学习:【UI资源管理】

OpenHarmony 应用的资源分类和资源的访问以及应用开发使用的像素单位以及各单位之间相互转换的方法。 资源分类 移动端应用开发常用到的资源比如图片&#xff0c;音视频&#xff0c;字符串等都有固定的存放目录&#xff0c;OpenHarmony 把这些应用的资源文件统一放在 resourc…

什么是人工智能?人工智能、机器学习、深度学习三者之间有什么关系吗?

深度学习是机器学习的一个分支。深度学习是机器学习的一部分&#xff0c;与机器学习的其他分支学科&#xff0c;以及统计学、人工智能等学科都有着紧密的联系。深度学习、机器学习、人工智能、统计学之间的关系如图1-4所示。 图1-4 深度学习、机器学习、人工智能、统计学之间的…

如何利用Flutter将应用成功上架至iOS平台:详细指南

引言 &#x1f680; Flutter作为一种跨平台的移动应用程序开发框架&#xff0c;为开发者提供了便利&#xff0c;使他们能够通过单一的代码库构建出高性能、高保真度的应用程序&#xff0c;同时支持Android和iOS两个平台。然而&#xff0c;完成Flutter应用程序的开发只是第一步…

【鸿蒙开发】系统组件Column

Column组件 Column沿垂直方向布局的容器。 接口&#xff1a; Column(value?: {space?: string | number}) 参数&#xff1a; 参数名 参数类型 必填 参数描述 space string | number 否 纵向布局元素垂直方向间距。 从API version 9开始&#xff0c;space为负数或者…

【网络】什么是RPC

RPC 是Remote Procedure Call的缩写&#xff0c;译为远程过程调用。是一个计算机通信协议。 1、为什么需要远程调用 在如何给女朋友解释什么是分布式这一篇文章中介绍过&#xff0c;为了提升饭店的服务能力&#xff0c;饭店从一开始只有一个负责所有事情的厨师发展成有厨师、切…