当前位置:网站首页>反射、枚举以及lambda表达式
反射、枚举以及lambda表达式
2022-07-26 15:12:00 【快到锅里来呀】
目录
1. 反射的理解
(1)反射机制(reflection)
java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性,既然可以拿到,那就可以修改部分类型信息;这种动态获取信息以及动态调用方法的功能称为java语言的反射机制
(2)应用
1.反射最重要的作用是开发各种通用的框架
2.在日常的第三方应用开发的过程中,经常遇到某个类的某个成员变量、方法或是私有的或是只对系统应用开发的,这时候就可以用java反射机制获取私有成员或方法
(3)反射基本信息
java程序中许多对象运行时会有两种类型:
运行时类型和编译时类型
程序运行本质是在运行时发现对象的类的真实信息,通过反射机制就可以判断出该对象和类属于那些类
2. 反射相关的类
| 类名 | 用途 |
|---|---|
| Class类 | 代表类的实体,在运行java应用程序中表示类的接口 |
| Field类 | 代表类的成员变量 / 类的属性 |
| Method类 | 代表类的方法 |
| Constructor类 | 代表类的构造方法 |
2.1 Class类中的相关方法

(1)常用获得类相关的方法
| 方法 | 用途 |
|---|---|
| getClassLoader() | 获得类的加载器 |
| getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有) |
| forName(String className) | 根据类名返回类的对象 |
| newInstance() | 创建类的实例 |
| getName() | 获得类的完整路径名字 |
(2)常用获得类中属性相关的方法(返回值为Field相关)
| 方法 | 用途 |
|---|---|
| getField(String name) | 获得某个公有的属性对象 |
| getFields() | 获得所有公有的属性对象 |
| getDeclaredField(String name) | 获得某个属性对象 |
| getDeclaredFields() | 获得所有属性对象 |
(3)获得类中的构造器相关的方法(返回值为Constructor相关)
| 方法 | 用途 |
|---|---|
| getConstructor(Class...<?>parameter Types) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所有公有构造方法 |
getDeclaredConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
(4)获得类中方法 相关的方法(返回值为Method相关)
| 方法 | 用途 |
|---|---|
getMethod(String name, Class...<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class...<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
2.2 反射使用
(1)获得Class对象的三种方式
1. 使用Class.forName("类的全路径名");静态方法
public static void main(String[] args) throws ClassNotFoundException { //1.通过Class对象的forName()静态方法获取(用的最多,注意抛异常) Class<?> c1 = Class.forName("reflectdemo.Student"); }2. 使用.class方法
//3.直接通过 类型.class获取(更安全可靠,程序性能更高) Class<?> c3 = Student.class;3. 使用类对象的getClass()方法
//2.通过getClass获取class对象 Student student = new Student(); Class<?> c2 = student.getClass();
(2)反射的使用
所有和反射相关的包都在import.java.lang.reflect包下
1.通过反射创建对象
public static void reflectNewInstance() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
System.out.println(student);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}2.反射私有的构造方法,屏蔽内容为获得公有的构造方法
public static void reflectPrivateConstructor() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
//注意传入对应的参数
Constructor<?> constructor =
c1.getDeclaredConstructor(String.class, int.class);
//你确定要在类外访问私有方法吗.设置为true后可修改访问权限
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("xiangyu",22);
System.out.println(student);
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}3.反射私有属性
public static void reflectPrivateField() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
//可以修改该属性的值
Field field = c1.getDeclaredField("name");
//访问私有的,提前询问一下是否确定访问
field.setAccessible(true);
field.set(student,"liubang");
System.out.println(student);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}4. 反射私有方法
public static void reflectPrivateMethod() {
try {
Class<?> c1 = Class.forName("reflectdemo.Student");
Student student = (Student) c1.newInstance();
Method method = c1.getDeclaredMethod("function", String.class);
method.setAccessible(true);
method.invoke(student,"通过反射给你传参");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}2.3 反射优缺点
优点:
1.任意一个类,都能够知道这个类的所有属性和方法
任意一个对象,都能够调用它的任意一个方法
2.增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
3.反射运用在很多框架上
缺点:
1.反射因为调用很多方法,就会有效率降低的问题
2.反射技术绕过了源代码的技术,会有维护的问题,并且反射代码比相应直接代码更复杂
3. 枚举的使用
(1)枚举理解
枚举是在JDK1.5引入使用的
作用:将一组常量组织起来,在这之前表示一组常量通过使用定义常量的方式
本质:是java.lang.Enum的子类,也就是自定义的枚举类,就是没有显示继承Enum,默认也继承了这个类
public enum enumDemo01 {
ONE,TWE,TREE;//枚举对象
}(2)switch语句
public static void main1(String[] args) {
enumDemo01 enumDemo01 = enumdemo.enumDemo01.TWE;
switch (enumDemo01) {
case ONE:
System.out.println("1");
break;
case TWE:
System.out.println("2");
break;
case TREE:
System.out.println("3");
break;
default:
break;
}
}
(3)Enum类的常用方法
| 方法名称 | 描述 |
|---|---|
| values() | 以数组形式返回枚举类型的所有成员 |
| ordinal() | 获取枚举成员的索引位置 |
| valueOf() | 将普通字符串转换为枚举实例 |
| compareTo() | 比较两个枚举成员在定义时的顺序 |
public static void main2(String[] args) {
enumDemo01[] enumDemo01s = enumDemo01.values();
for (int i = 0; i < enumDemo01s.length; i++) {
System.out.println(enumDemo01s[i] + " 序号:" + enumDemo01s[i].ordinal());
}
enumDemo01 e1 = enumDemo01.valueOf("TREE");
System.out.println(e1);
}public static void main(String[] args) {
//拿到枚举实例TWE
enumDemo01 e1 = enumDemo01.TWE;
//拿到枚举实例TREE
enumDemo01 e2 = enumDemo01.TREE;
//比较的是序号
System.out.println(enumDemo01.TREE.compareTo(e1));
System.out.println(ONE.compareTo(TWE));
System.out.println(ONE.compareTo(TREE));
}(4)枚举的构造方法默认是私有的
public enum enumDemo01 {
ONE,TWE("twe",2),TREE;//枚举对象
public String figure;
public int ordinal;
//枚举的构造方法默认是私有的
enumDemo01(String figure, int ordinal) {
this.figure = figure;
this.ordinal = ordinal;
}
enumDemo01() {
}
}(5)枚举优缺点
优点:
1.枚举常量更简单安全
2.枚举具有内置方法,代码跟美观
3.枚举无法被反射和序列化
缺点:
1.不可继承,无法扩展
4.枚举不能被反射
前面学过了反射,对任何一个类,即使构造方法是私有的,也可以通过反射拿到实例对象,那么枚举的构造方法也是私有的,通过反射可以拿到吗?
public class Demo01 {
public static void reflectPrivateConstructor() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> c1 = Class.forName("enumdemo.enumDemo01");
Constructor<?> constructor =
c1.getDeclaredConstructor(String.class, int.class,String.class, int.class);
constructor.setAccessible(true);
enumDemo01 e1 = (enumDemo01)constructor.newInstance("xigua",66);
System.out.println(e1);
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
reflectPrivateConstructor();
}
}
可以看到是报错的,找到newInstance源码
可以看到

枚举是不能被反射的。所以枚举是很安全的
5. Lambda表达式
5.1 Lambda表达式语法
(1)理解
Lambda表达式相当于匿名函数一样,Lambda表达式允许将一个函数作为另外一个函数的参数;
Lambda表达式允许通过表达式来代替功能接口;
Lambda表达式就和方法一样,提供一个正常的参数列表和使用这些参数的主体(可以是表达式、代码块)
lambda表达式也可称为闭包
(2)语法
语法:(parameters)-> expression 或 (parameters) -> {statements;}
Lambda表达式三部分组成:
1) paraments:相当于方法中的参数列表,这里的参数是函数式接口里的函数
参数类型可以明确声明,也可以又jvm隐含判断
当只有一个推断类型时可以省略圆括号
2)->:相当于 “被用于”
3)方法体:表达式可以是代码块,也可以是函数式接口里方法的实现
可以有返回值,也可以不返回
//1.不需要参数,直接返回值
()-> 6
//2.一个参数类型,返回值
x -> 2*x
//3.两个参数,返回值
(x,y) -> x+y
//4.两个int型整数,返回值
(int x,int y) -> x*y
//5.接收一个string对象,在控制台打印,不返回值
(String s) -> system.out.print(s)5.2 函数式接口
函数式接口定义:一个接口有且只有一个抽象方法 。
我们在写函数式接口时可以声明@FunctionalInterface 注解,这样编译器就可以根据函数式接口的定义来要求该接口,此时如果有两个抽象方法,编译器就会报错

public class Demo01 {
public static void main(String[] args) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
}
//此时这里相当于一个类实现了Comparator接口 同时重写了抽象方法compare
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> {return o2-o1;});
PriorityQueue<Integer> priorityQueue1 = new PriorityQueue<>(((o1, o2) -> o2-o1));
}
5.3 Lambda表达式的基本使用
Lambda表达式本质上是一个匿名函数可以理解为:Lambda就是匿名内部类的简化实际上是创建了一个类,实现了接口,重写了接口的方法
下面来写几个接口,分别用Lambda表达式和不适用Lambda表达式来调用对比一下
(1)无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}两种方式分别调用对比
public static void main(String[] args) {
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("测试一下");
}
};
noParameterNoReturn.test();
NoParameterNoReturn noParameterNoReturn1 = () -> {System.out.println("测试一下");};
NoParameterNoReturn noParameterNoReturn2 = () -> System.out.println("测试一下");
NoParameterNoReturn noParameterNoReturn3 = () -> {
System.out.println("测试1下");
System.out.println("测试2下");
};
}(2)无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
} public static void main(String[] args) {
OneParameterNoReturn oneParameterNoReturn = (int x) -> {
System.out.println(x);
};
oneParameterNoReturn.test(100);
System.out.println("简化:");
OneParameterNoReturn oneParameterNoReturn1 = x -> System.out.println(x);
OneParameterNoReturn oneParameterNoReturn2 = System.out::println;
oneParameterNoReturn1.test(10);
}(3)无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
} public static void main(String[] args) {
MoreParameterNoReturn moreParameterNoReturn = (int a,int b) -> {
System.out.println(a+b);
};
moreParameterNoReturn.test(10,20);
//要求两个类型同时省略
MoreParameterNoReturn moreParameterNoReturn1 = (a,b) -> System.out.println(a+b);
moreParameterNoReturn1.test(20,30);
}(4)有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
int test();
} public static void main(String[] args) {
NoParameterReturn noParameterReturn = () -> {return 10;};
int ret = noParameterReturn.test();
System.out.println(ret);
NoParameterReturn noParameterReturn1 = () ->10;
int ret2 = noParameterReturn1.test();
System.out.println(ret2);
}(5)有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
int test(int a);
} public static void main(String[] args) {
OneParameterReturn oneParameterReturn = x -> 2*x;
System.out.println(oneParameterReturn.test(10));
}(6)有返回值多个参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
} public static void main(String[] args) {
MoreParameterReturn moreParameterReturn = (x,y) -> x+y;
System.out.println(moreParameterReturn.test(10, 20));
}Lambda语法简略规则:1. 参数类型可以省略,并且要省略就要全部省略2. 参数的括号当里面只有一个参数时,括号可以省略3. 如果方法体中只有一句代码,那么大括号可以省略4. 如果方法体中只有一句代码,尤其是return语句,那么大括号和return关键字都可以省略
5.4 变量捕获
(1)匿名内部类变量捕获
class Demo {
void fun() {
System.out.println("dasd");
}
}在匿名内部类中,变量捕获是指外部变量的捕获
外部变量在匿名内部类中使用,一定是在匿名内部类中没有被修改过的
内部变量不影响
public static void main7(String[] args) {
int a = 10;
//在匿名内部类中,变量捕获(外部变量的捕获),看使用的外部变量一定是未被修改过的
new Demo() {
@Override
void fun() {
int c = 99;
c = 100;
System.out.println(c+"重写一下" + a);
}
}.fun();
}(2)Lambda变量捕获
Lambda 表达式中存在变量捕获 ,必须理解Lambda变量捕获后,才可以明白Lambda 表达式的作用域,其变量捕获规则和匿名内部类规则类似
5.5 Lambda在集合中使用
集合中新增了部分接口,便于和Lambda表达式对接
这里举几个例子
(1)Collection接口中forEach()打印全部
(2)List接口中sort()排序
分别写出使用Lambda表达式和不使用的方法
public static void main(String[] args) {
//Lambda内部也是匿名内部类,用外部变量不能被修改
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("bit");
list.add("hellol");
list.add("lambda");
//打印全部
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
list.forEach(s -> System.out.println(s));
//排序
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
list.sort(((o1, o2) -> o1.compareTo(o2)));
list.forEach(s -> System.out.println(s));
}(3)Map接口中forEach()
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "hello");
map.put(2, "bit");
map.put(3, "hello");
map.put(4, "lambda");
map.forEach(new BiConsumer<Integer, String>() {
@Override
public void accept(Integer integer, String s) {
System.out.println("key:"+integer+"val:"+s);
}
});
map.forEach((x,y)-> System.out.println("key:"+x+"val:"+y));
}5.6 Lambda表达式优缺点
优点:
1.代码简介,开发迅速
2.方便函数式变成
3.改善集合操作
缺点:
1.代码可读性差
2.不容易进行调试
3.在非并行计算中,很多计算未必有传统for性能高
边栏推荐
- 带你熟悉云网络的“电话簿”:DNS
- [5 minutes paper] Pointer network
- Zhaoqi science and technology innovation high-end talent project was introduced and implemented, mass entrepreneurship and innovation competition was organized, and online live roadshow was broadcast
- 【LeetCode每日一题】——121.买卖股票的最佳时机
- Bluetooth ble4.0-hm-10 device pairing Guide
- Sword finger offer II 009. subarray with product less than k
- 筑牢生态安全防线,广州开展突发环境事件应急演练
- 什么是虚拟摄像头
- 81.(cesium之家)cesium修改灰色背景(默认蓝色)
- Where is the foreign literature needed to write the graduation thesis?
猜你喜欢

Digital commerce cloud: lead the digital upgrading of chemical industry and see how Mobei can quickly open up the whole scene of mutual integration and interoperability
![[static code quality analysis tool] Shanghai daoning brings you sonarource/sonarqube download, trial and tutorial](/img/fe/3baec8f6def4e569842a683fcb9fd1.png)
[static code quality analysis tool] Shanghai daoning brings you sonarource/sonarqube download, trial and tutorial

Practical task scheduling platform (scheduled task)

Unity URP entry practice

Google tries to introduce password strength indicator for chromeos to improve online security

数据中台、BI业务访谈(四)—— 十个问题看本质

固态硬盘对游戏运行的帮助有多少

FOC学习笔记-坐标变换以及仿真验证

Double the efficiency of dual screen collaboration lingyao x dual screen Pro leads the new trend of dual screen technology
![[5 minutes paper] Pointer network](/img/9a/66edc27f08f245447cc6b8867d2383.png)
[5 minutes paper] Pointer network
随机推荐
兆骑科创高端人才项目引进落地,双创大赛承办,线上直播路演
Notes (5)
FOC learning notes - coordinate transformation and simulation verification
Soft test (VII) performance test (1) brief introduction
2023餐饮业展,中国餐饮供应链展,江西餐饮食材展2月举办
Sword finger offer II 009. subarray with product less than k
How to translate academic documents?
带你熟悉云网络的“电话簿”:DNS
Ner of NLP: Exploration and practice of product title attribute recognition
The IPO of shengtaier technology was terminated: it was planned to raise 560million yuan, and Qiming and Jifeng capital were shareholders
Write a summary, want to use a reliable software to sort out documents, is there any recommendation?
2023 catering industry exhibition, China catering supply chain exhibition and Jiangxi catering Ingredients Exhibition were held in February
Creation and traversal of binary tree
蓝牙BLE4.0-HM-10设备配对指南
NAT/NAPT地址转换(内外网通信)技术详解【华为eNSP】
VP视频结构化框架
Prometheus adds email alarm and enterprise wechat robot alarm
DevSecOps,让速度和安全兼顾
The R language uses the histogram function in the lattice package to visualize the histogram (histogram plot), the col parameter to customize the fill color, and the type parameter to customize the hi
R language uses LM function to build a multiple regression model with interactive terms, and uses step function to build a stepwise regression model to screen the best subset of predictive variables (