个人网站推荐,网站文章不显示,莱芜手机网站建设报价,seo排名怎样Java的反射机制、Lambda表达式和枚举 文章目录 Java的反射机制、Lambda表达式和枚举1.反射机制反射的概念、用途、优缺点反射相关的类及使用#xff08;重要#xff01;#xff01;#xff09;相关类Class类#xff1a;代表类实体#xff0c;表示类和接口Field类#xf…Java的反射机制、Lambda表达式和枚举 文章目录 Java的反射机制、Lambda表达式和枚举1.反射机制反射的概念、用途、优缺点反射相关的类及使用重要相关类Class类代表类实体表示类和接口Field类代表类的成员变量/类的属性Method类代表类的方法Constructor类:代表类的构造方法获取类中注解相关的方法了解 使用获取Class对象的三种方式例子通过反射创建对象反射私有构造方法创建对象反射私有属性反射私有方法 2.Lambda表达式Lambda是什么、语法基本使用用途1变量捕获匿名内部类变量捕获Lambda表达式变量捕获 用途2在集合中的使用Collection接口List接口Map接口 3.枚举枚举简介、优缺点枚举的构造方法创建与使用枚举与反射 1.反射机制
反射的概念、用途、优缺点
Java的反射机制就是在运行状态中对于任意一个类都能知道它所有属性和方法对于任意一个对象都能调用它的任意方法和属性并进行部分类型信息的修改这种动态获取信息以及动态调用对象方法的功能叫做Java的反射机制。 Java程序中很多对象在运行时会出现两种基本类型运行时类型RTTI和编译时类型。 例如Person pnew Student()这句代码中p在编译时就是Person运行时就是Student程序需要再运行时发现对象和类的真实信息通过反射就可以判断出这个对象和类属于哪些类。 在日常的第三方应用开发过程中可以利用Java的反射机制通过反射来获取所需要的私有成员或者方法比较常见 最重要的用途就是开发各种框架。 例如在spring中我们把所有的类Bean交给spring容器管理不管是xml配置还是注解配置Bean当我们从容器中获取Bean来依赖注入时容器就读取配置而配置中给的就是类的信息spring根据这些信息动态的创建Bean
优点
对于任意类都能知道它的属性和方法对于任意对象都能调用它的任意方法可以增加程序的灵活性和扩展性已经运用在很多流行的框架如spring中
缺点
会有效率问题导致程序效率降低代码可能比较复杂
反射相关的类及使用重要
在Java中实现反射都要依赖于Class类。
这是因为Java文件被编译后生成.class文件JVM需要去解读.class文件被编译后的Java文件.class也被JVM解析成一个对象这个对象就是java.lang.Class。
这样当程序运行时每个Java文件最终都变成了Class类对象的一个实例。
因此将反射机制应用到这个实例上时就可以获取或添加改变这个类的属性和方法时这个类就会成为一个动态的类。
注意所有和反射相关的包都在 import java.lang.reflect 包下面
相关类
所有的这些类都是加了declared能够访问的范围是更大的。
Class类代表类实体表示类和接口
方法用途getClassLoader()获取类的加载器getDeclaredClasser()返回一个数组数组中包含这个类中所有的类和接口类的对象forName(String className)根据类名返回类的对象newInstance创建类的实例getName()获取类的完整路径名字
Field类代表类的成员变量/类的属性
方法用途getField(String name)获取某个公有的属性对象getFields()获取所有公有的属性对象getDeclaredField(String name)获取某个属性对象getDeclaredFields()获取所有属性对象
Method类代表类的方法
方法用途getMethod(String name,Class…? parameterTypes)获取该类某个公有的方法getMethods()获取该类所有公有的方法getDeclaredMethod(String name,Class…? parameterTypes)获取该类某个方法getDeclaredMethods()获取该类所有方法
Constructor类:代表类的构造方法
方法用途getConstructor(Class…? parameterTypes)获取该类中与参数类型匹配的公有构造方法getConstructors()获取该类中所有公有构造方法getDeclaredConstructor(Class…? parameterTypes)获取该类中与参数类型匹配的构造方法getDeclaredConstructors()获取该类所有构造方法
获取类中注解相关的方法了解
方法用途getAnnotation(Class annotationClass)返回该类中与参数类型匹配的公有注解对象getAnnotations()返回该类中所有公有注解对象getDeclaredAnnotation(Class annotationClass)返回该类中与参数类型匹配的所有注解对象getDeclaredAnnotations()返回该类中所有的注解对象
使用
在进行反射之前需要做的第一步就是拿到当前需要反射的类的Class对象然后根据Class对象的核心方法达到反射的目的获取或修改相关信息。
获取Class对象的三种方式
第一种使用Class.forName(“类的全路径名”)【使用的比较多的】
第二种使用.class方法适合在编译时就已经明确要操作的Class
第三种使用类对象的getClass()方法
class Student{//私有属性nameprivate String name school;//公有属性agepublic int age 18;//不带参数的构造public Student(){System.out.println(Student());}//私有带参构造private Student(String name,int age) {this.name name;this.age age;System.out.println(Student(String,name));}//私有不带参private void eat(){System.out.println(i am eating);}//公开不带参public void sleep(){System.out.println(i am sleeping);}//私有带参private void function(String str) {System.out.println(str);}Overridepublic String toString() {return Student{ name name \ , age age };}
}
public class Reflect {public static void main(String[] args) throws ClassNotFoundException {Student studentnew Student();//获取Class对象的三种方法//1.通过getClass方法Class? c1student.getClass();//2.通过类名.class获取Class? c2Student.class;//3.通过Class.forName(全路径)[需要处理异常——自己处理or交给JVM处理]Class? c3Class.forName(Student);//在当前类System.out.println(c1.equals(c2));System.out.println(c1.equals(c3));System.out.println(c3.equals(c2));}
}例子
通过反射创建对象 public static void reflectNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class? c3 Class.forName(Student);Student student (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象reflectNewInstance();}反射私有构造方法创建对象 //反射私有的构造方法public static void reflectPrivateConstructor() {try {Class? c3Class.forName(Student);Constructor? constructorc3.getDeclaredConstructor(String.class,int.class);//设置为true之后可以修改访问权限constructor.setAccessible(true);Student student(Student) constructor.newInstance(zhangsan,17);System.out.println(student);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}//反射私有属性public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象reflectPrivateConstructor();}反射私有属性 //反射私有属性public static void reflectPrivateField(){try {Class? c3Class.forName(Student);Field fieldc3.getDeclaredField(name);field.setAccessible(true);//修改属性的访问权限Object objectStudentc3.newInstance();Student student(Student)objectStudent;field.set(student,张三);String name(String)field.get(student);System.out.println(反射私有属性修改名字为name);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchFieldException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象
// reflectPrivateConstructor();//反射私有属性reflectPrivateField();}反射私有方法 //反射私有方法public static void reflectPrivateMethod(){try {Class? c3Class.forName(Student);Method method c3.getDeclaredMethod(function,String.class);method.setAccessible(true);Object objectc3.newInstance();Student student(Student) object;method.invoke(student,给私有function函数传的参数);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象
// reflectPrivateConstructor();//反射私有属性
// reflectPrivateField();//反射私有方法reflectPrivateMethod();}2.Lambda表达式
相当于只有一个抽象方法的接口的简化。
Lambda是什么、语法
它是JavaSE8中的一个新的特性Lambda表达式允许我们通过表达式代替功能接口。Lambda 表达式Lambda expression基于数学中的λ演算得名也可称为闭包Closure。
基本语法: **(parameters) - expression** 或 **(parameters) -{ statements; }**
parameters就是函数式接口里的形参列表。这里的参数类型可以明确的生命也可以由JVM隐含判断。当只有一个推断类型时可以省略圆括号。
-被用于的意思
方法体可以是表达式也可以是代码块是函数式接口方法的实现可返回可不返回
// 1. 不需要参数,返回值为 2
() - 2
// 2. 接收一个参数(数字类型),返回其2倍的值
x - 2 * x
// 3. 接受2个参数(数字),并返回他们的和
(x, y) - x y
// 4. 接收2个int型整数,返回他们的乘积
(int x, int y) - x * y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) - System.out.print(s)函数式接口一个接口有且只有一个抽象方法 如果我们在某个接口上声明了 FunctionalInterface 注解那么编译器就会按照函数式接口的定义来要求该接口这样如果有两个抽象方法程序编译就会报错的。 定义方法 FunctionalInterface
interface NoParameterNoReturn {//注意只能有一个方法void test();
}FunctionalInterface
interface NoParameterNoReturn {void test();default void test2() {System.out.println(JDK1.8新特性default默认方法可以有具体的实现);}
}基本使用
FunctionalInterface
interface NoParameterNoReturn{void test();
}
FunctionalInterface
interface OneParameterNoReturn{void test(int a);
}
FunctionalInterface
interface MoreParameterNoReturn{void test(int a,int b);
}
FunctionalInterface
interface NoParameterReturn{int test();
}
FunctionalInterface
interface OneParameterReturn{int test(int a);
}
FunctionalInterface
interface MoreParameterReturn{int test(int a,int b);
}
public class LambdaDemo {public static void main(String[] args) {//匿名内部类重写了实现接口的方法NoParameterNoReturn noParameterNoReturnnew NoParameterNoReturn(){Overridepublic void test() {System.out.println(无参无返回值);}};noParameterNoReturn.test();NoParameterNoReturn noParameterNoReturn1()-{System.out.println(L:无参无返回值);};noParameterNoReturn1.test();OneParameterNoReturn oneParameterNoReturnnew OneParameterNoReturn() {Overridepublic void test(int a) {System.out.println(一参无返回值);}};oneParameterNoReturn.test(1);OneParameterNoReturn oneParameterNoReturn1 (x)-{System.out.println(L:一参无返回值);};oneParameterNoReturn1.test(1);MoreParameterNoReturn moreParameterNoReturnnew MoreParameterNoReturn() {Overridepublic void test(int a,int b) {System.out.println(多参无返回值);}};moreParameterNoReturn.test(1,2);MoreParameterNoReturn moreParameterNoReturn1(x,y)-{System.out.println(L:多参无返回值);};moreParameterNoReturn1.test(1,2);//匿名内部类重写了实现接口的方法NoParameterReturn noParameterReturnnew NoParameterReturn(){Overridepublic int test() {System.out.println(无参有返回值);return 0;}};noParameterReturn.test();NoParameterReturn noParameterReturn1()-{System.out.println(L:无参有返回值);return 0;};noParameterNoReturn1.test();OneParameterReturn oneParameterReturnnew OneParameterReturn() {Overridepublic int test(int a) {System.out.println(一参有返回值);return 0;}};oneParameterNoReturn.test(1);OneParameterReturn oneParameterReturn1 (x)-{System.out.println(L:一参有返回值);return x;};oneParameterNoReturn1.test(1);MoreParameterReturn moreParameterReturnnew MoreParameterReturn() {Overridepublic int test(int a,int b) {System.out.println(多参有返回值);return ab;}};moreParameterReturn.test(1,2);MoreParameterReturn moreParameterReturn1(x,y)-{System.out.println(L:多参有返回值);return xy;};moreParameterNoReturn1.test(1,2);}
}用途1变量捕获
变量捕获可以使我们更好的理解Lambda表达式的作用域Java中的匿名内部类和Lambda表达式会存在变量捕获。
匿名内部类变量捕获
FunctionalInterface
interface Test{void test();
}
public class LambdaDemo2 {//匿名内部类变量捕获public static void test01() {int a100;final int b10;
// int c100;
// c20;Test tnew Test(){Overridepublic void test() {System.out.println(匿名内部类的变量捕获:(常量或者没有被改变过值的变量)a);System.out.println(匿名内部类的变量捕获:(常量或者没有被改变过值的变量)b);
// System.out.println(匿名内部类的变量捕获:(常量或者没有被改变过值的变量)c);}};t.test();}public static void main(String[] args) {test01();}
}可以被捕获的只能是常量或者没有被修改过的常量否则就会直接报错 Lambda表达式变量捕获
FunctionalInterface
interface Test{void test();
}
public class LambdaDemo2 {//匿名内部类变量捕获public static void test01() {int a100;final int b10;
// int c100;
// c20;Test tnew Test(){Overridepublic void test() {System.out.println(匿名内部类的变量捕获:(常量或者没有被改变过值的变量)a);System.out.println(匿名内部类的变量捕获:(常量或者没有被改变过值的变量)b);
// System.out.println(匿名内部类的变量捕获:(常量或者没有被改变过值的变量)c);}};t.test();}//Lambda表达式的变量捕获public static void test02() {int a100;final int b10;Test t()-{System.out.println(L的变量捕获:(常量或者没有被改变过值的变量)a);System.out.println(L的变量捕获:(常量或者没有被改变过值的变量)b);};t.test();}public static void main(String[] args) {
// test01();test02();}
}用途2在集合中的使用
Collection接口
以实现Collection接口方法实现了Iterable接口的forEach方法为例
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;public class LambdaDemo3 {public static void main(String[] args) {ArrayListInteger listnew ArrayList();list.add(1);list.add(19);list.add(17);list.add(16);list.add(12);list.add(12);//使用foreach迭代器System.out.println(迭代器);for (int x:list) {System.out.print(x );}System.out.println();//使用匿名内部类方式System.out.println(匿名内部类);list.forEach(new ConsumerInteger() {Overridepublic void accept(Integer integer) {System.out.print(integer );}});System.out.println();System.out.println(Lambda表达式);//使用Lambda表达式方式list.forEach((i)-{System.out.print(i );});}
}List接口
以sort方法为例
//sort方法
list.sort((a,b)-{return b-a;});//修改排序规则为降序排序
System.out.println(list);Map接口
import java.util.HashMap;
import java.util.function.BiConsumer;public class LambdaDemo4 {public static void main(String[] args) {//Map接口的forEach方法HashMapInteger,String mapnew HashMap();map.put(1,张三);map.put(2,李四);map.put(3,王五);//匿名内部类map.forEach(new BiConsumerInteger, String() {Overridepublic void accept(Integer integer, String s) {System.out.println(integer:s);}});//Lambda表达式map.forEach((integer,s)-{System.out.println(L:integer:s);});}
}3.枚举
枚举简介、优缺点
它是在JDK1.5之后引入的主要用来将常量组织起来。通常应用在错误状态码消息类型颜色划分和状态机上等等。 定义好的是枚举对象。
枚举类型实际上是 java.lang.Enum 的子类也就是说自己写的枚举类就算没有显示的继承 Enum 但是其默认继承了这个类。
优点
枚举常量更安全简单枚举具有内置方法更优雅
缺点
没法继承不能被实例化【原因就是它构造方法是私有的】不可扩展
枚举的构造方法
默认是私有的也只能是私有的不能被继承并且只能在定义枚举对象的时候被调用。
public enum TestEnum {RED,BLACK,WHITE,BLUE(BLUE,4),PINK;TestEnum(){}private String color;private int ri;TestEnum(String color,int ri){this.colorcolor;this.riri;}
}创建与使用 public enum TestEnum {RED,BLACK,WHITE;public static void main(String[] args) {test01();test02();test03();}//测试枚举的switch用法public static void test01() {TestEnum testEnum TestEnum.BLACK;switch(testEnum){case RED:System.out.println(red);break;case BLACK:System.out.println(black);break;case WHITE:System.out.println(white);break;default:System.out.println(没有当前颜色);break;}}//以数组形式返回枚举类型的所有成员public static void test02() {TestEnum[] testEnumTestEnum.values();for (int i 0; i testEnum.length; i) {System.out.println(testEnum[i]:testEnum[i]);}}public static void test03(){//将普通字符串转换成枚举实例
// TestEnum testEnumTestEnum.valueOf(GREEN);//需要是已经定义的否则报错 No enum constant TestEnum.GREENTestEnum testEnumTestEnum.valueOf(RED);System.out.println(testEnum);//获取枚举成员的索引位置int indexTestEnum.BLACK.ordinal();System.out.println(BLACK:index);//比较两个枚举成员在定义时的顺序默认拿序号比较System.out.println(BLACK.compareTo(RED));}}枚举与反射
能不能通过反射创建枚举实例
不能看源码分析 //反射枚举 私有的构造方法public static void reflectEnumPrivateConstructor() throws Exception {Class? c3Class.forName(TestEnum);Constructor? constructorc3.getDeclaredConstructor(String.class,int.class);//设置为true之后可以修改访问权限constructor.setAccessible(true);TestEnum testEnum(TestEnum) constructor.newInstance(GREY,10);System.out.println(testEnum);}public static void main(String[] args) throws Exception {//通过反射创建对象
// reflectNewInstance();//通过反射得到私有构造方法创建对象
// reflectPrivateConstructor();//反射私有属性
// reflectPrivateField();//反射私有方法
// reflectPrivateMethod();//反射枚举类型私有方法reflectEnumPrivateConstructor();}通过查看源码我们发现枚举在这里被过滤了。
总的来说因为枚举的构造方法是私有的所以不能实例化另外反射拿到的类对象再去new实例的时候会因为枚举类型被过滤掉所以枚举实现的单例模式是安全的。
所以枚举具有构造方法默认是私有的并且都是默认继承java.lang.Enum这个类可以避免反射和序列化问题枚举常量更安全更简单代码更加优雅。